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