2 ** License Applicability. Except to the extent portions of this file are
3 ** made subject to an alternative license as permitted in the SGI Free
4 ** Software License B, Version 1.1 (the "License"), the contents of this
5 ** file are subject only to the provisions of the License. You may not use
6 ** this file except in compliance with the License. You may obtain a copy
7 ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
8 ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
10 ** http://oss.sgi.com/projects/FreeB
12 ** Note that, as provided in the License, the Software is distributed on an
13 ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
14 ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
15 ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
16 ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
18 ** Original Code. The Original Code is: OpenGL Sample Implementation,
19 ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
20 ** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
21 ** Copyright in any portions created by third parties is as indicated
22 ** elsewhere herein. All Rights Reserved.
24 ** Additional Notice Provisions: The application programming interfaces
25 ** established by SGI in conjunction with the Original Code are The
26 ** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
27 ** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
28 ** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
29 ** Window System(R) (Version 1.3), released October 19, 1998. This software
30 ** was created using the OpenGL(R) version 1.2.1 Sample Implementation
31 ** published by SGI, but has not been independently verified as being
32 ** compliant with the OpenGL(R) version 1.2.1 Specification.
45 #define GLU_ERROR 100103
48 /* Make it not a power of two to avoid cache thrashing on the chip */
49 #define CACHE_SIZE 240
52 #define PI 3.14159265358979323846
56 GLboolean textureCoords
;
59 void (GLAPIENTRY
*errorCallback
)( GLint
);
62 GLUquadric
* GLAPIENTRY
67 newstate
= (GLUquadric
*) malloc(sizeof(GLUquadric
));
68 if (newstate
== NULL
) {
69 /* Can't report an error at this point... */
72 newstate
->normals
= GLU_SMOOTH
;
73 newstate
->textureCoords
= GL_FALSE
;
74 newstate
->orientation
= GLU_OUTSIDE
;
75 newstate
->drawStyle
= GLU_FILL
;
76 newstate
->errorCallback
= NULL
;
82 gluDeleteQuadric(GLUquadric
*state
)
87 static void gluQuadricError(GLUquadric
*qobj
, GLenum which
)
89 if (qobj
->errorCallback
) {
90 qobj
->errorCallback(which
);
95 gluQuadricCallback(GLUquadric
*qobj
, GLenum which
, _GLUfuncptr fn
)
99 qobj
->errorCallback
= (void (GLAPIENTRY
*)(GLint
)) fn
;
102 gluQuadricError(qobj
, GLU_INVALID_ENUM
);
108 gluQuadricNormals(GLUquadric
*qobj
, GLenum normals
)
116 gluQuadricError(qobj
, GLU_INVALID_ENUM
);
119 qobj
->normals
= normals
;
123 gluQuadricTexture(GLUquadric
*qobj
, GLboolean textureCoords
)
125 qobj
->textureCoords
= textureCoords
;
129 gluQuadricOrientation(GLUquadric
*qobj
, GLenum orientation
)
131 switch(orientation
) {
136 gluQuadricError(qobj
, GLU_INVALID_ENUM
);
139 qobj
->orientation
= orientation
;
143 gluQuadricDrawStyle(GLUquadric
*qobj
, GLenum drawStyle
)
152 gluQuadricError(qobj
, GLU_INVALID_ENUM
);
155 qobj
->drawStyle
= drawStyle
;
159 gluCylinder(GLUquadric
*qobj
, GLdouble baseRadius
, GLdouble topRadius
,
160 GLdouble height
, GLint slices
, GLint stacks
)
163 GLfloat sinCache
[CACHE_SIZE
];
164 GLfloat cosCache
[CACHE_SIZE
];
165 GLfloat sinCache2
[CACHE_SIZE
];
166 GLfloat cosCache2
[CACHE_SIZE
];
167 GLfloat sinCache3
[CACHE_SIZE
];
168 GLfloat cosCache3
[CACHE_SIZE
];
171 GLfloat sintemp
, costemp
;
175 GLfloat xyNormalRatio
;
176 GLfloat radiusLow
, radiusHigh
;
177 int needCache2
, needCache3
;
179 if (slices
>= CACHE_SIZE
) slices
= CACHE_SIZE
-1;
181 if (slices
< 2 || stacks
< 1 || baseRadius
< 0.0 || topRadius
< 0.0 ||
183 gluQuadricError(qobj
, GLU_INVALID_VALUE
);
187 /* Compute length (needed for normal calculations) */
188 deltaRadius
= baseRadius
- topRadius
;
189 length
= SQRT(deltaRadius
*deltaRadius
+ height
*height
);
191 gluQuadricError(qobj
, GLU_INVALID_VALUE
);
195 /* Cache is the vertex locations cache */
196 /* Cache2 is the various normals at the vertices themselves */
197 /* Cache3 is the various normals for the faces */
198 needCache2
= needCache3
= 0;
199 if (qobj
->normals
== GLU_SMOOTH
) {
203 if (qobj
->normals
== GLU_FLAT
) {
204 if (qobj
->drawStyle
!= GLU_POINT
) {
207 if (qobj
->drawStyle
== GLU_LINE
) {
212 zNormal
= deltaRadius
/ length
;
213 xyNormalRatio
= height
/ length
;
215 for (i
= 0; i
< slices
; i
++) {
216 angle
= 2 * PI
* i
/ slices
;
218 if (qobj
->orientation
== GLU_OUTSIDE
) {
219 sinCache2
[i
] = xyNormalRatio
* SIN(angle
);
220 cosCache2
[i
] = xyNormalRatio
* COS(angle
);
222 sinCache2
[i
] = -xyNormalRatio
* SIN(angle
);
223 cosCache2
[i
] = -xyNormalRatio
* COS(angle
);
226 sinCache
[i
] = SIN(angle
);
227 cosCache
[i
] = COS(angle
);
231 for (i
= 0; i
< slices
; i
++) {
232 angle
= 2 * PI
* (i
-0.5) / slices
;
233 if (qobj
->orientation
== GLU_OUTSIDE
) {
234 sinCache3
[i
] = xyNormalRatio
* SIN(angle
);
235 cosCache3
[i
] = xyNormalRatio
* COS(angle
);
237 sinCache3
[i
] = -xyNormalRatio
* SIN(angle
);
238 cosCache3
[i
] = -xyNormalRatio
* COS(angle
);
243 sinCache
[slices
] = sinCache
[0];
244 cosCache
[slices
] = cosCache
[0];
246 sinCache2
[slices
] = sinCache2
[0];
247 cosCache2
[slices
] = cosCache2
[0];
250 sinCache3
[slices
] = sinCache3
[0];
251 cosCache3
[slices
] = cosCache3
[0];
254 switch (qobj
->drawStyle
) {
257 ** An argument could be made for using a TRIANGLE_FAN for the end
258 ** of the cylinder of either radii is 0.0 (a cone). However, a
259 ** TRIANGLE_FAN would not work in smooth shading mode (the common
260 ** case) because the normal for the apex is different for every
261 ** triangle (and TRIANGLE_FAN doesn't let me respecify that normal).
262 ** Now, my choice is GL_TRIANGLES, or leave the GL_QUAD_STRIP and
263 ** just let the GL trivially reject one of the two triangles of the
264 ** QUAD. GL_QUAD_STRIP is probably faster, so I will leave this code
267 for (j
= 0; j
< stacks
; j
++) {
268 zLow
= j
* height
/ stacks
;
269 zHigh
= (j
+ 1) * height
/ stacks
;
270 radiusLow
= baseRadius
- deltaRadius
* ((float) j
/ stacks
);
271 radiusHigh
= baseRadius
- deltaRadius
* ((float) (j
+ 1) / stacks
);
273 glBegin(GL_QUAD_STRIP
);
274 for (i
= 0; i
<= slices
; i
++) {
275 switch(qobj
->normals
) {
277 glNormal3f(sinCache3
[i
], cosCache3
[i
], zNormal
);
280 glNormal3f(sinCache2
[i
], cosCache2
[i
], zNormal
);
286 if (qobj
->orientation
== GLU_OUTSIDE
) {
287 if (qobj
->textureCoords
) {
288 glTexCoord2f(1 - (float) i
/ slices
,
291 glVertex3f(radiusLow
* sinCache
[i
],
292 radiusLow
* cosCache
[i
], zLow
);
293 if (qobj
->textureCoords
) {
294 glTexCoord2f(1 - (float) i
/ slices
,
295 (float) (j
+1) / stacks
);
297 glVertex3f(radiusHigh
* sinCache
[i
],
298 radiusHigh
* cosCache
[i
], zHigh
);
300 if (qobj
->textureCoords
) {
301 glTexCoord2f(1 - (float) i
/ slices
,
302 (float) (j
+1) / stacks
);
304 glVertex3f(radiusHigh
* sinCache
[i
],
305 radiusHigh
* cosCache
[i
], zHigh
);
306 if (qobj
->textureCoords
) {
307 glTexCoord2f(1 - (float) i
/ slices
,
310 glVertex3f(radiusLow
* sinCache
[i
],
311 radiusLow
* cosCache
[i
], zLow
);
319 for (i
= 0; i
< slices
; i
++) {
320 switch(qobj
->normals
) {
323 glNormal3f(sinCache2
[i
], cosCache2
[i
], zNormal
);
329 sintemp
= sinCache
[i
];
330 costemp
= cosCache
[i
];
331 for (j
= 0; j
<= stacks
; j
++) {
332 zLow
= j
* height
/ stacks
;
333 radiusLow
= baseRadius
- deltaRadius
* ((float) j
/ stacks
);
335 if (qobj
->textureCoords
) {
336 glTexCoord2f(1 - (float) i
/ slices
,
339 glVertex3f(radiusLow
* sintemp
,
340 radiusLow
* costemp
, zLow
);
346 for (j
= 1; j
< stacks
; j
++) {
347 zLow
= j
* height
/ stacks
;
348 radiusLow
= baseRadius
- deltaRadius
* ((float) j
/ stacks
);
350 glBegin(GL_LINE_STRIP
);
351 for (i
= 0; i
<= slices
; i
++) {
352 switch(qobj
->normals
) {
354 glNormal3f(sinCache3
[i
], cosCache3
[i
], zNormal
);
357 glNormal3f(sinCache2
[i
], cosCache2
[i
], zNormal
);
363 if (qobj
->textureCoords
) {
364 glTexCoord2f(1 - (float) i
/ slices
,
367 glVertex3f(radiusLow
* sinCache
[i
],
368 radiusLow
* cosCache
[i
], zLow
);
372 /* Intentionally fall through here... */
374 for (j
= 0; j
<= stacks
; j
+= stacks
) {
375 zLow
= j
* height
/ stacks
;
376 radiusLow
= baseRadius
- deltaRadius
* ((float) j
/ stacks
);
378 glBegin(GL_LINE_STRIP
);
379 for (i
= 0; i
<= slices
; i
++) {
380 switch(qobj
->normals
) {
382 glNormal3f(sinCache3
[i
], cosCache3
[i
], zNormal
);
385 glNormal3f(sinCache2
[i
], cosCache2
[i
], zNormal
);
391 if (qobj
->textureCoords
) {
392 glTexCoord2f(1 - (float) i
/ slices
,
395 glVertex3f(radiusLow
* sinCache
[i
], radiusLow
* cosCache
[i
],
400 for (i
= 0; i
< slices
; i
++) {
401 switch(qobj
->normals
) {
404 glNormal3f(sinCache2
[i
], cosCache2
[i
], 0.0);
410 sintemp
= sinCache
[i
];
411 costemp
= cosCache
[i
];
412 glBegin(GL_LINE_STRIP
);
413 for (j
= 0; j
<= stacks
; j
++) {
414 zLow
= j
* height
/ stacks
;
415 radiusLow
= baseRadius
- deltaRadius
* ((float) j
/ stacks
);
417 if (qobj
->textureCoords
) {
418 glTexCoord2f(1 - (float) i
/ slices
,
421 glVertex3f(radiusLow
* sintemp
,
422 radiusLow
* costemp
, zLow
);
433 gluDisk(GLUquadric
*qobj
, GLdouble innerRadius
, GLdouble outerRadius
,
434 GLint slices
, GLint loops
)
436 gluPartialDisk(qobj
, innerRadius
, outerRadius
, slices
, loops
, 0.0, 360.0);
440 gluPartialDisk(GLUquadric
*qobj
, GLdouble innerRadius
,
441 GLdouble outerRadius
, GLint slices
, GLint loops
,
442 GLdouble startAngle
, GLdouble sweepAngle
)
445 GLfloat sinCache
[CACHE_SIZE
];
446 GLfloat cosCache
[CACHE_SIZE
];
448 GLfloat sintemp
, costemp
;
450 GLfloat radiusLow
, radiusHigh
;
451 GLfloat texLow
= 0, texHigh
= 0;
456 if (slices
>= CACHE_SIZE
) slices
= CACHE_SIZE
-1;
457 if (slices
< 2 || loops
< 1 || outerRadius
<= 0.0 || innerRadius
< 0.0 ||
458 innerRadius
> outerRadius
) {
459 gluQuadricError(qobj
, GLU_INVALID_VALUE
);
463 if (sweepAngle
< -360.0) sweepAngle
= 360.0;
464 if (sweepAngle
> 360.0) sweepAngle
= 360.0;
465 if (sweepAngle
< 0) {
466 startAngle
+= sweepAngle
;
467 sweepAngle
= -sweepAngle
;
470 if (sweepAngle
== 360.0) {
473 slices2
= slices
+ 1;
476 /* Compute length (needed for normal calculations) */
477 deltaRadius
= outerRadius
- innerRadius
;
479 /* Cache is the vertex locations cache */
481 angleOffset
= startAngle
/ 180.0 * PI
;
482 for (i
= 0; i
<= slices
; i
++) {
483 angle
= angleOffset
+ ((PI
* sweepAngle
) / 180.0) * i
/ slices
;
484 sinCache
[i
] = SIN(angle
);
485 cosCache
[i
] = COS(angle
);
488 if (sweepAngle
== 360.0) {
489 sinCache
[slices
] = sinCache
[0];
490 cosCache
[slices
] = cosCache
[0];
493 switch(qobj
->normals
) {
496 if (qobj
->orientation
== GLU_OUTSIDE
) {
497 glNormal3f(0.0, 0.0, 1.0);
499 glNormal3f(0.0, 0.0, -1.0);
507 switch (qobj
->drawStyle
) {
509 if (innerRadius
== 0.0) {
511 /* Triangle strip for inner polygons */
512 glBegin(GL_TRIANGLE_FAN
);
513 if (qobj
->textureCoords
) {
514 glTexCoord2f(0.5, 0.5);
516 glVertex3f(0.0, 0.0, 0.0);
517 radiusLow
= outerRadius
-
518 deltaRadius
* ((float) (loops
-1) / loops
);
519 if (qobj
->textureCoords
) {
520 texLow
= radiusLow
/ outerRadius
/ 2;
523 if (qobj
->orientation
== GLU_OUTSIDE
) {
524 for (i
= slices
; i
>= 0; i
--) {
525 if (qobj
->textureCoords
) {
526 glTexCoord2f(texLow
* sinCache
[i
] + 0.5,
527 texLow
* cosCache
[i
] + 0.5);
529 glVertex3f(radiusLow
* sinCache
[i
],
530 radiusLow
* cosCache
[i
], 0.0);
533 for (i
= 0; i
<= slices
; i
++) {
534 if (qobj
->textureCoords
) {
535 glTexCoord2f(texLow
* sinCache
[i
] + 0.5,
536 texLow
* cosCache
[i
] + 0.5);
538 glVertex3f(radiusLow
* sinCache
[i
],
539 radiusLow
* cosCache
[i
], 0.0);
546 for (j
= 0; j
< finish
; j
++) {
547 radiusLow
= outerRadius
- deltaRadius
* ((float) j
/ loops
);
548 radiusHigh
= outerRadius
- deltaRadius
* ((float) (j
+ 1) / loops
);
549 if (qobj
->textureCoords
) {
550 texLow
= radiusLow
/ outerRadius
/ 2;
551 texHigh
= radiusHigh
/ outerRadius
/ 2;
554 glBegin(GL_QUAD_STRIP
);
555 for (i
= 0; i
<= slices
; i
++) {
556 if (qobj
->orientation
== GLU_OUTSIDE
) {
557 if (qobj
->textureCoords
) {
558 glTexCoord2f(texLow
* sinCache
[i
] + 0.5,
559 texLow
* cosCache
[i
] + 0.5);
561 glVertex3f(radiusLow
* sinCache
[i
],
562 radiusLow
* cosCache
[i
], 0.0);
564 if (qobj
->textureCoords
) {
565 glTexCoord2f(texHigh
* sinCache
[i
] + 0.5,
566 texHigh
* cosCache
[i
] + 0.5);
568 glVertex3f(radiusHigh
* sinCache
[i
],
569 radiusHigh
* cosCache
[i
], 0.0);
571 if (qobj
->textureCoords
) {
572 glTexCoord2f(texHigh
* sinCache
[i
] + 0.5,
573 texHigh
* cosCache
[i
] + 0.5);
575 glVertex3f(radiusHigh
* sinCache
[i
],
576 radiusHigh
* cosCache
[i
], 0.0);
578 if (qobj
->textureCoords
) {
579 glTexCoord2f(texLow
* sinCache
[i
] + 0.5,
580 texLow
* cosCache
[i
] + 0.5);
582 glVertex3f(radiusLow
* sinCache
[i
],
583 radiusLow
* cosCache
[i
], 0.0);
591 for (i
= 0; i
< slices2
; i
++) {
592 sintemp
= sinCache
[i
];
593 costemp
= cosCache
[i
];
594 for (j
= 0; j
<= loops
; j
++) {
595 radiusLow
= outerRadius
- deltaRadius
* ((float) j
/ loops
);
597 if (qobj
->textureCoords
) {
598 texLow
= radiusLow
/ outerRadius
/ 2;
600 glTexCoord2f(texLow
* sinCache
[i
] + 0.5,
601 texLow
* cosCache
[i
] + 0.5);
603 glVertex3f(radiusLow
* sintemp
, radiusLow
* costemp
, 0.0);
609 if (innerRadius
== outerRadius
) {
610 glBegin(GL_LINE_STRIP
);
612 for (i
= 0; i
<= slices
; i
++) {
613 if (qobj
->textureCoords
) {
614 glTexCoord2f(sinCache
[i
] / 2 + 0.5,
615 cosCache
[i
] / 2 + 0.5);
617 glVertex3f(innerRadius
* sinCache
[i
],
618 innerRadius
* cosCache
[i
], 0.0);
623 for (j
= 0; j
<= loops
; j
++) {
624 radiusLow
= outerRadius
- deltaRadius
* ((float) j
/ loops
);
625 if (qobj
->textureCoords
) {
626 texLow
= radiusLow
/ outerRadius
/ 2;
629 glBegin(GL_LINE_STRIP
);
630 for (i
= 0; i
<= slices
; i
++) {
631 if (qobj
->textureCoords
) {
632 glTexCoord2f(texLow
* sinCache
[i
] + 0.5,
633 texLow
* cosCache
[i
] + 0.5);
635 glVertex3f(radiusLow
* sinCache
[i
],
636 radiusLow
* cosCache
[i
], 0.0);
640 for (i
=0; i
< slices2
; i
++) {
641 sintemp
= sinCache
[i
];
642 costemp
= cosCache
[i
];
643 glBegin(GL_LINE_STRIP
);
644 for (j
= 0; j
<= loops
; j
++) {
645 radiusLow
= outerRadius
- deltaRadius
* ((float) j
/ loops
);
646 if (qobj
->textureCoords
) {
647 texLow
= radiusLow
/ outerRadius
/ 2;
650 if (qobj
->textureCoords
) {
651 glTexCoord2f(texLow
* sinCache
[i
] + 0.5,
652 texLow
* cosCache
[i
] + 0.5);
654 glVertex3f(radiusLow
* sintemp
, radiusLow
* costemp
, 0.0);
660 if (sweepAngle
< 360.0) {
661 for (i
= 0; i
<= slices
; i
+= slices
) {
662 sintemp
= sinCache
[i
];
663 costemp
= cosCache
[i
];
664 glBegin(GL_LINE_STRIP
);
665 for (j
= 0; j
<= loops
; j
++) {
666 radiusLow
= outerRadius
- deltaRadius
* ((float) j
/ loops
);
668 if (qobj
->textureCoords
) {
669 texLow
= radiusLow
/ outerRadius
/ 2;
670 glTexCoord2f(texLow
* sinCache
[i
] + 0.5,
671 texLow
* cosCache
[i
] + 0.5);
673 glVertex3f(radiusLow
* sintemp
, radiusLow
* costemp
, 0.0);
678 for (j
= 0; j
<= loops
; j
+= loops
) {
679 radiusLow
= outerRadius
- deltaRadius
* ((float) j
/ loops
);
680 if (qobj
->textureCoords
) {
681 texLow
= radiusLow
/ outerRadius
/ 2;
684 glBegin(GL_LINE_STRIP
);
685 for (i
= 0; i
<= slices
; i
++) {
686 if (qobj
->textureCoords
) {
687 glTexCoord2f(texLow
* sinCache
[i
] + 0.5,
688 texLow
* cosCache
[i
] + 0.5);
690 glVertex3f(radiusLow
* sinCache
[i
],
691 radiusLow
* cosCache
[i
], 0.0);
694 if (innerRadius
== outerRadius
) break;
703 gluSphere(GLUquadric
*qobj
, GLdouble radius
, GLint slices
, GLint stacks
)
706 GLfloat sinCache1a
[CACHE_SIZE
];
707 GLfloat cosCache1a
[CACHE_SIZE
];
708 GLfloat sinCache2a
[CACHE_SIZE
];
709 GLfloat cosCache2a
[CACHE_SIZE
];
710 GLfloat sinCache3a
[CACHE_SIZE
];
711 GLfloat cosCache3a
[CACHE_SIZE
];
712 GLfloat sinCache1b
[CACHE_SIZE
];
713 GLfloat cosCache1b
[CACHE_SIZE
];
714 GLfloat sinCache2b
[CACHE_SIZE
];
715 GLfloat cosCache2b
[CACHE_SIZE
];
716 GLfloat sinCache3b
[CACHE_SIZE
];
717 GLfloat cosCache3b
[CACHE_SIZE
];
720 GLfloat sintemp1
, sintemp2
=0, sintemp3
=0, sintemp4
=0;
721 GLfloat costemp1
, costemp2
=0, costemp3
=0, costemp4
=0;
722 GLboolean needCache2
, needCache3
;
725 if (slices
>= CACHE_SIZE
) slices
= CACHE_SIZE
-1;
726 if (stacks
>= CACHE_SIZE
) stacks
= CACHE_SIZE
-1;
727 if (slices
< 2 || stacks
< 1 || radius
< 0.0) {
728 gluQuadricError(qobj
, GLU_INVALID_VALUE
);
732 /* Cache is the vertex locations cache */
733 /* Cache2 is the various normals at the vertices themselves */
734 /* Cache3 is the various normals for the faces */
735 needCache2
= needCache3
= GL_FALSE
;
737 if (qobj
->normals
== GLU_SMOOTH
) {
738 needCache2
= GL_TRUE
;
741 if (qobj
->normals
== GLU_FLAT
) {
742 if (qobj
->drawStyle
!= GLU_POINT
) {
743 needCache3
= GL_TRUE
;
745 if (qobj
->drawStyle
== GLU_LINE
) {
746 needCache2
= GL_TRUE
;
750 for (i
= 0; i
< slices
; i
++) {
751 angle
= 2 * PI
* i
/ slices
;
752 sinCache1a
[i
] = SIN(angle
);
753 cosCache1a
[i
] = COS(angle
);
755 sinCache2a
[i
] = sinCache1a
[i
];
756 cosCache2a
[i
] = cosCache1a
[i
];
760 for (j
= 0; j
<= stacks
; j
++) {
761 angle
= PI
* j
/ stacks
;
763 if (qobj
->orientation
== GLU_OUTSIDE
) {
764 sinCache2b
[j
] = SIN(angle
);
765 cosCache2b
[j
] = COS(angle
);
767 sinCache2b
[j
] = -SIN(angle
);
768 cosCache2b
[j
] = -COS(angle
);
771 sinCache1b
[j
] = radius
* SIN(angle
);
772 cosCache1b
[j
] = radius
* COS(angle
);
774 /* Make sure it comes to a point */
776 sinCache1b
[stacks
] = 0;
779 for (i
= 0; i
< slices
; i
++) {
780 angle
= 2 * PI
* (i
-0.5) / slices
;
781 sinCache3a
[i
] = SIN(angle
);
782 cosCache3a
[i
] = COS(angle
);
784 for (j
= 0; j
<= stacks
; j
++) {
785 angle
= PI
* (j
- 0.5) / stacks
;
786 if (qobj
->orientation
== GLU_OUTSIDE
) {
787 sinCache3b
[j
] = SIN(angle
);
788 cosCache3b
[j
] = COS(angle
);
790 sinCache3b
[j
] = -SIN(angle
);
791 cosCache3b
[j
] = -COS(angle
);
796 sinCache1a
[slices
] = sinCache1a
[0];
797 cosCache1a
[slices
] = cosCache1a
[0];
799 sinCache2a
[slices
] = sinCache2a
[0];
800 cosCache2a
[slices
] = cosCache2a
[0];
803 sinCache3a
[slices
] = sinCache3a
[0];
804 cosCache3a
[slices
] = cosCache3a
[0];
807 switch (qobj
->drawStyle
) {
809 /* Do ends of sphere as TRIANGLE_FAN's (if not texturing)
810 ** We don't do it when texturing because we need to respecify the
811 ** texture coordinates of the apex for every adjacent vertex (because
812 ** it isn't a constant for that point)
814 if (!(qobj
->textureCoords
)) {
818 /* Low end first (j == 0 iteration) */
819 sintemp2
= sinCache1b
[1];
820 zHigh
= cosCache1b
[1];
821 switch(qobj
->normals
) {
823 sintemp3
= sinCache3b
[1];
824 costemp3
= cosCache3b
[1];
827 sintemp3
= sinCache2b
[1];
828 costemp3
= cosCache2b
[1];
829 glNormal3f(sinCache2a
[0] * sinCache2b
[0],
830 cosCache2a
[0] * sinCache2b
[0],
836 glBegin(GL_TRIANGLE_FAN
);
837 glVertex3f(0.0, 0.0, radius
);
838 if (qobj
->orientation
== GLU_OUTSIDE
) {
839 for (i
= slices
; i
>= 0; i
--) {
840 switch(qobj
->normals
) {
842 glNormal3f(sinCache2a
[i
] * sintemp3
,
843 cosCache2a
[i
] * sintemp3
,
848 glNormal3f(sinCache3a
[i
+1] * sintemp3
,
849 cosCache3a
[i
+1] * sintemp3
,
857 glVertex3f(sintemp2
* sinCache1a
[i
],
858 sintemp2
* cosCache1a
[i
], zHigh
);
861 for (i
= 0; i
<= slices
; i
++) {
862 switch(qobj
->normals
) {
864 glNormal3f(sinCache2a
[i
] * sintemp3
,
865 cosCache2a
[i
] * sintemp3
,
869 glNormal3f(sinCache3a
[i
] * sintemp3
,
870 cosCache3a
[i
] * sintemp3
,
877 glVertex3f(sintemp2
* sinCache1a
[i
],
878 sintemp2
* cosCache1a
[i
], zHigh
);
883 /* High end next (j == stacks-1 iteration) */
884 sintemp2
= sinCache1b
[stacks
-1];
885 zHigh
= cosCache1b
[stacks
-1];
886 switch(qobj
->normals
) {
888 sintemp3
= sinCache3b
[stacks
];
889 costemp3
= cosCache3b
[stacks
];
892 sintemp3
= sinCache2b
[stacks
-1];
893 costemp3
= cosCache2b
[stacks
-1];
894 glNormal3f(sinCache2a
[stacks
] * sinCache2b
[stacks
],
895 cosCache2a
[stacks
] * sinCache2b
[stacks
],
901 glBegin(GL_TRIANGLE_FAN
);
902 glVertex3f(0.0, 0.0, -radius
);
903 if (qobj
->orientation
== GLU_OUTSIDE
) {
904 for (i
= 0; i
<= slices
; i
++) {
905 switch(qobj
->normals
) {
907 glNormal3f(sinCache2a
[i
] * sintemp3
,
908 cosCache2a
[i
] * sintemp3
,
912 glNormal3f(sinCache3a
[i
] * sintemp3
,
913 cosCache3a
[i
] * sintemp3
,
920 glVertex3f(sintemp2
* sinCache1a
[i
],
921 sintemp2
* cosCache1a
[i
], zHigh
);
924 for (i
= slices
; i
>= 0; i
--) {
925 switch(qobj
->normals
) {
927 glNormal3f(sinCache2a
[i
] * sintemp3
,
928 cosCache2a
[i
] * sintemp3
,
933 glNormal3f(sinCache3a
[i
+1] * sintemp3
,
934 cosCache3a
[i
+1] * sintemp3
,
942 glVertex3f(sintemp2
* sinCache1a
[i
],
943 sintemp2
* cosCache1a
[i
], zHigh
);
951 for (j
= start
; j
< finish
; j
++) {
952 zLow
= cosCache1b
[j
];
953 zHigh
= cosCache1b
[j
+1];
954 sintemp1
= sinCache1b
[j
];
955 sintemp2
= sinCache1b
[j
+1];
956 switch(qobj
->normals
) {
958 sintemp4
= sinCache3b
[j
+1];
959 costemp4
= cosCache3b
[j
+1];
962 if (qobj
->orientation
== GLU_OUTSIDE
) {
963 sintemp3
= sinCache2b
[j
+1];
964 costemp3
= cosCache2b
[j
+1];
965 sintemp4
= sinCache2b
[j
];
966 costemp4
= cosCache2b
[j
];
968 sintemp3
= sinCache2b
[j
];
969 costemp3
= cosCache2b
[j
];
970 sintemp4
= sinCache2b
[j
+1];
971 costemp4
= cosCache2b
[j
+1];
978 glBegin(GL_QUAD_STRIP
);
979 for (i
= 0; i
<= slices
; i
++) {
980 switch(qobj
->normals
) {
982 glNormal3f(sinCache2a
[i
] * sintemp3
,
983 cosCache2a
[i
] * sintemp3
,
991 if (qobj
->orientation
== GLU_OUTSIDE
) {
992 if (qobj
->textureCoords
) {
993 glTexCoord2f(1 - (float) i
/ slices
,
994 1 - (float) (j
+1) / stacks
);
996 glVertex3f(sintemp2
* sinCache1a
[i
],
997 sintemp2
* cosCache1a
[i
], zHigh
);
999 if (qobj
->textureCoords
) {
1000 glTexCoord2f(1 - (float) i
/ slices
,
1001 1 - (float) j
/ stacks
);
1003 glVertex3f(sintemp1
* sinCache1a
[i
],
1004 sintemp1
* cosCache1a
[i
], zLow
);
1006 switch(qobj
->normals
) {
1008 glNormal3f(sinCache2a
[i
] * sintemp4
,
1009 cosCache2a
[i
] * sintemp4
,
1013 glNormal3f(sinCache3a
[i
] * sintemp4
,
1014 cosCache3a
[i
] * sintemp4
,
1021 if (qobj
->orientation
== GLU_OUTSIDE
) {
1022 if (qobj
->textureCoords
) {
1023 glTexCoord2f(1 - (float) i
/ slices
,
1024 1 - (float) j
/ stacks
);
1026 glVertex3f(sintemp1
* sinCache1a
[i
],
1027 sintemp1
* cosCache1a
[i
], zLow
);
1029 if (qobj
->textureCoords
) {
1030 glTexCoord2f(1 - (float) i
/ slices
,
1031 1 - (float) (j
+1) / stacks
);
1033 glVertex3f(sintemp2
* sinCache1a
[i
],
1034 sintemp2
* cosCache1a
[i
], zHigh
);
1042 for (j
= 0; j
<= stacks
; j
++) {
1043 sintemp1
= sinCache1b
[j
];
1044 costemp1
= cosCache1b
[j
];
1045 switch(qobj
->normals
) {
1048 sintemp2
= sinCache2b
[j
];
1049 costemp2
= cosCache2b
[j
];
1054 for (i
= 0; i
< slices
; i
++) {
1055 switch(qobj
->normals
) {
1058 glNormal3f(sinCache2a
[i
] * sintemp2
,
1059 cosCache2a
[i
] * sintemp2
,
1067 zLow
= j
* radius
/ stacks
;
1069 if (qobj
->textureCoords
) {
1070 glTexCoord2f(1 - (float) i
/ slices
,
1071 1 - (float) j
/ stacks
);
1073 glVertex3f(sintemp1
* sinCache1a
[i
],
1074 sintemp1
* cosCache1a
[i
], costemp1
);
1080 case GLU_SILHOUETTE
:
1081 for (j
= 1; j
< stacks
; j
++) {
1082 sintemp1
= sinCache1b
[j
];
1083 costemp1
= cosCache1b
[j
];
1084 switch(qobj
->normals
) {
1087 sintemp2
= sinCache2b
[j
];
1088 costemp2
= cosCache2b
[j
];
1094 glBegin(GL_LINE_STRIP
);
1095 for (i
= 0; i
<= slices
; i
++) {
1096 switch(qobj
->normals
) {
1098 glNormal3f(sinCache3a
[i
] * sintemp2
,
1099 cosCache3a
[i
] * sintemp2
,
1103 glNormal3f(sinCache2a
[i
] * sintemp2
,
1104 cosCache2a
[i
] * sintemp2
,
1111 if (qobj
->textureCoords
) {
1112 glTexCoord2f(1 - (float) i
/ slices
,
1113 1 - (float) j
/ stacks
);
1115 glVertex3f(sintemp1
* sinCache1a
[i
],
1116 sintemp1
* cosCache1a
[i
], costemp1
);
1120 for (i
= 0; i
< slices
; i
++) {
1121 sintemp1
= sinCache1a
[i
];
1122 costemp1
= cosCache1a
[i
];
1123 switch(qobj
->normals
) {
1126 sintemp2
= sinCache2a
[i
];
1127 costemp2
= cosCache2a
[i
];
1133 glBegin(GL_LINE_STRIP
);
1134 for (j
= 0; j
<= stacks
; j
++) {
1135 switch(qobj
->normals
) {
1137 glNormal3f(sintemp2
* sinCache3b
[j
],
1138 costemp2
* sinCache3b
[j
],
1142 glNormal3f(sintemp2
* sinCache2b
[j
],
1143 costemp2
* sinCache2b
[j
],
1151 if (qobj
->textureCoords
) {
1152 glTexCoord2f(1 - (float) i
/ slices
,
1153 1 - (float) j
/ stacks
);
1155 glVertex3f(sintemp1
* sinCache1b
[j
],
1156 costemp1
* sinCache1b
[j
], cosCache1b
[j
]);