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.
32 #include "wine/port.h"
42 /* Make it not a power of two to avoid cache thrashing on the chip */
43 #define CACHE_SIZE 240
47 GLboolean textureCoords
;
50 void (GLAPIENTRY
*errorCallback
)( GLint
);
53 /***********************************************************************
54 * gluNewQuadric (GLU32.@)
56 GLUquadric
* WINAPI
gluNewQuadric(void)
60 newstate
= HeapAlloc(GetProcessHeap(), 0, sizeof(GLUquadric
));
61 if (newstate
== NULL
) {
62 /* Can't report an error at this point... */
65 newstate
->normals
= GLU_SMOOTH
;
66 newstate
->textureCoords
= GL_FALSE
;
67 newstate
->orientation
= GLU_OUTSIDE
;
68 newstate
->drawStyle
= GLU_FILL
;
69 newstate
->errorCallback
= NULL
;
74 /***********************************************************************
75 * gluDeleteQuadric (GLU32.@)
77 void WINAPI
gluDeleteQuadric( GLUquadric
*state
)
79 HeapFree(GetProcessHeap(), 0, state
);
82 static void gluQuadricError(GLUquadric
*qobj
, GLenum which
)
84 if (qobj
->errorCallback
) {
85 qobj
->errorCallback(which
);
89 /***********************************************************************
90 * gluQuadricCallback (GLU32.@)
92 void WINAPI
gluQuadricCallback( GLUquadric
*qobj
, GLenum which
, void (CALLBACK
*fn
)(void) )
96 qobj
->errorCallback
= (void (GLAPIENTRY
*)(GLint
)) fn
;
99 gluQuadricError(qobj
, GLU_INVALID_ENUM
);
104 /***********************************************************************
105 * gluQuadricNormals (GLU32.@)
107 void WINAPI
gluQuadricNormals( GLUquadric
*qobj
, GLenum normals
)
115 gluQuadricError(qobj
, GLU_INVALID_ENUM
);
118 qobj
->normals
= normals
;
121 /***********************************************************************
122 * gluQuadricTexture (GLU32.@)
124 void WINAPI
gluQuadricTexture( GLUquadric
*qobj
, GLboolean textureCoords
)
126 qobj
->textureCoords
= textureCoords
;
129 /***********************************************************************
130 * gluQuadricOrientation (GLU32.@)
132 void WINAPI
gluQuadricOrientation( GLUquadric
*qobj
, GLenum orientation
)
134 switch(orientation
) {
139 gluQuadricError(qobj
, GLU_INVALID_ENUM
);
142 qobj
->orientation
= orientation
;
145 /***********************************************************************
146 * gluQuadricDrawStyle (GLU32.@)
148 void WINAPI
gluQuadricDrawStyle( GLUquadric
*qobj
, GLenum drawStyle
)
157 gluQuadricError(qobj
, GLU_INVALID_ENUM
);
160 qobj
->drawStyle
= drawStyle
;
163 /***********************************************************************
164 * gluCylinder (GLU32.@)
166 void WINAPI
gluCylinder( GLUquadric
*qobj
, GLdouble baseRadius
, GLdouble topRadius
,
167 GLdouble height
, GLint slices
, GLint stacks
)
170 GLfloat sinCache
[CACHE_SIZE
];
171 GLfloat cosCache
[CACHE_SIZE
];
172 GLfloat sinCache2
[CACHE_SIZE
];
173 GLfloat cosCache2
[CACHE_SIZE
];
174 GLfloat sinCache3
[CACHE_SIZE
];
175 GLfloat cosCache3
[CACHE_SIZE
];
178 GLfloat sintemp
, costemp
;
182 GLfloat xyNormalRatio
;
183 GLfloat radiusLow
, radiusHigh
;
184 int needCache2
, needCache3
;
186 if (slices
>= CACHE_SIZE
) slices
= CACHE_SIZE
-1;
188 if (slices
< 2 || stacks
< 1 || baseRadius
< 0.0 || topRadius
< 0.0 ||
190 gluQuadricError(qobj
, GLU_INVALID_VALUE
);
194 /* Compute length (needed for normal calculations) */
195 deltaRadius
= baseRadius
- topRadius
;
196 length
= sqrtf(deltaRadius
*deltaRadius
+ height
*height
);
198 gluQuadricError(qobj
, GLU_INVALID_VALUE
);
202 /* Cache is the vertex locations cache */
203 /* Cache2 is the various normals at the vertices themselves */
204 /* Cache3 is the various normals for the faces */
205 needCache2
= needCache3
= 0;
206 if (qobj
->normals
== GLU_SMOOTH
) {
210 if (qobj
->normals
== GLU_FLAT
) {
211 if (qobj
->drawStyle
!= GLU_POINT
) {
214 if (qobj
->drawStyle
== GLU_LINE
) {
219 zNormal
= deltaRadius
/ length
;
220 xyNormalRatio
= height
/ length
;
222 for (i
= 0; i
< slices
; i
++) {
223 angle
= 2 * M_PI
* i
/ slices
;
225 if (qobj
->orientation
== GLU_OUTSIDE
) {
226 sinCache2
[i
] = xyNormalRatio
* sinf(angle
);
227 cosCache2
[i
] = xyNormalRatio
* cosf(angle
);
229 sinCache2
[i
] = -xyNormalRatio
* sinf(angle
);
230 cosCache2
[i
] = -xyNormalRatio
* cosf(angle
);
233 sinCache
[i
] = sinf(angle
);
234 cosCache
[i
] = cosf(angle
);
238 for (i
= 0; i
< slices
; i
++) {
239 angle
= 2 * M_PI
* (i
-0.5) / slices
;
240 if (qobj
->orientation
== GLU_OUTSIDE
) {
241 sinCache3
[i
] = xyNormalRatio
* sinf(angle
);
242 cosCache3
[i
] = xyNormalRatio
* cosf(angle
);
244 sinCache3
[i
] = -xyNormalRatio
* sinf(angle
);
245 cosCache3
[i
] = -xyNormalRatio
* cosf(angle
);
250 sinCache
[slices
] = sinCache
[0];
251 cosCache
[slices
] = cosCache
[0];
253 sinCache2
[slices
] = sinCache2
[0];
254 cosCache2
[slices
] = cosCache2
[0];
257 sinCache3
[slices
] = sinCache3
[0];
258 cosCache3
[slices
] = cosCache3
[0];
261 switch (qobj
->drawStyle
) {
264 ** An argument could be made for using a TRIANGLE_FAN for the end
265 ** of the cylinder of either radii is 0.0 (a cone). However, a
266 ** TRIANGLE_FAN would not work in smooth shading mode (the common
267 ** case) because the normal for the apex is different for every
268 ** triangle (and TRIANGLE_FAN doesn't let me respecify that normal).
269 ** Now, my choice is GL_TRIANGLES, or leave the GL_QUAD_STRIP and
270 ** just let the GL trivially reject one of the two triangles of the
271 ** QUAD. GL_QUAD_STRIP is probably faster, so I will leave this code
274 for (j
= 0; j
< stacks
; j
++) {
275 zLow
= j
* height
/ stacks
;
276 zHigh
= (j
+ 1) * height
/ stacks
;
277 radiusLow
= baseRadius
- deltaRadius
* ((float) j
/ stacks
);
278 radiusHigh
= baseRadius
- deltaRadius
* ((float) (j
+ 1) / stacks
);
280 glBegin(GL_QUAD_STRIP
);
281 for (i
= 0; i
<= slices
; i
++) {
282 switch(qobj
->normals
) {
284 glNormal3f(sinCache3
[i
], cosCache3
[i
], zNormal
);
287 glNormal3f(sinCache2
[i
], cosCache2
[i
], zNormal
);
293 if (qobj
->orientation
== GLU_OUTSIDE
) {
294 if (qobj
->textureCoords
) {
295 glTexCoord2f(1 - (float) i
/ slices
,
298 glVertex3f(radiusLow
* sinCache
[i
],
299 radiusLow
* cosCache
[i
], zLow
);
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
);
307 if (qobj
->textureCoords
) {
308 glTexCoord2f(1 - (float) i
/ slices
,
309 (float) (j
+1) / stacks
);
311 glVertex3f(radiusHigh
* sinCache
[i
],
312 radiusHigh
* cosCache
[i
], zHigh
);
313 if (qobj
->textureCoords
) {
314 glTexCoord2f(1 - (float) i
/ slices
,
317 glVertex3f(radiusLow
* sinCache
[i
],
318 radiusLow
* cosCache
[i
], zLow
);
326 for (i
= 0; i
< slices
; i
++) {
327 switch(qobj
->normals
) {
330 glNormal3f(sinCache2
[i
], cosCache2
[i
], zNormal
);
336 sintemp
= sinCache
[i
];
337 costemp
= cosCache
[i
];
338 for (j
= 0; j
<= stacks
; j
++) {
339 zLow
= j
* height
/ stacks
;
340 radiusLow
= baseRadius
- deltaRadius
* ((float) j
/ stacks
);
342 if (qobj
->textureCoords
) {
343 glTexCoord2f(1 - (float) i
/ slices
,
346 glVertex3f(radiusLow
* sintemp
,
347 radiusLow
* costemp
, zLow
);
353 for (j
= 1; j
< stacks
; j
++) {
354 zLow
= j
* height
/ stacks
;
355 radiusLow
= baseRadius
- deltaRadius
* ((float) j
/ stacks
);
357 glBegin(GL_LINE_STRIP
);
358 for (i
= 0; i
<= slices
; i
++) {
359 switch(qobj
->normals
) {
361 glNormal3f(sinCache3
[i
], cosCache3
[i
], zNormal
);
364 glNormal3f(sinCache2
[i
], cosCache2
[i
], zNormal
);
370 if (qobj
->textureCoords
) {
371 glTexCoord2f(1 - (float) i
/ slices
,
374 glVertex3f(radiusLow
* sinCache
[i
],
375 radiusLow
* cosCache
[i
], zLow
);
379 /* Intentionally fall through here... */
381 for (j
= 0; j
<= stacks
; j
+= stacks
) {
382 zLow
= j
* height
/ stacks
;
383 radiusLow
= baseRadius
- deltaRadius
* ((float) j
/ stacks
);
385 glBegin(GL_LINE_STRIP
);
386 for (i
= 0; i
<= slices
; i
++) {
387 switch(qobj
->normals
) {
389 glNormal3f(sinCache3
[i
], cosCache3
[i
], zNormal
);
392 glNormal3f(sinCache2
[i
], cosCache2
[i
], zNormal
);
398 if (qobj
->textureCoords
) {
399 glTexCoord2f(1 - (float) i
/ slices
,
402 glVertex3f(radiusLow
* sinCache
[i
], radiusLow
* cosCache
[i
],
407 for (i
= 0; i
< slices
; i
++) {
408 switch(qobj
->normals
) {
411 glNormal3f(sinCache2
[i
], cosCache2
[i
], 0.0);
417 sintemp
= sinCache
[i
];
418 costemp
= cosCache
[i
];
419 glBegin(GL_LINE_STRIP
);
420 for (j
= 0; j
<= stacks
; j
++) {
421 zLow
= j
* height
/ stacks
;
422 radiusLow
= baseRadius
- deltaRadius
* ((float) j
/ stacks
);
424 if (qobj
->textureCoords
) {
425 glTexCoord2f(1 - (float) i
/ slices
,
428 glVertex3f(radiusLow
* sintemp
,
429 radiusLow
* costemp
, zLow
);
439 /***********************************************************************
442 void WINAPI
gluDisk( GLUquadric
*qobj
, GLdouble innerRadius
, GLdouble outerRadius
,
443 GLint slices
, GLint loops
)
445 gluPartialDisk(qobj
, innerRadius
, outerRadius
, slices
, loops
, 0.0, 360.0);
448 /***********************************************************************
449 * gluPartialDisk (GLU32.@)
451 void WINAPI
gluPartialDisk( GLUquadric
*qobj
, GLdouble innerRadius
, GLdouble outerRadius
,
452 GLint slices
, GLint loops
, GLdouble startAngle
, GLdouble sweepAngle
)
455 GLfloat sinCache
[CACHE_SIZE
];
456 GLfloat cosCache
[CACHE_SIZE
];
458 GLfloat sintemp
, costemp
;
460 GLfloat radiusLow
, radiusHigh
;
461 GLfloat texLow
= 0.0, texHigh
= 0.0;
466 if (slices
>= CACHE_SIZE
) slices
= CACHE_SIZE
-1;
467 if (slices
< 2 || loops
< 1 || outerRadius
<= 0.0 || innerRadius
< 0.0 ||
468 innerRadius
> outerRadius
) {
469 gluQuadricError(qobj
, GLU_INVALID_VALUE
);
473 if (sweepAngle
< -360.0) sweepAngle
= 360.0;
474 if (sweepAngle
> 360.0) sweepAngle
= 360.0;
475 if (sweepAngle
< 0) {
476 startAngle
+= sweepAngle
;
477 sweepAngle
= -sweepAngle
;
480 if (sweepAngle
== 360.0) {
483 slices2
= slices
+ 1;
486 /* Compute length (needed for normal calculations) */
487 deltaRadius
= outerRadius
- innerRadius
;
489 /* Cache is the vertex locations cache */
491 angleOffset
= startAngle
/ 180.0 * M_PI
;
492 for (i
= 0; i
<= slices
; i
++) {
493 angle
= angleOffset
+ ((M_PI
* sweepAngle
) / 180.0) * i
/ slices
;
494 sinCache
[i
] = sinf(angle
);
495 cosCache
[i
] = cosf(angle
);
498 if (sweepAngle
== 360.0) {
499 sinCache
[slices
] = sinCache
[0];
500 cosCache
[slices
] = cosCache
[0];
503 switch(qobj
->normals
) {
506 if (qobj
->orientation
== GLU_OUTSIDE
) {
507 glNormal3f(0.0, 0.0, 1.0);
509 glNormal3f(0.0, 0.0, -1.0);
517 switch (qobj
->drawStyle
) {
519 if (innerRadius
== 0.0) {
521 /* Triangle strip for inner polygons */
522 glBegin(GL_TRIANGLE_FAN
);
523 if (qobj
->textureCoords
) {
524 glTexCoord2f(0.5, 0.5);
526 glVertex3f(0.0, 0.0, 0.0);
527 radiusLow
= outerRadius
-
528 deltaRadius
* ((float) (loops
-1) / loops
);
529 if (qobj
->textureCoords
) {
530 texLow
= radiusLow
/ outerRadius
/ 2;
533 if (qobj
->orientation
== GLU_OUTSIDE
) {
534 for (i
= slices
; i
>= 0; i
--) {
535 if (qobj
->textureCoords
) {
536 glTexCoord2f(texLow
* sinCache
[i
] + 0.5,
537 texLow
* cosCache
[i
] + 0.5);
539 glVertex3f(radiusLow
* sinCache
[i
],
540 radiusLow
* cosCache
[i
], 0.0);
543 for (i
= 0; i
<= slices
; i
++) {
544 if (qobj
->textureCoords
) {
545 glTexCoord2f(texLow
* sinCache
[i
] + 0.5,
546 texLow
* cosCache
[i
] + 0.5);
548 glVertex3f(radiusLow
* sinCache
[i
],
549 radiusLow
* cosCache
[i
], 0.0);
556 for (j
= 0; j
< finish
; j
++) {
557 radiusLow
= outerRadius
- deltaRadius
* ((float) j
/ loops
);
558 radiusHigh
= outerRadius
- deltaRadius
* ((float) (j
+ 1) / loops
);
559 if (qobj
->textureCoords
) {
560 texLow
= radiusLow
/ outerRadius
/ 2;
561 texHigh
= radiusHigh
/ outerRadius
/ 2;
564 glBegin(GL_QUAD_STRIP
);
565 for (i
= 0; i
<= slices
; i
++) {
566 if (qobj
->orientation
== GLU_OUTSIDE
) {
567 if (qobj
->textureCoords
) {
568 glTexCoord2f(texLow
* sinCache
[i
] + 0.5,
569 texLow
* cosCache
[i
] + 0.5);
571 glVertex3f(radiusLow
* sinCache
[i
],
572 radiusLow
* cosCache
[i
], 0.0);
574 if (qobj
->textureCoords
) {
575 glTexCoord2f(texHigh
* sinCache
[i
] + 0.5,
576 texHigh
* cosCache
[i
] + 0.5);
578 glVertex3f(radiusHigh
* sinCache
[i
],
579 radiusHigh
* cosCache
[i
], 0.0);
581 if (qobj
->textureCoords
) {
582 glTexCoord2f(texHigh
* sinCache
[i
] + 0.5,
583 texHigh
* cosCache
[i
] + 0.5);
585 glVertex3f(radiusHigh
* sinCache
[i
],
586 radiusHigh
* cosCache
[i
], 0.0);
588 if (qobj
->textureCoords
) {
589 glTexCoord2f(texLow
* sinCache
[i
] + 0.5,
590 texLow
* cosCache
[i
] + 0.5);
592 glVertex3f(radiusLow
* sinCache
[i
],
593 radiusLow
* cosCache
[i
], 0.0);
601 for (i
= 0; i
< slices2
; i
++) {
602 sintemp
= sinCache
[i
];
603 costemp
= cosCache
[i
];
604 for (j
= 0; j
<= loops
; j
++) {
605 radiusLow
= outerRadius
- deltaRadius
* ((float) j
/ loops
);
607 if (qobj
->textureCoords
) {
608 texLow
= radiusLow
/ outerRadius
/ 2;
610 glTexCoord2f(texLow
* sinCache
[i
] + 0.5,
611 texLow
* cosCache
[i
] + 0.5);
613 glVertex3f(radiusLow
* sintemp
, radiusLow
* costemp
, 0.0);
619 if (innerRadius
== outerRadius
) {
620 glBegin(GL_LINE_STRIP
);
622 for (i
= 0; i
<= slices
; i
++) {
623 if (qobj
->textureCoords
) {
624 glTexCoord2f(sinCache
[i
] / 2 + 0.5,
625 cosCache
[i
] / 2 + 0.5);
627 glVertex3f(innerRadius
* sinCache
[i
],
628 innerRadius
* cosCache
[i
], 0.0);
633 for (j
= 0; j
<= loops
; j
++) {
634 radiusLow
= outerRadius
- deltaRadius
* ((float) j
/ loops
);
635 if (qobj
->textureCoords
) {
636 texLow
= radiusLow
/ outerRadius
/ 2;
639 glBegin(GL_LINE_STRIP
);
640 for (i
= 0; i
<= slices
; i
++) {
641 if (qobj
->textureCoords
) {
642 glTexCoord2f(texLow
* sinCache
[i
] + 0.5,
643 texLow
* cosCache
[i
] + 0.5);
645 glVertex3f(radiusLow
* sinCache
[i
],
646 radiusLow
* cosCache
[i
], 0.0);
650 for (i
=0; i
< slices2
; i
++) {
651 sintemp
= sinCache
[i
];
652 costemp
= cosCache
[i
];
653 glBegin(GL_LINE_STRIP
);
654 for (j
= 0; j
<= loops
; j
++) {
655 radiusLow
= outerRadius
- deltaRadius
* ((float) j
/ loops
);
656 if (qobj
->textureCoords
) {
657 texLow
= radiusLow
/ outerRadius
/ 2;
660 if (qobj
->textureCoords
) {
661 glTexCoord2f(texLow
* sinCache
[i
] + 0.5,
662 texLow
* cosCache
[i
] + 0.5);
664 glVertex3f(radiusLow
* sintemp
, radiusLow
* costemp
, 0.0);
670 if (sweepAngle
< 360.0) {
671 for (i
= 0; i
<= slices
; i
+= slices
) {
672 sintemp
= sinCache
[i
];
673 costemp
= cosCache
[i
];
674 glBegin(GL_LINE_STRIP
);
675 for (j
= 0; j
<= loops
; j
++) {
676 radiusLow
= outerRadius
- deltaRadius
* ((float) j
/ loops
);
678 if (qobj
->textureCoords
) {
679 texLow
= radiusLow
/ outerRadius
/ 2;
680 glTexCoord2f(texLow
* sinCache
[i
] + 0.5,
681 texLow
* cosCache
[i
] + 0.5);
683 glVertex3f(radiusLow
* sintemp
, radiusLow
* costemp
, 0.0);
688 for (j
= 0; j
<= loops
; j
+= loops
) {
689 radiusLow
= outerRadius
- deltaRadius
* ((float) j
/ loops
);
690 if (qobj
->textureCoords
) {
691 texLow
= radiusLow
/ outerRadius
/ 2;
694 glBegin(GL_LINE_STRIP
);
695 for (i
= 0; i
<= slices
; i
++) {
696 if (qobj
->textureCoords
) {
697 glTexCoord2f(texLow
* sinCache
[i
] + 0.5,
698 texLow
* cosCache
[i
] + 0.5);
700 glVertex3f(radiusLow
* sinCache
[i
],
701 radiusLow
* cosCache
[i
], 0.0);
704 if (innerRadius
== outerRadius
) break;
712 /***********************************************************************
713 * gluSphere (GLU32.@)
715 void WINAPI
gluSphere( GLUquadric
*qobj
, GLdouble radius
, GLint slices
, GLint stacks
)
718 GLfloat sinCache1a
[CACHE_SIZE
];
719 GLfloat cosCache1a
[CACHE_SIZE
];
720 GLfloat sinCache2a
[CACHE_SIZE
];
721 GLfloat cosCache2a
[CACHE_SIZE
];
722 GLfloat sinCache3a
[CACHE_SIZE
];
723 GLfloat cosCache3a
[CACHE_SIZE
];
724 GLfloat sinCache1b
[CACHE_SIZE
];
725 GLfloat cosCache1b
[CACHE_SIZE
];
726 GLfloat sinCache2b
[CACHE_SIZE
];
727 GLfloat cosCache2b
[CACHE_SIZE
];
728 GLfloat sinCache3b
[CACHE_SIZE
];
729 GLfloat cosCache3b
[CACHE_SIZE
];
732 GLfloat sintemp1
= 0.0, sintemp2
= 0.0, sintemp3
= 0.0, sintemp4
= 0.0;
733 GLfloat costemp1
= 0.0, costemp2
= 0.0, costemp3
= 0.0, costemp4
= 0.0;
734 GLboolean needCache2
, needCache3
;
737 if (slices
>= CACHE_SIZE
) slices
= CACHE_SIZE
-1;
738 if (stacks
>= CACHE_SIZE
) stacks
= CACHE_SIZE
-1;
739 if (slices
< 2 || stacks
< 1 || radius
< 0.0) {
740 gluQuadricError(qobj
, GLU_INVALID_VALUE
);
744 /* Cache is the vertex locations cache */
745 /* Cache2 is the various normals at the vertices themselves */
746 /* Cache3 is the various normals for the faces */
747 needCache2
= needCache3
= GL_FALSE
;
749 if (qobj
->normals
== GLU_SMOOTH
) {
750 needCache2
= GL_TRUE
;
753 if (qobj
->normals
== GLU_FLAT
) {
754 if (qobj
->drawStyle
!= GLU_POINT
) {
755 needCache3
= GL_TRUE
;
757 if (qobj
->drawStyle
== GLU_LINE
) {
758 needCache2
= GL_TRUE
;
762 for (i
= 0; i
< slices
; i
++) {
763 angle
= 2 * M_PI
* i
/ slices
;
764 sinCache1a
[i
] = sinf(angle
);
765 cosCache1a
[i
] = cosf(angle
);
767 sinCache2a
[i
] = sinCache1a
[i
];
768 cosCache2a
[i
] = cosCache1a
[i
];
772 for (j
= 0; j
<= stacks
; j
++) {
773 angle
= M_PI
* j
/ stacks
;
775 if (qobj
->orientation
== GLU_OUTSIDE
) {
776 sinCache2b
[j
] = sinf(angle
);
777 cosCache2b
[j
] = cosf(angle
);
779 sinCache2b
[j
] = -sinf(angle
);
780 cosCache2b
[j
] = -cosf(angle
);
783 sinCache1b
[j
] = radius
* sinf(angle
);
784 cosCache1b
[j
] = radius
* cosf(angle
);
786 /* Make sure it comes to a point */
788 sinCache1b
[stacks
] = 0;
791 for (i
= 0; i
< slices
; i
++) {
792 angle
= 2 * M_PI
* (i
-0.5) / slices
;
793 sinCache3a
[i
] = sinf(angle
);
794 cosCache3a
[i
] = cosf(angle
);
796 for (j
= 0; j
<= stacks
; j
++) {
797 angle
= M_PI
* (j
- 0.5) / stacks
;
798 if (qobj
->orientation
== GLU_OUTSIDE
) {
799 sinCache3b
[j
] = sinf(angle
);
800 cosCache3b
[j
] = cosf(angle
);
802 sinCache3b
[j
] = -sinf(angle
);
803 cosCache3b
[j
] = -cosf(angle
);
808 sinCache1a
[slices
] = sinCache1a
[0];
809 cosCache1a
[slices
] = cosCache1a
[0];
811 sinCache2a
[slices
] = sinCache2a
[0];
812 cosCache2a
[slices
] = cosCache2a
[0];
815 sinCache3a
[slices
] = sinCache3a
[0];
816 cosCache3a
[slices
] = cosCache3a
[0];
819 switch (qobj
->drawStyle
) {
821 /* Do ends of sphere as TRIANGLE_FAN's (if not texturing)
822 ** We don't do it when texturing because we need to respecify the
823 ** texture coordinates of the apex for every adjacent vertex (because
824 ** it isn't a constant for that point)
826 if (!(qobj
->textureCoords
)) {
830 /* Low end first (j == 0 iteration) */
831 sintemp2
= sinCache1b
[1];
832 zHigh
= cosCache1b
[1];
833 switch(qobj
->normals
) {
835 sintemp3
= sinCache3b
[1];
836 costemp3
= cosCache3b
[1];
839 sintemp3
= sinCache2b
[1];
840 costemp3
= cosCache2b
[1];
841 glNormal3f(sinCache2a
[0] * sinCache2b
[0],
842 cosCache2a
[0] * sinCache2b
[0],
848 glBegin(GL_TRIANGLE_FAN
);
849 glVertex3f(0.0, 0.0, radius
);
850 if (qobj
->orientation
== GLU_OUTSIDE
) {
851 for (i
= slices
; i
>= 0; i
--) {
852 switch(qobj
->normals
) {
854 glNormal3f(sinCache2a
[i
] * sintemp3
,
855 cosCache2a
[i
] * sintemp3
,
860 glNormal3f(sinCache3a
[i
+1] * sintemp3
,
861 cosCache3a
[i
+1] * sintemp3
,
869 glVertex3f(sintemp2
* sinCache1a
[i
],
870 sintemp2
* cosCache1a
[i
], zHigh
);
873 for (i
= 0; i
<= slices
; i
++) {
874 switch(qobj
->normals
) {
876 glNormal3f(sinCache2a
[i
] * sintemp3
,
877 cosCache2a
[i
] * sintemp3
,
881 glNormal3f(sinCache3a
[i
] * sintemp3
,
882 cosCache3a
[i
] * sintemp3
,
889 glVertex3f(sintemp2
* sinCache1a
[i
],
890 sintemp2
* cosCache1a
[i
], zHigh
);
895 /* High end next (j == stacks-1 iteration) */
896 sintemp2
= sinCache1b
[stacks
-1];
897 zHigh
= cosCache1b
[stacks
-1];
898 switch(qobj
->normals
) {
900 sintemp3
= sinCache3b
[stacks
];
901 costemp3
= cosCache3b
[stacks
];
904 sintemp3
= sinCache2b
[stacks
-1];
905 costemp3
= cosCache2b
[stacks
-1];
906 glNormal3f(sinCache2a
[stacks
] * sinCache2b
[stacks
],
907 cosCache2a
[stacks
] * sinCache2b
[stacks
],
913 glBegin(GL_TRIANGLE_FAN
);
914 glVertex3f(0.0, 0.0, -radius
);
915 if (qobj
->orientation
== GLU_OUTSIDE
) {
916 for (i
= 0; i
<= slices
; i
++) {
917 switch(qobj
->normals
) {
919 glNormal3f(sinCache2a
[i
] * sintemp3
,
920 cosCache2a
[i
] * sintemp3
,
924 glNormal3f(sinCache3a
[i
] * sintemp3
,
925 cosCache3a
[i
] * sintemp3
,
932 glVertex3f(sintemp2
* sinCache1a
[i
],
933 sintemp2
* cosCache1a
[i
], zHigh
);
936 for (i
= slices
; i
>= 0; i
--) {
937 switch(qobj
->normals
) {
939 glNormal3f(sinCache2a
[i
] * sintemp3
,
940 cosCache2a
[i
] * sintemp3
,
945 glNormal3f(sinCache3a
[i
+1] * sintemp3
,
946 cosCache3a
[i
+1] * sintemp3
,
954 glVertex3f(sintemp2
* sinCache1a
[i
],
955 sintemp2
* cosCache1a
[i
], zHigh
);
963 for (j
= start
; j
< finish
; j
++) {
964 zLow
= cosCache1b
[j
];
965 zHigh
= cosCache1b
[j
+1];
966 sintemp1
= sinCache1b
[j
];
967 sintemp2
= sinCache1b
[j
+1];
968 switch(qobj
->normals
) {
970 sintemp4
= sinCache3b
[j
+1];
971 costemp4
= cosCache3b
[j
+1];
974 if (qobj
->orientation
== GLU_OUTSIDE
) {
975 sintemp3
= sinCache2b
[j
+1];
976 costemp3
= cosCache2b
[j
+1];
977 sintemp4
= sinCache2b
[j
];
978 costemp4
= cosCache2b
[j
];
980 sintemp3
= sinCache2b
[j
];
981 costemp3
= cosCache2b
[j
];
982 sintemp4
= sinCache2b
[j
+1];
983 costemp4
= cosCache2b
[j
+1];
990 glBegin(GL_QUAD_STRIP
);
991 for (i
= 0; i
<= slices
; i
++) {
992 switch(qobj
->normals
) {
994 glNormal3f(sinCache2a
[i
] * sintemp3
,
995 cosCache2a
[i
] * sintemp3
,
1003 if (qobj
->orientation
== GLU_OUTSIDE
) {
1004 if (qobj
->textureCoords
) {
1005 glTexCoord2f(1 - (float) i
/ slices
,
1006 1 - (float) (j
+1) / stacks
);
1008 glVertex3f(sintemp2
* sinCache1a
[i
],
1009 sintemp2
* cosCache1a
[i
], zHigh
);
1011 if (qobj
->textureCoords
) {
1012 glTexCoord2f(1 - (float) i
/ slices
,
1013 1 - (float) j
/ stacks
);
1015 glVertex3f(sintemp1
* sinCache1a
[i
],
1016 sintemp1
* cosCache1a
[i
], zLow
);
1018 switch(qobj
->normals
) {
1020 glNormal3f(sinCache2a
[i
] * sintemp4
,
1021 cosCache2a
[i
] * sintemp4
,
1025 glNormal3f(sinCache3a
[i
] * sintemp4
,
1026 cosCache3a
[i
] * sintemp4
,
1033 if (qobj
->orientation
== GLU_OUTSIDE
) {
1034 if (qobj
->textureCoords
) {
1035 glTexCoord2f(1 - (float) i
/ slices
,
1036 1 - (float) j
/ stacks
);
1038 glVertex3f(sintemp1
* sinCache1a
[i
],
1039 sintemp1
* cosCache1a
[i
], zLow
);
1041 if (qobj
->textureCoords
) {
1042 glTexCoord2f(1 - (float) i
/ slices
,
1043 1 - (float) (j
+1) / stacks
);
1045 glVertex3f(sintemp2
* sinCache1a
[i
],
1046 sintemp2
* cosCache1a
[i
], zHigh
);
1054 for (j
= 0; j
<= stacks
; j
++) {
1055 sintemp1
= sinCache1b
[j
];
1056 costemp1
= cosCache1b
[j
];
1057 switch(qobj
->normals
) {
1060 sintemp2
= sinCache2b
[j
];
1061 costemp2
= cosCache2b
[j
];
1066 for (i
= 0; i
< slices
; i
++) {
1067 switch(qobj
->normals
) {
1070 glNormal3f(sinCache2a
[i
] * sintemp2
,
1071 cosCache2a
[i
] * sintemp2
,
1079 zLow
= j
* radius
/ stacks
;
1081 if (qobj
->textureCoords
) {
1082 glTexCoord2f(1 - (float) i
/ slices
,
1083 1 - (float) j
/ stacks
);
1085 glVertex3f(sintemp1
* sinCache1a
[i
],
1086 sintemp1
* cosCache1a
[i
], costemp1
);
1092 case GLU_SILHOUETTE
:
1093 for (j
= 1; j
< stacks
; j
++) {
1094 sintemp1
= sinCache1b
[j
];
1095 costemp1
= cosCache1b
[j
];
1096 switch(qobj
->normals
) {
1099 sintemp2
= sinCache2b
[j
];
1100 costemp2
= cosCache2b
[j
];
1106 glBegin(GL_LINE_STRIP
);
1107 for (i
= 0; i
<= slices
; i
++) {
1108 switch(qobj
->normals
) {
1110 glNormal3f(sinCache3a
[i
] * sintemp2
,
1111 cosCache3a
[i
] * sintemp2
,
1115 glNormal3f(sinCache2a
[i
] * sintemp2
,
1116 cosCache2a
[i
] * sintemp2
,
1123 if (qobj
->textureCoords
) {
1124 glTexCoord2f(1 - (float) i
/ slices
,
1125 1 - (float) j
/ stacks
);
1127 glVertex3f(sintemp1
* sinCache1a
[i
],
1128 sintemp1
* cosCache1a
[i
], costemp1
);
1132 for (i
= 0; i
< slices
; i
++) {
1133 sintemp1
= sinCache1a
[i
];
1134 costemp1
= cosCache1a
[i
];
1135 switch(qobj
->normals
) {
1138 sintemp2
= sinCache2a
[i
];
1139 costemp2
= cosCache2a
[i
];
1145 glBegin(GL_LINE_STRIP
);
1146 for (j
= 0; j
<= stacks
; j
++) {
1147 switch(qobj
->normals
) {
1149 glNormal3f(sintemp2
* sinCache3b
[j
],
1150 costemp2
* sinCache3b
[j
],
1154 glNormal3f(sintemp2
* sinCache2b
[j
],
1155 costemp2
* sinCache2b
[j
],
1163 if (qobj
->textureCoords
) {
1164 glTexCoord2f(1 - (float) i
/ slices
,
1165 1 - (float) j
/ stacks
);
1167 glVertex3f(sintemp1
* sinCache1b
[j
],
1168 costemp1
* sinCache1b
[j
], cosCache1b
[j
]);