source: trunk/src/opengl/glu/util/quad.c

Last change on this file was 3079, checked in by jeroen, 25 years ago

* empty log message *

File size: 39.0 KB
Line 
1/* $Id: quad.c,v 1.2 2000-03-11 09:05:04 jeroen Exp $ */
2/*
3** License Applicability. Except to the extent portions of this file are
4** made subject to an alternative license as permitted in the SGI Free
5** Software License B, Version 1.0 (the "License"), the contents of this
6** file are subject only to the provisions of the License. You may not use
7** this file except in compliance with the License. You may obtain a copy
8** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
9** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
10**
11** http://oss.sgi.com/projects/FreeB
12**
13** Note that, as provided in the License, the Software is distributed on an
14** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
15** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
16** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
17** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
18**
19** Original Code. The Original Code is: OpenGL Sample Implementation,
20** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
21** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
22** Copyright in any portions created by third parties is as indicated
23** elsewhere herein. All Rights Reserved.
24**
25** Additional Notice Provisions: The application programming interfaces
26** established by SGI in conjunction with the Original Code are The
27** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
28** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
29** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
30** Window System(R) (Version 1.3), released October 19, 1998. This software
31** was created using the OpenGL(R) version 1.2.1 Sample Implementation
32** published by SGI, but has not been independently verified as being
33** compliant with the OpenGL(R) version 1.2.1 Specification.
34**
35** $Date: 2000-03-11 09:05:04 $ $Revision: 1.2 $
36** $Header: /home/ktk/tmp/odin/2007/netlabs.cvs/odin32/src/opengl/glu/util/quad.c,v 1.2 2000-03-11 09:05:04 jeroen Exp $
37*/
38
39#include "gluos.h"
40#include "gluint.h"
41#include <stdio.h>
42#include <stdlib.h>
43#include <math.h>
44#include "gl.h"
45#include "glu.h"
46
47/* Make it not a power of two to avoid cache thrashing on the chip */
48#define CACHE_SIZE 240
49
50#define PI 3.14159265358979323846
51
52struct GLUquadric {
53 GLint normals;
54 GLboolean textureCoords;
55 GLint orientation;
56 GLint drawStyle;
57 void (GLCALLBACK *errorCallback)( GLint );
58};
59
60GLUquadric * GLAPI
61gluNewQuadric(void)
62{
63 GLUquadric *newstate;
64
65 newstate = (GLUquadric *) malloc(sizeof(GLUquadric));
66 if (newstate == NULL) {
67 /* Can't report an error at this point... */
68 return NULL;
69 }
70 newstate->normals = GLU_SMOOTH;
71 newstate->textureCoords = GL_FALSE;
72 newstate->orientation = GLU_OUTSIDE;
73 newstate->drawStyle = GLU_FILL;
74 newstate->errorCallback = NULL;
75 return newstate;
76}
77
78
79void GLAPI
80gluDeleteQuadric(GLUquadric *state)
81{
82 free(state);
83}
84
85static void gluQuadricError(GLUquadric *qobj, GLenum which)
86{
87 if (qobj->errorCallback) {
88 qobj->errorCallback(which);
89 }
90}
91
92void GLAPI
93gluQuadricCallback(GLUquadric *qobj, GLenum which, void (GLCALLBACK *fn)())
94{
95 switch (which) {
96 case GLU_ERROR:
97 qobj->errorCallback = (void (GLCALLBACK *)(GLint)) fn;
98 break;
99 default:
100 gluQuadricError(qobj, GLU_INVALID_ENUM);
101 return;
102 }
103}
104
105void GLAPI
106gluQuadricNormals(GLUquadric *qobj, GLenum normals)
107{
108 switch (normals) {
109 case GLU_SMOOTH:
110 case GLU_FLAT:
111 case GLU_NONE:
112 break;
113 default:
114 gluQuadricError(qobj, GLU_INVALID_ENUM);
115 return;
116 }
117 qobj->normals = normals;
118}
119
120void GLAPI
121gluQuadricTexture(GLUquadric *qobj, GLboolean textureCoords)
122{
123 qobj->textureCoords = textureCoords;
124}
125
126void GLAPI
127gluQuadricOrientation(GLUquadric *qobj, GLenum orientation)
128{
129 switch(orientation) {
130 case GLU_OUTSIDE:
131 case GLU_INSIDE:
132 break;
133 default:
134 gluQuadricError(qobj, GLU_INVALID_ENUM);
135 return;
136 }
137 qobj->orientation = orientation;
138}
139
140void GLAPI
141gluQuadricDrawStyle(GLUquadric *qobj, GLenum drawStyle)
142{
143 switch(drawStyle) {
144 case GLU_POINT:
145 case GLU_LINE:
146 case GLU_FILL:
147 case GLU_SILHOUETTE:
148 break;
149 default:
150 gluQuadricError(qobj, GLU_INVALID_ENUM);
151 return;
152 }
153 qobj->drawStyle = drawStyle;
154}
155
156void GLAPI
157gluCylinder(GLUquadric *qobj, GLdouble baseRadius, GLdouble topRadius,
158 GLdouble height, GLint slices, GLint stacks)
159{
160 GLint i,j,max;
161 GLfloat sinCache[CACHE_SIZE];
162 GLfloat cosCache[CACHE_SIZE];
163 GLfloat sinCache2[CACHE_SIZE];
164 GLfloat cosCache2[CACHE_SIZE];
165 GLfloat sinCache3[CACHE_SIZE];
166 GLfloat cosCache3[CACHE_SIZE];
167 GLfloat angle;
168 GLfloat x, y, zLow, zHigh;
169 GLfloat sintemp, costemp;
170 GLfloat length;
171 GLfloat deltaRadius;
172 GLfloat zNormal;
173 GLfloat xyNormalRatio;
174 GLfloat radiusLow, radiusHigh;
175 int needCache2, needCache3;
176
177 if (slices >= CACHE_SIZE) slices = CACHE_SIZE-1;
178
179 if (slices < 2 || stacks < 1 || baseRadius < 0.0 || topRadius < 0.0 ||
180 height < 0.0) {
181 gluQuadricError(qobj, GLU_INVALID_VALUE);
182 return;
183 }
184
185 /* Compute length (needed for normal calculations) */
186 deltaRadius = baseRadius - topRadius;
187 length = SQRT(deltaRadius*deltaRadius + height*height);
188 if (length == 0.0) {
189 gluQuadricError(qobj, GLU_INVALID_VALUE);
190 return;
191 }
192
193 /* Cache is the vertex locations cache */
194 /* Cache2 is the various normals at the vertices themselves */
195 /* Cache3 is the various normals for the faces */
196 needCache2 = needCache3 = 0;
197 if (qobj->normals == GLU_SMOOTH) {
198 needCache2 = 1;
199 }
200
201 if (qobj->normals == GLU_FLAT) {
202 if (qobj->drawStyle != GLU_POINT) {
203 needCache3 = 1;
204 }
205 if (qobj->drawStyle == GLU_LINE) {
206 needCache2 = 1;
207 }
208 }
209
210 zNormal = deltaRadius / length;
211 xyNormalRatio = height / length;
212
213 for (i = 0; i < slices; i++) {
214 angle = 2 * PI * i / slices;
215 if (needCache2) {
216 if (qobj->orientation == GLU_OUTSIDE) {
217 sinCache2[i] = xyNormalRatio * SIN(angle);
218 cosCache2[i] = xyNormalRatio * COS(angle);
219 } else {
220 sinCache2[i] = -xyNormalRatio * SIN(angle);
221 cosCache2[i] = -xyNormalRatio * COS(angle);
222 }
223 }
224 sinCache[i] = SIN(angle);
225 cosCache[i] = COS(angle);
226 }
227
228 if (needCache3) {
229 for (i = 0; i < slices; i++) {
230 angle = 2 * PI * (i-0.5) / slices;
231 if (qobj->orientation == GLU_OUTSIDE) {
232 sinCache3[i] = xyNormalRatio * SIN(angle);
233 cosCache3[i] = xyNormalRatio * COS(angle);
234 } else {
235 sinCache3[i] = -xyNormalRatio * SIN(angle);
236 cosCache3[i] = -xyNormalRatio * COS(angle);
237 }
238 }
239 }
240
241 sinCache[slices] = sinCache[0];
242 cosCache[slices] = cosCache[0];
243 if (needCache2) {
244 sinCache2[slices] = sinCache2[0];
245 cosCache2[slices] = cosCache2[0];
246 }
247 if (needCache3) {
248 sinCache3[slices] = sinCache3[0];
249 cosCache3[slices] = cosCache3[0];
250 }
251
252 switch (qobj->drawStyle) {
253 case GLU_FILL:
254 /* Note:
255 ** An argument could be made for using a TRIANGLE_FAN for the end
256 ** of the cylinder of either radii is 0.0 (a cone). However, a
257 ** TRIANGLE_FAN would not work in smooth shading mode (the common
258 ** case) because the normal for the apex is different for every
259 ** triangle (and TRIANGLE_FAN doesn't let me respecify that normal).
260 ** Now, my choice is GL_TRIANGLES, or leave the GL_QUAD_STRIP and
261 ** just let the GL trivially reject one of the two triangles of the
262 ** QUAD. GL_QUAD_STRIP is probably faster, so I will leave this code
263 ** alone.
264 */
265 for (j = 0; j < stacks; j++) {
266 zLow = j * height / stacks;
267 zHigh = (j + 1) * height / stacks;
268 radiusLow = baseRadius - deltaRadius * ((float) j / stacks);
269 radiusHigh = baseRadius - deltaRadius * ((float) (j + 1) / stacks);
270
271 glBegin(GL_QUAD_STRIP);
272 for (i = 0; i <= slices; i++) {
273 switch(qobj->normals) {
274 case GLU_FLAT:
275 glNormal3f(sinCache3[i], cosCache3[i], zNormal);
276 break;
277 case GLU_SMOOTH:
278 glNormal3f(sinCache2[i], cosCache2[i], zNormal);
279 break;
280 case GLU_NONE:
281 default:
282 break;
283 }
284 if (qobj->orientation == GLU_OUTSIDE) {
285 if (qobj->textureCoords) {
286 glTexCoord2f(1 - (float) i / slices,
287 (float) j / stacks);
288 }
289 glVertex3f(radiusLow * sinCache[i],
290 radiusLow * cosCache[i], zLow);
291 if (qobj->textureCoords) {
292 glTexCoord2f(1 - (float) i / slices,
293 (float) (j+1) / stacks);
294 }
295 glVertex3f(radiusHigh * sinCache[i],
296 radiusHigh * cosCache[i], zHigh);
297 } else {
298 if (qobj->textureCoords) {
299 glTexCoord2f(1 - (float) i / slices,
300 (float) (j+1) / stacks);
301 }
302 glVertex3f(radiusHigh * sinCache[i],
303 radiusHigh * cosCache[i], zHigh);
304 if (qobj->textureCoords) {
305 glTexCoord2f(1 - (float) i / slices,
306 (float) j / stacks);
307 }
308 glVertex3f(radiusLow * sinCache[i],
309 radiusLow * cosCache[i], zLow);
310 }
311 }
312 glEnd();
313 }
314 break;
315 case GLU_POINT:
316 glBegin(GL_POINTS);
317 for (i = 0; i < slices; i++) {
318 switch(qobj->normals) {
319 case GLU_FLAT:
320 case GLU_SMOOTH:
321 glNormal3f(sinCache2[i], cosCache2[i], zNormal);
322 break;
323 case GLU_NONE:
324 default:
325 break;
326 }
327 sintemp = sinCache[i];
328 costemp = cosCache[i];
329 for (j = 0; j <= stacks; j++) {
330 zLow = j * height / stacks;
331 radiusLow = baseRadius - deltaRadius * ((float) j / stacks);
332
333 if (qobj->textureCoords) {
334 glTexCoord2f(1 - (float) i / slices,
335 (float) j / stacks);
336 }
337 glVertex3f(radiusLow * sintemp,
338 radiusLow * costemp, zLow);
339 }
340 }
341 glEnd();
342 break;
343 case GLU_LINE:
344 for (j = 1; j < stacks; j++) {
345 zLow = j * height / stacks;
346 radiusLow = baseRadius - deltaRadius * ((float) j / stacks);
347
348 glBegin(GL_LINE_STRIP);
349 for (i = 0; i <= slices; i++) {
350 switch(qobj->normals) {
351 case GLU_FLAT:
352 glNormal3f(sinCache3[i], cosCache3[i], zNormal);
353 break;
354 case GLU_SMOOTH:
355 glNormal3f(sinCache2[i], cosCache2[i], zNormal);
356 break;
357 case GLU_NONE:
358 default:
359 break;
360 }
361 if (qobj->textureCoords) {
362 glTexCoord2f(1 - (float) i / slices,
363 (float) j / stacks);
364 }
365 glVertex3f(radiusLow * sinCache[i],
366 radiusLow * cosCache[i], zLow);
367 }
368 glEnd();
369 }
370 /* Intentionally fall through here... */
371 case GLU_SILHOUETTE:
372 for (j = 0; j <= stacks; j += stacks) {
373 zLow = j * height / stacks;
374 radiusLow = baseRadius - deltaRadius * ((float) j / stacks);
375
376 glBegin(GL_LINE_STRIP);
377 for (i = 0; i <= slices; i++) {
378 switch(qobj->normals) {
379 case GLU_FLAT:
380 glNormal3f(sinCache3[i], cosCache3[i], zNormal);
381 break;
382 case GLU_SMOOTH:
383 glNormal3f(sinCache2[i], cosCache2[i], zNormal);
384 break;
385 case GLU_NONE:
386 default:
387 break;
388 }
389 if (qobj->textureCoords) {
390 glTexCoord2f(1 - (float) i / slices,
391 (float) j / stacks);
392 }
393 glVertex3f(radiusLow * sinCache[i], radiusLow * cosCache[i],
394 zLow);
395 }
396 glEnd();
397 }
398 for (i = 0; i < slices; i++) {
399 switch(qobj->normals) {
400 case GLU_FLAT:
401 case GLU_SMOOTH:
402 glNormal3f(sinCache2[i], cosCache2[i], 0.0);
403 break;
404 case GLU_NONE:
405 default:
406 break;
407 }
408 sintemp = sinCache[i];
409 costemp = cosCache[i];
410 glBegin(GL_LINE_STRIP);
411 for (j = 0; j <= stacks; j++) {
412 zLow = j * height / stacks;
413 radiusLow = baseRadius - deltaRadius * ((float) j / stacks);
414
415 if (qobj->textureCoords) {
416 glTexCoord2f(1 - (float) i / slices,
417 (float) j / stacks);
418 }
419 glVertex3f(radiusLow * sintemp,
420 radiusLow * costemp, zLow);
421 }
422 glEnd();
423 }
424 break;
425 default:
426 break;
427 }
428}
429
430void GLAPI
431gluDisk(GLUquadric *qobj, GLdouble innerRadius, GLdouble outerRadius,
432 GLint slices, GLint loops)
433{
434 gluPartialDisk(qobj, innerRadius, outerRadius, slices, loops, 0.0, 360.0);
435}
436
437void GLAPI
438gluPartialDisk(GLUquadric *qobj, GLdouble innerRadius,
439 GLdouble outerRadius, GLint slices, GLint loops,
440 GLdouble startAngle, GLdouble sweepAngle)
441{
442 GLint i,j,max;
443 GLfloat sinCache[CACHE_SIZE];
444 GLfloat cosCache[CACHE_SIZE];
445 GLfloat angle;
446 GLfloat x, y;
447 GLfloat sintemp, costemp;
448 GLfloat deltaRadius;
449 GLfloat radiusLow, radiusHigh;
450 GLfloat texLow, texHigh;
451 GLfloat angleOffset;
452 GLint slices2;
453 GLint finish;
454
455 if (slices >= CACHE_SIZE) slices = CACHE_SIZE-1;
456 if (slices < 2 || loops < 1 || outerRadius <= 0.0 || innerRadius < 0.0 ||
457 innerRadius > outerRadius) {
458 gluQuadricError(qobj, GLU_INVALID_VALUE);
459 return;
460 }
461
462 if (sweepAngle < -360.0) sweepAngle = 360.0;
463 if (sweepAngle > 360.0) sweepAngle = 360.0;
464 if (sweepAngle < 0) {
465 startAngle += sweepAngle;
466 sweepAngle = -sweepAngle;
467 }
468
469 if (sweepAngle == 360.0) {
470 slices2 = slices;
471 } else {
472 slices2 = slices + 1;
473 }
474
475 /* Compute length (needed for normal calculations) */
476 deltaRadius = outerRadius - innerRadius;
477
478 /* Cache is the vertex locations cache */
479
480 angleOffset = startAngle / 180.0 * PI;
481 for (i = 0; i <= slices; i++) {
482 angle = angleOffset + ((PI * sweepAngle) / 180.0) * i / slices;
483 sinCache[i] = SIN(angle);
484 cosCache[i] = COS(angle);
485 }
486
487 if (sweepAngle == 360.0) {
488 sinCache[slices] = sinCache[0];
489 cosCache[slices] = cosCache[0];
490 }
491
492 switch(qobj->normals) {
493 case GLU_FLAT:
494 case GLU_SMOOTH:
495 if (qobj->orientation == GLU_OUTSIDE) {
496 glNormal3f(0.0, 0.0, 1.0);
497 } else {
498 glNormal3f(0.0, 0.0, -1.0);
499 }
500 break;
501 default:
502 case GLU_NONE:
503 break;
504 }
505
506 switch (qobj->drawStyle) {
507 case GLU_FILL:
508 if (innerRadius == 0.0) {
509 finish = loops - 1;
510 /* Triangle strip for inner polygons */
511 glBegin(GL_TRIANGLE_FAN);
512 if (qobj->textureCoords) {
513 glTexCoord2f(0.5, 0.5);
514 }
515 glVertex3f(0.0, 0.0, 0.0);
516 radiusLow = outerRadius -
517 deltaRadius * ((float) (loops-1) / loops);
518 if (qobj->textureCoords) {
519 texLow = radiusLow / outerRadius / 2;
520 }
521
522 if (qobj->orientation == GLU_OUTSIDE) {
523 for (i = slices; i >= 0; i--) {
524 if (qobj->textureCoords) {
525 glTexCoord2f(texLow * sinCache[i] + 0.5,
526 texLow * cosCache[i] + 0.5);
527 }
528 glVertex3f(radiusLow * sinCache[i],
529 radiusLow * cosCache[i], 0.0);
530 }
531 } else {
532 for (i = 0; i <= slices; i++) {
533 if (qobj->textureCoords) {
534 glTexCoord2f(texLow * sinCache[i] + 0.5,
535 texLow * cosCache[i] + 0.5);
536 }
537 glVertex3f(radiusLow * sinCache[i],
538 radiusLow * cosCache[i], 0.0);
539 }
540 }
541 glEnd();
542 } else {
543 finish = loops;
544 }
545 for (j = 0; j < finish; j++) {
546 radiusLow = outerRadius - deltaRadius * ((float) j / loops);
547 radiusHigh = outerRadius - deltaRadius * ((float) (j + 1) / loops);
548 if (qobj->textureCoords) {
549 texLow = radiusLow / outerRadius / 2;
550 texHigh = radiusHigh / outerRadius / 2;
551 }
552
553 glBegin(GL_QUAD_STRIP);
554 for (i = 0; i <= slices; i++) {
555 if (qobj->orientation == GLU_OUTSIDE) {
556 if (qobj->textureCoords) {
557 glTexCoord2f(texLow * sinCache[i] + 0.5,
558 texLow * cosCache[i] + 0.5);
559 }
560 glVertex3f(radiusLow * sinCache[i],
561 radiusLow * cosCache[i], 0.0);
562
563 if (qobj->textureCoords) {
564 glTexCoord2f(texHigh * sinCache[i] + 0.5,
565 texHigh * cosCache[i] + 0.5);
566 }
567 glVertex3f(radiusHigh * sinCache[i],
568 radiusHigh * cosCache[i], 0.0);
569 } else {
570 if (qobj->textureCoords) {
571 glTexCoord2f(texHigh * sinCache[i] + 0.5,
572 texHigh * cosCache[i] + 0.5);
573 }
574 glVertex3f(radiusHigh * sinCache[i],
575 radiusHigh * cosCache[i], 0.0);
576
577 if (qobj->textureCoords) {
578 glTexCoord2f(texLow * sinCache[i] + 0.5,
579 texLow * cosCache[i] + 0.5);
580 }
581 glVertex3f(radiusLow * sinCache[i],
582 radiusLow * cosCache[i], 0.0);
583 }
584 }
585 glEnd();
586 }
587 break;
588 case GLU_POINT:
589 glBegin(GL_POINTS);
590 for (i = 0; i < slices2; i++) {
591 sintemp = sinCache[i];
592 costemp = cosCache[i];
593 for (j = 0; j <= loops; j++) {
594 radiusLow = outerRadius - deltaRadius * ((float) j / loops);
595
596 if (qobj->textureCoords) {
597 texLow = radiusLow / outerRadius / 2;
598
599 glTexCoord2f(texLow * sinCache[i] + 0.5,
600 texLow * cosCache[i] + 0.5);
601 }
602 glVertex3f(radiusLow * sintemp, radiusLow * costemp, 0.0);
603 }
604 }
605 glEnd();
606 break;
607 case GLU_LINE:
608 if (innerRadius == outerRadius) {
609 glBegin(GL_LINE_STRIP);
610
611 for (i = 0; i <= slices; i++) {
612 if (qobj->textureCoords) {
613 glTexCoord2f(sinCache[i] / 2 + 0.5,
614 cosCache[i] / 2 + 0.5);
615 }
616 glVertex3f(innerRadius * sinCache[i],
617 innerRadius * cosCache[i], 0.0);
618 }
619 glEnd();
620 break;
621 }
622 for (j = 0; j <= loops; j++) {
623 radiusLow = outerRadius - deltaRadius * ((float) j / loops);
624 if (qobj->textureCoords) {
625 texLow = radiusLow / outerRadius / 2;
626 }
627
628 glBegin(GL_LINE_STRIP);
629 for (i = 0; i <= slices; i++) {
630 if (qobj->textureCoords) {
631 glTexCoord2f(texLow * sinCache[i] + 0.5,
632 texLow * cosCache[i] + 0.5);
633 }
634 glVertex3f(radiusLow * sinCache[i],
635 radiusLow * cosCache[i], 0.0);
636 }
637 glEnd();
638 }
639 for (i=0; i < slices2; i++) {
640 sintemp = sinCache[i];
641 costemp = cosCache[i];
642 glBegin(GL_LINE_STRIP);
643 for (j = 0; j <= loops; j++) {
644 radiusLow = outerRadius - deltaRadius * ((float) j / loops);
645 if (qobj->textureCoords) {
646 texLow = radiusLow / outerRadius / 2;
647 }
648
649 if (qobj->textureCoords) {
650 glTexCoord2f(texLow * sinCache[i] + 0.5,
651 texLow * cosCache[i] + 0.5);
652 }
653 glVertex3f(radiusLow * sintemp, radiusLow * costemp, 0.0);
654 }
655 glEnd();
656 }
657 break;
658 case GLU_SILHOUETTE:
659 if (sweepAngle < 360.0) {
660 for (i = 0; i <= slices; i+= slices) {
661 sintemp = sinCache[i];
662 costemp = cosCache[i];
663 glBegin(GL_LINE_STRIP);
664 for (j = 0; j <= loops; j++) {
665 radiusLow = outerRadius - deltaRadius * ((float) j / loops);
666
667 if (qobj->textureCoords) {
668 texLow = radiusLow / outerRadius / 2;
669 glTexCoord2f(texLow * sinCache[i] + 0.5,
670 texLow * cosCache[i] + 0.5);
671 }
672 glVertex3f(radiusLow * sintemp, radiusLow * costemp, 0.0);
673 }
674 glEnd();
675 }
676 }
677 for (j = 0; j <= loops; j += loops) {
678 radiusLow = outerRadius - deltaRadius * ((float) j / loops);
679 if (qobj->textureCoords) {
680 texLow = radiusLow / outerRadius / 2;
681 }
682
683 glBegin(GL_LINE_STRIP);
684 for (i = 0; i <= slices; i++) {
685 if (qobj->textureCoords) {
686 glTexCoord2f(texLow * sinCache[i] + 0.5,
687 texLow * cosCache[i] + 0.5);
688 }
689 glVertex3f(radiusLow * sinCache[i],
690 radiusLow * cosCache[i], 0.0);
691 }
692 glEnd();
693 if (innerRadius == outerRadius) break;
694 }
695 break;
696 default:
697 break;
698 }
699}
700
701void GLAPI
702gluSphere(GLUquadric *qobj, GLdouble radius, GLint slices, GLint stacks)
703{
704 GLint i,j,max;
705 GLfloat sinCache1a[CACHE_SIZE];
706 GLfloat cosCache1a[CACHE_SIZE];
707 GLfloat sinCache2a[CACHE_SIZE];
708 GLfloat cosCache2a[CACHE_SIZE];
709 GLfloat sinCache3a[CACHE_SIZE];
710 GLfloat cosCache3a[CACHE_SIZE];
711 GLfloat sinCache1b[CACHE_SIZE];
712 GLfloat cosCache1b[CACHE_SIZE];
713 GLfloat sinCache2b[CACHE_SIZE];
714 GLfloat cosCache2b[CACHE_SIZE];
715 GLfloat sinCache3b[CACHE_SIZE];
716 GLfloat cosCache3b[CACHE_SIZE];
717 GLfloat angle;
718 GLfloat x, y, zLow, zHigh;
719 GLfloat sintemp1, sintemp2, sintemp3, sintemp4;
720 GLfloat costemp1, costemp2, costemp3, costemp4;
721 GLfloat zNormal;
722 GLfloat xyNormalRatio;
723 GLboolean needCache2, needCache3;
724 GLint start, finish;
725
726 if (slices >= CACHE_SIZE) slices = CACHE_SIZE-1;
727 if (stacks >= CACHE_SIZE) stacks = CACHE_SIZE-1;
728 if (slices < 2 || stacks < 1 || radius < 0.0) {
729 gluQuadricError(qobj, GLU_INVALID_VALUE);
730 return;
731 }
732
733 /* Cache is the vertex locations cache */
734 /* Cache2 is the various normals at the vertices themselves */
735 /* Cache3 is the various normals for the faces */
736 needCache2 = needCache3 = GL_FALSE;
737
738 if (qobj->normals == GLU_SMOOTH) {
739 needCache2 = GL_TRUE;
740 }
741
742 if (qobj->normals == GLU_FLAT) {
743 if (qobj->drawStyle != GLU_POINT) {
744 needCache3 = GL_TRUE;
745 }
746 if (qobj->drawStyle == GLU_LINE) {
747 needCache2 = GL_TRUE;
748 }
749 }
750
751 for (i = 0; i < slices; i++) {
752 angle = 2 * PI * i / slices;
753 sinCache1a[i] = SIN(angle);
754 cosCache1a[i] = COS(angle);
755 if (needCache2) {
756 sinCache2a[i] = sinCache1a[i];
757 cosCache2a[i] = cosCache1a[i];
758 }
759 }
760
761 for (j = 0; j <= stacks; j++) {
762 angle = PI * j / stacks;
763 if (needCache2) {
764 if (qobj->orientation == GLU_OUTSIDE) {
765 sinCache2b[j] = SIN(angle);
766 cosCache2b[j] = COS(angle);
767 } else {
768 sinCache2b[j] = -SIN(angle);
769 cosCache2b[j] = -COS(angle);
770 }
771 }
772 sinCache1b[j] = radius * SIN(angle);
773 cosCache1b[j] = radius * COS(angle);
774 }
775 /* Make sure it comes to a point */
776 sinCache1b[0] = 0;
777 sinCache1b[stacks] = 0;
778
779 if (needCache3) {
780 for (i = 0; i < slices; i++) {
781 angle = 2 * PI * (i-0.5) / slices;
782 sinCache3a[i] = SIN(angle);
783 cosCache3a[i] = COS(angle);
784 }
785 for (j = 0; j <= stacks; j++) {
786 angle = PI * (j - 0.5) / stacks;
787 if (qobj->orientation == GLU_OUTSIDE) {
788 sinCache3b[j] = SIN(angle);
789 cosCache3b[j] = COS(angle);
790 } else {
791 sinCache3b[j] = -SIN(angle);
792 cosCache3b[j] = -COS(angle);
793 }
794 }
795 }
796
797 sinCache1a[slices] = sinCache1a[0];
798 cosCache1a[slices] = cosCache1a[0];
799 if (needCache2) {
800 sinCache2a[slices] = sinCache2a[0];
801 cosCache2a[slices] = cosCache2a[0];
802 }
803 if (needCache3) {
804 sinCache3a[slices] = sinCache3a[0];
805 cosCache3a[slices] = cosCache3a[0];
806 }
807
808 switch (qobj->drawStyle) {
809 case GLU_FILL:
810 /* Do ends of sphere as TRIANGLE_FAN's (if not texturing)
811 ** We don't do it when texturing because we need to respecify the
812 ** texture coordinates of the apex for every adjacent vertex (because
813 ** it isn't a constant for that point)
814 */
815 if (!(qobj->textureCoords)) {
816 start = 1;
817 finish = stacks - 1;
818
819 /* Low end first (j == 0 iteration) */
820 sintemp2 = sinCache1b[1];
821 zHigh = cosCache1b[1];
822 switch(qobj->normals) {
823 case GLU_FLAT:
824 sintemp3 = sinCache3b[1];
825 costemp3 = cosCache3b[1];
826 break;
827 case GLU_SMOOTH:
828 sintemp3 = sinCache2b[1];
829 costemp3 = cosCache2b[1];
830 glNormal3f(sinCache2a[0] * sinCache2b[0],
831 cosCache2a[0] * sinCache2b[0],
832 cosCache2b[0]);
833 break;
834 default:
835 break;
836 }
837 glBegin(GL_TRIANGLE_FAN);
838 glVertex3f(0.0, 0.0, radius);
839 if (qobj->orientation == GLU_OUTSIDE) {
840 for (i = slices; i >= 0; i--) {
841 switch(qobj->normals) {
842 case GLU_SMOOTH:
843 glNormal3f(sinCache2a[i] * sintemp3,
844 cosCache2a[i] * sintemp3,
845 costemp3);
846 break;
847 case GLU_FLAT:
848 if (i != slices) {
849 glNormal3f(sinCache3a[i+1] * sintemp3,
850 cosCache3a[i+1] * sintemp3,
851 costemp3);
852 }
853 break;
854 case GLU_NONE:
855 default:
856 break;
857 }
858 glVertex3f(sintemp2 * sinCache1a[i],
859 sintemp2 * cosCache1a[i], zHigh);
860 }
861 } else {
862 for (i = 0; i <= slices; i++) {
863 switch(qobj->normals) {
864 case GLU_SMOOTH:
865 glNormal3f(sinCache2a[i] * sintemp3,
866 cosCache2a[i] * sintemp3,
867 costemp3);
868 break;
869 case GLU_FLAT:
870 glNormal3f(sinCache3a[i] * sintemp3,
871 cosCache3a[i] * sintemp3,
872 costemp3);
873 break;
874 case GLU_NONE:
875 default:
876 break;
877 }
878 glVertex3f(sintemp2 * sinCache1a[i],
879 sintemp2 * cosCache1a[i], zHigh);
880 }
881 }
882 glEnd();
883
884 /* High end next (j == stacks-1 iteration) */
885 sintemp2 = sinCache1b[stacks-1];
886 zHigh = cosCache1b[stacks-1];
887 switch(qobj->normals) {
888 case GLU_FLAT:
889 sintemp3 = sinCache3b[stacks];
890 costemp3 = cosCache3b[stacks];
891 break;
892 case GLU_SMOOTH:
893 sintemp3 = sinCache2b[stacks-1];
894 costemp3 = cosCache2b[stacks-1];
895 glNormal3f(sinCache2a[stacks] * sinCache2b[stacks],
896 cosCache2a[stacks] * sinCache2b[stacks],
897 cosCache2b[stacks]);
898 break;
899 default:
900 break;
901 }
902 glBegin(GL_TRIANGLE_FAN);
903 glVertex3f(0.0, 0.0, -radius);
904 if (qobj->orientation == GLU_OUTSIDE) {
905 for (i = 0; i <= slices; i++) {
906 switch(qobj->normals) {
907 case GLU_SMOOTH:
908 glNormal3f(sinCache2a[i] * sintemp3,
909 cosCache2a[i] * sintemp3,
910 costemp3);
911 break;
912 case GLU_FLAT:
913 glNormal3f(sinCache3a[i] * sintemp3,
914 cosCache3a[i] * sintemp3,
915 costemp3);
916 break;
917 case GLU_NONE:
918 default:
919 break;
920 }
921 glVertex3f(sintemp2 * sinCache1a[i],
922 sintemp2 * cosCache1a[i], zHigh);
923 }
924 } else {
925 for (i = slices; i >= 0; i--) {
926 switch(qobj->normals) {
927 case GLU_SMOOTH:
928 glNormal3f(sinCache2a[i] * sintemp3,
929 cosCache2a[i] * sintemp3,
930 costemp3);
931 break;
932 case GLU_FLAT:
933 if (i != slices) {
934 glNormal3f(sinCache3a[i+1] * sintemp3,
935 cosCache3a[i+1] * sintemp3,
936 costemp3);
937 }
938 break;
939 case GLU_NONE:
940 default:
941 break;
942 }
943 glVertex3f(sintemp2 * sinCache1a[i],
944 sintemp2 * cosCache1a[i], zHigh);
945 }
946 }
947 glEnd();
948 } else {
949 start = 0;
950 finish = stacks;
951 }
952 for (j = start; j < finish; j++) {
953 zLow = cosCache1b[j];
954 zHigh = cosCache1b[j+1];
955 sintemp1 = sinCache1b[j];
956 sintemp2 = sinCache1b[j+1];
957 switch(qobj->normals) {
958 case GLU_FLAT:
959 sintemp4 = sinCache3b[j+1];
960 costemp4 = cosCache3b[j+1];
961 break;
962 case GLU_SMOOTH:
963 if (qobj->orientation == GLU_OUTSIDE) {
964 sintemp3 = sinCache2b[j+1];
965 costemp3 = cosCache2b[j+1];
966 sintemp4 = sinCache2b[j];
967 costemp4 = cosCache2b[j];
968 } else {
969 sintemp3 = sinCache2b[j];
970 costemp3 = cosCache2b[j];
971 sintemp4 = sinCache2b[j+1];
972 costemp4 = cosCache2b[j+1];
973 }
974 break;
975 default:
976 break;
977 }
978
979 glBegin(GL_QUAD_STRIP);
980 for (i = 0; i <= slices; i++) {
981 switch(qobj->normals) {
982 case GLU_SMOOTH:
983 glNormal3f(sinCache2a[i] * sintemp3,
984 cosCache2a[i] * sintemp3,
985 costemp3);
986 break;
987 case GLU_FLAT:
988 case GLU_NONE:
989 default:
990 break;
991 }
992 if (qobj->orientation == GLU_OUTSIDE) {
993 if (qobj->textureCoords) {
994 glTexCoord2f(1 - (float) i / slices,
995 1 - (float) (j+1) / stacks);
996 }
997 glVertex3f(sintemp2 * sinCache1a[i],
998 sintemp2 * cosCache1a[i], zHigh);
999 } else {
1000 if (qobj->textureCoords) {
1001 glTexCoord2f(1 - (float) i / slices,
1002 1 - (float) j / stacks);
1003 }
1004 glVertex3f(sintemp1 * sinCache1a[i],
1005 sintemp1 * cosCache1a[i], zLow);
1006 }
1007 switch(qobj->normals) {
1008 case GLU_SMOOTH:
1009 glNormal3f(sinCache2a[i] * sintemp4,
1010 cosCache2a[i] * sintemp4,
1011 costemp4);
1012 break;
1013 case GLU_FLAT:
1014 glNormal3f(sinCache3a[i] * sintemp4,
1015 cosCache3a[i] * sintemp4,
1016 costemp4);
1017 break;
1018 case GLU_NONE:
1019 default:
1020 break;
1021 }
1022 if (qobj->orientation == GLU_OUTSIDE) {
1023 if (qobj->textureCoords) {
1024 glTexCoord2f(1 - (float) i / slices,
1025 1 - (float) j / stacks);
1026 }
1027 glVertex3f(sintemp1 * sinCache1a[i],
1028 sintemp1 * cosCache1a[i], zLow);
1029 } else {
1030 if (qobj->textureCoords) {
1031 glTexCoord2f(1 - (float) i / slices,
1032 1 - (float) (j+1) / stacks);
1033 }
1034 glVertex3f(sintemp2 * sinCache1a[i],
1035 sintemp2 * cosCache1a[i], zHigh);
1036 }
1037 }
1038 glEnd();
1039 }
1040 break;
1041 case GLU_POINT:
1042 glBegin(GL_POINTS);
1043 for (j = 0; j <= stacks; j++) {
1044 sintemp1 = sinCache1b[j];
1045 costemp1 = cosCache1b[j];
1046 switch(qobj->normals) {
1047 case GLU_FLAT:
1048 case GLU_SMOOTH:
1049 sintemp2 = sinCache2b[j];
1050 costemp2 = cosCache2b[j];
1051 break;
1052 default:
1053 break;
1054 }
1055 for (i = 0; i < slices; i++) {
1056 switch(qobj->normals) {
1057 case GLU_FLAT:
1058 case GLU_SMOOTH:
1059 glNormal3f(sinCache2a[i] * sintemp2,
1060 cosCache2a[i] * sintemp2,
1061 costemp2);
1062 break;
1063 case GLU_NONE:
1064 default:
1065 break;
1066 }
1067
1068 zLow = j * radius / stacks;
1069
1070 if (qobj->textureCoords) {
1071 glTexCoord2f(1 - (float) i / slices,
1072 1 - (float) j / stacks);
1073 }
1074 glVertex3f(sintemp1 * sinCache1a[i],
1075 sintemp1 * cosCache1a[i], costemp1);
1076 }
1077 }
1078 glEnd();
1079 break;
1080 case GLU_LINE:
1081 case GLU_SILHOUETTE:
1082 for (j = 1; j < stacks; j++) {
1083 sintemp1 = sinCache1b[j];
1084 costemp1 = cosCache1b[j];
1085 switch(qobj->normals) {
1086 case GLU_FLAT:
1087 case GLU_SMOOTH:
1088 sintemp2 = sinCache2b[j];
1089 costemp2 = cosCache2b[j];
1090 break;
1091 default:
1092 break;
1093 }
1094
1095 glBegin(GL_LINE_STRIP);
1096 for (i = 0; i <= slices; i++) {
1097 switch(qobj->normals) {
1098 case GLU_FLAT:
1099 glNormal3f(sinCache3a[i] * sintemp2,
1100 cosCache3a[i] * sintemp2,
1101 costemp2);
1102 break;
1103 case GLU_SMOOTH:
1104 glNormal3f(sinCache2a[i] * sintemp2,
1105 cosCache2a[i] * sintemp2,
1106 costemp2);
1107 break;
1108 case GLU_NONE:
1109 default:
1110 break;
1111 }
1112 if (qobj->textureCoords) {
1113 glTexCoord2f(1 - (float) i / slices,
1114 1 - (float) j / stacks);
1115 }
1116 glVertex3f(sintemp1 * sinCache1a[i],
1117 sintemp1 * cosCache1a[i], costemp1);
1118 }
1119 glEnd();
1120 }
1121 for (i = 0; i < slices; i++) {
1122 sintemp1 = sinCache1a[i];
1123 costemp1 = cosCache1a[i];
1124 switch(qobj->normals) {
1125 case GLU_FLAT:
1126 case GLU_SMOOTH:
1127 sintemp2 = sinCache2a[i];
1128 costemp2 = cosCache2a[i];
1129 break;
1130 default:
1131 break;
1132 }
1133
1134 glBegin(GL_LINE_STRIP);
1135 for (j = 0; j <= stacks; j++) {
1136 switch(qobj->normals) {
1137 case GLU_FLAT:
1138 glNormal3f(sintemp2 * sinCache3b[j],
1139 costemp2 * sinCache3b[j],
1140 cosCache3b[j]);
1141 break;
1142 case GLU_SMOOTH:
1143 glNormal3f(sintemp2 * sinCache2b[j],
1144 costemp2 * sinCache2b[j],
1145 cosCache2b[j]);
1146 break;
1147 case GLU_NONE:
1148 default:
1149 break;
1150 }
1151
1152 if (qobj->textureCoords) {
1153 glTexCoord2f(1 - (float) i / slices,
1154 1 - (float) j / stacks);
1155 }
1156 glVertex3f(sintemp1 * sinCache1b[j],
1157 costemp1 * sinCache1b[j], cosCache1b[j]);
1158 }
1159 glEnd();
1160 }
1161 break;
1162 default:
1163 break;
1164 }
1165}
Note: See TracBrowser for help on using the repository browser.