1 /* $Id: glu.c,v 1.11 1999/09/17 01:00:38 brianp Exp $ */
4 * Mesa 3-D graphics library
6 * Copyright (C) 1995-1999 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.
26 * Revision 1.11 1999/09/17 01:00:38 brianp
29 * Revision 1.10 1999/09/17 00:06:14 brianp
30 * gluGetProcAddressEXT change for C++ / BeOS
32 * Revision 1.9 1999/09/16 22:37:56 brianp
33 * added some casts in gluGetProcAddressEXT()
35 * Revision 1.8 1999/09/16 16:53:28 brianp
36 * clean-up of GLU_EXT_get_proc_address
38 * Revision 1.7 1999/09/14 00:11:40 brianp
39 * added gluCheckExtension()
41 * Revision 1.6 1999/09/13 14:31:32 joukj
43 * strcmp needs the string.h
45 * Revision 1.5 1999/09/11 12:04:54 brianp
46 * added 1.2 function to gluGetProcAddressEXT()
48 * Revision 1.4 1999/09/11 11:36:26 brianp
49 * added GLU_EXT_get_proc_address
51 * Revision 1.3 1999/09/10 04:32:10 gareth
52 * Fixed triangle output, recovery process termination.
54 * Revision 1.2 1999/09/10 02:03:31 gareth
55 * Added GLU 1.3 tessellation (except winding rule code).
57 * Revision 1.1.1.1 1999/08/19 00:55:42 jtg
60 * Revision 1.13 1999/03/31 19:07:28 brianp
61 * added GL_EXT_abgr to extensions
63 * Revision 1.12 1999/02/06 06:12:41 brianp
64 * updated version string to 3.1
66 * Revision 1.11 1999/01/03 03:23:15 brianp
67 * now using GLAPIENTRY and GLCALLBACK keywords (Ted Jump)
69 * Revision 1.10 1998/04/22 00:35:50 brianp
70 * changed version to 3.0
72 * Revision 1.9 1997/12/09 03:03:32 brianp
73 * changed version to 2.6
75 * Revision 1.8 1997/10/04 01:30:20 brianp
76 * changed version to 2.5
78 * Revision 1.7 1997/08/13 01:25:21 brianp
79 * changed version string to 2.4
81 * Revision 1.6 1997/07/24 01:28:44 brianp
82 * changed precompiled header symbol from PCH to PC_HEADER
84 * Revision 1.5 1997/07/13 22:59:11 brianp
85 * added const to viewport parameter of gluPickMatrix()
87 * Revision 1.4 1997/05/28 02:29:38 brianp
88 * added support for precompiled headers (PCH), inserted APIENTRY keyword
90 * Revision 1.3 1997/04/12 16:19:02 brianp
91 * changed version to 2.3
93 * Revision 1.2 1997/03/11 00:58:34 brianp
94 * changed version to 2.2
96 * Revision 1.1 1996/09/27 01:19:39 brianp
115 * Miscellaneous utility functions
120 #define M_PI 3.1415926536
127 void GLAPIENTRY
gluLookAt( GLdouble eyex
, GLdouble eyey
, GLdouble eyez
,
128 GLdouble centerx
, GLdouble centery
, GLdouble centerz
,
129 GLdouble upx
, GLdouble upy
, GLdouble upz
)
132 GLdouble x
[3], y
[3], z
[3];
135 /* Make rotation matrix */
138 z
[0] = eyex
- centerx
;
139 z
[1] = eyey
- centery
;
140 z
[2] = eyez
- centerz
;
141 mag
= sqrt( z
[0]*z
[0] + z
[1]*z
[1] + z
[2]*z
[2] );
142 if (mag
) { /* mpichler, 19950515 */
153 /* X vector = Y cross Z */
154 x
[0] = y
[1]*z
[2] - y
[2]*z
[1];
155 x
[1] = -y
[0]*z
[2] + y
[2]*z
[0];
156 x
[2] = y
[0]*z
[1] - y
[1]*z
[0];
158 /* Recompute Y = Z cross X */
159 y
[0] = z
[1]*x
[2] - z
[2]*x
[1];
160 y
[1] = -z
[0]*x
[2] + z
[2]*x
[0];
161 y
[2] = z
[0]*x
[1] - z
[1]*x
[0];
163 /* mpichler, 19950515 */
164 /* cross product gives area of parallelogram, which is < 1.0 for
165 * non-perpendicular unit-length vectors; so normalize x, y here
168 mag
= sqrt( x
[0]*x
[0] + x
[1]*x
[1] + x
[2]*x
[2] );
175 mag
= sqrt( y
[0]*y
[0] + y
[1]*y
[1] + y
[2]*y
[2] );
182 #define M(row,col) m[col*4+row]
183 M(0,0) = x
[0]; M(0,1) = x
[1]; M(0,2) = x
[2]; M(0,3) = 0.0;
184 M(1,0) = y
[0]; M(1,1) = y
[1]; M(1,2) = y
[2]; M(1,3) = 0.0;
185 M(2,0) = z
[0]; M(2,1) = z
[1]; M(2,2) = z
[2]; M(2,3) = 0.0;
186 M(3,0) = 0.0; M(3,1) = 0.0; M(3,2) = 0.0; M(3,3) = 1.0;
190 /* Translate Eye to Origin */
191 glTranslated( -eyex
, -eyey
, -eyez
);
197 void GLAPIENTRY
gluOrtho2D( GLdouble left
, GLdouble right
,
198 GLdouble bottom
, GLdouble top
)
200 glOrtho( left
, right
, bottom
, top
, -1.0, 1.0 );
205 void GLAPIENTRY
gluPerspective( GLdouble fovy
, GLdouble aspect
,
206 GLdouble zNear
, GLdouble zFar
)
208 GLdouble xmin
, xmax
, ymin
, ymax
;
210 ymax
= zNear
* tan( fovy
* M_PI
/ 360.0 );
213 xmin
= ymin
* aspect
;
214 xmax
= ymax
* aspect
;
216 glFrustum( xmin
, xmax
, ymin
, ymax
, zNear
, zFar
);
221 void GLAPIENTRY
gluPickMatrix( GLdouble x
, GLdouble y
,
222 GLdouble width
, GLdouble height
,
223 const GLint viewport
[4] )
229 sx
= viewport
[2] / width
;
230 sy
= viewport
[3] / height
;
231 tx
= (viewport
[2] + 2.0 * (viewport
[0] - x
)) / width
;
232 ty
= (viewport
[3] + 2.0 * (viewport
[1] - y
)) / height
;
234 #define M(row,col) m[col*4+row]
235 M(0,0) = sx
; M(0,1) = 0.0; M(0,2) = 0.0; M(0,3) = tx
;
236 M(1,0) = 0.0; M(1,1) = sy
; M(1,2) = 0.0; M(1,3) = ty
;
237 M(2,0) = 0.0; M(2,1) = 0.0; M(2,2) = 1.0; M(2,3) = 0.0;
238 M(3,0) = 0.0; M(3,1) = 0.0; M(3,2) = 0.0; M(3,3) = 1.0;
246 const GLubyte
* GLAPIENTRY
gluErrorString( GLenum errorCode
)
248 static char *tess_error
[] = {
249 "missing gluBeginPolygon",
250 "missing gluBeginContour",
251 "missing gluEndPolygon",
252 "missing gluEndContour",
253 "misoriented or self-intersecting loops",
254 "coincident vertices",
256 "FIST recovery process fatal error"
258 static char *nurbs_error
[] = {
259 "spline order un-supported",
261 "valid knot range is empty",
262 "decreasing knot sequence knot",
263 "knot multiplicity greater than order of spline",
264 "endcurve() must follow bgncurve()",
265 "bgncurve() must precede endcurve()",
266 "missing or extra geometric data",
267 "can't draw pwlcurves",
268 "missing bgncurve()",
269 "missing bgnsurface()",
270 "endtrim() must precede endsurface()",
271 "bgnsurface() must precede endsurface()",
272 "curve of improper type passed as trim curve",
273 "bgnsurface() must precede bgntrim()",
274 "endtrim() must follow bgntrim()",
275 "bgntrim() must precede endtrim()",
276 "invalid or missing trim curve",
277 "bgntrim() must precede pwlcurve()",
278 "pwlcurve referenced twice",
279 "pwlcurve and nurbscurve mixed",
280 "improper usage of trim data type",
281 "nurbscurve referenced twice",
282 "nurbscurve and pwlcurve mixed",
283 "nurbssurface referenced twice",
285 "endsurface() must follow bgnsurface()",
286 "misoriented trim curves",
287 "intersecting trim curves",
289 "unconnected trim curves",
290 "unknown knot error",
291 "negative vertex count encountered",
292 "negative byte-stride encounteed",
293 "unknown type descriptor",
294 "null control array or knot vector",
295 "duplicate point on pwlcurve"
299 if (errorCode
==GL_NO_ERROR
) {
300 return (GLubyte
*) "no error";
302 else if (errorCode
==GL_INVALID_VALUE
) {
303 return (GLubyte
*) "invalid value";
305 else if (errorCode
==GL_INVALID_ENUM
) {
306 return (GLubyte
*) "invalid enum";
308 else if (errorCode
==GL_INVALID_OPERATION
) {
309 return (GLubyte
*) "invalid operation";
311 else if (errorCode
==GL_STACK_OVERFLOW
) {
312 return (GLubyte
*) "stack overflow";
314 else if (errorCode
==GL_STACK_UNDERFLOW
) {
315 return (GLubyte
*) "stack underflow";
317 else if (errorCode
==GL_OUT_OF_MEMORY
) {
318 return (GLubyte
*) "out of memory";
321 else if (errorCode
==GLU_NO_ERROR
) {
322 return (GLubyte
*) "no error";
324 else if (errorCode
==GLU_INVALID_ENUM
) {
325 return (GLubyte
*) "invalid enum";
327 else if (errorCode
==GLU_INVALID_VALUE
) {
328 return (GLubyte
*) "invalid value";
330 else if (errorCode
==GLU_OUT_OF_MEMORY
) {
331 return (GLubyte
*) "out of memory";
333 else if (errorCode
==GLU_INCOMPATIBLE_GL_VERSION
) {
334 return (GLubyte
*) "incompatible GL version";
336 else if (errorCode
>=GLU_TESS_ERROR1
&& errorCode
<=GLU_TESS_ERROR8
) {
337 return (GLubyte
*) tess_error
[errorCode
-GLU_TESS_ERROR1
];
339 else if (errorCode
>=GLU_NURBS_ERROR1
&& errorCode
<=GLU_NURBS_ERROR37
) {
340 return (GLubyte
*) nurbs_error
[errorCode
-GLU_NURBS_ERROR1
];
353 const GLubyte
* GLAPIENTRY
gluGetString( GLenum name
)
355 static char *extensions
= "GL_EXT_abgr GLU_EXT_get_proc_address";
356 static char *version
= "1.2 Mesa 3.1";
360 return (GLubyte
*) extensions
;
362 return (GLubyte
*) version
;
370 #ifdef GLU_EXT_get_proc_address
374 void GLAPIENTRY (*gluGetProcAddressEXT(const GLubyte
*procName
))(...)
376 void GLAPIENTRY (*gluGetProcAddressEXT(const GLubyte
*procName
))()
383 static struct proc procTable
[] = {
384 { "gluGetProcAddressEXT", (void *) gluGetProcAddressEXT
}, /* me! */
386 /* new 1.1 functions */
387 { "gluGetString", (void *) gluGetString
},
389 /* new 1.2 functions */
390 { "gluTessBeginPolygon", (void *) gluTessBeginPolygon
},
391 { "gluTessBeginContour", (void *) gluTessBeginContour
},
392 { "gluTessEndContour", (void *) gluTessEndContour
},
393 { "gluTessEndPolygon", (void *) gluTessEndPolygon
},
394 { "gluGetTessProperty", (void *) gluGetTessProperty
},
396 /* new 1.3 functions */
402 for (i
= 0; procTable
[i
].address
; i
++) {
403 if (strcmp((const char *) procName
, procTable
[i
].name
) == 0)
404 return (void (*)()) procTable
[i
].address
;
418 gluCheckExtension( const char *extName
, const GLubyte
*extString
)
423 const int len
= strlen(extName
);
424 const char *start
= (const char *) extString
;
427 const char *c
= strstr( start
, extName
);
431 if ((c
== start
|| c
[-1] == ' ') && (c
[len
] == ' ' || c
[len
] == 0))