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