Subversion Repositories shark

Rev

Details | Last modification | View Log | RSS feed

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