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 */
__gluMakeIdentityd(GLdouble m[16])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
__gluMakeIdentityf(GLfloat m[16])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*/
gluOrtho2D(GLdouble left,GLdouble right,GLdouble bottom,GLdouble top)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*/
gluPerspective(GLdouble fovy,GLdouble aspect,GLdouble zNear,GLdouble zFar)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
normalize(float v[3])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
cross(float v1[3],float v2[3],float result[3])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*/
gluLookAt(GLdouble eyex,GLdouble eyey,GLdouble eyez,GLdouble centerx,GLdouble centery,GLdouble centerz,GLdouble upx,GLdouble upy,GLdouble upz)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
__gluMultMatrixVecd(const GLdouble matrix[16],const GLdouble in[4],GLdouble out[4])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 */
__gluInvertMatrixd(const GLdouble m[16],GLdouble invOut[16])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
__gluMultMatricesd(const GLdouble a[16],const GLdouble b[16],GLdouble r[16])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*/
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)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*/
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)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*/
gluUnProject4(GLdouble winx,GLdouble winy,GLdouble winz,GLdouble clipw,const GLdouble modelMatrix[16],const GLdouble projMatrix[16],const GLint viewport[4],GLclampd nearVal,GLclampd farVal,GLdouble * objx,GLdouble * objy,GLdouble * objz,GLdouble * objw)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*/
gluPickMatrix(GLdouble x,GLdouble y,GLdouble deltax,GLdouble deltay,GLint viewport[4])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