/* * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008) * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice including the dates of first publication and * either this permission notice or a reference to * http://oss.sgi.com/projects/FreeB/ * shall be included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. * * Except as contained in this notice, the name of Silicon Graphics, Inc. * shall not be used in advertising or otherwise to promote the sale, use or * other dealings in this Software without prior written authorization from * Silicon Graphics, Inc. */ #include "gluos.h" #include #include #include #include "gluint.h" /* ** Make m an identity matrix */ static void __gluMakeIdentityd(GLdouble m[16]) { m[0+4*0] = 1; m[0+4*1] = 0; m[0+4*2] = 0; m[0+4*3] = 0; m[1+4*0] = 0; m[1+4*1] = 1; m[1+4*2] = 0; m[1+4*3] = 0; m[2+4*0] = 0; m[2+4*1] = 0; m[2+4*2] = 1; m[2+4*3] = 0; m[3+4*0] = 0; m[3+4*1] = 0; m[3+4*2] = 0; m[3+4*3] = 1; } static void __gluMakeIdentityf(GLfloat m[16]) { m[0+4*0] = 1; m[0+4*1] = 0; m[0+4*2] = 0; m[0+4*3] = 0; m[1+4*0] = 0; m[1+4*1] = 1; m[1+4*2] = 0; m[1+4*3] = 0; m[2+4*0] = 0; m[2+4*1] = 0; m[2+4*2] = 1; m[2+4*3] = 0; m[3+4*0] = 0; m[3+4*1] = 0; m[3+4*2] = 0; m[3+4*3] = 1; } void GLAPIENTRY gluOrtho2D(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top) { glOrtho(left, right, bottom, top, -1, 1); } #define __glPi 3.14159265358979323846 void GLAPIENTRY gluPerspective(GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zFar) { GLdouble m[4][4]; double sine, cotangent, deltaZ; double radians = fovy / 2 * __glPi / 180; deltaZ = zFar - zNear; sine = sin(radians); if ((deltaZ == 0) || (sine == 0) || (aspect == 0)) { return; } cotangent = COS(radians) / sine; __gluMakeIdentityd(&m[0][0]); m[0][0] = cotangent / aspect; m[1][1] = cotangent; m[2][2] = -(zFar + zNear) / deltaZ; m[2][3] = -1; m[3][2] = -2 * zNear * zFar / deltaZ; m[3][3] = 0; glMultMatrixd(&m[0][0]); } static void normalize(float v[3]) { float r; r = sqrt( v[0]*v[0] + v[1]*v[1] + v[2]*v[2] ); if (r == 0.0) return; v[0] /= r; v[1] /= r; v[2] /= r; } static void cross(float v1[3], float v2[3], float result[3]) { result[0] = v1[1]*v2[2] - v1[2]*v2[1]; result[1] = v1[2]*v2[0] - v1[0]*v2[2]; result[2] = v1[0]*v2[1] - v1[1]*v2[0]; } void GLAPIENTRY gluLookAt(GLdouble eyex, GLdouble eyey, GLdouble eyez, GLdouble centerx, GLdouble centery, GLdouble centerz, GLdouble upx, GLdouble upy, GLdouble upz) { float forward[3], side[3], up[3]; GLfloat m[4][4]; forward[0] = centerx - eyex; forward[1] = centery - eyey; forward[2] = centerz - eyez; up[0] = upx; up[1] = upy; up[2] = upz; normalize(forward); /* Side = forward x up */ cross(forward, up, side); normalize(side); /* Recompute up as: up = side x forward */ cross(side, forward, up); __gluMakeIdentityf(&m[0][0]); m[0][0] = side[0]; m[1][0] = side[1]; m[2][0] = side[2]; m[0][1] = up[0]; m[1][1] = up[1]; m[2][1] = up[2]; m[0][2] = -forward[0]; m[1][2] = -forward[1]; m[2][2] = -forward[2]; glMultMatrixf(&m[0][0]); glTranslated(-eyex, -eyey, -eyez); } static void __gluMultMatrixVecd(const GLdouble matrix[16], const GLdouble in[4], GLdouble out[4]) { int i; for (i=0; i<4; i++) { out[i] = in[0] * matrix[0*4+i] + in[1] * matrix[1*4+i] + in[2] * matrix[2*4+i] + in[3] * matrix[3*4+i]; } } /* ** Invert 4x4 matrix. ** Contributed by David Moore (See Mesa bug #6748) */ static int __gluInvertMatrixd(const GLdouble m[16], GLdouble invOut[16]) { double inv[16], det; int i; inv[0] = m[5]*m[10]*m[15] - m[5]*m[11]*m[14] - m[9]*m[6]*m[15] + m[9]*m[7]*m[14] + m[13]*m[6]*m[11] - m[13]*m[7]*m[10]; inv[4] = -m[4]*m[10]*m[15] + m[4]*m[11]*m[14] + m[8]*m[6]*m[15] - m[8]*m[7]*m[14] - m[12]*m[6]*m[11] + m[12]*m[7]*m[10]; inv[8] = m[4]*m[9]*m[15] - m[4]*m[11]*m[13] - m[8]*m[5]*m[15] + m[8]*m[7]*m[13] + m[12]*m[5]*m[11] - m[12]*m[7]*m[9]; inv[12] = -m[4]*m[9]*m[14] + m[4]*m[10]*m[13] + m[8]*m[5]*m[14] - m[8]*m[6]*m[13] - m[12]*m[5]*m[10] + m[12]*m[6]*m[9]; inv[1] = -m[1]*m[10]*m[15] + m[1]*m[11]*m[14] + m[9]*m[2]*m[15] - m[9]*m[3]*m[14] - m[13]*m[2]*m[11] + m[13]*m[3]*m[10]; inv[5] = m[0]*m[10]*m[15] - m[0]*m[11]*m[14] - m[8]*m[2]*m[15] + m[8]*m[3]*m[14] + m[12]*m[2]*m[11] - m[12]*m[3]*m[10]; inv[9] = -m[0]*m[9]*m[15] + m[0]*m[11]*m[13] + m[8]*m[1]*m[15] - m[8]*m[3]*m[13] - m[12]*m[1]*m[11] + m[12]*m[3]*m[9]; inv[13] = m[0]*m[9]*m[14] - m[0]*m[10]*m[13] - m[8]*m[1]*m[14] + m[8]*m[2]*m[13] + m[12]*m[1]*m[10] - m[12]*m[2]*m[9]; inv[2] = m[1]*m[6]*m[15] - m[1]*m[7]*m[14] - m[5]*m[2]*m[15] + m[5]*m[3]*m[14] + m[13]*m[2]*m[7] - m[13]*m[3]*m[6]; inv[6] = -m[0]*m[6]*m[15] + m[0]*m[7]*m[14] + m[4]*m[2]*m[15] - m[4]*m[3]*m[14] - m[12]*m[2]*m[7] + m[12]*m[3]*m[6]; inv[10] = m[0]*m[5]*m[15] - m[0]*m[7]*m[13] - m[4]*m[1]*m[15] + m[4]*m[3]*m[13] + m[12]*m[1]*m[7] - m[12]*m[3]*m[5]; inv[14] = -m[0]*m[5]*m[14] + m[0]*m[6]*m[13] + m[4]*m[1]*m[14] - m[4]*m[2]*m[13] - m[12]*m[1]*m[6] + m[12]*m[2]*m[5]; inv[3] = -m[1]*m[6]*m[11] + m[1]*m[7]*m[10] + m[5]*m[2]*m[11] - m[5]*m[3]*m[10] - m[9]*m[2]*m[7] + m[9]*m[3]*m[6]; inv[7] = m[0]*m[6]*m[11] - m[0]*m[7]*m[10] - m[4]*m[2]*m[11] + m[4]*m[3]*m[10] + m[8]*m[2]*m[7] - m[8]*m[3]*m[6]; inv[11] = -m[0]*m[5]*m[11] + m[0]*m[7]*m[9] + m[4]*m[1]*m[11] - m[4]*m[3]*m[9] - m[8]*m[1]*m[7] + m[8]*m[3]*m[5]; inv[15] = m[0]*m[5]*m[10] - m[0]*m[6]*m[9] - m[4]*m[1]*m[10] + m[4]*m[2]*m[9] + m[8]*m[1]*m[6] - m[8]*m[2]*m[5]; det = m[0]*inv[0] + m[1]*inv[4] + m[2]*inv[8] + m[3]*inv[12]; if (det == 0) return GL_FALSE; det = 1.0 / det; for (i = 0; i < 16; i++) invOut[i] = inv[i] * det; return GL_TRUE; } static void __gluMultMatricesd(const GLdouble a[16], const GLdouble b[16], GLdouble r[16]) { int i, j; for (i = 0; i < 4; i++) { for (j = 0; j < 4; j++) { r[i*4+j] = a[i*4+0]*b[0*4+j] + a[i*4+1]*b[1*4+j] + a[i*4+2]*b[2*4+j] + a[i*4+3]*b[3*4+j]; } } } GLint GLAPIENTRY gluProject(GLdouble objx, GLdouble objy, GLdouble objz, const GLdouble modelMatrix[16], const GLdouble projMatrix[16], const GLint viewport[4], GLdouble *winx, GLdouble *winy, GLdouble *winz) { double in[4]; double out[4]; in[0]=objx; in[1]=objy; in[2]=objz; in[3]=1.0; __gluMultMatrixVecd(modelMatrix, in, out); __gluMultMatrixVecd(projMatrix, out, in); if (in[3] == 0.0) return(GL_FALSE); in[0] /= in[3]; in[1] /= in[3]; in[2] /= in[3]; /* Map x, y and z to range 0-1 */ in[0] = in[0] * 0.5 + 0.5; in[1] = in[1] * 0.5 + 0.5; in[2] = in[2] * 0.5 + 0.5; /* Map x,y to viewport */ in[0] = in[0] * viewport[2] + viewport[0]; in[1] = in[1] * viewport[3] + viewport[1]; *winx=in[0]; *winy=in[1]; *winz=in[2]; return(GL_TRUE); } GLint GLAPIENTRY gluUnProject(GLdouble winx, GLdouble winy, GLdouble winz, const GLdouble modelMatrix[16], const GLdouble projMatrix[16], const GLint viewport[4], GLdouble *objx, GLdouble *objy, GLdouble *objz) { double finalMatrix[16]; double in[4]; double out[4]; __gluMultMatricesd(modelMatrix, projMatrix, finalMatrix); if (!__gluInvertMatrixd(finalMatrix, finalMatrix)) return(GL_FALSE); in[0]=winx; in[1]=winy; in[2]=winz; in[3]=1.0; /* Map x and y from window coordinates */ in[0] = (in[0] - viewport[0]) / viewport[2]; in[1] = (in[1] - viewport[1]) / viewport[3]; /* Map to range -1 to 1 */ in[0] = in[0] * 2 - 1; in[1] = in[1] * 2 - 1; in[2] = in[2] * 2 - 1; __gluMultMatrixVecd(finalMatrix, in, out); if (out[3] == 0.0) return(GL_FALSE); out[0] /= out[3]; out[1] /= out[3]; out[2] /= out[3]; *objx = out[0]; *objy = out[1]; *objz = out[2]; return(GL_TRUE); } GLint GLAPIENTRY gluUnProject4(GLdouble winx, GLdouble winy, GLdouble winz, GLdouble clipw, const GLdouble modelMatrix[16], const GLdouble projMatrix[16], const GLint viewport[4], GLclampd nearVal, GLclampd farVal, GLdouble *objx, GLdouble *objy, GLdouble *objz, GLdouble *objw) { double finalMatrix[16]; double in[4]; double out[4]; __gluMultMatricesd(modelMatrix, projMatrix, finalMatrix); if (!__gluInvertMatrixd(finalMatrix, finalMatrix)) return(GL_FALSE); in[0]=winx; in[1]=winy; in[2]=winz; in[3]=clipw; /* Map x and y from window coordinates */ in[0] = (in[0] - viewport[0]) / viewport[2]; in[1] = (in[1] - viewport[1]) / viewport[3]; in[2] = (in[2] - nearVal) / (farVal - nearVal); /* Map to range -1 to 1 */ in[0] = in[0] * 2 - 1; in[1] = in[1] * 2 - 1; in[2] = in[2] * 2 - 1; __gluMultMatrixVecd(finalMatrix, in, out); if (out[3] == 0.0) return(GL_FALSE); *objx = out[0]; *objy = out[1]; *objz = out[2]; *objw = out[3]; return(GL_TRUE); } void GLAPIENTRY gluPickMatrix(GLdouble x, GLdouble y, GLdouble deltax, GLdouble deltay, GLint viewport[4]) { if (deltax <= 0 || deltay <= 0) { return; } /* Translate and scale the picked region to the entire window */ glTranslatef((viewport[2] - 2 * (x - viewport[0])) / deltax, (viewport[3] - 2 * (y - viewport[1])) / deltay, 0); glScalef(viewport[2] / deltax, viewport[3] / deltay, 1.0); }