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 */ 40 static 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 48 static 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 56 void GLAPIENTRY 57 gluOrtho2D(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 64 void GLAPIENTRY 65 gluPerspective(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 88 static 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 100 static 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 107 void GLAPIENTRY 108 gluLookAt(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 149 static 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 */ 167 static 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 217 static 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 233 GLint GLAPIENTRY 234 gluProject(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 268 GLint GLAPIENTRY 269 gluUnProject(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 307 GLint GLAPIENTRY 308 gluUnProject4(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 347 void GLAPIENTRY 348 gluPickMatrix(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