diff options
Diffstat (limited to 'src/glu/sgi/libutil/project.c')
-rw-r--r-- | src/glu/sgi/libutil/project.c | 381 |
1 files changed, 381 insertions, 0 deletions
diff --git a/src/glu/sgi/libutil/project.c b/src/glu/sgi/libutil/project.c new file mode 100644 index 00000000000..9440f429da3 --- /dev/null +++ b/src/glu/sgi/libutil/project.c @@ -0,0 +1,381 @@ +/* +** 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: 2001/03/17 00:25:41 $ $Revision: 1.1 $ +** $Header: /home/krh/git/sync/mesa-cvs-repo/Mesa/src/glu/sgi/libutil/project.c,v 1.1 2001/03/17 00:25:41 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) +{ + int i; + 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]; + } +} + +/* +** inverse = invert(src) +*/ +static int __gluInvertMatrixd(const GLdouble src[16], GLdouble inverse[16]) +{ + int i, j, k, swap; + double t; + GLdouble temp[4][4]; + + for (i=0; i<4; i++) { + for (j=0; j<4; j++) { + temp[i][j] = src[i*4+j]; + } + } + __gluMakeIdentityd(inverse); + + for (i = 0; i < 4; i++) { + /* + ** Look for largest element in column + */ + swap = i; + for (j = i + 1; j < 4; j++) { + if (fabs(temp[j][i]) > fabs(temp[i][i])) { + swap = j; + } + } + + if (swap != i) { + /* + ** Swap rows. + */ + for (k = 0; k < 4; k++) { + t = temp[i][k]; + temp[i][k] = temp[swap][k]; + temp[swap][k] = t; + + t = inverse[i*4+k]; + inverse[i*4+k] = inverse[swap*4+k]; + inverse[swap*4+k] = t; + } + } + + if (temp[i][i] == 0) { + /* + ** No non-zero pivot. The matrix is singular, which shouldn't + ** happen. This means the user gave us a bad matrix. + */ + return GL_FALSE; + } + + t = temp[i][i]; + for (k = 0; k < 4; k++) { + temp[i][k] /= t; + inverse[i*4+k] /= t; + } + for (j = 0; j < 4; j++) { + if (j != i) { + t = temp[j][i]; + for (k = 0; k < 4; k++) { + temp[j][k] -= temp[i][k]*t; + inverse[j*4+k] -= inverse[i*4+k]*t; + } + } + } + } + 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 near, GLclampd far, + 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] - near) / (far - near); + + /* 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); +} |