d88b20f5566fbebe4b338e669007e5ec2ee12df5
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
43 #define PI 3.14159265358979323846
47 GLboolean textureCoords
;
50 void (GLAPIENTRY
*errorCallback
)( GLint
);
53 GLUquadric
* GLAPIENTRY
58 newstate
= (GLUquadric
*) malloc(sizeof(GLUquadric
));
59 if (newstate
== NULL
) {
60 /* Can't report an error at this point... */
63 newstate
->normals
= GLU_SMOOTH
;
64 newstate
->textureCoords
= GL_FALSE
;
65 newstate
->orientation
= GLU_OUTSIDE
;
66 newstate
->drawStyle
= GLU_FILL
;
67 newstate
->errorCallback
= NULL
;
73 gluDeleteQuadric(GLUquadric
*state
)
78 static void gluQuadricError(GLUquadric
*qobj
, GLenum which
)
80 if (qobj
->errorCallback
) {
81 qobj
->errorCallback(which
);
86 gluQuadricCallback(GLUquadric
*qobj
, GLenum which
, _GLUfuncptr fn
)
90 qobj
->errorCallback
= (void (GLAPIENTRY
*)(GLint
)) fn
;
93 gluQuadricError(qobj
, GLU_INVALID_ENUM
);
99 gluQuadricNormals(GLUquadric
*qobj
, GLenum normals
)
107 gluQuadricError(qobj
, GLU_INVALID_ENUM
);
110 qobj
->normals
= normals
;
114 gluQuadricTexture(GLUquadric
*qobj
, GLboolean textureCoords
)
116 qobj
->textureCoords
= textureCoords
;
120 gluQuadricOrientation(GLUquadric
*qobj
, GLenum orientation
)
122 switch(orientation
) {
127 gluQuadricError(qobj
, GLU_INVALID_ENUM
);
130 qobj
->orientation
= orientation
;
134 gluQuadricDrawStyle(GLUquadric
*qobj
, GLenum drawStyle
)
143 gluQuadricError(qobj
, GLU_INVALID_ENUM
);
146 qobj
->drawStyle
= drawStyle
;
150 gluCylinder(GLUquadric
*qobj
, GLdouble baseRadius
, GLdouble topRadius
,
151 GLdouble height
, GLint slices
, GLint stacks
)
154 GLfloat sinCache
[CACHE_SIZE
];
155 GLfloat cosCache
[CACHE_SIZE
];
156 GLfloat sinCache2
[CACHE_SIZE
];
157 GLfloat cosCache2
[CACHE_SIZE
];
158 GLfloat sinCache3
[CACHE_SIZE
];
159 GLfloat cosCache3
[CACHE_SIZE
];
162 GLfloat sintemp
, costemp
;
166 GLfloat xyNormalRatio
;
167 GLfloat radiusLow
, radiusHigh
;
168 int needCache2
, needCache3
;
170 if (slices
>= CACHE_SIZE
) slices
= CACHE_SIZE
-1;
172 if (slices
< 2 || stacks
< 1 || baseRadius
< 0.0 || topRadius
< 0.0 ||
174 gluQuadricError(qobj
, GLU_INVALID_VALUE
);
178 /* Compute length (needed for normal calculations) */
179 deltaRadius
= baseRadius
- topRadius
;
180 length
= SQRT(deltaRadius
*deltaRadius
+ height
*height
);
182 gluQuadricError(qobj
, GLU_INVALID_VALUE
);
186 /* Cache is the vertex locations cache */
187 /* Cache2 is the various normals at the vertices themselves */
188 /* Cache3 is the various normals for the faces */
189 needCache2
= needCache3
= 0;
190 if (qobj
->normals
== GLU_SMOOTH
) {
194 if (qobj
->normals
== GLU_FLAT
) {
195 if (qobj
->drawStyle
!= GLU_POINT
) {
198 if (qobj
->drawStyle
== GLU_LINE
) {
203 zNormal
= deltaRadius
/ length
;
204 xyNormalRatio
= height
/ length
;
206 for (i
= 0; i
< slices
; i
++) {
207 angle
= 2 * PI
* i
/ slices
;
209 if (qobj
->orientation
== GLU_OUTSIDE
) {
210 sinCache2
[i
] = xyNormalRatio
* SIN(angle
);
211 cosCache2
[i
] = xyNormalRatio
* COS(angle
);
213 sinCache2
[i
] = -xyNormalRatio
* SIN(angle
);
214 cosCache2
[i
] = -xyNormalRatio
* COS(angle
);
217 sinCache
[i
] = SIN(angle
);
218 cosCache
[i
] = COS(angle
);
222 for (i
= 0; i
< slices
; i
++) {
223 angle
= 2 * PI
* (i
-0.5) / slices
;
224 if (qobj
->orientation
== GLU_OUTSIDE
) {
225 sinCache3
[i
] = xyNormalRatio
* SIN(angle
);
226 cosCache3
[i
] = xyNormalRatio
* COS(angle
);
228 sinCache3
[i
] = -xyNormalRatio
* SIN(angle
);
229 cosCache3
[i
] = -xyNormalRatio
* COS(angle
);
234 sinCache
[slices
] = sinCache
[0];
235 cosCache
[slices
] = cosCache
[0];
237 sinCache2
[slices
] = sinCache2
[0];
238 cosCache2
[slices
] = cosCache2
[0];
241 sinCache3
[slices
] = sinCache3
[0];
242 cosCache3
[slices
] = cosCache3
[0];
245 switch (qobj
->drawStyle
) {
248 ** An argument could be made for using a TRIANGLE_FAN for the end
249 ** of the cylinder of either radii is 0.0 (a cone). However, a
250 ** TRIANGLE_FAN would not work in smooth shading mode (the common
251 ** case) because the normal for the apex is different for every
252 ** triangle (and TRIANGLE_FAN doesn't let me respecify that normal).
253 ** Now, my choice is GL_TRIANGLES, or leave the GL_QUAD_STRIP and
254 ** just let the GL trivially reject one of the two triangles of the
255 ** QUAD. GL_QUAD_STRIP is probably faster, so I will leave this code
258 for (j
= 0; j
< stacks
; j
++) {
259 zLow
= j
* height
/ stacks
;
260 zHigh
= (j
+ 1) * height
/ stacks
;
261 radiusLow
= baseRadius
- deltaRadius
* ((float) j
/ stacks
);
262 radiusHigh
= baseRadius
- deltaRadius
* ((float) (j
+ 1) / stacks
);
264 glBegin(GL_QUAD_STRIP
);
265 for (i
= 0; i
<= slices
; i
++) {
266 switch(qobj
->normals
) {
268 glNormal3f(sinCache3
[i
], cosCache3
[i
], zNormal
);
271 glNormal3f(sinCache2
[i
], cosCache2
[i
], zNormal
);
277 if (qobj
->orientation
== GLU_OUTSIDE
) {
278 if (qobj
->textureCoords
) {
279 glTexCoord2f(1 - (float) i
/ slices
,
282 glVertex3f(radiusLow
* sinCache
[i
],
283 radiusLow
* cosCache
[i
], zLow
);
284 if (qobj
->textureCoords
) {
285 glTexCoord2f(1 - (float) i
/ slices
,
286 (float) (j
+1) / stacks
);
288 glVertex3f(radiusHigh
* sinCache
[i
],
289 radiusHigh
* cosCache
[i
], zHigh
);
291 if (qobj
->textureCoords
) {
292 glTexCoord2f(1 - (float) i
/ slices
,
293 (float) (j
+1) / stacks
);
295 glVertex3f(radiusHigh
* sinCache
[i
],
296 radiusHigh
* cosCache
[i
], zHigh
);
297 if (qobj
->textureCoords
) {
298 glTexCoord2f(1 - (float) i
/ slices
,
301 glVertex3f(radiusLow
* sinCache
[i
],
302 radiusLow
* cosCache
[i
], zLow
);
310 for (i
= 0; i
< slices
; i
++) {
311 switch(qobj
->normals
) {
314 glNormal3f(sinCache2
[i
], cosCache2
[i
], zNormal
);
320 sintemp
= sinCache
[i
];
321 costemp
= cosCache
[i
];
322 for (j
= 0; j
<= stacks
; j
++) {
323 zLow
= j
* height
/ stacks
;
324 radiusLow
= baseRadius
- deltaRadius
* ((float) j
/ stacks
);
326 if (qobj
->textureCoords
) {
327 glTexCoord2f(1 - (float) i
/ slices
,
330 glVertex3f(radiusLow
* sintemp
,
331 radiusLow
* costemp
, zLow
);
337 for (j
= 1; j
< stacks
; j
++) {
338 zLow
= j
* height
/ stacks
;
339 radiusLow
= baseRadius
- deltaRadius
* ((float) j
/ stacks
);
341 glBegin(GL_LINE_STRIP
);
342 for (i
= 0; i
<= slices
; i
++) {
343 switch(qobj
->normals
) {
345 glNormal3f(sinCache3
[i
], cosCache3
[i
], zNormal
);
348 glNormal3f(sinCache2
[i
], cosCache2
[i
], zNormal
);
354 if (qobj
->textureCoords
) {
355 glTexCoord2f(1 - (float) i
/ slices
,
358 glVertex3f(radiusLow
* sinCache
[i
],
359 radiusLow
* cosCache
[i
], zLow
);
363 /* Intentionally fall through here... */
365 for (j
= 0; j
<= stacks
; j
+= stacks
) {
366 zLow
= j
* height
/ stacks
;
367 radiusLow
= baseRadius
- deltaRadius
* ((float) j
/ stacks
);
369 glBegin(GL_LINE_STRIP
);
370 for (i
= 0; i
<= slices
; i
++) {
371 switch(qobj
->normals
) {
373 glNormal3f(sinCache3
[i
], cosCache3
[i
], zNormal
);
376 glNormal3f(sinCache2
[i
], cosCache2
[i
], zNormal
);
382 if (qobj
->textureCoords
) {
383 glTexCoord2f(1 - (float) i
/ slices
,
386 glVertex3f(radiusLow
* sinCache
[i
], radiusLow
* cosCache
[i
],
391 for (i
= 0; i
< slices
; i
++) {
392 switch(qobj
->normals
) {
395 glNormal3f(sinCache2
[i
], cosCache2
[i
], 0.0);
401 sintemp
= sinCache
[i
];
402 costemp
= cosCache
[i
];
403 glBegin(GL_LINE_STRIP
);
404 for (j
= 0; j
<= stacks
; j
++) {
405 zLow
= j
* height
/ stacks
;
406 radiusLow
= baseRadius
- deltaRadius
* ((float) j
/ stacks
);
408 if (qobj
->textureCoords
) {
409 glTexCoord2f(1 - (float) i
/ slices
,
412 glVertex3f(radiusLow
* sintemp
,
413 radiusLow
* costemp
, zLow
);
424 gluDisk(GLUquadric
*qobj
, GLdouble innerRadius
, GLdouble outerRadius
,
425 GLint slices
, GLint loops
)
427 gluPartialDisk(qobj
, innerRadius
, outerRadius
, slices
, loops
, 0.0, 360.0);
431 gluPartialDisk(GLUquadric
*qobj
, GLdouble innerRadius
,
432 GLdouble outerRadius
, GLint slices
, GLint loops
,
433 GLdouble startAngle
, GLdouble sweepAngle
)
436 GLfloat sinCache
[CACHE_SIZE
];
437 GLfloat cosCache
[CACHE_SIZE
];
439 GLfloat sintemp
, costemp
;
441 GLfloat radiusLow
, radiusHigh
;
442 GLfloat texLow
= 0.0, texHigh
= 0.0;
447 if (slices
>= CACHE_SIZE
) slices
= CACHE_SIZE
-1;
448 if (slices
< 2 || loops
< 1 || outerRadius
<= 0.0 || innerRadius
< 0.0 ||
449 innerRadius
> outerRadius
) {
450 gluQuadricError(qobj
, GLU_INVALID_VALUE
);
454 if (sweepAngle
< -360.0) sweepAngle
= 360.0;
455 if (sweepAngle
> 360.0) sweepAngle
= 360.0;
456 if (sweepAngle
< 0) {
457 startAngle
+= sweepAngle
;
458 sweepAngle
= -sweepAngle
;
461 if (sweepAngle
== 360.0) {
464 slices2
= slices
+ 1;
467 /* Compute length (needed for normal calculations) */
468 deltaRadius
= outerRadius
- innerRadius
;
470 /* Cache is the vertex locations cache */
472 angleOffset
= startAngle
/ 180.0 * PI
;
473 for (i
= 0; i
<= slices
; i
++) {
474 angle
= angleOffset
+ ((PI
* sweepAngle
) / 180.0) * i
/ slices
;
475 sinCache
[i
] = SIN(angle
);
476 cosCache
[i
] = COS(angle
);
479 if (sweepAngle
== 360.0) {
480 sinCache
[slices
] = sinCache
[0];
481 cosCache
[slices
] = cosCache
[0];
484 switch(qobj
->normals
) {
487 if (qobj
->orientation
== GLU_OUTSIDE
) {
488 glNormal3f(0.0, 0.0, 1.0);
490 glNormal3f(0.0, 0.0, -1.0);
498 switch (qobj
->drawStyle
) {
500 if (innerRadius
== 0.0) {
502 /* Triangle strip for inner polygons */
503 glBegin(GL_TRIANGLE_FAN
);
504 if (qobj
->textureCoords
) {
505 glTexCoord2f(0.5, 0.5);
507 glVertex3f(0.0, 0.0, 0.0);
508 radiusLow
= outerRadius
-
509 deltaRadius
* ((float) (loops
-1) / loops
);
510 if (qobj
->textureCoords
) {
511 texLow
= radiusLow
/ outerRadius
/ 2;
514 if (qobj
->orientation
== GLU_OUTSIDE
) {
515 for (i
= slices
; i
>= 0; i
--) {
516 if (qobj
->textureCoords
) {
517 glTexCoord2f(texLow
* sinCache
[i
] + 0.5,
518 texLow
* cosCache
[i
] + 0.5);
520 glVertex3f(radiusLow
* sinCache
[i
],
521 radiusLow
* cosCache
[i
], 0.0);
524 for (i
= 0; i
<= slices
; 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);
537 for (j
= 0; j
< finish
; j
++) {
538 radiusLow
= outerRadius
- deltaRadius
* ((float) j
/ loops
);
539 radiusHigh
= outerRadius
- deltaRadius
* ((float) (j
+ 1) / loops
);
540 if (qobj
->textureCoords
) {
541 texLow
= radiusLow
/ outerRadius
/ 2;
542 texHigh
= radiusHigh
/ outerRadius
/ 2;
545 glBegin(GL_QUAD_STRIP
);
546 for (i
= 0; i
<= slices
; i
++) {
547 if (qobj
->orientation
== GLU_OUTSIDE
) {
548 if (qobj
->textureCoords
) {
549 glTexCoord2f(texLow
* sinCache
[i
] + 0.5,
550 texLow
* cosCache
[i
] + 0.5);
552 glVertex3f(radiusLow
* sinCache
[i
],
553 radiusLow
* cosCache
[i
], 0.0);
555 if (qobj
->textureCoords
) {
556 glTexCoord2f(texHigh
* sinCache
[i
] + 0.5,
557 texHigh
* cosCache
[i
] + 0.5);
559 glVertex3f(radiusHigh
* sinCache
[i
],
560 radiusHigh
* 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(texLow
* sinCache
[i
] + 0.5,
571 texLow
* cosCache
[i
] + 0.5);
573 glVertex3f(radiusLow
* sinCache
[i
],
574 radiusLow
* cosCache
[i
], 0.0);
582 for (i
= 0; i
< slices2
; i
++) {
583 sintemp
= sinCache
[i
];
584 costemp
= cosCache
[i
];
585 for (j
= 0; j
<= loops
; j
++) {
586 radiusLow
= outerRadius
- deltaRadius
* ((float) j
/ loops
);
588 if (qobj
->textureCoords
) {
589 texLow
= radiusLow
/ outerRadius
/ 2;
591 glTexCoord2f(texLow
* sinCache
[i
] + 0.5,
592 texLow
* cosCache
[i
] + 0.5);
594 glVertex3f(radiusLow
* sintemp
, radiusLow
* costemp
, 0.0);
600 if (innerRadius
== outerRadius
) {
601 glBegin(GL_LINE_STRIP
);
603 for (i
= 0; i
<= slices
; i
++) {
604 if (qobj
->textureCoords
) {
605 glTexCoord2f(sinCache
[i
] / 2 + 0.5,
606 cosCache
[i
] / 2 + 0.5);
608 glVertex3f(innerRadius
* sinCache
[i
],
609 innerRadius
* cosCache
[i
], 0.0);
614 for (j
= 0; j
<= loops
; j
++) {
615 radiusLow
= outerRadius
- deltaRadius
* ((float) j
/ loops
);
616 if (qobj
->textureCoords
) {
617 texLow
= radiusLow
/ outerRadius
/ 2;
620 glBegin(GL_LINE_STRIP
);
621 for (i
= 0; i
<= slices
; i
++) {
622 if (qobj
->textureCoords
) {
623 glTexCoord2f(texLow
* sinCache
[i
] + 0.5,
624 texLow
* cosCache
[i
] + 0.5);
626 glVertex3f(radiusLow
* sinCache
[i
],
627 radiusLow
* cosCache
[i
], 0.0);
631 for (i
=0; i
< slices2
; i
++) {
632 sintemp
= sinCache
[i
];
633 costemp
= cosCache
[i
];
634 glBegin(GL_LINE_STRIP
);
635 for (j
= 0; j
<= loops
; j
++) {
636 radiusLow
= outerRadius
- deltaRadius
* ((float) j
/ loops
);
637 if (qobj
->textureCoords
) {
638 texLow
= radiusLow
/ outerRadius
/ 2;
641 if (qobj
->textureCoords
) {
642 glTexCoord2f(texLow
* sinCache
[i
] + 0.5,
643 texLow
* cosCache
[i
] + 0.5);
645 glVertex3f(radiusLow
* sintemp
, radiusLow
* costemp
, 0.0);
651 if (sweepAngle
< 360.0) {
652 for (i
= 0; i
<= slices
; i
+= slices
) {
653 sintemp
= sinCache
[i
];
654 costemp
= cosCache
[i
];
655 glBegin(GL_LINE_STRIP
);
656 for (j
= 0; j
<= loops
; j
++) {
657 radiusLow
= outerRadius
- deltaRadius
* ((float) j
/ loops
);
659 if (qobj
->textureCoords
) {
660 texLow
= radiusLow
/ outerRadius
/ 2;
661 glTexCoord2f(texLow
* sinCache
[i
] + 0.5,
662 texLow
* cosCache
[i
] + 0.5);
664 glVertex3f(radiusLow
* sintemp
, radiusLow
* costemp
, 0.0);
669 for (j
= 0; j
<= loops
; j
+= loops
) {
670 radiusLow
= outerRadius
- deltaRadius
* ((float) j
/ loops
);
671 if (qobj
->textureCoords
) {
672 texLow
= radiusLow
/ outerRadius
/ 2;
675 glBegin(GL_LINE_STRIP
);
676 for (i
= 0; i
<= slices
; i
++) {
677 if (qobj
->textureCoords
) {
678 glTexCoord2f(texLow
* sinCache
[i
] + 0.5,
679 texLow
* cosCache
[i
] + 0.5);
681 glVertex3f(radiusLow
* sinCache
[i
],
682 radiusLow
* cosCache
[i
], 0.0);
685 if (innerRadius
== outerRadius
) break;
694 gluSphere(GLUquadric
*qobj
, GLdouble radius
, GLint slices
, GLint stacks
)
697 GLfloat sinCache1a
[CACHE_SIZE
];
698 GLfloat cosCache1a
[CACHE_SIZE
];
699 GLfloat sinCache2a
[CACHE_SIZE
];
700 GLfloat cosCache2a
[CACHE_SIZE
];
701 GLfloat sinCache3a
[CACHE_SIZE
];
702 GLfloat cosCache3a
[CACHE_SIZE
];
703 GLfloat sinCache1b
[CACHE_SIZE
];
704 GLfloat cosCache1b
[CACHE_SIZE
];
705 GLfloat sinCache2b
[CACHE_SIZE
];
706 GLfloat cosCache2b
[CACHE_SIZE
];
707 GLfloat sinCache3b
[CACHE_SIZE
];
708 GLfloat cosCache3b
[CACHE_SIZE
];
711 GLfloat sintemp1
= 0.0, sintemp2
= 0.0, sintemp3
= 0.0, sintemp4
= 0.0;
712 GLfloat costemp1
= 0.0, costemp2
= 0.0, costemp3
= 0.0, costemp4
= 0.0;
713 GLboolean needCache2
, needCache3
;
716 if (slices
>= CACHE_SIZE
) slices
= CACHE_SIZE
-1;
717 if (stacks
>= CACHE_SIZE
) stacks
= CACHE_SIZE
-1;
718 if (slices
< 2 || stacks
< 1 || radius
< 0.0) {
719 gluQuadricError(qobj
, GLU_INVALID_VALUE
);
723 /* Cache is the vertex locations cache */
724 /* Cache2 is the various normals at the vertices themselves */
725 /* Cache3 is the various normals for the faces */
726 needCache2
= needCache3
= GL_FALSE
;
728 if (qobj
->normals
== GLU_SMOOTH
) {
729 needCache2
= GL_TRUE
;
732 if (qobj
->normals
== GLU_FLAT
) {
733 if (qobj
->drawStyle
!= GLU_POINT
) {
734 needCache3
= GL_TRUE
;
736 if (qobj
->drawStyle
== GLU_LINE
) {
737 needCache2
= GL_TRUE
;
741 for (i
= 0; i
< slices
; i
++) {
742 angle
= 2 * PI
* i
/ slices
;
743 sinCache1a
[i
] = SIN(angle
);
744 cosCache1a
[i
] = COS(angle
);
746 sinCache2a
[i
] = sinCache1a
[i
];
747 cosCache2a
[i
] = cosCache1a
[i
];
751 for (j
= 0; j
<= stacks
; j
++) {
752 angle
= PI
* j
/ stacks
;
754 if (qobj
->orientation
== GLU_OUTSIDE
) {
755 sinCache2b
[j
] = SIN(angle
);
756 cosCache2b
[j
] = COS(angle
);
758 sinCache2b
[j
] = -SIN(angle
);
759 cosCache2b
[j
] = -COS(angle
);
762 sinCache1b
[j
] = radius
* SIN(angle
);
763 cosCache1b
[j
] = radius
* COS(angle
);
765 /* Make sure it comes to a point */
767 sinCache1b
[stacks
] = 0;
770 for (i
= 0; i
< slices
; i
++) {
771 angle
= 2 * PI
* (i
-0.5) / slices
;
772 sinCache3a
[i
] = SIN(angle
);
773 cosCache3a
[i
] = COS(angle
);
775 for (j
= 0; j
<= stacks
; j
++) {
776 angle
= PI
* (j
- 0.5) / stacks
;
777 if (qobj
->orientation
== GLU_OUTSIDE
) {
778 sinCache3b
[j
] = SIN(angle
);
779 cosCache3b
[j
] = COS(angle
);
781 sinCache3b
[j
] = -SIN(angle
);
782 cosCache3b
[j
] = -COS(angle
);
787 sinCache1a
[slices
] = sinCache1a
[0];
788 cosCache1a
[slices
] = cosCache1a
[0];
790 sinCache2a
[slices
] = sinCache2a
[0];
791 cosCache2a
[slices
] = cosCache2a
[0];
794 sinCache3a
[slices
] = sinCache3a
[0];
795 cosCache3a
[slices
] = cosCache3a
[0];
798 switch (qobj
->drawStyle
) {
800 /* Do ends of sphere as TRIANGLE_FAN's (if not texturing)
801 ** We don't do it when texturing because we need to respecify the
802 ** texture coordinates of the apex for every adjacent vertex (because
803 ** it isn't a constant for that point)
805 if (!(qobj
->textureCoords
)) {
809 /* Low end first (j == 0 iteration) */
810 sintemp2
= sinCache1b
[1];
811 zHigh
= cosCache1b
[1];
812 switch(qobj
->normals
) {
814 sintemp3
= sinCache3b
[1];
815 costemp3
= cosCache3b
[1];
818 sintemp3
= sinCache2b
[1];
819 costemp3
= cosCache2b
[1];
820 glNormal3f(sinCache2a
[0] * sinCache2b
[0],
821 cosCache2a
[0] * sinCache2b
[0],
827 glBegin(GL_TRIANGLE_FAN
);
828 glVertex3f(0.0, 0.0, radius
);
829 if (qobj
->orientation
== GLU_OUTSIDE
) {
830 for (i
= slices
; i
>= 0; i
--) {
831 switch(qobj
->normals
) {
833 glNormal3f(sinCache2a
[i
] * sintemp3
,
834 cosCache2a
[i
] * sintemp3
,
839 glNormal3f(sinCache3a
[i
+1] * sintemp3
,
840 cosCache3a
[i
+1] * sintemp3
,
848 glVertex3f(sintemp2
* sinCache1a
[i
],
849 sintemp2
* cosCache1a
[i
], zHigh
);
852 for (i
= 0; i
<= slices
; i
++) {
853 switch(qobj
->normals
) {
855 glNormal3f(sinCache2a
[i
] * sintemp3
,
856 cosCache2a
[i
] * sintemp3
,
860 glNormal3f(sinCache3a
[i
] * sintemp3
,
861 cosCache3a
[i
] * sintemp3
,
868 glVertex3f(sintemp2
* sinCache1a
[i
],
869 sintemp2
* cosCache1a
[i
], zHigh
);
874 /* High end next (j == stacks-1 iteration) */
875 sintemp2
= sinCache1b
[stacks
-1];
876 zHigh
= cosCache1b
[stacks
-1];
877 switch(qobj
->normals
) {
879 sintemp3
= sinCache3b
[stacks
];
880 costemp3
= cosCache3b
[stacks
];
883 sintemp3
= sinCache2b
[stacks
-1];
884 costemp3
= cosCache2b
[stacks
-1];
885 glNormal3f(sinCache2a
[stacks
] * sinCache2b
[stacks
],
886 cosCache2a
[stacks
] * sinCache2b
[stacks
],
892 glBegin(GL_TRIANGLE_FAN
);
893 glVertex3f(0.0, 0.0, -radius
);
894 if (qobj
->orientation
== GLU_OUTSIDE
) {
895 for (i
= 0; i
<= slices
; i
++) {
896 switch(qobj
->normals
) {
898 glNormal3f(sinCache2a
[i
] * sintemp3
,
899 cosCache2a
[i
] * sintemp3
,
903 glNormal3f(sinCache3a
[i
] * sintemp3
,
904 cosCache3a
[i
] * sintemp3
,
911 glVertex3f(sintemp2
* sinCache1a
[i
],
912 sintemp2
* cosCache1a
[i
], zHigh
);
915 for (i
= slices
; i
>= 0; i
--) {
916 switch(qobj
->normals
) {
918 glNormal3f(sinCache2a
[i
] * sintemp3
,
919 cosCache2a
[i
] * sintemp3
,
924 glNormal3f(sinCache3a
[i
+1] * sintemp3
,
925 cosCache3a
[i
+1] * sintemp3
,
933 glVertex3f(sintemp2
* sinCache1a
[i
],
934 sintemp2
* cosCache1a
[i
], zHigh
);
942 for (j
= start
; j
< finish
; j
++) {
943 zLow
= cosCache1b
[j
];
944 zHigh
= cosCache1b
[j
+1];
945 sintemp1
= sinCache1b
[j
];
946 sintemp2
= sinCache1b
[j
+1];
947 switch(qobj
->normals
) {
949 sintemp4
= sinCache3b
[j
+1];
950 costemp4
= cosCache3b
[j
+1];
953 if (qobj
->orientation
== GLU_OUTSIDE
) {
954 sintemp3
= sinCache2b
[j
+1];
955 costemp3
= cosCache2b
[j
+1];
956 sintemp4
= sinCache2b
[j
];
957 costemp4
= cosCache2b
[j
];
959 sintemp3
= sinCache2b
[j
];
960 costemp3
= cosCache2b
[j
];
961 sintemp4
= sinCache2b
[j
+1];
962 costemp4
= cosCache2b
[j
+1];
969 glBegin(GL_QUAD_STRIP
);
970 for (i
= 0; i
<= slices
; i
++) {
971 switch(qobj
->normals
) {
973 glNormal3f(sinCache2a
[i
] * sintemp3
,
974 cosCache2a
[i
] * sintemp3
,
982 if (qobj
->orientation
== GLU_OUTSIDE
) {
983 if (qobj
->textureCoords
) {
984 glTexCoord2f(1 - (float) i
/ slices
,
985 1 - (float) (j
+1) / stacks
);
987 glVertex3f(sintemp2
* sinCache1a
[i
],
988 sintemp2
* cosCache1a
[i
], zHigh
);
990 if (qobj
->textureCoords
) {
991 glTexCoord2f(1 - (float) i
/ slices
,
992 1 - (float) j
/ stacks
);
994 glVertex3f(sintemp1
* sinCache1a
[i
],
995 sintemp1
* cosCache1a
[i
], zLow
);
997 switch(qobj
->normals
) {
999 glNormal3f(sinCache2a
[i
] * sintemp4
,
1000 cosCache2a
[i
] * sintemp4
,
1004 glNormal3f(sinCache3a
[i
] * sintemp4
,
1005 cosCache3a
[i
] * sintemp4
,
1012 if (qobj
->orientation
== GLU_OUTSIDE
) {
1013 if (qobj
->textureCoords
) {
1014 glTexCoord2f(1 - (float) i
/ slices
,
1015 1 - (float) j
/ stacks
);
1017 glVertex3f(sintemp1
* sinCache1a
[i
],
1018 sintemp1
* cosCache1a
[i
], zLow
);
1020 if (qobj
->textureCoords
) {
1021 glTexCoord2f(1 - (float) i
/ slices
,
1022 1 - (float) (j
+1) / stacks
);
1024 glVertex3f(sintemp2
* sinCache1a
[i
],
1025 sintemp2
* cosCache1a
[i
], zHigh
);
1033 for (j
= 0; j
<= stacks
; j
++) {
1034 sintemp1
= sinCache1b
[j
];
1035 costemp1
= cosCache1b
[j
];
1036 switch(qobj
->normals
) {
1039 sintemp2
= sinCache2b
[j
];
1040 costemp2
= cosCache2b
[j
];
1045 for (i
= 0; i
< slices
; i
++) {
1046 switch(qobj
->normals
) {
1049 glNormal3f(sinCache2a
[i
] * sintemp2
,
1050 cosCache2a
[i
] * sintemp2
,
1058 zLow
= j
* radius
/ stacks
;
1060 if (qobj
->textureCoords
) {
1061 glTexCoord2f(1 - (float) i
/ slices
,
1062 1 - (float) j
/ stacks
);
1064 glVertex3f(sintemp1
* sinCache1a
[i
],
1065 sintemp1
* cosCache1a
[i
], costemp1
);
1071 case GLU_SILHOUETTE
:
1072 for (j
= 1; j
< stacks
; j
++) {
1073 sintemp1
= sinCache1b
[j
];
1074 costemp1
= cosCache1b
[j
];
1075 switch(qobj
->normals
) {
1078 sintemp2
= sinCache2b
[j
];
1079 costemp2
= cosCache2b
[j
];
1085 glBegin(GL_LINE_STRIP
);
1086 for (i
= 0; i
<= slices
; i
++) {
1087 switch(qobj
->normals
) {
1089 glNormal3f(sinCache3a
[i
] * sintemp2
,
1090 cosCache3a
[i
] * sintemp2
,
1094 glNormal3f(sinCache2a
[i
] * sintemp2
,
1095 cosCache2a
[i
] * sintemp2
,
1102 if (qobj
->textureCoords
) {
1103 glTexCoord2f(1 - (float) i
/ slices
,
1104 1 - (float) j
/ stacks
);
1106 glVertex3f(sintemp1
* sinCache1a
[i
],
1107 sintemp1
* cosCache1a
[i
], costemp1
);
1111 for (i
= 0; i
< slices
; i
++) {
1112 sintemp1
= sinCache1a
[i
];
1113 costemp1
= cosCache1a
[i
];
1114 switch(qobj
->normals
) {
1117 sintemp2
= sinCache2a
[i
];
1118 costemp2
= cosCache2a
[i
];
1124 glBegin(GL_LINE_STRIP
);
1125 for (j
= 0; j
<= stacks
; j
++) {
1126 switch(qobj
->normals
) {
1128 glNormal3f(sintemp2
* sinCache3b
[j
],
1129 costemp2
* sinCache3b
[j
],
1133 glNormal3f(sintemp2
* sinCache2b
[j
],
1134 costemp2
* sinCache2b
[j
],
1142 if (qobj
->textureCoords
) {
1143 glTexCoord2f(1 - (float) i
/ slices
,
1144 1 - (float) j
/ stacks
);
1146 glVertex3f(sintemp1
* sinCache1b
[j
],
1147 costemp1
* sinCache1b
[j
], cosCache1b
[j
]);