d3d10/effect: Add a helper to read raw variable values.
[wine.git] / dlls / glu32 / quad.c
blob9ffaa6bd4de3c2eddf714d8865b18d850533bf62
1 /*
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
23 * SOFTWARE.
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.
31 #include <stdarg.h>
32 #include <math.h>
34 #include "windef.h"
35 #include "winbase.h"
36 #include "wine/wgl.h"
37 #include "wine/glu.h"
39 /* Make it not a power of two to avoid cache thrashing on the chip */
40 #define CACHE_SIZE 240
42 struct GLUquadric {
43 GLint normals;
44 GLboolean textureCoords;
45 GLint orientation;
46 GLint drawStyle;
47 void (GLAPIENTRY *errorCallback)( GLint );
50 /***********************************************************************
51 * gluNewQuadric (GLU32.@)
53 GLUquadric * WINAPI gluNewQuadric(void)
55 GLUquadric *newstate;
57 newstate = HeapAlloc(GetProcessHeap(), 0, sizeof(GLUquadric));
58 if (newstate == NULL) {
59 /* Can't report an error at this point... */
60 return NULL;
62 newstate->normals = GLU_SMOOTH;
63 newstate->textureCoords = GL_FALSE;
64 newstate->orientation = GLU_OUTSIDE;
65 newstate->drawStyle = GLU_FILL;
66 newstate->errorCallback = NULL;
67 return newstate;
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) )
91 switch (which) {
92 case GLU_ERROR:
93 qobj->errorCallback = (void (GLAPIENTRY *)(GLint)) fn;
94 break;
95 default:
96 gluQuadricError(qobj, GLU_INVALID_ENUM);
97 return;
101 /***********************************************************************
102 * gluQuadricNormals (GLU32.@)
104 void WINAPI gluQuadricNormals( GLUquadric *qobj, GLenum normals )
106 switch (normals) {
107 case GLU_SMOOTH:
108 case GLU_FLAT:
109 case GLU_NONE:
110 break;
111 default:
112 gluQuadricError(qobj, GLU_INVALID_ENUM);
113 return;
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) {
132 case GLU_OUTSIDE:
133 case GLU_INSIDE:
134 break;
135 default:
136 gluQuadricError(qobj, GLU_INVALID_ENUM);
137 return;
139 qobj->orientation = orientation;
142 /***********************************************************************
143 * gluQuadricDrawStyle (GLU32.@)
145 void WINAPI gluQuadricDrawStyle( GLUquadric *qobj, GLenum drawStyle )
147 switch(drawStyle) {
148 case GLU_POINT:
149 case GLU_LINE:
150 case GLU_FILL:
151 case GLU_SILHOUETTE:
152 break;
153 default:
154 gluQuadricError(qobj, GLU_INVALID_ENUM);
155 return;
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 )
166 GLint i,j;
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];
173 GLfloat angle;
174 GLfloat zLow, zHigh;
175 GLfloat sintemp, costemp;
176 GLfloat length;
177 GLfloat deltaRadius;
178 GLfloat zNormal;
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 ||
186 height < 0.0) {
187 gluQuadricError(qobj, GLU_INVALID_VALUE);
188 return;
191 /* Compute length (needed for normal calculations) */
192 deltaRadius = baseRadius - topRadius;
193 length = sqrtf(deltaRadius*deltaRadius + height*height);
194 if (length == 0.0) {
195 gluQuadricError(qobj, GLU_INVALID_VALUE);
196 return;
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) {
204 needCache2 = 1;
207 if (qobj->normals == GLU_FLAT) {
208 if (qobj->drawStyle != GLU_POINT) {
209 needCache3 = 1;
211 if (qobj->drawStyle == GLU_LINE) {
212 needCache2 = 1;
216 zNormal = deltaRadius / length;
217 xyNormalRatio = height / length;
219 for (i = 0; i < slices; i++) {
220 angle = 2 * M_PI * i / slices;
221 if (needCache2) {
222 if (qobj->orientation == GLU_OUTSIDE) {
223 sinCache2[i] = xyNormalRatio * sinf(angle);
224 cosCache2[i] = xyNormalRatio * cosf(angle);
225 } else {
226 sinCache2[i] = -xyNormalRatio * sinf(angle);
227 cosCache2[i] = -xyNormalRatio * cosf(angle);
230 sinCache[i] = sinf(angle);
231 cosCache[i] = cosf(angle);
234 if (needCache3) {
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);
240 } else {
241 sinCache3[i] = -xyNormalRatio * sinf(angle);
242 cosCache3[i] = -xyNormalRatio * cosf(angle);
247 sinCache[slices] = sinCache[0];
248 cosCache[slices] = cosCache[0];
249 if (needCache2) {
250 sinCache2[slices] = sinCache2[0];
251 cosCache2[slices] = cosCache2[0];
253 if (needCache3) {
254 sinCache3[slices] = sinCache3[0];
255 cosCache3[slices] = cosCache3[0];
258 switch (qobj->drawStyle) {
259 case GLU_FILL:
260 /* Note:
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
269 ** alone.
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) {
280 case GLU_FLAT:
281 glNormal3f(sinCache3[i], cosCache3[i], zNormal);
282 break;
283 case GLU_SMOOTH:
284 glNormal3f(sinCache2[i], cosCache2[i], zNormal);
285 break;
286 case GLU_NONE:
287 default:
288 break;
290 if (qobj->orientation == GLU_OUTSIDE) {
291 if (qobj->textureCoords) {
292 glTexCoord2f(1 - (float) i / slices,
293 (float) j / stacks);
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);
303 } else {
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,
312 (float) j / stacks);
314 glVertex3f(radiusLow * sinCache[i],
315 radiusLow * cosCache[i], zLow);
318 glEnd();
320 break;
321 case GLU_POINT:
322 glBegin(GL_POINTS);
323 for (i = 0; i < slices; i++) {
324 switch(qobj->normals) {
325 case GLU_FLAT:
326 case GLU_SMOOTH:
327 glNormal3f(sinCache2[i], cosCache2[i], zNormal);
328 break;
329 case GLU_NONE:
330 default:
331 break;
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,
341 (float) j / stacks);
343 glVertex3f(radiusLow * sintemp,
344 radiusLow * costemp, zLow);
347 glEnd();
348 break;
349 case GLU_LINE:
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) {
357 case GLU_FLAT:
358 glNormal3f(sinCache3[i], cosCache3[i], zNormal);
359 break;
360 case GLU_SMOOTH:
361 glNormal3f(sinCache2[i], cosCache2[i], zNormal);
362 break;
363 case GLU_NONE:
364 default:
365 break;
367 if (qobj->textureCoords) {
368 glTexCoord2f(1 - (float) i / slices,
369 (float) j / stacks);
371 glVertex3f(radiusLow * sinCache[i],
372 radiusLow * cosCache[i], zLow);
374 glEnd();
376 /* Intentionally fall through here... */
377 case GLU_SILHOUETTE:
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) {
385 case GLU_FLAT:
386 glNormal3f(sinCache3[i], cosCache3[i], zNormal);
387 break;
388 case GLU_SMOOTH:
389 glNormal3f(sinCache2[i], cosCache2[i], zNormal);
390 break;
391 case GLU_NONE:
392 default:
393 break;
395 if (qobj->textureCoords) {
396 glTexCoord2f(1 - (float) i / slices,
397 (float) j / stacks);
399 glVertex3f(radiusLow * sinCache[i], radiusLow * cosCache[i],
400 zLow);
402 glEnd();
404 for (i = 0; i < slices; i++) {
405 switch(qobj->normals) {
406 case GLU_FLAT:
407 case GLU_SMOOTH:
408 glNormal3f(sinCache2[i], cosCache2[i], 0.0);
409 break;
410 case GLU_NONE:
411 default:
412 break;
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,
423 (float) j / stacks);
425 glVertex3f(radiusLow * sintemp,
426 radiusLow * costemp, zLow);
428 glEnd();
430 break;
431 default:
432 break;
436 /***********************************************************************
437 * gluDisk (GLU32.@)
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 )
451 GLint i,j;
452 GLfloat sinCache[CACHE_SIZE];
453 GLfloat cosCache[CACHE_SIZE];
454 GLfloat angle;
455 GLfloat sintemp, costemp;
456 GLfloat deltaRadius;
457 GLfloat radiusLow, radiusHigh;
458 GLfloat texLow = 0.0, texHigh = 0.0;
459 GLfloat angleOffset;
460 GLint slices2;
461 GLint finish;
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);
467 return;
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) {
478 slices2 = slices;
479 } else {
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) {
501 case GLU_FLAT:
502 case GLU_SMOOTH:
503 if (qobj->orientation == GLU_OUTSIDE) {
504 glNormal3f(0.0, 0.0, 1.0);
505 } else {
506 glNormal3f(0.0, 0.0, -1.0);
508 break;
509 default:
510 case GLU_NONE:
511 break;
514 switch (qobj->drawStyle) {
515 case GLU_FILL:
516 if (innerRadius == 0.0) {
517 finish = loops - 1;
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);
539 } else {
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);
549 glEnd();
550 } else {
551 finish = loops;
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);
577 } else {
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);
593 glEnd();
595 break;
596 case GLU_POINT:
597 glBegin(GL_POINTS);
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);
613 glEnd();
614 break;
615 case GLU_LINE:
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);
627 glEnd();
628 break;
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);
645 glEnd();
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);
663 glEnd();
665 break;
666 case GLU_SILHOUETTE:
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);
682 glEnd();
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);
700 glEnd();
701 if (innerRadius == outerRadius) break;
703 break;
704 default:
705 break;
709 /***********************************************************************
710 * gluSphere (GLU32.@)
712 void WINAPI gluSphere( GLUquadric *qobj, GLdouble radius, GLint slices, GLint stacks )
714 GLint i,j;
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];
727 GLfloat angle;
728 GLfloat zLow, zHigh;
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;
732 GLint start, finish;
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);
738 return;
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);
763 if (needCache2) {
764 sinCache2a[i] = sinCache1a[i];
765 cosCache2a[i] = cosCache1a[i];
769 for (j = 0; j <= stacks; j++) {
770 angle = M_PI * j / stacks;
771 if (needCache2) {
772 if (qobj->orientation == GLU_OUTSIDE) {
773 sinCache2b[j] = sinf(angle);
774 cosCache2b[j] = cosf(angle);
775 } else {
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 */
784 sinCache1b[0] = 0;
785 sinCache1b[stacks] = 0;
787 if (needCache3) {
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);
798 } else {
799 sinCache3b[j] = -sinf(angle);
800 cosCache3b[j] = -cosf(angle);
805 sinCache1a[slices] = sinCache1a[0];
806 cosCache1a[slices] = cosCache1a[0];
807 if (needCache2) {
808 sinCache2a[slices] = sinCache2a[0];
809 cosCache2a[slices] = cosCache2a[0];
811 if (needCache3) {
812 sinCache3a[slices] = sinCache3a[0];
813 cosCache3a[slices] = cosCache3a[0];
816 switch (qobj->drawStyle) {
817 case GLU_FILL:
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)) {
824 start = 1;
825 finish = stacks - 1;
827 /* Low end first (j == 0 iteration) */
828 sintemp2 = sinCache1b[1];
829 zHigh = cosCache1b[1];
830 switch(qobj->normals) {
831 case GLU_FLAT:
832 sintemp3 = sinCache3b[1];
833 costemp3 = cosCache3b[1];
834 break;
835 case GLU_SMOOTH:
836 sintemp3 = sinCache2b[1];
837 costemp3 = cosCache2b[1];
838 glNormal3f(sinCache2a[0] * sinCache2b[0],
839 cosCache2a[0] * sinCache2b[0],
840 cosCache2b[0]);
841 break;
842 default:
843 break;
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) {
850 case GLU_SMOOTH:
851 glNormal3f(sinCache2a[i] * sintemp3,
852 cosCache2a[i] * sintemp3,
853 costemp3);
854 break;
855 case GLU_FLAT:
856 if (i != slices) {
857 glNormal3f(sinCache3a[i+1] * sintemp3,
858 cosCache3a[i+1] * sintemp3,
859 costemp3);
861 break;
862 case GLU_NONE:
863 default:
864 break;
866 glVertex3f(sintemp2 * sinCache1a[i],
867 sintemp2 * cosCache1a[i], zHigh);
869 } else {
870 for (i = 0; i <= slices; i++) {
871 switch(qobj->normals) {
872 case GLU_SMOOTH:
873 glNormal3f(sinCache2a[i] * sintemp3,
874 cosCache2a[i] * sintemp3,
875 costemp3);
876 break;
877 case GLU_FLAT:
878 glNormal3f(sinCache3a[i] * sintemp3,
879 cosCache3a[i] * sintemp3,
880 costemp3);
881 break;
882 case GLU_NONE:
883 default:
884 break;
886 glVertex3f(sintemp2 * sinCache1a[i],
887 sintemp2 * cosCache1a[i], zHigh);
890 glEnd();
892 /* High end next (j == stacks-1 iteration) */
893 sintemp2 = sinCache1b[stacks-1];
894 zHigh = cosCache1b[stacks-1];
895 switch(qobj->normals) {
896 case GLU_FLAT:
897 sintemp3 = sinCache3b[stacks];
898 costemp3 = cosCache3b[stacks];
899 break;
900 case GLU_SMOOTH:
901 sintemp3 = sinCache2b[stacks-1];
902 costemp3 = cosCache2b[stacks-1];
903 glNormal3f(sinCache2a[stacks] * sinCache2b[stacks],
904 cosCache2a[stacks] * sinCache2b[stacks],
905 cosCache2b[stacks]);
906 break;
907 default:
908 break;
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) {
915 case GLU_SMOOTH:
916 glNormal3f(sinCache2a[i] * sintemp3,
917 cosCache2a[i] * sintemp3,
918 costemp3);
919 break;
920 case GLU_FLAT:
921 glNormal3f(sinCache3a[i] * sintemp3,
922 cosCache3a[i] * sintemp3,
923 costemp3);
924 break;
925 case GLU_NONE:
926 default:
927 break;
929 glVertex3f(sintemp2 * sinCache1a[i],
930 sintemp2 * cosCache1a[i], zHigh);
932 } else {
933 for (i = slices; i >= 0; i--) {
934 switch(qobj->normals) {
935 case GLU_SMOOTH:
936 glNormal3f(sinCache2a[i] * sintemp3,
937 cosCache2a[i] * sintemp3,
938 costemp3);
939 break;
940 case GLU_FLAT:
941 if (i != slices) {
942 glNormal3f(sinCache3a[i+1] * sintemp3,
943 cosCache3a[i+1] * sintemp3,
944 costemp3);
946 break;
947 case GLU_NONE:
948 default:
949 break;
951 glVertex3f(sintemp2 * sinCache1a[i],
952 sintemp2 * cosCache1a[i], zHigh);
955 glEnd();
956 } else {
957 start = 0;
958 finish = stacks;
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) {
966 case GLU_FLAT:
967 sintemp4 = sinCache3b[j+1];
968 costemp4 = cosCache3b[j+1];
969 break;
970 case GLU_SMOOTH:
971 if (qobj->orientation == GLU_OUTSIDE) {
972 sintemp3 = sinCache2b[j+1];
973 costemp3 = cosCache2b[j+1];
974 sintemp4 = sinCache2b[j];
975 costemp4 = cosCache2b[j];
976 } else {
977 sintemp3 = sinCache2b[j];
978 costemp3 = cosCache2b[j];
979 sintemp4 = sinCache2b[j+1];
980 costemp4 = cosCache2b[j+1];
982 break;
983 default:
984 break;
987 glBegin(GL_QUAD_STRIP);
988 for (i = 0; i <= slices; i++) {
989 switch(qobj->normals) {
990 case GLU_SMOOTH:
991 glNormal3f(sinCache2a[i] * sintemp3,
992 cosCache2a[i] * sintemp3,
993 costemp3);
994 break;
995 case GLU_FLAT:
996 case GLU_NONE:
997 default:
998 break;
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);
1007 } else {
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) {
1016 case GLU_SMOOTH:
1017 glNormal3f(sinCache2a[i] * sintemp4,
1018 cosCache2a[i] * sintemp4,
1019 costemp4);
1020 break;
1021 case GLU_FLAT:
1022 glNormal3f(sinCache3a[i] * sintemp4,
1023 cosCache3a[i] * sintemp4,
1024 costemp4);
1025 break;
1026 case GLU_NONE:
1027 default:
1028 break;
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);
1037 } else {
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);
1046 glEnd();
1048 break;
1049 case GLU_POINT:
1050 glBegin(GL_POINTS);
1051 for (j = 0; j <= stacks; j++) {
1052 sintemp1 = sinCache1b[j];
1053 costemp1 = cosCache1b[j];
1054 switch(qobj->normals) {
1055 case GLU_FLAT:
1056 case GLU_SMOOTH:
1057 sintemp2 = sinCache2b[j];
1058 costemp2 = cosCache2b[j];
1059 break;
1060 default:
1061 break;
1063 for (i = 0; i < slices; i++) {
1064 switch(qobj->normals) {
1065 case GLU_FLAT:
1066 case GLU_SMOOTH:
1067 glNormal3f(sinCache2a[i] * sintemp2,
1068 cosCache2a[i] * sintemp2,
1069 costemp2);
1070 break;
1071 case GLU_NONE:
1072 default:
1073 break;
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);
1086 glEnd();
1087 break;
1088 case GLU_LINE:
1089 case GLU_SILHOUETTE:
1090 for (j = 1; j < stacks; j++) {
1091 sintemp1 = sinCache1b[j];
1092 costemp1 = cosCache1b[j];
1093 switch(qobj->normals) {
1094 case GLU_FLAT:
1095 case GLU_SMOOTH:
1096 sintemp2 = sinCache2b[j];
1097 costemp2 = cosCache2b[j];
1098 break;
1099 default:
1100 break;
1103 glBegin(GL_LINE_STRIP);
1104 for (i = 0; i <= slices; i++) {
1105 switch(qobj->normals) {
1106 case GLU_FLAT:
1107 glNormal3f(sinCache3a[i] * sintemp2,
1108 cosCache3a[i] * sintemp2,
1109 costemp2);
1110 break;
1111 case GLU_SMOOTH:
1112 glNormal3f(sinCache2a[i] * sintemp2,
1113 cosCache2a[i] * sintemp2,
1114 costemp2);
1115 break;
1116 case GLU_NONE:
1117 default:
1118 break;
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);
1127 glEnd();
1129 for (i = 0; i < slices; i++) {
1130 sintemp1 = sinCache1a[i];
1131 costemp1 = cosCache1a[i];
1132 switch(qobj->normals) {
1133 case GLU_FLAT:
1134 case GLU_SMOOTH:
1135 sintemp2 = sinCache2a[i];
1136 costemp2 = cosCache2a[i];
1137 break;
1138 default:
1139 break;
1142 glBegin(GL_LINE_STRIP);
1143 for (j = 0; j <= stacks; j++) {
1144 switch(qobj->normals) {
1145 case GLU_FLAT:
1146 glNormal3f(sintemp2 * sinCache3b[j],
1147 costemp2 * sinCache3b[j],
1148 cosCache3b[j]);
1149 break;
1150 case GLU_SMOOTH:
1151 glNormal3f(sintemp2 * sinCache2b[j],
1152 costemp2 * sinCache2b[j],
1153 cosCache2b[j]);
1154 break;
1155 case GLU_NONE:
1156 default:
1157 break;
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]);
1167 glEnd();
1169 break;
1170 default:
1171 break;