| /* |
| * 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); |
| } |