1 /* $Id: glu.c,v 1.2 2003/08/22 20:11:43 brianp Exp $ */
4 * Mesa 3-D graphics library
6 * Copyright (C) 1995-2001 Brian Paul
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Library General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Library General Public License for more details.
18 * You should have received a copy of the GNU Library General Public
19 * License along with this library; if not, write to the Free
20 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
37 * Miscellaneous utility functions
42 #define M_PI 3.1415926536
46 #ifndef GLU_INCOMPATIBLE_GL_VERSION
47 #define GLU_INCOMPATIBLE_GL_VERSION 100903
52 gluLookAt(GLdouble eyex
, GLdouble eyey
, GLdouble eyez
,
53 GLdouble centerx
, GLdouble centery
, GLdouble centerz
,
54 GLdouble upx
, GLdouble upy
, GLdouble upz
)
57 GLfloat x
[3], y
[3], z
[3];
60 /* Make rotation matrix */
63 z
[0] = eyex
- centerx
;
64 z
[1] = eyey
- centery
;
65 z
[2] = eyez
- centerz
;
66 mag
= sqrt(z
[0] * z
[0] + z
[1] * z
[1] + z
[2] * z
[2]);
67 if (mag
) { /* mpichler, 19950515 */
78 /* X vector = Y cross Z */
79 x
[0] = y
[1] * z
[2] - y
[2] * z
[1];
80 x
[1] = -y
[0] * z
[2] + y
[2] * z
[0];
81 x
[2] = y
[0] * z
[1] - y
[1] * z
[0];
83 /* Recompute Y = Z cross X */
84 y
[0] = z
[1] * x
[2] - z
[2] * x
[1];
85 y
[1] = -z
[0] * x
[2] + z
[2] * x
[0];
86 y
[2] = z
[0] * x
[1] - z
[1] * x
[0];
88 /* mpichler, 19950515 */
89 /* cross product gives area of parallelogram, which is < 1.0 for
90 * non-perpendicular unit-length vectors; so normalize x, y here
93 mag
= sqrt(x
[0] * x
[0] + x
[1] * x
[1] + x
[2] * x
[2]);
100 mag
= sqrt(y
[0] * y
[0] + y
[1] * y
[1] + y
[2] * y
[2]);
107 #define M(row,col) m[col*4+row]
127 /* Translate Eye to Origin */
128 glTranslatef(-eyex
, -eyey
, -eyez
);
135 gluOrtho2D(GLdouble left
, GLdouble right
, GLdouble bottom
, GLdouble top
)
137 glOrtho(left
, right
, bottom
, top
, -1.0, 1.0);
143 frustum(GLfloat left
, GLfloat right
,
144 GLfloat bottom
, GLfloat top
,
145 GLfloat nearval
, GLfloat farval
)
147 GLfloat x
, y
, a
, b
, c
, d
;
150 x
= (2.0 * nearval
) / (right
- left
);
151 y
= (2.0 * nearval
) / (top
- bottom
);
152 a
= (right
+ left
) / (right
- left
);
153 b
= (top
+ bottom
) / (top
- bottom
);
154 c
= -(farval
+ nearval
) / ( farval
- nearval
);
155 d
= -(2.0 * farval
* nearval
) / (farval
- nearval
);
157 #define M(row,col) m[col*4+row]
158 M(0,0) = x
; M(0,1) = 0.0F
; M(0,2) = a
; M(0,3) = 0.0F
;
159 M(1,0) = 0.0F
; M(1,1) = y
; M(1,2) = b
; M(1,3) = 0.0F
;
160 M(2,0) = 0.0F
; M(2,1) = 0.0F
; M(2,2) = c
; M(2,3) = d
;
161 M(3,0) = 0.0F
; M(3,1) = 0.0F
; M(3,2) = -1.0F
; M(3,3) = 0.0F
;
169 gluPerspective(GLdouble fovy
, GLdouble aspect
, GLdouble zNear
, GLdouble zFar
)
171 GLfloat xmin
, xmax
, ymin
, ymax
;
173 ymax
= zNear
* tan(fovy
* M_PI
/ 360.0);
175 xmin
= ymin
* aspect
;
176 xmax
= ymax
* aspect
;
178 /* don't call glFrustum() because of error semantics (covglu) */
179 frustum(xmin
, xmax
, ymin
, ymax
, zNear
, zFar
);
185 gluPickMatrix(GLdouble x
, GLdouble y
,
186 GLdouble width
, GLdouble height
, GLint viewport
[4])
192 sx
= viewport
[2] / width
;
193 sy
= viewport
[3] / height
;
194 tx
= (viewport
[2] + 2.0 * (viewport
[0] - x
)) / width
;
195 ty
= (viewport
[3] + 2.0 * (viewport
[1] - y
)) / height
;
197 #define M(row,col) m[col*4+row]
221 const GLubyte
*GLAPIENTRY
222 gluErrorString(GLenum errorCode
)
224 static char *tess_error
[] = {
225 "missing gluBeginPolygon",
226 "missing gluBeginContour",
227 "missing gluEndPolygon",
228 "missing gluEndContour",
229 "misoriented or self-intersecting loops",
230 "coincident vertices",
232 "FIST recovery process fatal error"
234 static char *nurbs_error
[] = {
235 "spline order un-supported",
237 "valid knot range is empty",
238 "decreasing knot sequence knot",
239 "knot multiplicity greater than order of spline",
240 "endcurve() must follow bgncurve()",
241 "bgncurve() must precede endcurve()",
242 "missing or extra geometric data",
243 "can't draw pwlcurves",
244 "missing bgncurve()",
245 "missing bgnsurface()",
246 "endtrim() must precede endsurface()",
247 "bgnsurface() must precede endsurface()",
248 "curve of improper type passed as trim curve",
249 "bgnsurface() must precede bgntrim()",
250 "endtrim() must follow bgntrim()",
251 "bgntrim() must precede endtrim()",
252 "invalid or missing trim curve",
253 "bgntrim() must precede pwlcurve()",
254 "pwlcurve referenced twice",
255 "pwlcurve and nurbscurve mixed",
256 "improper usage of trim data type",
257 "nurbscurve referenced twice",
258 "nurbscurve and pwlcurve mixed",
259 "nurbssurface referenced twice",
261 "endsurface() must follow bgnsurface()",
262 "misoriented trim curves",
263 "intersecting trim curves",
265 "unconnected trim curves",
266 "unknown knot error",
267 "negative vertex count encountered",
268 "negative byte-stride encountered",
269 "unknown type descriptor",
270 "null control array or knot vector",
271 "duplicate point on pwlcurve"
275 if (errorCode
== GL_NO_ERROR
) {
276 return (GLubyte
*) "no error";
278 else if (errorCode
== GL_INVALID_VALUE
) {
279 return (GLubyte
*) "invalid value";
281 else if (errorCode
== GL_INVALID_ENUM
) {
282 return (GLubyte
*) "invalid enum";
284 else if (errorCode
== GL_INVALID_OPERATION
) {
285 return (GLubyte
*) "invalid operation";
287 else if (errorCode
== GL_STACK_OVERFLOW
) {
288 return (GLubyte
*) "stack overflow";
290 else if (errorCode
== GL_STACK_UNDERFLOW
) {
291 return (GLubyte
*) "stack underflow";
293 else if (errorCode
== GL_OUT_OF_MEMORY
) {
294 return (GLubyte
*) "out of memory";
297 else if (errorCode
== GLU_NO_ERROR
) {
298 return (GLubyte
*) "no error";
300 else if (errorCode
== GLU_INVALID_ENUM
) {
301 return (GLubyte
*) "invalid enum";
303 else if (errorCode
== GLU_INVALID_VALUE
) {
304 return (GLubyte
*) "invalid value";
306 else if (errorCode
== GLU_OUT_OF_MEMORY
) {
307 return (GLubyte
*) "out of memory";
309 else if (errorCode
== GLU_INCOMPATIBLE_GL_VERSION
) {
310 return (GLubyte
*) "incompatible GL version";
312 else if (errorCode
>= GLU_TESS_ERROR1
&& errorCode
<= GLU_TESS_ERROR8
) {
313 return (GLubyte
*) tess_error
[errorCode
- GLU_TESS_ERROR1
];
315 else if (errorCode
>= GLU_NURBS_ERROR1
&& errorCode
<= GLU_NURBS_ERROR37
) {
316 return (GLubyte
*) nurbs_error
[errorCode
- GLU_NURBS_ERROR1
];
329 const GLubyte
*GLAPIENTRY
330 gluGetString(GLenum name
)
332 static char *extensions
= "GL_EXT_abgr";
333 static char *version
= "1.1 Mesa 3.5";
337 return (GLubyte
*) extensions
;
339 return (GLubyte
*) version
;
347 #if 0 /* gluGetProcAddressEXT not finalized yet! */
351 void GLAPIENTRY(*gluGetProcAddressEXT(const GLubyte
* procName
)) (...)
353 void (GLAPIENTRY
* gluGetProcAddressEXT(const GLubyte
* procName
)) ()
361 static struct proc procTable
[] = {
362 {"gluGetProcAddressEXT", (void *) gluGetProcAddressEXT
}, /* me! */
364 /* new 1.1 functions */
365 {"gluGetString", (void *) gluGetString
},
367 /* new 1.2 functions */
368 {"gluTessBeginPolygon", (void *) gluTessBeginPolygon
},
369 {"gluTessBeginContour", (void *) gluTessBeginContour
},
370 {"gluTessEndContour", (void *) gluTessEndContour
},
371 {"gluTessEndPolygon", (void *) gluTessEndPolygon
},
372 {"gluGetTessProperty", (void *) gluGetTessProperty
},
374 /* new 1.3 functions */
380 for (i
= 0; procTable
[i
].address
; i
++) {
381 if (strcmp((const char *) procName
, procTable
[i
].name
) == 0)
382 return (void (GLAPIENTRY
*) ()) procTable
[i
].address
;
395 #ifdef GLU_VERSION_1_3
397 gluCheckExtension(const GLubyte
*extName
, const GLubyte
* extString
)
402 const int len
= strlen((const char *) extName
);
403 const char *start
= (const char *) extString
;
406 const char *c
= strstr(start
, (const char *) extName
);
410 if ((c
== start
|| c
[-1] == ' ') && (c
[len
] == ' ' || c
[len
] == 0))