| /* |
| ** License Applicability. Except to the extent portions of this file are |
| ** made subject to an alternative license as permitted in the SGI Free |
| ** Software License B, Version 1.1 (the "License"), the contents of this |
| ** file are subject only to the provisions of the License. You may not use |
| ** this file except in compliance with the License. You may obtain a copy |
| ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 |
| ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: |
| ** |
| ** http://oss.sgi.com/projects/FreeB |
| ** |
| ** Note that, as provided in the License, the Software is distributed on an |
| ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS |
| ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND |
| ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A |
| ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. |
| ** |
| ** Original Code. The Original Code is: OpenGL Sample Implementation, |
| ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, |
| ** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. |
| ** Copyright in any portions created by third parties is as indicated |
| ** elsewhere herein. All Rights Reserved. |
| ** |
| ** Additional Notice Provisions: The application programming interfaces |
| ** established by SGI in conjunction with the Original Code are The |
| ** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released |
| ** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version |
| ** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X |
| ** Window System(R) (Version 1.3), released October 19, 1998. This software |
| ** was created using the OpenGL(R) version 1.2.1 Sample Implementation |
| ** published by SGI, but has not been independently verified as being |
| ** compliant with the OpenGL(R) version 1.2.1 Specification. |
| ** |
| ** $Date: 2006/05/01 16:01:17 $ $Revision: 1.6 $ |
| ** $Header: /home/krh/git/sync/mesa-cvs-repo/Mesa/src/glu/sgi/libutil/project.c,v 1.6 2006/05/01 16:01:17 brianp Exp $ |
| */ |
| |
| #include "gluos.h" |
| #include <math.h> |
| #include <GL/gl.h> |
| #include <GL/glu.h> |
| #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); |
| } |