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