2 * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
3 * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
12 * The above copyright notice including the dates of first publication and
13 * either this permission notice or a reference to
14 * http://oss.sgi.com/projects/FreeB/
15 * shall be included in all copies or substantial portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
22 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25 * Except as contained in this notice, the name of Silicon Graphics, Inc.
26 * shall not be used in advertising or otherwise to promote the sale, use or
27 * other dealings in this Software without prior written authorization from
28 * Silicon Graphics, Inc.
39 /* Make it not a power of two to avoid cache thrashing on the chip */
40 #define CACHE_SIZE 240
44 GLboolean textureCoords
;
47 void (GLAPIENTRY
*errorCallback
)( GLint
);
50 /***********************************************************************
51 * gluNewQuadric (GLU32.@)
53 GLUquadric
* WINAPI
gluNewQuadric(void)
57 newstate
= HeapAlloc(GetProcessHeap(), 0, sizeof(GLUquadric
));
58 if (newstate
== NULL
) {
59 /* Can't report an error at this point... */
62 newstate
->normals
= GLU_SMOOTH
;
63 newstate
->textureCoords
= GL_FALSE
;
64 newstate
->orientation
= GLU_OUTSIDE
;
65 newstate
->drawStyle
= GLU_FILL
;
66 newstate
->errorCallback
= NULL
;
71 /***********************************************************************
72 * gluDeleteQuadric (GLU32.@)
74 void WINAPI
gluDeleteQuadric( GLUquadric
*state
)
76 HeapFree(GetProcessHeap(), 0, state
);
79 static void gluQuadricError(GLUquadric
*qobj
, GLenum which
)
81 if (qobj
->errorCallback
) {
82 qobj
->errorCallback(which
);
86 /***********************************************************************
87 * gluQuadricCallback (GLU32.@)
89 void WINAPI
gluQuadricCallback( GLUquadric
*qobj
, GLenum which
, void (CALLBACK
*fn
)(void) )
93 qobj
->errorCallback
= (void (GLAPIENTRY
*)(GLint
)) fn
;
96 gluQuadricError(qobj
, GLU_INVALID_ENUM
);
101 /***********************************************************************
102 * gluQuadricNormals (GLU32.@)
104 void WINAPI
gluQuadricNormals( GLUquadric
*qobj
, GLenum normals
)
112 gluQuadricError(qobj
, GLU_INVALID_ENUM
);
115 qobj
->normals
= normals
;
118 /***********************************************************************
119 * gluQuadricTexture (GLU32.@)
121 void WINAPI
gluQuadricTexture( GLUquadric
*qobj
, GLboolean textureCoords
)
123 qobj
->textureCoords
= textureCoords
;
126 /***********************************************************************
127 * gluQuadricOrientation (GLU32.@)
129 void WINAPI
gluQuadricOrientation( GLUquadric
*qobj
, GLenum orientation
)
131 switch(orientation
) {
136 gluQuadricError(qobj
, GLU_INVALID_ENUM
);
139 qobj
->orientation
= orientation
;
142 /***********************************************************************
143 * gluQuadricDrawStyle (GLU32.@)
145 void WINAPI
gluQuadricDrawStyle( GLUquadric
*qobj
, GLenum drawStyle
)
154 gluQuadricError(qobj
, GLU_INVALID_ENUM
);
157 qobj
->drawStyle
= drawStyle
;
160 /***********************************************************************
161 * gluCylinder (GLU32.@)
163 void WINAPI
gluCylinder( GLUquadric
*qobj
, GLdouble baseRadius
, GLdouble topRadius
,
164 GLdouble height
, GLint slices
, GLint stacks
)
167 GLfloat sinCache
[CACHE_SIZE
];
168 GLfloat cosCache
[CACHE_SIZE
];
169 GLfloat sinCache2
[CACHE_SIZE
];
170 GLfloat cosCache2
[CACHE_SIZE
];
171 GLfloat sinCache3
[CACHE_SIZE
];
172 GLfloat cosCache3
[CACHE_SIZE
];
175 GLfloat sintemp
, costemp
;
179 GLfloat xyNormalRatio
;
180 GLfloat radiusLow
, radiusHigh
;
181 int needCache2
, needCache3
;
183 if (slices
>= CACHE_SIZE
) slices
= CACHE_SIZE
-1;
185 if (slices
< 2 || stacks
< 1 || baseRadius
< 0.0 || topRadius
< 0.0 ||
187 gluQuadricError(qobj
, GLU_INVALID_VALUE
);
191 /* Compute length (needed for normal calculations) */
192 deltaRadius
= baseRadius
- topRadius
;
193 length
= sqrtf(deltaRadius
*deltaRadius
+ height
*height
);
195 gluQuadricError(qobj
, GLU_INVALID_VALUE
);
199 /* Cache is the vertex locations cache */
200 /* Cache2 is the various normals at the vertices themselves */
201 /* Cache3 is the various normals for the faces */
202 needCache2
= needCache3
= 0;
203 if (qobj
->normals
== GLU_SMOOTH
) {
207 if (qobj
->normals
== GLU_FLAT
) {
208 if (qobj
->drawStyle
!= GLU_POINT
) {
211 if (qobj
->drawStyle
== GLU_LINE
) {
216 zNormal
= deltaRadius
/ length
;
217 xyNormalRatio
= height
/ length
;
219 for (i
= 0; i
< slices
; i
++) {
220 angle
= 2 * M_PI
* i
/ slices
;
222 if (qobj
->orientation
== GLU_OUTSIDE
) {
223 sinCache2
[i
] = xyNormalRatio
* sinf(angle
);
224 cosCache2
[i
] = xyNormalRatio
* cosf(angle
);
226 sinCache2
[i
] = -xyNormalRatio
* sinf(angle
);
227 cosCache2
[i
] = -xyNormalRatio
* cosf(angle
);
230 sinCache
[i
] = sinf(angle
);
231 cosCache
[i
] = cosf(angle
);
235 for (i
= 0; i
< slices
; i
++) {
236 angle
= 2 * M_PI
* (i
-0.5) / slices
;
237 if (qobj
->orientation
== GLU_OUTSIDE
) {
238 sinCache3
[i
] = xyNormalRatio
* sinf(angle
);
239 cosCache3
[i
] = xyNormalRatio
* cosf(angle
);
241 sinCache3
[i
] = -xyNormalRatio
* sinf(angle
);
242 cosCache3
[i
] = -xyNormalRatio
* cosf(angle
);
247 sinCache
[slices
] = sinCache
[0];
248 cosCache
[slices
] = cosCache
[0];
250 sinCache2
[slices
] = sinCache2
[0];
251 cosCache2
[slices
] = cosCache2
[0];
254 sinCache3
[slices
] = sinCache3
[0];
255 cosCache3
[slices
] = cosCache3
[0];
258 switch (qobj
->drawStyle
) {
261 ** An argument could be made for using a TRIANGLE_FAN for the end
262 ** of the cylinder of either radii is 0.0 (a cone). However, a
263 ** TRIANGLE_FAN would not work in smooth shading mode (the common
264 ** case) because the normal for the apex is different for every
265 ** triangle (and TRIANGLE_FAN doesn't let me respecify that normal).
266 ** Now, my choice is GL_TRIANGLES, or leave the GL_QUAD_STRIP and
267 ** just let the GL trivially reject one of the two triangles of the
268 ** QUAD. GL_QUAD_STRIP is probably faster, so I will leave this code
271 for (j
= 0; j
< stacks
; j
++) {
272 zLow
= j
* height
/ stacks
;
273 zHigh
= (j
+ 1) * height
/ stacks
;
274 radiusLow
= baseRadius
- deltaRadius
* ((float) j
/ stacks
);
275 radiusHigh
= baseRadius
- deltaRadius
* ((float) (j
+ 1) / stacks
);
277 glBegin(GL_QUAD_STRIP
);
278 for (i
= 0; i
<= slices
; i
++) {
279 switch(qobj
->normals
) {
281 glNormal3f(sinCache3
[i
], cosCache3
[i
], zNormal
);
284 glNormal3f(sinCache2
[i
], cosCache2
[i
], zNormal
);
290 if (qobj
->orientation
== GLU_OUTSIDE
) {
291 if (qobj
->textureCoords
) {
292 glTexCoord2f(1 - (float) i
/ slices
,
295 glVertex3f(radiusLow
* sinCache
[i
],
296 radiusLow
* cosCache
[i
], zLow
);
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
);
304 if (qobj
->textureCoords
) {
305 glTexCoord2f(1 - (float) i
/ slices
,
306 (float) (j
+1) / stacks
);
308 glVertex3f(radiusHigh
* sinCache
[i
],
309 radiusHigh
* cosCache
[i
], zHigh
);
310 if (qobj
->textureCoords
) {
311 glTexCoord2f(1 - (float) i
/ slices
,
314 glVertex3f(radiusLow
* sinCache
[i
],
315 radiusLow
* cosCache
[i
], zLow
);
323 for (i
= 0; i
< slices
; i
++) {
324 switch(qobj
->normals
) {
327 glNormal3f(sinCache2
[i
], cosCache2
[i
], zNormal
);
333 sintemp
= sinCache
[i
];
334 costemp
= cosCache
[i
];
335 for (j
= 0; j
<= stacks
; j
++) {
336 zLow
= j
* height
/ stacks
;
337 radiusLow
= baseRadius
- deltaRadius
* ((float) j
/ stacks
);
339 if (qobj
->textureCoords
) {
340 glTexCoord2f(1 - (float) i
/ slices
,
343 glVertex3f(radiusLow
* sintemp
,
344 radiusLow
* costemp
, zLow
);
350 for (j
= 1; j
< stacks
; j
++) {
351 zLow
= j
* height
/ stacks
;
352 radiusLow
= baseRadius
- deltaRadius
* ((float) j
/ stacks
);
354 glBegin(GL_LINE_STRIP
);
355 for (i
= 0; i
<= slices
; i
++) {
356 switch(qobj
->normals
) {
358 glNormal3f(sinCache3
[i
], cosCache3
[i
], zNormal
);
361 glNormal3f(sinCache2
[i
], cosCache2
[i
], zNormal
);
367 if (qobj
->textureCoords
) {
368 glTexCoord2f(1 - (float) i
/ slices
,
371 glVertex3f(radiusLow
* sinCache
[i
],
372 radiusLow
* cosCache
[i
], zLow
);
376 /* Intentionally fall through here... */
378 for (j
= 0; j
<= stacks
; j
+= stacks
) {
379 zLow
= j
* height
/ stacks
;
380 radiusLow
= baseRadius
- deltaRadius
* ((float) j
/ stacks
);
382 glBegin(GL_LINE_STRIP
);
383 for (i
= 0; i
<= slices
; i
++) {
384 switch(qobj
->normals
) {
386 glNormal3f(sinCache3
[i
], cosCache3
[i
], zNormal
);
389 glNormal3f(sinCache2
[i
], cosCache2
[i
], zNormal
);
395 if (qobj
->textureCoords
) {
396 glTexCoord2f(1 - (float) i
/ slices
,
399 glVertex3f(radiusLow
* sinCache
[i
], radiusLow
* cosCache
[i
],
404 for (i
= 0; i
< slices
; i
++) {
405 switch(qobj
->normals
) {
408 glNormal3f(sinCache2
[i
], cosCache2
[i
], 0.0);
414 sintemp
= sinCache
[i
];
415 costemp
= cosCache
[i
];
416 glBegin(GL_LINE_STRIP
);
417 for (j
= 0; j
<= stacks
; j
++) {
418 zLow
= j
* height
/ stacks
;
419 radiusLow
= baseRadius
- deltaRadius
* ((float) j
/ stacks
);
421 if (qobj
->textureCoords
) {
422 glTexCoord2f(1 - (float) i
/ slices
,
425 glVertex3f(radiusLow
* sintemp
,
426 radiusLow
* costemp
, zLow
);
436 /***********************************************************************
439 void WINAPI
gluDisk( GLUquadric
*qobj
, GLdouble innerRadius
, GLdouble outerRadius
,
440 GLint slices
, GLint loops
)
442 gluPartialDisk(qobj
, innerRadius
, outerRadius
, slices
, loops
, 0.0, 360.0);
445 /***********************************************************************
446 * gluPartialDisk (GLU32.@)
448 void WINAPI
gluPartialDisk( GLUquadric
*qobj
, GLdouble innerRadius
, GLdouble outerRadius
,
449 GLint slices
, GLint loops
, GLdouble startAngle
, GLdouble sweepAngle
)
452 GLfloat sinCache
[CACHE_SIZE
];
453 GLfloat cosCache
[CACHE_SIZE
];
455 GLfloat sintemp
, costemp
;
457 GLfloat radiusLow
, radiusHigh
;
458 GLfloat texLow
= 0.0, texHigh
= 0.0;
463 if (slices
>= CACHE_SIZE
) slices
= CACHE_SIZE
-1;
464 if (slices
< 2 || loops
< 1 || outerRadius
<= 0.0 || innerRadius
< 0.0 ||
465 innerRadius
> outerRadius
) {
466 gluQuadricError(qobj
, GLU_INVALID_VALUE
);
470 if (sweepAngle
< -360.0) sweepAngle
= 360.0;
471 if (sweepAngle
> 360.0) sweepAngle
= 360.0;
472 if (sweepAngle
< 0) {
473 startAngle
+= sweepAngle
;
474 sweepAngle
= -sweepAngle
;
477 if (sweepAngle
== 360.0) {
480 slices2
= slices
+ 1;
483 /* Compute length (needed for normal calculations) */
484 deltaRadius
= outerRadius
- innerRadius
;
486 /* Cache is the vertex locations cache */
488 angleOffset
= startAngle
/ 180.0 * M_PI
;
489 for (i
= 0; i
<= slices
; i
++) {
490 angle
= angleOffset
+ ((M_PI
* sweepAngle
) / 180.0) * i
/ slices
;
491 sinCache
[i
] = sinf(angle
);
492 cosCache
[i
] = cosf(angle
);
495 if (sweepAngle
== 360.0) {
496 sinCache
[slices
] = sinCache
[0];
497 cosCache
[slices
] = cosCache
[0];
500 switch(qobj
->normals
) {
503 if (qobj
->orientation
== GLU_OUTSIDE
) {
504 glNormal3f(0.0, 0.0, 1.0);
506 glNormal3f(0.0, 0.0, -1.0);
514 switch (qobj
->drawStyle
) {
516 if (innerRadius
== 0.0) {
518 /* Triangle strip for inner polygons */
519 glBegin(GL_TRIANGLE_FAN
);
520 if (qobj
->textureCoords
) {
521 glTexCoord2f(0.5, 0.5);
523 glVertex3f(0.0, 0.0, 0.0);
524 radiusLow
= outerRadius
-
525 deltaRadius
* ((float) (loops
-1) / loops
);
526 if (qobj
->textureCoords
) {
527 texLow
= radiusLow
/ outerRadius
/ 2;
530 if (qobj
->orientation
== GLU_OUTSIDE
) {
531 for (i
= slices
; i
>= 0; 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);
540 for (i
= 0; i
<= slices
; i
++) {
541 if (qobj
->textureCoords
) {
542 glTexCoord2f(texLow
* sinCache
[i
] + 0.5,
543 texLow
* cosCache
[i
] + 0.5);
545 glVertex3f(radiusLow
* sinCache
[i
],
546 radiusLow
* cosCache
[i
], 0.0);
553 for (j
= 0; j
< finish
; j
++) {
554 radiusLow
= outerRadius
- deltaRadius
* ((float) j
/ loops
);
555 radiusHigh
= outerRadius
- deltaRadius
* ((float) (j
+ 1) / loops
);
556 if (qobj
->textureCoords
) {
557 texLow
= radiusLow
/ outerRadius
/ 2;
558 texHigh
= radiusHigh
/ outerRadius
/ 2;
561 glBegin(GL_QUAD_STRIP
);
562 for (i
= 0; i
<= slices
; i
++) {
563 if (qobj
->orientation
== GLU_OUTSIDE
) {
564 if (qobj
->textureCoords
) {
565 glTexCoord2f(texLow
* sinCache
[i
] + 0.5,
566 texLow
* cosCache
[i
] + 0.5);
568 glVertex3f(radiusLow
* sinCache
[i
],
569 radiusLow
* 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(texHigh
* sinCache
[i
] + 0.5,
580 texHigh
* cosCache
[i
] + 0.5);
582 glVertex3f(radiusHigh
* sinCache
[i
],
583 radiusHigh
* cosCache
[i
], 0.0);
585 if (qobj
->textureCoords
) {
586 glTexCoord2f(texLow
* sinCache
[i
] + 0.5,
587 texLow
* cosCache
[i
] + 0.5);
589 glVertex3f(radiusLow
* sinCache
[i
],
590 radiusLow
* cosCache
[i
], 0.0);
598 for (i
= 0; i
< slices2
; i
++) {
599 sintemp
= sinCache
[i
];
600 costemp
= cosCache
[i
];
601 for (j
= 0; j
<= loops
; j
++) {
602 radiusLow
= outerRadius
- deltaRadius
* ((float) j
/ loops
);
604 if (qobj
->textureCoords
) {
605 texLow
= radiusLow
/ outerRadius
/ 2;
607 glTexCoord2f(texLow
* sinCache
[i
] + 0.5,
608 texLow
* cosCache
[i
] + 0.5);
610 glVertex3f(radiusLow
* sintemp
, radiusLow
* costemp
, 0.0);
616 if (innerRadius
== outerRadius
) {
617 glBegin(GL_LINE_STRIP
);
619 for (i
= 0; i
<= slices
; i
++) {
620 if (qobj
->textureCoords
) {
621 glTexCoord2f(sinCache
[i
] / 2 + 0.5,
622 cosCache
[i
] / 2 + 0.5);
624 glVertex3f(innerRadius
* sinCache
[i
],
625 innerRadius
* cosCache
[i
], 0.0);
630 for (j
= 0; j
<= loops
; j
++) {
631 radiusLow
= outerRadius
- deltaRadius
* ((float) j
/ loops
);
632 if (qobj
->textureCoords
) {
633 texLow
= radiusLow
/ outerRadius
/ 2;
636 glBegin(GL_LINE_STRIP
);
637 for (i
= 0; i
<= slices
; i
++) {
638 if (qobj
->textureCoords
) {
639 glTexCoord2f(texLow
* sinCache
[i
] + 0.5,
640 texLow
* cosCache
[i
] + 0.5);
642 glVertex3f(radiusLow
* sinCache
[i
],
643 radiusLow
* cosCache
[i
], 0.0);
647 for (i
=0; i
< slices2
; i
++) {
648 sintemp
= sinCache
[i
];
649 costemp
= cosCache
[i
];
650 glBegin(GL_LINE_STRIP
);
651 for (j
= 0; j
<= loops
; j
++) {
652 radiusLow
= outerRadius
- deltaRadius
* ((float) j
/ loops
);
653 if (qobj
->textureCoords
) {
654 texLow
= radiusLow
/ outerRadius
/ 2;
657 if (qobj
->textureCoords
) {
658 glTexCoord2f(texLow
* sinCache
[i
] + 0.5,
659 texLow
* cosCache
[i
] + 0.5);
661 glVertex3f(radiusLow
* sintemp
, radiusLow
* costemp
, 0.0);
667 if (sweepAngle
< 360.0) {
668 for (i
= 0; i
<= slices
; i
+= slices
) {
669 sintemp
= sinCache
[i
];
670 costemp
= cosCache
[i
];
671 glBegin(GL_LINE_STRIP
);
672 for (j
= 0; j
<= loops
; j
++) {
673 radiusLow
= outerRadius
- deltaRadius
* ((float) j
/ loops
);
675 if (qobj
->textureCoords
) {
676 texLow
= radiusLow
/ outerRadius
/ 2;
677 glTexCoord2f(texLow
* sinCache
[i
] + 0.5,
678 texLow
* cosCache
[i
] + 0.5);
680 glVertex3f(radiusLow
* sintemp
, radiusLow
* costemp
, 0.0);
685 for (j
= 0; j
<= loops
; j
+= loops
) {
686 radiusLow
= outerRadius
- deltaRadius
* ((float) j
/ loops
);
687 if (qobj
->textureCoords
) {
688 texLow
= radiusLow
/ outerRadius
/ 2;
691 glBegin(GL_LINE_STRIP
);
692 for (i
= 0; i
<= slices
; i
++) {
693 if (qobj
->textureCoords
) {
694 glTexCoord2f(texLow
* sinCache
[i
] + 0.5,
695 texLow
* cosCache
[i
] + 0.5);
697 glVertex3f(radiusLow
* sinCache
[i
],
698 radiusLow
* cosCache
[i
], 0.0);
701 if (innerRadius
== outerRadius
) break;
709 /***********************************************************************
710 * gluSphere (GLU32.@)
712 void WINAPI
gluSphere( GLUquadric
*qobj
, GLdouble radius
, GLint slices
, GLint stacks
)
715 GLfloat sinCache1a
[CACHE_SIZE
];
716 GLfloat cosCache1a
[CACHE_SIZE
];
717 GLfloat sinCache2a
[CACHE_SIZE
];
718 GLfloat cosCache2a
[CACHE_SIZE
];
719 GLfloat sinCache3a
[CACHE_SIZE
];
720 GLfloat cosCache3a
[CACHE_SIZE
];
721 GLfloat sinCache1b
[CACHE_SIZE
];
722 GLfloat cosCache1b
[CACHE_SIZE
];
723 GLfloat sinCache2b
[CACHE_SIZE
];
724 GLfloat cosCache2b
[CACHE_SIZE
];
725 GLfloat sinCache3b
[CACHE_SIZE
];
726 GLfloat cosCache3b
[CACHE_SIZE
];
729 GLfloat sintemp1
= 0.0, sintemp2
= 0.0, sintemp3
= 0.0, sintemp4
= 0.0;
730 GLfloat costemp1
= 0.0, costemp2
= 0.0, costemp3
= 0.0, costemp4
= 0.0;
731 GLboolean needCache2
, needCache3
;
734 if (slices
>= CACHE_SIZE
) slices
= CACHE_SIZE
-1;
735 if (stacks
>= CACHE_SIZE
) stacks
= CACHE_SIZE
-1;
736 if (slices
< 2 || stacks
< 1 || radius
< 0.0) {
737 gluQuadricError(qobj
, GLU_INVALID_VALUE
);
741 /* Cache is the vertex locations cache */
742 /* Cache2 is the various normals at the vertices themselves */
743 /* Cache3 is the various normals for the faces */
744 needCache2
= needCache3
= GL_FALSE
;
746 if (qobj
->normals
== GLU_SMOOTH
) {
747 needCache2
= GL_TRUE
;
750 if (qobj
->normals
== GLU_FLAT
) {
751 if (qobj
->drawStyle
!= GLU_POINT
) {
752 needCache3
= GL_TRUE
;
754 if (qobj
->drawStyle
== GLU_LINE
) {
755 needCache2
= GL_TRUE
;
759 for (i
= 0; i
< slices
; i
++) {
760 angle
= 2 * M_PI
* i
/ slices
;
761 sinCache1a
[i
] = sinf(angle
);
762 cosCache1a
[i
] = cosf(angle
);
764 sinCache2a
[i
] = sinCache1a
[i
];
765 cosCache2a
[i
] = cosCache1a
[i
];
769 for (j
= 0; j
<= stacks
; j
++) {
770 angle
= M_PI
* j
/ stacks
;
772 if (qobj
->orientation
== GLU_OUTSIDE
) {
773 sinCache2b
[j
] = sinf(angle
);
774 cosCache2b
[j
] = cosf(angle
);
776 sinCache2b
[j
] = -sinf(angle
);
777 cosCache2b
[j
] = -cosf(angle
);
780 sinCache1b
[j
] = radius
* sinf(angle
);
781 cosCache1b
[j
] = radius
* cosf(angle
);
783 /* Make sure it comes to a point */
785 sinCache1b
[stacks
] = 0;
788 for (i
= 0; i
< slices
; i
++) {
789 angle
= 2 * M_PI
* (i
-0.5) / slices
;
790 sinCache3a
[i
] = sinf(angle
);
791 cosCache3a
[i
] = cosf(angle
);
793 for (j
= 0; j
<= stacks
; j
++) {
794 angle
= M_PI
* (j
- 0.5) / stacks
;
795 if (qobj
->orientation
== GLU_OUTSIDE
) {
796 sinCache3b
[j
] = sinf(angle
);
797 cosCache3b
[j
] = cosf(angle
);
799 sinCache3b
[j
] = -sinf(angle
);
800 cosCache3b
[j
] = -cosf(angle
);
805 sinCache1a
[slices
] = sinCache1a
[0];
806 cosCache1a
[slices
] = cosCache1a
[0];
808 sinCache2a
[slices
] = sinCache2a
[0];
809 cosCache2a
[slices
] = cosCache2a
[0];
812 sinCache3a
[slices
] = sinCache3a
[0];
813 cosCache3a
[slices
] = cosCache3a
[0];
816 switch (qobj
->drawStyle
) {
818 /* Do ends of sphere as TRIANGLE_FAN's (if not texturing)
819 ** We don't do it when texturing because we need to respecify the
820 ** texture coordinates of the apex for every adjacent vertex (because
821 ** it isn't a constant for that point)
823 if (!(qobj
->textureCoords
)) {
827 /* Low end first (j == 0 iteration) */
828 sintemp2
= sinCache1b
[1];
829 zHigh
= cosCache1b
[1];
830 switch(qobj
->normals
) {
832 sintemp3
= sinCache3b
[1];
833 costemp3
= cosCache3b
[1];
836 sintemp3
= sinCache2b
[1];
837 costemp3
= cosCache2b
[1];
838 glNormal3f(sinCache2a
[0] * sinCache2b
[0],
839 cosCache2a
[0] * sinCache2b
[0],
845 glBegin(GL_TRIANGLE_FAN
);
846 glVertex3f(0.0, 0.0, radius
);
847 if (qobj
->orientation
== GLU_OUTSIDE
) {
848 for (i
= slices
; i
>= 0; i
--) {
849 switch(qobj
->normals
) {
851 glNormal3f(sinCache2a
[i
] * sintemp3
,
852 cosCache2a
[i
] * sintemp3
,
857 glNormal3f(sinCache3a
[i
+1] * sintemp3
,
858 cosCache3a
[i
+1] * sintemp3
,
866 glVertex3f(sintemp2
* sinCache1a
[i
],
867 sintemp2
* cosCache1a
[i
], zHigh
);
870 for (i
= 0; i
<= slices
; i
++) {
871 switch(qobj
->normals
) {
873 glNormal3f(sinCache2a
[i
] * sintemp3
,
874 cosCache2a
[i
] * sintemp3
,
878 glNormal3f(sinCache3a
[i
] * sintemp3
,
879 cosCache3a
[i
] * sintemp3
,
886 glVertex3f(sintemp2
* sinCache1a
[i
],
887 sintemp2
* cosCache1a
[i
], zHigh
);
892 /* High end next (j == stacks-1 iteration) */
893 sintemp2
= sinCache1b
[stacks
-1];
894 zHigh
= cosCache1b
[stacks
-1];
895 switch(qobj
->normals
) {
897 sintemp3
= sinCache3b
[stacks
];
898 costemp3
= cosCache3b
[stacks
];
901 sintemp3
= sinCache2b
[stacks
-1];
902 costemp3
= cosCache2b
[stacks
-1];
903 glNormal3f(sinCache2a
[stacks
] * sinCache2b
[stacks
],
904 cosCache2a
[stacks
] * sinCache2b
[stacks
],
910 glBegin(GL_TRIANGLE_FAN
);
911 glVertex3f(0.0, 0.0, -radius
);
912 if (qobj
->orientation
== GLU_OUTSIDE
) {
913 for (i
= 0; i
<= slices
; i
++) {
914 switch(qobj
->normals
) {
916 glNormal3f(sinCache2a
[i
] * sintemp3
,
917 cosCache2a
[i
] * sintemp3
,
921 glNormal3f(sinCache3a
[i
] * sintemp3
,
922 cosCache3a
[i
] * sintemp3
,
929 glVertex3f(sintemp2
* sinCache1a
[i
],
930 sintemp2
* cosCache1a
[i
], zHigh
);
933 for (i
= slices
; i
>= 0; i
--) {
934 switch(qobj
->normals
) {
936 glNormal3f(sinCache2a
[i
] * sintemp3
,
937 cosCache2a
[i
] * sintemp3
,
942 glNormal3f(sinCache3a
[i
+1] * sintemp3
,
943 cosCache3a
[i
+1] * sintemp3
,
951 glVertex3f(sintemp2
* sinCache1a
[i
],
952 sintemp2
* cosCache1a
[i
], zHigh
);
960 for (j
= start
; j
< finish
; j
++) {
961 zLow
= cosCache1b
[j
];
962 zHigh
= cosCache1b
[j
+1];
963 sintemp1
= sinCache1b
[j
];
964 sintemp2
= sinCache1b
[j
+1];
965 switch(qobj
->normals
) {
967 sintemp4
= sinCache3b
[j
+1];
968 costemp4
= cosCache3b
[j
+1];
971 if (qobj
->orientation
== GLU_OUTSIDE
) {
972 sintemp3
= sinCache2b
[j
+1];
973 costemp3
= cosCache2b
[j
+1];
974 sintemp4
= sinCache2b
[j
];
975 costemp4
= cosCache2b
[j
];
977 sintemp3
= sinCache2b
[j
];
978 costemp3
= cosCache2b
[j
];
979 sintemp4
= sinCache2b
[j
+1];
980 costemp4
= cosCache2b
[j
+1];
987 glBegin(GL_QUAD_STRIP
);
988 for (i
= 0; i
<= slices
; i
++) {
989 switch(qobj
->normals
) {
991 glNormal3f(sinCache2a
[i
] * sintemp3
,
992 cosCache2a
[i
] * sintemp3
,
1000 if (qobj
->orientation
== GLU_OUTSIDE
) {
1001 if (qobj
->textureCoords
) {
1002 glTexCoord2f(1 - (float) i
/ slices
,
1003 1 - (float) (j
+1) / stacks
);
1005 glVertex3f(sintemp2
* sinCache1a
[i
],
1006 sintemp2
* cosCache1a
[i
], zHigh
);
1008 if (qobj
->textureCoords
) {
1009 glTexCoord2f(1 - (float) i
/ slices
,
1010 1 - (float) j
/ stacks
);
1012 glVertex3f(sintemp1
* sinCache1a
[i
],
1013 sintemp1
* cosCache1a
[i
], zLow
);
1015 switch(qobj
->normals
) {
1017 glNormal3f(sinCache2a
[i
] * sintemp4
,
1018 cosCache2a
[i
] * sintemp4
,
1022 glNormal3f(sinCache3a
[i
] * sintemp4
,
1023 cosCache3a
[i
] * sintemp4
,
1030 if (qobj
->orientation
== GLU_OUTSIDE
) {
1031 if (qobj
->textureCoords
) {
1032 glTexCoord2f(1 - (float) i
/ slices
,
1033 1 - (float) j
/ stacks
);
1035 glVertex3f(sintemp1
* sinCache1a
[i
],
1036 sintemp1
* cosCache1a
[i
], zLow
);
1038 if (qobj
->textureCoords
) {
1039 glTexCoord2f(1 - (float) i
/ slices
,
1040 1 - (float) (j
+1) / stacks
);
1042 glVertex3f(sintemp2
* sinCache1a
[i
],
1043 sintemp2
* cosCache1a
[i
], zHigh
);
1051 for (j
= 0; j
<= stacks
; j
++) {
1052 sintemp1
= sinCache1b
[j
];
1053 costemp1
= cosCache1b
[j
];
1054 switch(qobj
->normals
) {
1057 sintemp2
= sinCache2b
[j
];
1058 costemp2
= cosCache2b
[j
];
1063 for (i
= 0; i
< slices
; i
++) {
1064 switch(qobj
->normals
) {
1067 glNormal3f(sinCache2a
[i
] * sintemp2
,
1068 cosCache2a
[i
] * sintemp2
,
1076 zLow
= j
* radius
/ stacks
;
1078 if (qobj
->textureCoords
) {
1079 glTexCoord2f(1 - (float) i
/ slices
,
1080 1 - (float) j
/ stacks
);
1082 glVertex3f(sintemp1
* sinCache1a
[i
],
1083 sintemp1
* cosCache1a
[i
], costemp1
);
1089 case GLU_SILHOUETTE
:
1090 for (j
= 1; j
< stacks
; j
++) {
1091 sintemp1
= sinCache1b
[j
];
1092 costemp1
= cosCache1b
[j
];
1093 switch(qobj
->normals
) {
1096 sintemp2
= sinCache2b
[j
];
1097 costemp2
= cosCache2b
[j
];
1103 glBegin(GL_LINE_STRIP
);
1104 for (i
= 0; i
<= slices
; i
++) {
1105 switch(qobj
->normals
) {
1107 glNormal3f(sinCache3a
[i
] * sintemp2
,
1108 cosCache3a
[i
] * sintemp2
,
1112 glNormal3f(sinCache2a
[i
] * sintemp2
,
1113 cosCache2a
[i
] * sintemp2
,
1120 if (qobj
->textureCoords
) {
1121 glTexCoord2f(1 - (float) i
/ slices
,
1122 1 - (float) j
/ stacks
);
1124 glVertex3f(sintemp1
* sinCache1a
[i
],
1125 sintemp1
* cosCache1a
[i
], costemp1
);
1129 for (i
= 0; i
< slices
; i
++) {
1130 sintemp1
= sinCache1a
[i
];
1131 costemp1
= cosCache1a
[i
];
1132 switch(qobj
->normals
) {
1135 sintemp2
= sinCache2a
[i
];
1136 costemp2
= cosCache2a
[i
];
1142 glBegin(GL_LINE_STRIP
);
1143 for (j
= 0; j
<= stacks
; j
++) {
1144 switch(qobj
->normals
) {
1146 glNormal3f(sintemp2
* sinCache3b
[j
],
1147 costemp2
* sinCache3b
[j
],
1151 glNormal3f(sintemp2
* sinCache2b
[j
],
1152 costemp2
* sinCache2b
[j
],
1160 if (qobj
->textureCoords
) {
1161 glTexCoord2f(1 - (float) i
/ slices
,
1162 1 - (float) j
/ stacks
);
1164 glVertex3f(sintemp1
* sinCache1b
[j
],
1165 costemp1
* sinCache1b
[j
], cosCache1b
[j
]);