1/* 2 * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008) 3 * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved. 4 * 5 * Permission is hereby granted, free of charge, to any person obtaining a 6 * copy of this software and associated documentation files (the "Software"), 7 * to deal in the Software without restriction, including without limitation 8 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 * and/or sell copies of the Software, and to permit persons to whom the 10 * Software is furnished to do so, subject to the following conditions: 11 * 12 * The above copyright notice including the dates of first publication and 13 * either this permission notice or a reference to 14 * http://oss.sgi.com/projects/FreeB/ 15 * shall be included in all copies or substantial portions of the Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 21 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF 22 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 * SOFTWARE. 24 * 25 * Except as contained in this notice, the name of Silicon Graphics, Inc. 26 * shall not be used in advertising or otherwise to promote the sale, use or 27 * other dealings in this Software without prior written authorization from 28 * Silicon Graphics, Inc. 29 */ 30 31#include "gluos.h" 32#include <math.h> 33#include <GL/gl.h> 34#include <GL/glu.h> 35#include "gluint.h" 36 37/* 38** Make m an identity matrix 39*/ 40static void __gluMakeIdentityd(GLdouble m[16]) 41{ 42 m[0+4*0] = 1; m[0+4*1] = 0; m[0+4*2] = 0; m[0+4*3] = 0; 43 m[1+4*0] = 0; m[1+4*1] = 1; m[1+4*2] = 0; m[1+4*3] = 0; 44 m[2+4*0] = 0; m[2+4*1] = 0; m[2+4*2] = 1; m[2+4*3] = 0; 45 m[3+4*0] = 0; m[3+4*1] = 0; m[3+4*2] = 0; m[3+4*3] = 1; 46} 47 48static void __gluMakeIdentityf(GLfloat m[16]) 49{ 50 m[0+4*0] = 1; m[0+4*1] = 0; m[0+4*2] = 0; m[0+4*3] = 0; 51 m[1+4*0] = 0; m[1+4*1] = 1; m[1+4*2] = 0; m[1+4*3] = 0; 52 m[2+4*0] = 0; m[2+4*1] = 0; m[2+4*2] = 1; m[2+4*3] = 0; 53 m[3+4*0] = 0; m[3+4*1] = 0; m[3+4*2] = 0; m[3+4*3] = 1; 54} 55 56void GLAPIENTRY 57gluOrtho2D(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top) 58{ 59 glOrtho(left, right, bottom, top, -1, 1); 60} 61 62#define __glPi 3.14159265358979323846 63 64void GLAPIENTRY 65gluPerspective(GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zFar) 66{ 67 GLdouble m[4][4]; 68 double sine, cotangent, deltaZ; 69 double radians = fovy / 2 * __glPi / 180; 70 71 deltaZ = zFar - zNear; 72 sine = sin(radians); 73 if ((deltaZ == 0) || (sine == 0) || (aspect == 0)) { 74 return; 75 } 76 cotangent = COS(radians) / sine; 77 78 __gluMakeIdentityd(&m[0][0]); 79 m[0][0] = cotangent / aspect; 80 m[1][1] = cotangent; 81 m[2][2] = -(zFar + zNear) / deltaZ; 82 m[2][3] = -1; 83 m[3][2] = -2 * zNear * zFar / deltaZ; 84 m[3][3] = 0; 85 glMultMatrixd(&m[0][0]); 86} 87 88static void normalize(float v[3]) 89{ 90 float r; 91 92 r = sqrt( v[0]*v[0] + v[1]*v[1] + v[2]*v[2] ); 93 if (r == 0.0) return; 94 95 v[0] /= r; 96 v[1] /= r; 97 v[2] /= r; 98} 99 100static void cross(float v1[3], float v2[3], float result[3]) 101{ 102 result[0] = v1[1]*v2[2] - v1[2]*v2[1]; 103 result[1] = v1[2]*v2[0] - v1[0]*v2[2]; 104 result[2] = v1[0]*v2[1] - v1[1]*v2[0]; 105} 106 107void GLAPIENTRY 108gluLookAt(GLdouble eyex, GLdouble eyey, GLdouble eyez, GLdouble centerx, 109 GLdouble centery, GLdouble centerz, GLdouble upx, GLdouble upy, 110 GLdouble upz) 111{ 112 float forward[3], side[3], up[3]; 113 GLfloat m[4][4]; 114 115 forward[0] = centerx - eyex; 116 forward[1] = centery - eyey; 117 forward[2] = centerz - eyez; 118 119 up[0] = upx; 120 up[1] = upy; 121 up[2] = upz; 122 123 normalize(forward); 124 125 /* Side = forward x up */ 126 cross(forward, up, side); 127 normalize(side); 128 129 /* Recompute up as: up = side x forward */ 130 cross(side, forward, up); 131 132 __gluMakeIdentityf(&m[0][0]); 133 m[0][0] = side[0]; 134 m[1][0] = side[1]; 135 m[2][0] = side[2]; 136 137 m[0][1] = up[0]; 138 m[1][1] = up[1]; 139 m[2][1] = up[2]; 140 141 m[0][2] = -forward[0]; 142 m[1][2] = -forward[1]; 143 m[2][2] = -forward[2]; 144 145 glMultMatrixf(&m[0][0]); 146 glTranslated(-eyex, -eyey, -eyez); 147} 148 149static void __gluMultMatrixVecd(const GLdouble matrix[16], const GLdouble in[4], 150 GLdouble out[4]) 151{ 152 int i; 153 154 for (i=0; i<4; i++) { 155 out[i] = 156 in[0] * matrix[0*4+i] + 157 in[1] * matrix[1*4+i] + 158 in[2] * matrix[2*4+i] + 159 in[3] * matrix[3*4+i]; 160 } 161} 162 163/* 164** Invert 4x4 matrix. 165** Contributed by David Moore (See Mesa bug #6748) 166*/ 167static int __gluInvertMatrixd(const GLdouble m[16], GLdouble invOut[16]) 168{ 169 double inv[16], det; 170 int i; 171 172 inv[0] = m[5]*m[10]*m[15] - m[5]*m[11]*m[14] - m[9]*m[6]*m[15] 173 + m[9]*m[7]*m[14] + m[13]*m[6]*m[11] - m[13]*m[7]*m[10]; 174 inv[4] = -m[4]*m[10]*m[15] + m[4]*m[11]*m[14] + m[8]*m[6]*m[15] 175 - m[8]*m[7]*m[14] - m[12]*m[6]*m[11] + m[12]*m[7]*m[10]; 176 inv[8] = m[4]*m[9]*m[15] - m[4]*m[11]*m[13] - m[8]*m[5]*m[15] 177 + m[8]*m[7]*m[13] + m[12]*m[5]*m[11] - m[12]*m[7]*m[9]; 178 inv[12] = -m[4]*m[9]*m[14] + m[4]*m[10]*m[13] + m[8]*m[5]*m[14] 179 - m[8]*m[6]*m[13] - m[12]*m[5]*m[10] + m[12]*m[6]*m[9]; 180 inv[1] = -m[1]*m[10]*m[15] + m[1]*m[11]*m[14] + m[9]*m[2]*m[15] 181 - m[9]*m[3]*m[14] - m[13]*m[2]*m[11] + m[13]*m[3]*m[10]; 182 inv[5] = m[0]*m[10]*m[15] - m[0]*m[11]*m[14] - m[8]*m[2]*m[15] 183 + m[8]*m[3]*m[14] + m[12]*m[2]*m[11] - m[12]*m[3]*m[10]; 184 inv[9] = -m[0]*m[9]*m[15] + m[0]*m[11]*m[13] + m[8]*m[1]*m[15] 185 - m[8]*m[3]*m[13] - m[12]*m[1]*m[11] + m[12]*m[3]*m[9]; 186 inv[13] = m[0]*m[9]*m[14] - m[0]*m[10]*m[13] - m[8]*m[1]*m[14] 187 + m[8]*m[2]*m[13] + m[12]*m[1]*m[10] - m[12]*m[2]*m[9]; 188 inv[2] = m[1]*m[6]*m[15] - m[1]*m[7]*m[14] - m[5]*m[2]*m[15] 189 + m[5]*m[3]*m[14] + m[13]*m[2]*m[7] - m[13]*m[3]*m[6]; 190 inv[6] = -m[0]*m[6]*m[15] + m[0]*m[7]*m[14] + m[4]*m[2]*m[15] 191 - m[4]*m[3]*m[14] - m[12]*m[2]*m[7] + m[12]*m[3]*m[6]; 192 inv[10] = m[0]*m[5]*m[15] - m[0]*m[7]*m[13] - m[4]*m[1]*m[15] 193 + m[4]*m[3]*m[13] + m[12]*m[1]*m[7] - m[12]*m[3]*m[5]; 194 inv[14] = -m[0]*m[5]*m[14] + m[0]*m[6]*m[13] + m[4]*m[1]*m[14] 195 - m[4]*m[2]*m[13] - m[12]*m[1]*m[6] + m[12]*m[2]*m[5]; 196 inv[3] = -m[1]*m[6]*m[11] + m[1]*m[7]*m[10] + m[5]*m[2]*m[11] 197 - m[5]*m[3]*m[10] - m[9]*m[2]*m[7] + m[9]*m[3]*m[6]; 198 inv[7] = m[0]*m[6]*m[11] - m[0]*m[7]*m[10] - m[4]*m[2]*m[11] 199 + m[4]*m[3]*m[10] + m[8]*m[2]*m[7] - m[8]*m[3]*m[6]; 200 inv[11] = -m[0]*m[5]*m[11] + m[0]*m[7]*m[9] + m[4]*m[1]*m[11] 201 - m[4]*m[3]*m[9] - m[8]*m[1]*m[7] + m[8]*m[3]*m[5]; 202 inv[15] = m[0]*m[5]*m[10] - m[0]*m[6]*m[9] - m[4]*m[1]*m[10] 203 + m[4]*m[2]*m[9] + m[8]*m[1]*m[6] - m[8]*m[2]*m[5]; 204 205 det = m[0]*inv[0] + m[1]*inv[4] + m[2]*inv[8] + m[3]*inv[12]; 206 if (det == 0) 207 return GL_FALSE; 208 209 det = 1.0 / det; 210 211 for (i = 0; i < 16; i++) 212 invOut[i] = inv[i] * det; 213 214 return GL_TRUE; 215} 216 217static void __gluMultMatricesd(const GLdouble a[16], const GLdouble b[16], 218 GLdouble r[16]) 219{ 220 int i, j; 221 222 for (i = 0; i < 4; i++) { 223 for (j = 0; j < 4; j++) { 224 r[i*4+j] = 225 a[i*4+0]*b[0*4+j] + 226 a[i*4+1]*b[1*4+j] + 227 a[i*4+2]*b[2*4+j] + 228 a[i*4+3]*b[3*4+j]; 229 } 230 } 231} 232 233GLint GLAPIENTRY 234gluProject(GLdouble objx, GLdouble objy, GLdouble objz, 235 const GLdouble modelMatrix[16], 236 const GLdouble projMatrix[16], 237 const GLint viewport[4], 238 GLdouble *winx, GLdouble *winy, GLdouble *winz) 239{ 240 double in[4]; 241 double out[4]; 242 243 in[0]=objx; 244 in[1]=objy; 245 in[2]=objz; 246 in[3]=1.0; 247 __gluMultMatrixVecd(modelMatrix, in, out); 248 __gluMultMatrixVecd(projMatrix, out, in); 249 if (in[3] == 0.0) return(GL_FALSE); 250 in[0] /= in[3]; 251 in[1] /= in[3]; 252 in[2] /= in[3]; 253 /* Map x, y and z to range 0-1 */ 254 in[0] = in[0] * 0.5 + 0.5; 255 in[1] = in[1] * 0.5 + 0.5; 256 in[2] = in[2] * 0.5 + 0.5; 257 258 /* Map x,y to viewport */ 259 in[0] = in[0] * viewport[2] + viewport[0]; 260 in[1] = in[1] * viewport[3] + viewport[1]; 261 262 *winx=in[0]; 263 *winy=in[1]; 264 *winz=in[2]; 265 return(GL_TRUE); 266} 267 268GLint GLAPIENTRY 269gluUnProject(GLdouble winx, GLdouble winy, GLdouble winz, 270 const GLdouble modelMatrix[16], 271 const GLdouble projMatrix[16], 272 const GLint viewport[4], 273 GLdouble *objx, GLdouble *objy, GLdouble *objz) 274{ 275 double finalMatrix[16]; 276 double in[4]; 277 double out[4]; 278 279 __gluMultMatricesd(modelMatrix, projMatrix, finalMatrix); 280 if (!__gluInvertMatrixd(finalMatrix, finalMatrix)) return(GL_FALSE); 281 282 in[0]=winx; 283 in[1]=winy; 284 in[2]=winz; 285 in[3]=1.0; 286 287 /* Map x and y from window coordinates */ 288 in[0] = (in[0] - viewport[0]) / viewport[2]; 289 in[1] = (in[1] - viewport[1]) / viewport[3]; 290 291 /* Map to range -1 to 1 */ 292 in[0] = in[0] * 2 - 1; 293 in[1] = in[1] * 2 - 1; 294 in[2] = in[2] * 2 - 1; 295 296 __gluMultMatrixVecd(finalMatrix, in, out); 297 if (out[3] == 0.0) return(GL_FALSE); 298 out[0] /= out[3]; 299 out[1] /= out[3]; 300 out[2] /= out[3]; 301 *objx = out[0]; 302 *objy = out[1]; 303 *objz = out[2]; 304 return(GL_TRUE); 305} 306 307GLint GLAPIENTRY 308gluUnProject4(GLdouble winx, GLdouble winy, GLdouble winz, GLdouble clipw, 309 const GLdouble modelMatrix[16], 310 const GLdouble projMatrix[16], 311 const GLint viewport[4], 312 GLclampd nearVal, GLclampd farVal, 313 GLdouble *objx, GLdouble *objy, GLdouble *objz, 314 GLdouble *objw) 315{ 316 double finalMatrix[16]; 317 double in[4]; 318 double out[4]; 319 320 __gluMultMatricesd(modelMatrix, projMatrix, finalMatrix); 321 if (!__gluInvertMatrixd(finalMatrix, finalMatrix)) return(GL_FALSE); 322 323 in[0]=winx; 324 in[1]=winy; 325 in[2]=winz; 326 in[3]=clipw; 327 328 /* Map x and y from window coordinates */ 329 in[0] = (in[0] - viewport[0]) / viewport[2]; 330 in[1] = (in[1] - viewport[1]) / viewport[3]; 331 in[2] = (in[2] - nearVal) / (farVal - nearVal); 332 333 /* Map to range -1 to 1 */ 334 in[0] = in[0] * 2 - 1; 335 in[1] = in[1] * 2 - 1; 336 in[2] = in[2] * 2 - 1; 337 338 __gluMultMatrixVecd(finalMatrix, in, out); 339 if (out[3] == 0.0) return(GL_FALSE); 340 *objx = out[0]; 341 *objy = out[1]; 342 *objz = out[2]; 343 *objw = out[3]; 344 return(GL_TRUE); 345} 346 347void GLAPIENTRY 348gluPickMatrix(GLdouble x, GLdouble y, GLdouble deltax, GLdouble deltay, 349 GLint viewport[4]) 350{ 351 if (deltax <= 0 || deltay <= 0) { 352 return; 353 } 354 355 /* Translate and scale the picked region to the entire window */ 356 glTranslatef((viewport[2] - 2 * (x - viewport[0])) / deltax, 357 (viewport[3] - 2 * (y - viewport[1])) / deltay, 0); 358 glScalef(viewport[2] / deltax, viewport[3] / deltay, 1.0); 359} 360