1f220fa62Smrg/* 2f220fa62Smrg * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008) 3f220fa62Smrg * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved. 4f220fa62Smrg * 5f220fa62Smrg * Permission is hereby granted, free of charge, to any person obtaining a 6f220fa62Smrg * copy of this software and associated documentation files (the "Software"), 7f220fa62Smrg * to deal in the Software without restriction, including without limitation 8f220fa62Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9f220fa62Smrg * and/or sell copies of the Software, and to permit persons to whom the 10f220fa62Smrg * Software is furnished to do so, subject to the following conditions: 11f220fa62Smrg * 12f220fa62Smrg * The above copyright notice including the dates of first publication and 13f220fa62Smrg * either this permission notice or a reference to 14f220fa62Smrg * http://oss.sgi.com/projects/FreeB/ 15f220fa62Smrg * shall be included in all copies or substantial portions of the Software. 16f220fa62Smrg * 17f220fa62Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18f220fa62Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19f220fa62Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20f220fa62Smrg * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 21f220fa62Smrg * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF 22f220fa62Smrg * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23f220fa62Smrg * SOFTWARE. 24f220fa62Smrg * 25f220fa62Smrg * Except as contained in this notice, the name of Silicon Graphics, Inc. 26f220fa62Smrg * shall not be used in advertising or otherwise to promote the sale, use or 27f220fa62Smrg * other dealings in this Software without prior written authorization from 28f220fa62Smrg * Silicon Graphics, Inc. 29f220fa62Smrg */ 30f220fa62Smrg 31f220fa62Smrg#include "gluos.h" 32f220fa62Smrg#include <math.h> 33f220fa62Smrg#include <GL/gl.h> 34f220fa62Smrg#include <GL/glu.h> 35f220fa62Smrg#include "gluint.h" 36f220fa62Smrg 37f220fa62Smrg/* 38f220fa62Smrg** Make m an identity matrix 39f220fa62Smrg*/ 40f220fa62Smrgstatic void __gluMakeIdentityd(GLdouble m[16]) 41f220fa62Smrg{ 42f220fa62Smrg m[0+4*0] = 1; m[0+4*1] = 0; m[0+4*2] = 0; m[0+4*3] = 0; 43f220fa62Smrg m[1+4*0] = 0; m[1+4*1] = 1; m[1+4*2] = 0; m[1+4*3] = 0; 44f220fa62Smrg m[2+4*0] = 0; m[2+4*1] = 0; m[2+4*2] = 1; m[2+4*3] = 0; 45f220fa62Smrg m[3+4*0] = 0; m[3+4*1] = 0; m[3+4*2] = 0; m[3+4*3] = 1; 46f220fa62Smrg} 47f220fa62Smrg 48f220fa62Smrgstatic void __gluMakeIdentityf(GLfloat m[16]) 49f220fa62Smrg{ 50f220fa62Smrg m[0+4*0] = 1; m[0+4*1] = 0; m[0+4*2] = 0; m[0+4*3] = 0; 51f220fa62Smrg m[1+4*0] = 0; m[1+4*1] = 1; m[1+4*2] = 0; m[1+4*3] = 0; 52f220fa62Smrg m[2+4*0] = 0; m[2+4*1] = 0; m[2+4*2] = 1; m[2+4*3] = 0; 53f220fa62Smrg m[3+4*0] = 0; m[3+4*1] = 0; m[3+4*2] = 0; m[3+4*3] = 1; 54f220fa62Smrg} 55f220fa62Smrg 56f220fa62Smrgvoid GLAPIENTRY 57f220fa62SmrggluOrtho2D(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top) 58f220fa62Smrg{ 59f220fa62Smrg glOrtho(left, right, bottom, top, -1, 1); 60f220fa62Smrg} 61f220fa62Smrg 62f220fa62Smrg#define __glPi 3.14159265358979323846 63f220fa62Smrg 64f220fa62Smrgvoid GLAPIENTRY 65f220fa62SmrggluPerspective(GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zFar) 66f220fa62Smrg{ 67f220fa62Smrg GLdouble m[4][4]; 68f220fa62Smrg double sine, cotangent, deltaZ; 69f220fa62Smrg double radians = fovy / 2 * __glPi / 180; 70f220fa62Smrg 71f220fa62Smrg deltaZ = zFar - zNear; 72f220fa62Smrg sine = sin(radians); 73f220fa62Smrg if ((deltaZ == 0) || (sine == 0) || (aspect == 0)) { 74f220fa62Smrg return; 75f220fa62Smrg } 76f220fa62Smrg cotangent = COS(radians) / sine; 77f220fa62Smrg 78f220fa62Smrg __gluMakeIdentityd(&m[0][0]); 79f220fa62Smrg m[0][0] = cotangent / aspect; 80f220fa62Smrg m[1][1] = cotangent; 81f220fa62Smrg m[2][2] = -(zFar + zNear) / deltaZ; 82f220fa62Smrg m[2][3] = -1; 83f220fa62Smrg m[3][2] = -2 * zNear * zFar / deltaZ; 84f220fa62Smrg m[3][3] = 0; 85f220fa62Smrg glMultMatrixd(&m[0][0]); 86f220fa62Smrg} 87f220fa62Smrg 88f220fa62Smrgstatic void normalize(float v[3]) 89f220fa62Smrg{ 90f220fa62Smrg float r; 91f220fa62Smrg 92f220fa62Smrg r = sqrt( v[0]*v[0] + v[1]*v[1] + v[2]*v[2] ); 93f220fa62Smrg if (r == 0.0) return; 94f220fa62Smrg 95f220fa62Smrg v[0] /= r; 96f220fa62Smrg v[1] /= r; 97f220fa62Smrg v[2] /= r; 98f220fa62Smrg} 99f220fa62Smrg 100f220fa62Smrgstatic void cross(float v1[3], float v2[3], float result[3]) 101f220fa62Smrg{ 102f220fa62Smrg result[0] = v1[1]*v2[2] - v1[2]*v2[1]; 103f220fa62Smrg result[1] = v1[2]*v2[0] - v1[0]*v2[2]; 104f220fa62Smrg result[2] = v1[0]*v2[1] - v1[1]*v2[0]; 105f220fa62Smrg} 106f220fa62Smrg 107f220fa62Smrgvoid GLAPIENTRY 108f220fa62SmrggluLookAt(GLdouble eyex, GLdouble eyey, GLdouble eyez, GLdouble centerx, 109f220fa62Smrg GLdouble centery, GLdouble centerz, GLdouble upx, GLdouble upy, 110f220fa62Smrg GLdouble upz) 111f220fa62Smrg{ 112f220fa62Smrg float forward[3], side[3], up[3]; 113f220fa62Smrg GLfloat m[4][4]; 114f220fa62Smrg 115f220fa62Smrg forward[0] = centerx - eyex; 116f220fa62Smrg forward[1] = centery - eyey; 117f220fa62Smrg forward[2] = centerz - eyez; 118f220fa62Smrg 119f220fa62Smrg up[0] = upx; 120f220fa62Smrg up[1] = upy; 121f220fa62Smrg up[2] = upz; 122f220fa62Smrg 123f220fa62Smrg normalize(forward); 124f220fa62Smrg 125f220fa62Smrg /* Side = forward x up */ 126f220fa62Smrg cross(forward, up, side); 127f220fa62Smrg normalize(side); 128f220fa62Smrg 129f220fa62Smrg /* Recompute up as: up = side x forward */ 130f220fa62Smrg cross(side, forward, up); 131f220fa62Smrg 132f220fa62Smrg __gluMakeIdentityf(&m[0][0]); 133f220fa62Smrg m[0][0] = side[0]; 134f220fa62Smrg m[1][0] = side[1]; 135f220fa62Smrg m[2][0] = side[2]; 136f220fa62Smrg 137f220fa62Smrg m[0][1] = up[0]; 138f220fa62Smrg m[1][1] = up[1]; 139f220fa62Smrg m[2][1] = up[2]; 140f220fa62Smrg 141f220fa62Smrg m[0][2] = -forward[0]; 142f220fa62Smrg m[1][2] = -forward[1]; 143f220fa62Smrg m[2][2] = -forward[2]; 144f220fa62Smrg 145f220fa62Smrg glMultMatrixf(&m[0][0]); 146f220fa62Smrg glTranslated(-eyex, -eyey, -eyez); 147f220fa62Smrg} 148f220fa62Smrg 149f220fa62Smrgstatic void __gluMultMatrixVecd(const GLdouble matrix[16], const GLdouble in[4], 150f220fa62Smrg GLdouble out[4]) 151f220fa62Smrg{ 152f220fa62Smrg int i; 153f220fa62Smrg 154f220fa62Smrg for (i=0; i<4; i++) { 155f220fa62Smrg out[i] = 156f220fa62Smrg in[0] * matrix[0*4+i] + 157f220fa62Smrg in[1] * matrix[1*4+i] + 158f220fa62Smrg in[2] * matrix[2*4+i] + 159f220fa62Smrg in[3] * matrix[3*4+i]; 160f220fa62Smrg } 161f220fa62Smrg} 162f220fa62Smrg 163f220fa62Smrg/* 164f220fa62Smrg** Invert 4x4 matrix. 165f220fa62Smrg** Contributed by David Moore (See Mesa bug #6748) 166f220fa62Smrg*/ 167f220fa62Smrgstatic int __gluInvertMatrixd(const GLdouble m[16], GLdouble invOut[16]) 168f220fa62Smrg{ 169f220fa62Smrg double inv[16], det; 170f220fa62Smrg int i; 171f220fa62Smrg 172f220fa62Smrg inv[0] = m[5]*m[10]*m[15] - m[5]*m[11]*m[14] - m[9]*m[6]*m[15] 173f220fa62Smrg + m[9]*m[7]*m[14] + m[13]*m[6]*m[11] - m[13]*m[7]*m[10]; 174f220fa62Smrg inv[4] = -m[4]*m[10]*m[15] + m[4]*m[11]*m[14] + m[8]*m[6]*m[15] 175f220fa62Smrg - m[8]*m[7]*m[14] - m[12]*m[6]*m[11] + m[12]*m[7]*m[10]; 176f220fa62Smrg inv[8] = m[4]*m[9]*m[15] - m[4]*m[11]*m[13] - m[8]*m[5]*m[15] 177f220fa62Smrg + m[8]*m[7]*m[13] + m[12]*m[5]*m[11] - m[12]*m[7]*m[9]; 178f220fa62Smrg inv[12] = -m[4]*m[9]*m[14] + m[4]*m[10]*m[13] + m[8]*m[5]*m[14] 179f220fa62Smrg - m[8]*m[6]*m[13] - m[12]*m[5]*m[10] + m[12]*m[6]*m[9]; 180f220fa62Smrg inv[1] = -m[1]*m[10]*m[15] + m[1]*m[11]*m[14] + m[9]*m[2]*m[15] 181f220fa62Smrg - m[9]*m[3]*m[14] - m[13]*m[2]*m[11] + m[13]*m[3]*m[10]; 182f220fa62Smrg inv[5] = m[0]*m[10]*m[15] - m[0]*m[11]*m[14] - m[8]*m[2]*m[15] 183f220fa62Smrg + m[8]*m[3]*m[14] + m[12]*m[2]*m[11] - m[12]*m[3]*m[10]; 184f220fa62Smrg inv[9] = -m[0]*m[9]*m[15] + m[0]*m[11]*m[13] + m[8]*m[1]*m[15] 185f220fa62Smrg - m[8]*m[3]*m[13] - m[12]*m[1]*m[11] + m[12]*m[3]*m[9]; 186f220fa62Smrg inv[13] = m[0]*m[9]*m[14] - m[0]*m[10]*m[13] - m[8]*m[1]*m[14] 187f220fa62Smrg + m[8]*m[2]*m[13] + m[12]*m[1]*m[10] - m[12]*m[2]*m[9]; 188f220fa62Smrg inv[2] = m[1]*m[6]*m[15] - m[1]*m[7]*m[14] - m[5]*m[2]*m[15] 189f220fa62Smrg + m[5]*m[3]*m[14] + m[13]*m[2]*m[7] - m[13]*m[3]*m[6]; 190f220fa62Smrg inv[6] = -m[0]*m[6]*m[15] + m[0]*m[7]*m[14] + m[4]*m[2]*m[15] 191f220fa62Smrg - m[4]*m[3]*m[14] - m[12]*m[2]*m[7] + m[12]*m[3]*m[6]; 192f220fa62Smrg inv[10] = m[0]*m[5]*m[15] - m[0]*m[7]*m[13] - m[4]*m[1]*m[15] 193f220fa62Smrg + m[4]*m[3]*m[13] + m[12]*m[1]*m[7] - m[12]*m[3]*m[5]; 194f220fa62Smrg inv[14] = -m[0]*m[5]*m[14] + m[0]*m[6]*m[13] + m[4]*m[1]*m[14] 195f220fa62Smrg - m[4]*m[2]*m[13] - m[12]*m[1]*m[6] + m[12]*m[2]*m[5]; 196f220fa62Smrg inv[3] = -m[1]*m[6]*m[11] + m[1]*m[7]*m[10] + m[5]*m[2]*m[11] 197f220fa62Smrg - m[5]*m[3]*m[10] - m[9]*m[2]*m[7] + m[9]*m[3]*m[6]; 198f220fa62Smrg inv[7] = m[0]*m[6]*m[11] - m[0]*m[7]*m[10] - m[4]*m[2]*m[11] 199f220fa62Smrg + m[4]*m[3]*m[10] + m[8]*m[2]*m[7] - m[8]*m[3]*m[6]; 200f220fa62Smrg inv[11] = -m[0]*m[5]*m[11] + m[0]*m[7]*m[9] + m[4]*m[1]*m[11] 201f220fa62Smrg - m[4]*m[3]*m[9] - m[8]*m[1]*m[7] + m[8]*m[3]*m[5]; 202f220fa62Smrg inv[15] = m[0]*m[5]*m[10] - m[0]*m[6]*m[9] - m[4]*m[1]*m[10] 203f220fa62Smrg + m[4]*m[2]*m[9] + m[8]*m[1]*m[6] - m[8]*m[2]*m[5]; 204f220fa62Smrg 205f220fa62Smrg det = m[0]*inv[0] + m[1]*inv[4] + m[2]*inv[8] + m[3]*inv[12]; 206f220fa62Smrg if (det == 0) 207f220fa62Smrg return GL_FALSE; 208f220fa62Smrg 209f220fa62Smrg det = 1.0 / det; 210f220fa62Smrg 211f220fa62Smrg for (i = 0; i < 16; i++) 212f220fa62Smrg invOut[i] = inv[i] * det; 213f220fa62Smrg 214f220fa62Smrg return GL_TRUE; 215f220fa62Smrg} 216f220fa62Smrg 217f220fa62Smrgstatic void __gluMultMatricesd(const GLdouble a[16], const GLdouble b[16], 218f220fa62Smrg GLdouble r[16]) 219f220fa62Smrg{ 220f220fa62Smrg int i, j; 221f220fa62Smrg 222f220fa62Smrg for (i = 0; i < 4; i++) { 223f220fa62Smrg for (j = 0; j < 4; j++) { 224f220fa62Smrg r[i*4+j] = 225f220fa62Smrg a[i*4+0]*b[0*4+j] + 226f220fa62Smrg a[i*4+1]*b[1*4+j] + 227f220fa62Smrg a[i*4+2]*b[2*4+j] + 228f220fa62Smrg a[i*4+3]*b[3*4+j]; 229f220fa62Smrg } 230f220fa62Smrg } 231f220fa62Smrg} 232f220fa62Smrg 233f220fa62SmrgGLint GLAPIENTRY 234f220fa62SmrggluProject(GLdouble objx, GLdouble objy, GLdouble objz, 235f220fa62Smrg const GLdouble modelMatrix[16], 236f220fa62Smrg const GLdouble projMatrix[16], 237f220fa62Smrg const GLint viewport[4], 238f220fa62Smrg GLdouble *winx, GLdouble *winy, GLdouble *winz) 239f220fa62Smrg{ 240f220fa62Smrg double in[4]; 241f220fa62Smrg double out[4]; 242f220fa62Smrg 243f220fa62Smrg in[0]=objx; 244f220fa62Smrg in[1]=objy; 245f220fa62Smrg in[2]=objz; 246f220fa62Smrg in[3]=1.0; 247f220fa62Smrg __gluMultMatrixVecd(modelMatrix, in, out); 248f220fa62Smrg __gluMultMatrixVecd(projMatrix, out, in); 249f220fa62Smrg if (in[3] == 0.0) return(GL_FALSE); 250f220fa62Smrg in[0] /= in[3]; 251f220fa62Smrg in[1] /= in[3]; 252f220fa62Smrg in[2] /= in[3]; 253f220fa62Smrg /* Map x, y and z to range 0-1 */ 254f220fa62Smrg in[0] = in[0] * 0.5 + 0.5; 255f220fa62Smrg in[1] = in[1] * 0.5 + 0.5; 256f220fa62Smrg in[2] = in[2] * 0.5 + 0.5; 257f220fa62Smrg 258f220fa62Smrg /* Map x,y to viewport */ 259f220fa62Smrg in[0] = in[0] * viewport[2] + viewport[0]; 260f220fa62Smrg in[1] = in[1] * viewport[3] + viewport[1]; 261f220fa62Smrg 262f220fa62Smrg *winx=in[0]; 263f220fa62Smrg *winy=in[1]; 264f220fa62Smrg *winz=in[2]; 265f220fa62Smrg return(GL_TRUE); 266f220fa62Smrg} 267f220fa62Smrg 268f220fa62SmrgGLint GLAPIENTRY 269f220fa62SmrggluUnProject(GLdouble winx, GLdouble winy, GLdouble winz, 270f220fa62Smrg const GLdouble modelMatrix[16], 271f220fa62Smrg const GLdouble projMatrix[16], 272f220fa62Smrg const GLint viewport[4], 273f220fa62Smrg GLdouble *objx, GLdouble *objy, GLdouble *objz) 274f220fa62Smrg{ 275f220fa62Smrg double finalMatrix[16]; 276f220fa62Smrg double in[4]; 277f220fa62Smrg double out[4]; 278f220fa62Smrg 279f220fa62Smrg __gluMultMatricesd(modelMatrix, projMatrix, finalMatrix); 280f220fa62Smrg if (!__gluInvertMatrixd(finalMatrix, finalMatrix)) return(GL_FALSE); 281f220fa62Smrg 282f220fa62Smrg in[0]=winx; 283f220fa62Smrg in[1]=winy; 284f220fa62Smrg in[2]=winz; 285f220fa62Smrg in[3]=1.0; 286f220fa62Smrg 287f220fa62Smrg /* Map x and y from window coordinates */ 288f220fa62Smrg in[0] = (in[0] - viewport[0]) / viewport[2]; 289f220fa62Smrg in[1] = (in[1] - viewport[1]) / viewport[3]; 290f220fa62Smrg 291f220fa62Smrg /* Map to range -1 to 1 */ 292f220fa62Smrg in[0] = in[0] * 2 - 1; 293f220fa62Smrg in[1] = in[1] * 2 - 1; 294f220fa62Smrg in[2] = in[2] * 2 - 1; 295f220fa62Smrg 296f220fa62Smrg __gluMultMatrixVecd(finalMatrix, in, out); 297f220fa62Smrg if (out[3] == 0.0) return(GL_FALSE); 298f220fa62Smrg out[0] /= out[3]; 299f220fa62Smrg out[1] /= out[3]; 300f220fa62Smrg out[2] /= out[3]; 301f220fa62Smrg *objx = out[0]; 302f220fa62Smrg *objy = out[1]; 303f220fa62Smrg *objz = out[2]; 304f220fa62Smrg return(GL_TRUE); 305f220fa62Smrg} 306f220fa62Smrg 307f220fa62SmrgGLint GLAPIENTRY 308f220fa62SmrggluUnProject4(GLdouble winx, GLdouble winy, GLdouble winz, GLdouble clipw, 309f220fa62Smrg const GLdouble modelMatrix[16], 310f220fa62Smrg const GLdouble projMatrix[16], 311f220fa62Smrg const GLint viewport[4], 312f220fa62Smrg GLclampd nearVal, GLclampd farVal, 313f220fa62Smrg GLdouble *objx, GLdouble *objy, GLdouble *objz, 314f220fa62Smrg GLdouble *objw) 315f220fa62Smrg{ 316f220fa62Smrg double finalMatrix[16]; 317f220fa62Smrg double in[4]; 318f220fa62Smrg double out[4]; 319f220fa62Smrg 320f220fa62Smrg __gluMultMatricesd(modelMatrix, projMatrix, finalMatrix); 321f220fa62Smrg if (!__gluInvertMatrixd(finalMatrix, finalMatrix)) return(GL_FALSE); 322f220fa62Smrg 323f220fa62Smrg in[0]=winx; 324f220fa62Smrg in[1]=winy; 325f220fa62Smrg in[2]=winz; 326f220fa62Smrg in[3]=clipw; 327f220fa62Smrg 328f220fa62Smrg /* Map x and y from window coordinates */ 329f220fa62Smrg in[0] = (in[0] - viewport[0]) / viewport[2]; 330f220fa62Smrg in[1] = (in[1] - viewport[1]) / viewport[3]; 331f220fa62Smrg in[2] = (in[2] - nearVal) / (farVal - nearVal); 332f220fa62Smrg 333f220fa62Smrg /* Map to range -1 to 1 */ 334f220fa62Smrg in[0] = in[0] * 2 - 1; 335f220fa62Smrg in[1] = in[1] * 2 - 1; 336f220fa62Smrg in[2] = in[2] * 2 - 1; 337f220fa62Smrg 338f220fa62Smrg __gluMultMatrixVecd(finalMatrix, in, out); 339f220fa62Smrg if (out[3] == 0.0) return(GL_FALSE); 340f220fa62Smrg *objx = out[0]; 341f220fa62Smrg *objy = out[1]; 342f220fa62Smrg *objz = out[2]; 343f220fa62Smrg *objw = out[3]; 344f220fa62Smrg return(GL_TRUE); 345f220fa62Smrg} 346f220fa62Smrg 347f220fa62Smrgvoid GLAPIENTRY 348f220fa62SmrggluPickMatrix(GLdouble x, GLdouble y, GLdouble deltax, GLdouble deltay, 349f220fa62Smrg GLint viewport[4]) 350f220fa62Smrg{ 351f220fa62Smrg if (deltax <= 0 || deltay <= 0) { 352f220fa62Smrg return; 353f220fa62Smrg } 354f220fa62Smrg 355f220fa62Smrg /* Translate and scale the picked region to the entire window */ 356f220fa62Smrg glTranslatef((viewport[2] - 2 * (x - viewport[0])) / deltax, 357f220fa62Smrg (viewport[3] - 2 * (y - viewport[1])) / deltay, 0); 358f220fa62Smrg glScalef(viewport[2] / deltax, viewport[3] / deltay, 1.0); 359f220fa62Smrg} 360