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