| /* | |
| * 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 "config.h" | |
| #include "wine/port.h" | |
| #include <math.h> | |
| #include "windef.h" | |
| #include "wine/wgl.h" | |
| #include "wine/glu.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; | |
| } | |
| /*********************************************************************** | |
| * gluOrtho2D (GLU32.@) | |
| */ | |
| void WINAPI gluOrtho2D( GLdouble left, GLdouble right, GLdouble bottom, GLdouble top ) | |
| { | |
| glOrtho(left, right, bottom, top, -1, 1); | |
| } | |
| /*********************************************************************** | |
| * gluPerspective (GLU32.@) | |
| */ | |
| void WINAPI gluPerspective( GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zFar ) | |
| { | |
| GLdouble m[4][4]; | |
| double sine, cotangent, deltaZ; | |
| double radians = fovy / 2 * M_PI / 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]; | |
| } | |
| /*********************************************************************** | |
| * gluLookAt (GLU32.@) | |
| */ | |
| void WINAPI 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]; | |
| } | |
| } | |
| } | |
| /*********************************************************************** | |
| * gluProject (GLU32.@) | |
| */ | |
| GLint WINAPI 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); | |
| } | |
| /*********************************************************************** | |
| * gluUnProject (GLU32.@) | |
| */ | |
| GLint WINAPI 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); | |
| } | |
| /*********************************************************************** | |
| * gluPickMatrix (GLU32.@) | |
| */ | |
| void WINAPI 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); | |
| } |