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.
34 ** $Date: 2001/09/20 21:47:52 $ $Revision: 1.2 $
35 ** $Header: /home/krh/git/sync/mesa-cvs-repo/Mesa/src/glu/sgi/libutil/quad.c,v 1.2 2001/09/20 21:47:52 kschultz Exp $
46 /* Make it not a power of two to avoid cache thrashing on the chip */
47 #define CACHE_SIZE 240
49 #define PI 3.14159265358979323846
53 GLboolean textureCoords
;
56 void (GLAPIENTRY
*errorCallback
)( GLint
);
59 GLUquadric
* GLAPIENTRY
64 newstate
= (GLUquadric
*) malloc(sizeof(GLUquadric
));
65 if (newstate
== NULL
) {
66 /* Can't report an error at this point... */
69 newstate
->normals
= GLU_SMOOTH
;
70 newstate
->textureCoords
= GL_FALSE
;
71 newstate
->orientation
= GLU_OUTSIDE
;
72 newstate
->drawStyle
= GLU_FILL
;
73 newstate
->errorCallback
= NULL
;
79 gluDeleteQuadric(GLUquadric
*state
)
84 static void gluQuadricError(GLUquadric
*qobj
, GLenum which
)
86 if (qobj
->errorCallback
) {
87 qobj
->errorCallback(which
);
92 gluQuadricCallback(GLUquadric
*qobj
, GLenum which
, _GLUfuncptr fn
)
96 qobj
->errorCallback
= (void (GLAPIENTRY
*)(GLint
)) fn
;
99 gluQuadricError(qobj
, GLU_INVALID_ENUM
);
105 gluQuadricNormals(GLUquadric
*qobj
, GLenum normals
)
113 gluQuadricError(qobj
, GLU_INVALID_ENUM
);
116 qobj
->normals
= normals
;
120 gluQuadricTexture(GLUquadric
*qobj
, GLboolean textureCoords
)
122 qobj
->textureCoords
= textureCoords
;
126 gluQuadricOrientation(GLUquadric
*qobj
, GLenum orientation
)
128 switch(orientation
) {
133 gluQuadricError(qobj
, GLU_INVALID_ENUM
);
136 qobj
->orientation
= orientation
;
140 gluQuadricDrawStyle(GLUquadric
*qobj
, GLenum drawStyle
)
149 gluQuadricError(qobj
, GLU_INVALID_ENUM
);
152 qobj
->drawStyle
= drawStyle
;
156 gluCylinder(GLUquadric
*qobj
, GLdouble baseRadius
, GLdouble topRadius
,
157 GLdouble height
, GLint slices
, GLint stacks
)
160 GLfloat sinCache
[CACHE_SIZE
];
161 GLfloat cosCache
[CACHE_SIZE
];
162 GLfloat sinCache2
[CACHE_SIZE
];
163 GLfloat cosCache2
[CACHE_SIZE
];
164 GLfloat sinCache3
[CACHE_SIZE
];
165 GLfloat cosCache3
[CACHE_SIZE
];
167 GLfloat x
, y
, zLow
, zHigh
;
168 GLfloat sintemp
, costemp
;
172 GLfloat xyNormalRatio
;
173 GLfloat radiusLow
, radiusHigh
;
174 int needCache2
, needCache3
;
176 if (slices
>= CACHE_SIZE
) slices
= CACHE_SIZE
-1;
178 if (slices
< 2 || stacks
< 1 || baseRadius
< 0.0 || topRadius
< 0.0 ||
180 gluQuadricError(qobj
, GLU_INVALID_VALUE
);
184 /* Compute length (needed for normal calculations) */
185 deltaRadius
= baseRadius
- topRadius
;
186 length
= SQRT(deltaRadius
*deltaRadius
+ height
*height
);
188 gluQuadricError(qobj
, GLU_INVALID_VALUE
);
192 /* Cache is the vertex locations cache */
193 /* Cache2 is the various normals at the vertices themselves */
194 /* Cache3 is the various normals for the faces */
195 needCache2
= needCache3
= 0;
196 if (qobj
->normals
== GLU_SMOOTH
) {
200 if (qobj
->normals
== GLU_FLAT
) {
201 if (qobj
->drawStyle
!= GLU_POINT
) {
204 if (qobj
->drawStyle
== GLU_LINE
) {
209 zNormal
= deltaRadius
/ length
;
210 xyNormalRatio
= height
/ length
;
212 for (i
= 0; i
< slices
; i
++) {
213 angle
= 2 * PI
* i
/ slices
;
215 if (qobj
->orientation
== GLU_OUTSIDE
) {
216 sinCache2
[i
] = xyNormalRatio
* SIN(angle
);
217 cosCache2
[i
] = xyNormalRatio
* COS(angle
);
219 sinCache2
[i
] = -xyNormalRatio
* SIN(angle
);
220 cosCache2
[i
] = -xyNormalRatio
* COS(angle
);
223 sinCache
[i
] = SIN(angle
);
224 cosCache
[i
] = COS(angle
);
228 for (i
= 0; i
< slices
; i
++) {
229 angle
= 2 * PI
* (i
-0.5) / slices
;
230 if (qobj
->orientation
== GLU_OUTSIDE
) {
231 sinCache3
[i
] = xyNormalRatio
* SIN(angle
);
232 cosCache3
[i
] = xyNormalRatio
* COS(angle
);
234 sinCache3
[i
] = -xyNormalRatio
* SIN(angle
);
235 cosCache3
[i
] = -xyNormalRatio
* COS(angle
);
240 sinCache
[slices
] = sinCache
[0];
241 cosCache
[slices
] = cosCache
[0];
243 sinCache2
[slices
] = sinCache2
[0];
244 cosCache2
[slices
] = cosCache2
[0];
247 sinCache3
[slices
] = sinCache3
[0];
248 cosCache3
[slices
] = cosCache3
[0];
251 switch (qobj
->drawStyle
) {
254 ** An argument could be made for using a TRIANGLE_FAN for the end
255 ** of the cylinder of either radii is 0.0 (a cone). However, a
256 ** TRIANGLE_FAN would not work in smooth shading mode (the common
257 ** case) because the normal for the apex is different for every
258 ** triangle (and TRIANGLE_FAN doesn't let me respecify that normal).
259 ** Now, my choice is GL_TRIANGLES, or leave the GL_QUAD_STRIP and
260 ** just let the GL trivially reject one of the two triangles of the
261 ** QUAD. GL_QUAD_STRIP is probably faster, so I will leave this code
264 for (j
= 0; j
< stacks
; j
++) {
265 zLow
= j
* height
/ stacks
;
266 zHigh
= (j
+ 1) * height
/ stacks
;
267 radiusLow
= baseRadius
- deltaRadius
* ((float) j
/ stacks
);
268 radiusHigh
= baseRadius
- deltaRadius
* ((float) (j
+ 1) / stacks
);
270 glBegin(GL_QUAD_STRIP
);
271 for (i
= 0; i
<= slices
; i
++) {
272 switch(qobj
->normals
) {
274 glNormal3f(sinCache3
[i
], cosCache3
[i
], zNormal
);
277 glNormal3f(sinCache2
[i
], cosCache2
[i
], zNormal
);
283 if (qobj
->orientation
== GLU_OUTSIDE
) {
284 if (qobj
->textureCoords
) {
285 glTexCoord2f(1 - (float) i
/ slices
,
288 glVertex3f(radiusLow
* sinCache
[i
],
289 radiusLow
* cosCache
[i
], zLow
);
290 if (qobj
->textureCoords
) {
291 glTexCoord2f(1 - (float) i
/ slices
,
292 (float) (j
+1) / stacks
);
294 glVertex3f(radiusHigh
* sinCache
[i
],
295 radiusHigh
* cosCache
[i
], zHigh
);
297 if (qobj
->textureCoords
) {
298 glTexCoord2f(1 - (float) i
/ slices
,
299 (float) (j
+1) / stacks
);
301 glVertex3f(radiusHigh
* sinCache
[i
],
302 radiusHigh
* cosCache
[i
], zHigh
);
303 if (qobj
->textureCoords
) {
304 glTexCoord2f(1 - (float) i
/ slices
,
307 glVertex3f(radiusLow
* sinCache
[i
],
308 radiusLow
* cosCache
[i
], zLow
);
316 for (i
= 0; i
< slices
; i
++) {
317 switch(qobj
->normals
) {
320 glNormal3f(sinCache2
[i
], cosCache2
[i
], zNormal
);
326 sintemp
= sinCache
[i
];
327 costemp
= cosCache
[i
];
328 for (j
= 0; j
<= stacks
; j
++) {
329 zLow
= j
* height
/ stacks
;
330 radiusLow
= baseRadius
- deltaRadius
* ((float) j
/ stacks
);
332 if (qobj
->textureCoords
) {
333 glTexCoord2f(1 - (float) i
/ slices
,
336 glVertex3f(radiusLow
* sintemp
,
337 radiusLow
* costemp
, zLow
);
343 for (j
= 1; j
< stacks
; j
++) {
344 zLow
= j
* height
/ stacks
;
345 radiusLow
= baseRadius
- deltaRadius
* ((float) j
/ stacks
);
347 glBegin(GL_LINE_STRIP
);
348 for (i
= 0; i
<= slices
; i
++) {
349 switch(qobj
->normals
) {
351 glNormal3f(sinCache3
[i
], cosCache3
[i
], zNormal
);
354 glNormal3f(sinCache2
[i
], cosCache2
[i
], zNormal
);
360 if (qobj
->textureCoords
) {
361 glTexCoord2f(1 - (float) i
/ slices
,
364 glVertex3f(radiusLow
* sinCache
[i
],
365 radiusLow
* cosCache
[i
], zLow
);
369 /* Intentionally fall through here... */
371 for (j
= 0; j
<= stacks
; j
+= stacks
) {
372 zLow
= j
* height
/ stacks
;
373 radiusLow
= baseRadius
- deltaRadius
* ((float) j
/ stacks
);
375 glBegin(GL_LINE_STRIP
);
376 for (i
= 0; i
<= slices
; i
++) {
377 switch(qobj
->normals
) {
379 glNormal3f(sinCache3
[i
], cosCache3
[i
], zNormal
);
382 glNormal3f(sinCache2
[i
], cosCache2
[i
], zNormal
);
388 if (qobj
->textureCoords
) {
389 glTexCoord2f(1 - (float) i
/ slices
,
392 glVertex3f(radiusLow
* sinCache
[i
], radiusLow
* cosCache
[i
],
397 for (i
= 0; i
< slices
; i
++) {
398 switch(qobj
->normals
) {
401 glNormal3f(sinCache2
[i
], cosCache2
[i
], 0.0);
407 sintemp
= sinCache
[i
];
408 costemp
= cosCache
[i
];
409 glBegin(GL_LINE_STRIP
);
410 for (j
= 0; j
<= stacks
; j
++) {
411 zLow
= j
* height
/ stacks
;
412 radiusLow
= baseRadius
- deltaRadius
* ((float) j
/ stacks
);
414 if (qobj
->textureCoords
) {
415 glTexCoord2f(1 - (float) i
/ slices
,
418 glVertex3f(radiusLow
* sintemp
,
419 radiusLow
* costemp
, zLow
);
430 gluDisk(GLUquadric
*qobj
, GLdouble innerRadius
, GLdouble outerRadius
,
431 GLint slices
, GLint loops
)
433 gluPartialDisk(qobj
, innerRadius
, outerRadius
, slices
, loops
, 0.0, 360.0);
437 gluPartialDisk(GLUquadric
*qobj
, GLdouble innerRadius
,
438 GLdouble outerRadius
, GLint slices
, GLint loops
,
439 GLdouble startAngle
, GLdouble sweepAngle
)
442 GLfloat sinCache
[CACHE_SIZE
];
443 GLfloat cosCache
[CACHE_SIZE
];
446 GLfloat sintemp
, costemp
;
448 GLfloat radiusLow
, radiusHigh
;
449 GLfloat texLow
, texHigh
;
454 if (slices
>= CACHE_SIZE
) slices
= CACHE_SIZE
-1;
455 if (slices
< 2 || loops
< 1 || outerRadius
<= 0.0 || innerRadius
< 0.0 ||
456 innerRadius
> outerRadius
) {
457 gluQuadricError(qobj
, GLU_INVALID_VALUE
);
461 if (sweepAngle
< -360.0) sweepAngle
= 360.0;
462 if (sweepAngle
> 360.0) sweepAngle
= 360.0;
463 if (sweepAngle
< 0) {
464 startAngle
+= sweepAngle
;
465 sweepAngle
= -sweepAngle
;
468 if (sweepAngle
== 360.0) {
471 slices2
= slices
+ 1;
474 /* Compute length (needed for normal calculations) */
475 deltaRadius
= outerRadius
- innerRadius
;
477 /* Cache is the vertex locations cache */
479 angleOffset
= startAngle
/ 180.0 * PI
;
480 for (i
= 0; i
<= slices
; i
++) {
481 angle
= angleOffset
+ ((PI
* sweepAngle
) / 180.0) * i
/ slices
;
482 sinCache
[i
] = SIN(angle
);
483 cosCache
[i
] = COS(angle
);
486 if (sweepAngle
== 360.0) {
487 sinCache
[slices
] = sinCache
[0];
488 cosCache
[slices
] = cosCache
[0];
491 switch(qobj
->normals
) {
494 if (qobj
->orientation
== GLU_OUTSIDE
) {
495 glNormal3f(0.0, 0.0, 1.0);
497 glNormal3f(0.0, 0.0, -1.0);
505 switch (qobj
->drawStyle
) {
507 if (innerRadius
== 0.0) {
509 /* Triangle strip for inner polygons */
510 glBegin(GL_TRIANGLE_FAN
);
511 if (qobj
->textureCoords
) {
512 glTexCoord2f(0.5, 0.5);
514 glVertex3f(0.0, 0.0, 0.0);
515 radiusLow
= outerRadius
-
516 deltaRadius
* ((float) (loops
-1) / loops
);
517 if (qobj
->textureCoords
) {
518 texLow
= radiusLow
/ outerRadius
/ 2;
521 if (qobj
->orientation
== GLU_OUTSIDE
) {
522 for (i
= slices
; i
>= 0; i
--) {
523 if (qobj
->textureCoords
) {
524 glTexCoord2f(texLow
* sinCache
[i
] + 0.5,
525 texLow
* cosCache
[i
] + 0.5);
527 glVertex3f(radiusLow
* sinCache
[i
],
528 radiusLow
* cosCache
[i
], 0.0);
531 for (i
= 0; i
<= slices
; i
++) {
532 if (qobj
->textureCoords
) {
533 glTexCoord2f(texLow
* sinCache
[i
] + 0.5,
534 texLow
* cosCache
[i
] + 0.5);
536 glVertex3f(radiusLow
* sinCache
[i
],
537 radiusLow
* cosCache
[i
], 0.0);
544 for (j
= 0; j
< finish
; j
++) {
545 radiusLow
= outerRadius
- deltaRadius
* ((float) j
/ loops
);
546 radiusHigh
= outerRadius
- deltaRadius
* ((float) (j
+ 1) / loops
);
547 if (qobj
->textureCoords
) {
548 texLow
= radiusLow
/ outerRadius
/ 2;
549 texHigh
= radiusHigh
/ outerRadius
/ 2;
552 glBegin(GL_QUAD_STRIP
);
553 for (i
= 0; i
<= slices
; i
++) {
554 if (qobj
->orientation
== GLU_OUTSIDE
) {
555 if (qobj
->textureCoords
) {
556 glTexCoord2f(texLow
* sinCache
[i
] + 0.5,
557 texLow
* cosCache
[i
] + 0.5);
559 glVertex3f(radiusLow
* sinCache
[i
],
560 radiusLow
* cosCache
[i
], 0.0);
562 if (qobj
->textureCoords
) {
563 glTexCoord2f(texHigh
* sinCache
[i
] + 0.5,
564 texHigh
* cosCache
[i
] + 0.5);
566 glVertex3f(radiusHigh
* sinCache
[i
],
567 radiusHigh
* cosCache
[i
], 0.0);
569 if (qobj
->textureCoords
) {
570 glTexCoord2f(texHigh
* sinCache
[i
] + 0.5,
571 texHigh
* cosCache
[i
] + 0.5);
573 glVertex3f(radiusHigh
* sinCache
[i
],
574 radiusHigh
* cosCache
[i
], 0.0);
576 if (qobj
->textureCoords
) {
577 glTexCoord2f(texLow
* sinCache
[i
] + 0.5,
578 texLow
* cosCache
[i
] + 0.5);
580 glVertex3f(radiusLow
* sinCache
[i
],
581 radiusLow
* cosCache
[i
], 0.0);
589 for (i
= 0; i
< slices2
; i
++) {
590 sintemp
= sinCache
[i
];
591 costemp
= cosCache
[i
];
592 for (j
= 0; j
<= loops
; j
++) {
593 radiusLow
= outerRadius
- deltaRadius
* ((float) j
/ loops
);
595 if (qobj
->textureCoords
) {
596 texLow
= radiusLow
/ outerRadius
/ 2;
598 glTexCoord2f(texLow
* sinCache
[i
] + 0.5,
599 texLow
* cosCache
[i
] + 0.5);
601 glVertex3f(radiusLow
* sintemp
, radiusLow
* costemp
, 0.0);
607 if (innerRadius
== outerRadius
) {
608 glBegin(GL_LINE_STRIP
);
610 for (i
= 0; i
<= slices
; i
++) {
611 if (qobj
->textureCoords
) {
612 glTexCoord2f(sinCache
[i
] / 2 + 0.5,
613 cosCache
[i
] / 2 + 0.5);
615 glVertex3f(innerRadius
* sinCache
[i
],
616 innerRadius
* cosCache
[i
], 0.0);
621 for (j
= 0; j
<= loops
; j
++) {
622 radiusLow
= outerRadius
- deltaRadius
* ((float) j
/ loops
);
623 if (qobj
->textureCoords
) {
624 texLow
= radiusLow
/ outerRadius
/ 2;
627 glBegin(GL_LINE_STRIP
);
628 for (i
= 0; i
<= slices
; i
++) {
629 if (qobj
->textureCoords
) {
630 glTexCoord2f(texLow
* sinCache
[i
] + 0.5,
631 texLow
* cosCache
[i
] + 0.5);
633 glVertex3f(radiusLow
* sinCache
[i
],
634 radiusLow
* cosCache
[i
], 0.0);
638 for (i
=0; i
< slices2
; i
++) {
639 sintemp
= sinCache
[i
];
640 costemp
= cosCache
[i
];
641 glBegin(GL_LINE_STRIP
);
642 for (j
= 0; j
<= loops
; j
++) {
643 radiusLow
= outerRadius
- deltaRadius
* ((float) j
/ loops
);
644 if (qobj
->textureCoords
) {
645 texLow
= radiusLow
/ outerRadius
/ 2;
648 if (qobj
->textureCoords
) {
649 glTexCoord2f(texLow
* sinCache
[i
] + 0.5,
650 texLow
* cosCache
[i
] + 0.5);
652 glVertex3f(radiusLow
* sintemp
, radiusLow
* costemp
, 0.0);
658 if (sweepAngle
< 360.0) {
659 for (i
= 0; i
<= slices
; i
+= slices
) {
660 sintemp
= sinCache
[i
];
661 costemp
= cosCache
[i
];
662 glBegin(GL_LINE_STRIP
);
663 for (j
= 0; j
<= loops
; j
++) {
664 radiusLow
= outerRadius
- deltaRadius
* ((float) j
/ loops
);
666 if (qobj
->textureCoords
) {
667 texLow
= radiusLow
/ outerRadius
/ 2;
668 glTexCoord2f(texLow
* sinCache
[i
] + 0.5,
669 texLow
* cosCache
[i
] + 0.5);
671 glVertex3f(radiusLow
* sintemp
, radiusLow
* costemp
, 0.0);
676 for (j
= 0; j
<= loops
; j
+= loops
) {
677 radiusLow
= outerRadius
- deltaRadius
* ((float) j
/ loops
);
678 if (qobj
->textureCoords
) {
679 texLow
= radiusLow
/ outerRadius
/ 2;
682 glBegin(GL_LINE_STRIP
);
683 for (i
= 0; i
<= slices
; i
++) {
684 if (qobj
->textureCoords
) {
685 glTexCoord2f(texLow
* sinCache
[i
] + 0.5,
686 texLow
* cosCache
[i
] + 0.5);
688 glVertex3f(radiusLow
* sinCache
[i
],
689 radiusLow
* cosCache
[i
], 0.0);
692 if (innerRadius
== outerRadius
) break;
701 gluSphere(GLUquadric
*qobj
, GLdouble radius
, GLint slices
, GLint stacks
)
704 GLfloat sinCache1a
[CACHE_SIZE
];
705 GLfloat cosCache1a
[CACHE_SIZE
];
706 GLfloat sinCache2a
[CACHE_SIZE
];
707 GLfloat cosCache2a
[CACHE_SIZE
];
708 GLfloat sinCache3a
[CACHE_SIZE
];
709 GLfloat cosCache3a
[CACHE_SIZE
];
710 GLfloat sinCache1b
[CACHE_SIZE
];
711 GLfloat cosCache1b
[CACHE_SIZE
];
712 GLfloat sinCache2b
[CACHE_SIZE
];
713 GLfloat cosCache2b
[CACHE_SIZE
];
714 GLfloat sinCache3b
[CACHE_SIZE
];
715 GLfloat cosCache3b
[CACHE_SIZE
];
717 GLfloat x
, y
, zLow
, zHigh
;
718 GLfloat sintemp1
, sintemp2
, sintemp3
, sintemp4
;
719 GLfloat costemp1
, costemp2
, costemp3
, costemp4
;
721 GLfloat xyNormalRatio
;
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
]);