. More Watcom C++ warnings fixed in Mesa.
[mesa.git] / src / glu / mesa / quadric.c
1 /* $Id: quadric.c,v 1.3 1999/11/11 09:55:39 joukj Exp $ */
2
3 /*
4 * Mesa 3-D graphics library
5 * Version: 3.1
6 * Copyright (C) 1995-1999 Brian Paul
7 *
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.
12 *
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.
17 *
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.
21 */
22
23
24 /*
25 * $Log: quadric.c,v $
26 * Revision 1.3 1999/11/11 09:55:39 joukj
27 *
28 * tess_macro.h included
29 *
30 * Revision 1.2 1999/11/11 03:21:43 kendallb
31 *
32 * . Updated GL/gl.h with GLCALLACKP and GLAPIENTRYP macros for compatibility
33 * with the IBM VisualAge C++ compiler. Eventually some more code will be
34 * needed in the headers to enable the reversal of (__stdcall*) to (*__stdcall)
35 * for the IBM compilers, however we currently build using our own header files
36 * that already handle this.
37 *
38 * . Changed instances of (GLCALLBACK*) to GLCALLBACKP for compatibility
39 * with the IBM VisualAge C++ compiler in src-glu.
40 *
41 * . Misc cleanups for warnings generated with Watcom C++ in src-glu. Compiles
42 * with 0 warnings now.
43 *
44 * . tess_hash.c: line 244 - Why is this function stubbed out? I removed the
45 * code with a #if 0 to avoid a compiler warning, but it looks dangerous.
46 *
47 * Revision 1.1.1.1 1999/08/19 00:55:42 jtg
48 * Imported sources
49 *
50 * Revision 1.19 1999/02/27 13:55:31 brianp
51 * fixed BeOS-related GLU typedef problems
52 *
53 * Revision 1.18 1999/01/03 03:23:15 brianp
54 * now using GLAPIENTRY and GLCALLBACK keywords (Ted Jump)
55 *
56 * Revision 1.17 1999/01/03 03:19:15 brianp
57 * rewrote some of gluCylinder
58 *
59 * Revision 1.16 1998/06/01 01:08:36 brianp
60 * small update for Next/OpenStep from Alexander Mai
61 *
62 * Revision 1.15 1998/03/15 18:28:54 brianp
63 * reimplemented gluDisk() point and line mode
64 *
65 * Revision 1.14 1998/03/15 18:14:17 brianp
66 * fixed a compiler cast warning
67 *
68 * Revision 1.13 1998/02/07 14:28:34 brianp
69 * another change to gluQuadricCallback(), this time for StormC compiler
70 *
71 * Revision 1.12 1998/02/05 00:43:19 brianp
72 * Yes, still another change to gluQuadricCallback()!
73 *
74 * Revision 1.11 1998/02/04 00:27:43 brianp
75 * yet another change to gluQuadricCallback()!
76 *
77 * Revision 1.10 1998/02/04 00:23:23 brianp
78 * fixed CALLBACK problem in gluQuadricCallback() (Stephane Rehel)
79 *
80 * Revision 1.9 1998/02/04 00:20:09 brianp
81 * added missing (int) in ErrorFunc cast
82 *
83 * Revision 1.8 1998/01/16 03:37:51 brianp
84 * fixed another assignment warning in gluQuadricCallback()
85 *
86 * Revision 1.7 1998/01/16 03:35:26 brianp
87 * fixed Windows compilation warnings (Theodore Jump)
88 *
89 * Revision 1.6 1997/10/29 02:02:20 brianp
90 * various MS Windows compiler changes (David Bucciarelli, v20 3dfx driver)
91 *
92 * Revision 1.5 1997/09/17 01:51:48 brianp
93 * changed glu*Callback() functions to match prototype in glu.h
94 *
95 * Revision 1.4 1997/07/24 01:28:44 brianp
96 * changed precompiled header symbol from PCH to PC_HEADER
97 *
98 * Revision 1.3 1997/05/28 02:29:38 brianp
99 * added support for precompiled headers (PCH), inserted APIENTRY keyword
100 *
101 * Revision 1.2 1997/03/12 02:15:38 brianp
102 * fixed problem in gluPartialDisk() reported by Kenneth H. Carpenter
103 *
104 * Revision 1.1 1996/09/27 01:19:39 brianp
105 * Initial revision
106 *
107 */
108
109
110 /* TODO:
111 * texture coordinate support
112 * flip normals according to orientation
113 * there's still some inside/outside orientation bugs in possibly all
114 * but the sphere function
115 */
116
117
118 #ifdef PC_HEADER
119 #include "all.h"
120 #else
121 #include <math.h>
122 #include <stdio.h>
123 #include <stdlib.h>
124 #include "gluP.h"
125 #include "tess_macros.h"
126 #endif
127
128
129
130 /*
131 * Sin and Cos for degree angles:
132 */
133 #define SIND( A ) sin( (A)*(M_PI/180.0) )
134 #define COSD( A) cos( (A)*(M_PI/180.0) )
135
136
137 /*
138 * Texture coordinates if texture flag is set
139 */
140 #define TXTR_COORD(x,y) if (qobj->TextureFlag) glTexCoord2f(x,y);
141
142
143
144 struct GLUquadric {
145 GLenum DrawStyle; /* GLU_FILL, LINE, SILHOUETTE, or POINT */
146 GLenum Orientation; /* GLU_INSIDE or GLU_OUTSIDE */
147 GLboolean TextureFlag; /* Generate texture coords? */
148 GLenum Normals; /* GLU_NONE, GLU_FLAT, or GLU_SMOOTH */
149 void (GLCALLBACKP ErrorFunc)(GLenum err); /* Error handler callback function */
150 };
151
152
153
154 /*
155 * Process a GLU error.
156 */
157 static void quadric_error( GLUquadricObj *qobj, GLenum error, const char *msg )
158 {
159 /* Call the error call back function if any */
160 if (qobj->ErrorFunc) {
161 (*qobj->ErrorFunc)( error );
162 }
163 /* Print a message to stdout if MESA_DEBUG variable is defined */
164 if (getenv("MESA_DEBUG")) {
165 fprintf(stderr,"GLUError: %s: %s\n", (char*) gluErrorString(error), msg);
166 }
167 }
168
169
170
171
172 GLUquadricObj * GLAPIENTRY gluNewQuadric( void )
173 {
174 GLUquadricObj *q;
175
176 q = (GLUquadricObj *) malloc( sizeof(struct GLUquadric) );
177 if (q) {
178 q->DrawStyle = GLU_FILL;
179 q->Orientation = GLU_OUTSIDE;
180 q->TextureFlag = GL_FALSE;
181 q->Normals = GLU_SMOOTH;
182 q->ErrorFunc = NULL;
183 }
184 return q;
185 }
186
187
188
189 void GLAPIENTRY gluDeleteQuadric( GLUquadricObj *state )
190 {
191 if (state) {
192 free( (void *) state );
193 }
194 }
195
196
197
198 /*
199 * Set the drawing style to be GLU_FILL, GLU_LINE, GLU_SILHOUETTE,
200 * or GLU_POINT.
201 */
202 void GLAPIENTRY gluQuadricDrawStyle( GLUquadricObj *quadObject, GLenum drawStyle )
203 {
204 if (quadObject && (drawStyle==GLU_FILL || drawStyle==GLU_LINE
205 || drawStyle==GLU_SILHOUETTE || drawStyle==GLU_POINT)) {
206 quadObject->DrawStyle = drawStyle;
207 }
208 else {
209 quadric_error( quadObject, GLU_INVALID_ENUM, "qluQuadricDrawStyle" );
210 }
211 }
212
213
214
215 /*
216 * Set the orientation to GLU_INSIDE or GLU_OUTSIDE.
217 */
218 void GLAPIENTRY gluQuadricOrientation( GLUquadricObj *quadObject,
219 GLenum orientation )
220 {
221 if (quadObject && (orientation==GLU_INSIDE || orientation==GLU_OUTSIDE)) {
222 quadObject->Orientation = orientation;
223 }
224 else {
225 quadric_error( quadObject, GLU_INVALID_ENUM, "qluQuadricOrientation" );
226 }
227 }
228
229
230
231 /*
232 * Set the error handler callback function.
233 */
234 void GLAPIENTRY gluQuadricCallback( GLUquadricObj *qobj,
235 GLenum which, void (GLCALLBACKP fn)() )
236 {
237 /*
238 * UGH, this is a mess! I thought ANSI was a standard.
239 */
240 if (qobj && which==GLU_ERROR) {
241 #ifdef __CYGWIN32__
242 qobj->ErrorFunc = (void(*)(int))fn;
243 #elif defined(OPENSTEP)
244 qobj->ErrorFunc = (void(*)(GLenum))fn;
245 #elif defined(_WIN32)
246 qobj->ErrorFunc = (void(GLCALLBACKP)(int))fn;
247 #elif defined(__STORM__)
248 qobj->ErrorFunc = (void(GLCALLBACKP)(GLenum))fn;
249 #elif defined(__BEOS__)
250 qobj->ErrorFunc = (void(*)(GLenum))fn;
251 #else
252 qobj->ErrorFunc = (void(GLCALLBACKP)())fn;
253 #endif
254 }
255 }
256
257
258 void GLAPIENTRY gluQuadricNormals( GLUquadricObj *quadObject, GLenum normals )
259 {
260 if (quadObject
261 && (normals==GLU_NONE || normals==GLU_FLAT || normals==GLU_SMOOTH)) {
262 quadObject->Normals = normals;
263 }
264 }
265
266
267 void GLAPIENTRY gluQuadricTexture( GLUquadricObj *quadObject,
268 GLboolean textureCoords )
269 {
270 if (quadObject) {
271 quadObject->TextureFlag = textureCoords;
272 }
273 }
274
275
276
277
278 /*
279 * Call glNormal3f after scaling normal to unit length.
280 */
281 static void normal3f( GLfloat x, GLfloat y, GLfloat z )
282 {
283 GLdouble mag;
284
285 mag = sqrt( x*x + y*y + z*z );
286 if (mag>0.00001F) {
287 x /= mag;
288 y /= mag;
289 z /= mag;
290 }
291 glNormal3f( x, y, z );
292 }
293
294
295
296 void GLAPIENTRY gluCylinder( GLUquadricObj *qobj,
297 GLdouble baseRadius, GLdouble topRadius,
298 GLdouble height, GLint slices, GLint stacks )
299 {
300 GLdouble da, r, dr, dz;
301 GLfloat x, y, z, nz, nsign;
302 GLint i, j;
303
304 if (qobj->Orientation==GLU_INSIDE) {
305 nsign = -1.0;
306 }
307 else {
308 nsign = 1.0;
309 }
310
311 da = 2.0*M_PI / slices;
312 dr = (topRadius-baseRadius) / stacks;
313 dz = height / stacks;
314 nz = (baseRadius-topRadius) / height; /* Z component of normal vectors */
315
316 if (qobj->DrawStyle==GLU_POINT) {
317 glBegin( GL_POINTS );
318 for (i=0;i<slices;i++) {
319 x = cos(i*da);
320 y = sin(i*da);
321 normal3f( x*nsign, y*nsign, nz*nsign );
322
323 z = 0.0;
324 r = baseRadius;
325 for (j=0;j<=stacks;j++) {
326 glVertex3f( x*r, y*r, z );
327 z += dz;
328 r += dr;
329 }
330 }
331 glEnd();
332 }
333 else if (qobj->DrawStyle==GLU_LINE || qobj->DrawStyle==GLU_SILHOUETTE) {
334 /* Draw rings */
335 if (qobj->DrawStyle==GLU_LINE) {
336 z = 0.0;
337 r = baseRadius;
338 for (j=0;j<=stacks;j++) {
339 glBegin( GL_LINE_LOOP );
340 for (i=0;i<slices;i++) {
341 x = cos(i*da);
342 y = sin(i*da);
343 normal3f( x*nsign, y*nsign, nz*nsign );
344 glVertex3f( x*r, y*r, z );
345 }
346 glEnd();
347 z += dz;
348 r += dr;
349 }
350 }
351 else {
352 /* draw one ring at each end */
353 if (baseRadius!=0.0) {
354 glBegin( GL_LINE_LOOP );
355 for (i=0;i<slices;i++) {
356 x = cos(i*da);
357 y = sin(i*da);
358 normal3f( x*nsign, y*nsign, nz*nsign );
359 glVertex3f( x*baseRadius, y*baseRadius, 0.0 );
360 }
361 glEnd();
362 glBegin( GL_LINE_LOOP );
363 for (i=0;i<slices;i++) {
364 x = cos(i*da);
365 y = sin(i*da);
366 normal3f( x*nsign, y*nsign, nz*nsign );
367 glVertex3f( x*topRadius, y*topRadius, height );
368 }
369 glEnd();
370 }
371 }
372 /* draw length lines */
373 glBegin( GL_LINES );
374 for (i=0;i<slices;i++) {
375 x = cos(i*da);
376 y = sin(i*da);
377 normal3f( x*nsign, y*nsign, nz*nsign );
378 glVertex3f( x*baseRadius, y*baseRadius, 0.0 );
379 glVertex3f( x*topRadius, y*topRadius, height );
380 }
381 glEnd();
382 }
383 else if (qobj->DrawStyle==GLU_FILL) {
384 GLfloat ds = 1.0 / slices;
385 GLfloat dt = 1.0 / stacks;
386 GLfloat t = 0.0;
387 z = 0.0;
388 r = baseRadius;
389 for (j=0;j<stacks;j++) {
390 GLfloat s = 0.0;
391 glBegin( GL_QUAD_STRIP );
392 for (i=0;i<=slices;i++) {
393 GLfloat x, y;
394 if (i == slices) {
395 x = sin(0);
396 y = cos(0);
397 }
398 else {
399 x = sin(i * da);
400 y = cos(i * da);
401 }
402 if (nsign==1.0) {
403 normal3f( x*nsign, y*nsign, nz*nsign );
404 TXTR_COORD(s, t);
405 glVertex3f( x * r, y * r, z );
406 normal3f( x*nsign, y*nsign, nz*nsign );
407 TXTR_COORD(s, t + dt);
408 glVertex3f( x * (r + dr), y * (r + dr), z + dz);
409 }
410 else {
411 normal3f( x*nsign, y*nsign, nz*nsign );
412 TXTR_COORD(s, t);
413 glVertex3f( x * r, y * r, z );
414 normal3f( x*nsign, y*nsign, nz*nsign );
415 TXTR_COORD(s, t + dt);
416 glVertex3f( x * (r + dr), y * (r + dr), z + dz);
417 }
418 s += ds;
419 } /* for slices */
420 glEnd();
421 r += dr;
422 t += dt;
423 z += dz;
424 } /* for stacks */
425 }
426 }
427
428
429
430
431
432 void GLAPIENTRY gluSphere( GLUquadricObj *qobj,
433 GLdouble radius, GLint slices, GLint stacks )
434 {
435 GLfloat rho, drho, theta, dtheta;
436 GLfloat x, y, z;
437 GLfloat s, t, ds, dt;
438 GLint i, j, imin, imax;
439 GLboolean normals;
440 GLfloat nsign;
441
442 if (qobj->Normals==GLU_NONE) {
443 normals = GL_FALSE;
444 }
445 else {
446 normals = GL_TRUE;
447 }
448 if (qobj->Orientation==GLU_INSIDE) {
449 nsign = -1.0;
450 }
451 else {
452 nsign = 1.0;
453 }
454
455 drho = M_PI / (GLfloat) stacks;
456 dtheta = 2.0 * M_PI / (GLfloat) slices;
457
458 /* texturing: s goes from 0.0/0.25/0.5/0.75/1.0 at +y/+x/-y/-x/+y axis */
459 /* t goes from -1.0/+1.0 at z = -radius/+radius (linear along longitudes) */
460 /* cannot use triangle fan on texturing (s coord. at top/bottom tip varies) */
461
462 if (qobj->DrawStyle==GLU_FILL) {
463 if (!qobj->TextureFlag) {
464 /* draw +Z end as a triangle fan */
465 glBegin( GL_TRIANGLE_FAN );
466 glNormal3f( 0.0, 0.0, 1.0 );
467 TXTR_COORD(0.5,1.0);
468 glVertex3f( 0.0, 0.0, nsign * radius );
469 for (j=0;j<=slices;j++) {
470 theta = (j==slices) ? 0.0 : j * dtheta;
471 x = -sin(theta) * sin(drho);
472 y = cos(theta) * sin(drho);
473 z = nsign * cos(drho);
474 if (normals) glNormal3f( x*nsign, y*nsign, z*nsign );
475 glVertex3f( x*radius, y*radius, z*radius );
476 }
477 glEnd();
478 }
479
480 ds = 1.0 / slices;
481 dt = 1.0 / stacks;
482 t = 1.0; /* because loop now runs from 0 */
483 if (qobj->TextureFlag) {
484 imin = 0;
485 imax = stacks;
486 }
487 else {
488 imin = 1;
489 imax = stacks-1;
490 }
491
492 /* draw intermediate stacks as quad strips */
493 for (i=imin;i<imax;i++) {
494 rho = i * drho;
495 glBegin( GL_QUAD_STRIP );
496 s = 0.0;
497 for (j=0;j<=slices;j++) {
498 theta = (j==slices) ? 0.0 : j * dtheta;
499 x = -sin(theta) * sin(rho);
500 y = cos(theta) * sin(rho);
501 z = nsign * cos(rho);
502 if (normals) glNormal3f( x*nsign, y*nsign, z*nsign );
503 TXTR_COORD(s,t);
504 glVertex3f( x*radius, y*radius, z*radius );
505 x = -sin(theta) * sin(rho+drho);
506 y = cos(theta) * sin(rho+drho);
507 z = nsign * cos(rho+drho);
508 if (normals) glNormal3f( x*nsign, y*nsign, z*nsign );
509 TXTR_COORD(s,t-dt);
510 s += ds;
511 glVertex3f( x*radius, y*radius, z*radius );
512 }
513 glEnd();
514 t -= dt;
515 }
516
517 if (!qobj->TextureFlag) {
518 /* draw -Z end as a triangle fan */
519 glBegin( GL_TRIANGLE_FAN );
520 glNormal3f( 0.0, 0.0, -1.0 );
521 TXTR_COORD(0.5,0.0);
522 glVertex3f( 0.0, 0.0, -radius*nsign );
523 rho = M_PI - drho;
524 s = 1.0;
525 t = dt;
526 for (j=slices;j>=0;j--) {
527 theta = (j==slices) ? 0.0 : j * dtheta;
528 x = -sin(theta) * sin(rho);
529 y = cos(theta) * sin(rho);
530 z = nsign * cos(rho);
531 if (normals) glNormal3f( x*nsign, y*nsign, z*nsign );
532 TXTR_COORD(s,t);
533 s -= ds;
534 glVertex3f( x*radius, y*radius, z*radius );
535 }
536 glEnd();
537 }
538 }
539 else if (qobj->DrawStyle==GLU_LINE || qobj->DrawStyle==GLU_SILHOUETTE) {
540 /* draw stack lines */
541 for (i=1;i<stacks;i++) { /* stack line at i==stacks-1 was missing here */
542 rho = i * drho;
543 glBegin( GL_LINE_LOOP );
544 for (j=0;j<slices;j++) {
545 theta = j * dtheta;
546 x = cos(theta) * sin(rho);
547 y = sin(theta) * sin(rho);
548 z = cos(rho);
549 if (normals) glNormal3f( x*nsign, y*nsign, z*nsign );
550 glVertex3f( x*radius, y*radius, z*radius );
551 }
552 glEnd();
553 }
554 /* draw slice lines */
555 for (j=0;j<slices;j++) {
556 theta = j * dtheta;
557 glBegin( GL_LINE_STRIP );
558 for (i=0;i<=stacks;i++) {
559 rho = i * drho;
560 x = cos(theta) * sin(rho);
561 y = sin(theta) * sin(rho);
562 z = cos(rho);
563 if (normals) glNormal3f( x*nsign, y*nsign, z*nsign );
564 glVertex3f( x*radius, y*radius, z*radius );
565 }
566 glEnd();
567 }
568 }
569 else if (qobj->DrawStyle==GLU_POINT) {
570 /* top and bottom-most points */
571 glBegin( GL_POINTS );
572 if (normals) glNormal3f( 0.0, 0.0, nsign );
573 glVertex3d( 0.0, 0.0, radius );
574 if (normals) glNormal3f( 0.0, 0.0, -nsign );
575 glVertex3d( 0.0, 0.0, -radius );
576
577 /* loop over stacks */
578 for (i=1;i<stacks-1;i++) {
579 rho = i * drho;
580 for (j=0;j<slices;j++) {
581 theta = j * dtheta;
582 x = cos(theta) * sin(rho);
583 y = sin(theta) * sin(rho);
584 z = cos(rho);
585 if (normals) glNormal3f( x*nsign, y*nsign, z*nsign );
586 glVertex3f( x*radius, y*radius, z*radius );
587 }
588 }
589 glEnd();
590 }
591
592 }
593
594
595
596 void GLAPIENTRY gluDisk( GLUquadricObj *qobj,
597 GLdouble innerRadius, GLdouble outerRadius,
598 GLint slices, GLint loops )
599 {
600 GLfloat da, dr;
601 #if 0
602 GLdouble a, da;
603 GLfloat r, dr;
604 GLfloat x, y;
605 GLfloat r1, r2, dtc;
606 GLint s, l;
607 #endif
608
609 /* Normal vectors */
610 if (qobj->Normals!=GLU_NONE) {
611 if (qobj->Orientation==GLU_OUTSIDE) {
612 glNormal3f( 0.0, 0.0, +1.0 );
613 }
614 else {
615 glNormal3f( 0.0, 0.0, -1.0 );
616 }
617 }
618
619 da = 2.0*M_PI / slices;
620 dr = (outerRadius-innerRadius) / (GLfloat) loops;
621
622 switch (qobj->DrawStyle) {
623 case GLU_FILL:
624 {
625 /* texture of a gluDisk is a cut out of the texture unit square
626 * x, y in [-outerRadius, +outerRadius]; s, t in [0, 1]
627 * (linear mapping)
628 */
629 GLfloat dtc = 2.0f * outerRadius;
630 GLfloat sa,ca;
631 GLfloat r1 = innerRadius;
632 GLint l;
633 for (l=0; l<loops; l++) {
634 GLfloat r2 = r1 + dr;
635 if (qobj->Orientation==GLU_OUTSIDE) {
636 GLint s;
637 glBegin( GL_QUAD_STRIP );
638 for (s=0;s<=slices;s++) {
639 GLfloat a;
640 if (s==slices) a = 0.0;
641 else a = s * da;
642 sa = sin(a); ca = cos(a);
643 TXTR_COORD(0.5+sa*r2/dtc,0.5+ca*r2/dtc);
644 glVertex2f( r2*sa, r2*ca );
645 TXTR_COORD(0.5+sa*r1/dtc,0.5+ca*r1/dtc);
646 glVertex2f( r1*sa, r1*ca );
647 }
648 glEnd();
649 }
650 else {
651 GLint s;
652 glBegin( GL_QUAD_STRIP );
653 for (s=slices;s>=0;s--) {
654 GLfloat a;
655 if (s==slices) a = 0.0;
656 else a = s * da;
657 sa = sin(a); ca = cos(a);
658 TXTR_COORD(0.5-sa*r2/dtc,0.5+ca*r2/dtc);
659 glVertex2f( r2*sa, r2*ca );
660 TXTR_COORD(0.5-sa*r1/dtc,0.5+ca*r1/dtc);
661 glVertex2f( r1*sa, r1*ca );
662 }
663 glEnd();
664 }
665 r1 = r2;
666 }
667 break;
668 }
669 case GLU_LINE:
670 {
671 GLint l, s;
672 /* draw loops */
673 for (l=0; l<=loops; l++) {
674 GLfloat r = innerRadius + l * dr;
675 glBegin( GL_LINE_LOOP );
676 for (s=0; s<slices; s++) {
677 GLfloat a = s * da;
678 glVertex2f( r*sin(a), r*cos(a) );
679 }
680 glEnd();
681 }
682 /* draw spokes */
683 for (s=0; s<slices; s++) {
684 GLfloat a = s * da;
685 GLfloat x = sin(a);
686 GLfloat y = cos(a);
687 glBegin( GL_LINE_STRIP );
688 for (l=0; l<=loops; l++) {
689 GLfloat r = innerRadius + l * dr;
690 glVertex2f( r*x, r*y );
691 }
692 glEnd();
693 }
694 break;
695 }
696 case GLU_POINT:
697 {
698 GLint s;
699 glBegin( GL_POINTS );
700 for (s=0; s<slices; s++) {
701 GLfloat a = s * da;
702 GLfloat x = sin(a);
703 GLfloat y = cos(a);
704 GLint l;
705 for (l=0; l<=loops; l++) {
706 GLfloat r = innerRadius * l * dr;
707 glVertex2f( r*x, r*y );
708 }
709 }
710 glEnd();
711 break;
712 }
713 case GLU_SILHOUETTE:
714 {
715 if (innerRadius!=0.0) {
716 GLfloat a;
717 glBegin( GL_LINE_LOOP );
718 for (a=0.0; a<2.0*M_PI; a+=da) {
719 GLfloat x = innerRadius * sin(a);
720 GLfloat y = innerRadius * cos(a);
721 glVertex2f( x, y );
722 }
723 glEnd();
724 }
725 {
726 GLfloat a;
727 glBegin( GL_LINE_LOOP );
728 for (a=0; a<2.0*M_PI; a+=da) {
729 GLfloat x = outerRadius * sin(a);
730 GLfloat y = outerRadius * cos(a);
731 glVertex2f( x, y );
732 }
733 glEnd();
734 }
735 break;
736 }
737 default:
738 abort();
739 }
740 }
741
742
743
744 void GLAPIENTRY gluPartialDisk( GLUquadricObj *qobj, GLdouble innerRadius,
745 GLdouble outerRadius, GLint slices, GLint loops,
746 GLdouble startAngle, GLdouble sweepAngle )
747 {
748 if (qobj->Normals!=GLU_NONE) {
749 if (qobj->Orientation==GLU_OUTSIDE) {
750 glNormal3f( 0.0, 0.0, +1.0 );
751 }
752 else {
753 glNormal3f( 0.0, 0.0, -1.0 );
754 }
755 }
756
757 if (qobj->DrawStyle==GLU_POINT) {
758 GLint loop, slice;
759 GLdouble radius, delta_radius;
760 GLdouble angle, delta_angle;
761 delta_radius = (outerRadius - innerRadius) / (loops-1);
762 delta_angle = DEG_TO_RAD((sweepAngle) / (slices-1));
763 glBegin( GL_POINTS );
764 radius = innerRadius;
765 for (loop=0; loop<loops; loop++) {
766 angle = DEG_TO_RAD(startAngle);
767 for (slice=0; slice<slices; slice++) {
768 glVertex2d( radius * sin(angle), radius * cos(angle) );
769 angle += delta_angle;
770 }
771 radius += delta_radius;
772 }
773 glEnd();
774 }
775 else if (qobj->DrawStyle==GLU_LINE) {
776 GLint loop, slice;
777 GLdouble radius, delta_radius;
778 GLdouble angle, delta_angle;
779 delta_radius = (outerRadius - innerRadius) / loops;
780 delta_angle = DEG_TO_RAD(sweepAngle / slices);
781 /* draw rings */
782 radius = innerRadius;
783 for (loop=0; loop<loops; loop++) {
784 angle = DEG_TO_RAD(startAngle);
785 glBegin( GL_LINE_STRIP );
786 for (slice=0; slice<slices; slice++) {
787 glVertex2d( radius * sin(angle), radius * cos(angle) );
788 angle += delta_angle;
789 }
790 glEnd();
791 radius += delta_radius;
792 }
793 /* draw spokes */
794 angle = DEG_TO_RAD(startAngle);
795 for (slice=0; slice<slices; slice++) {
796 radius = innerRadius;
797 glBegin( GL_LINE_STRIP );
798 for (loop=0; loop<loops; loop++) {
799 glVertex2d( radius * sin(angle), radius * cos(angle) );
800 radius += delta_radius;
801 }
802 glEnd();
803 angle += delta_angle;
804 }
805 }
806 else if (qobj->DrawStyle==GLU_SILHOUETTE) {
807 GLint slice;
808 GLdouble angle, delta_angle;
809 delta_angle = DEG_TO_RAD(sweepAngle / slices);
810 /* draw outer ring */
811 glBegin( GL_LINE_STRIP );
812 angle = DEG_TO_RAD(startAngle);
813 for (slice=0; slice<=slices; slice++) {
814 glVertex2d( outerRadius * sin(angle), outerRadius * cos(angle) );
815 angle += delta_angle;
816 }
817 glEnd();
818 /* draw inner ring */
819 if (innerRadius>0.0) {
820 glBegin( GL_LINE_STRIP );
821 angle = DEG_TO_RAD(startAngle);
822 for (slice=0; slice<slices; slice++) {
823 glVertex2d( innerRadius * sin(angle), innerRadius * cos(angle) );
824 angle += delta_angle;
825 }
826 glEnd();
827 }
828 /* draw spokes */
829 if (sweepAngle<360.0) {
830 GLdouble stopAngle = startAngle + sweepAngle;
831 glBegin( GL_LINES );
832 glVertex2d( innerRadius*SIND(startAngle), innerRadius*COSD(startAngle) );
833 glVertex2d( outerRadius*SIND(startAngle), outerRadius*COSD(startAngle) );
834 glVertex2d( innerRadius*SIND(stopAngle), innerRadius*COSD(stopAngle) );
835 glVertex2d( outerRadius*SIND(stopAngle), outerRadius*COSD(stopAngle) );
836 glEnd();
837 }
838 }
839 else if (qobj->DrawStyle==GLU_FILL) {
840 GLint loop, slice;
841 GLdouble radius, delta_radius;
842 GLdouble angle, delta_angle;
843 delta_radius = (outerRadius - innerRadius) / loops;
844 delta_angle = DEG_TO_RAD(sweepAngle / slices);
845 radius = innerRadius;
846 for (loop=0; loop<loops; loop++) {
847 glBegin( GL_QUAD_STRIP );
848 angle = DEG_TO_RAD(startAngle);
849 for (slice=0; slice<slices; slice++) {
850 if (qobj->Orientation==GLU_OUTSIDE) {
851 glVertex2d( (radius+delta_radius)*sin(angle),
852 (radius+delta_radius)*cos(angle) );
853 glVertex2d( radius * sin(angle), radius * cos(angle) );
854 }
855 else {
856 glVertex2d( radius * sin(angle), radius * cos(angle) );
857 glVertex2d( (radius+delta_radius)*sin(angle),
858 (radius+delta_radius)*cos(angle) );
859 }
860 angle += delta_angle;
861 }
862 glEnd();
863 radius += delta_radius;
864 }
865 }
866 }
867
868
869