Files
commandergenius/project/jni/glu/src/glues_quad.c

1651 lines
50 KiB
C

/*
* SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
* Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice including the dates of first publication and
* either this permission notice or a reference to
* http://oss.sgi.com/projects/FreeB/
* shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Except as contained in this notice, the name of Silicon Graphics, Inc.
* shall not be used in advertising or otherwise to promote the sale, use or
* other dealings in this Software without prior written authorization from
* Silicon Graphics, Inc.
*
* OpenGL ES CM 1.0 port of GLU by Mike Gorchak <mike@malva.ua>.
*/
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "glues_quad.h"
/* Make it not a power of two to avoid cache thrashing on the chip */
#define CACHE_SIZE 240
#undef PI
#define PI 3.14159265358979323846f
struct GLUquadric
{
GLint normals;
GLboolean textureCoords;
GLint orientation;
GLint drawStyle;
void (APIENTRY* errorCallback)( GLint );
};
GLAPI GLUquadric* APIENTRY gluNewQuadric(void)
{
GLUquadric *newstate;
newstate=(GLUquadric*)malloc(sizeof(GLUquadric));
if (newstate==NULL)
{
/* Can't report an error at this point... */
return NULL;
}
newstate->normals=GLU_SMOOTH;
newstate->textureCoords=GL_FALSE;
newstate->orientation=GLU_OUTSIDE;
newstate->drawStyle=GLU_FILL;
newstate->errorCallback=NULL;
return newstate;
}
GLAPI void APIENTRY gluDeleteQuadric(GLUquadric* state)
{
if (state!=NULL)
{
free(state);
}
}
static void gluQuadricError(GLUquadric* qobj, GLenum which)
{
if (qobj->errorCallback)
{
qobj->errorCallback(which);
}
}
GLAPI void APIENTRY gluQuadricCallback(GLUquadric* qobj, GLenum which, _GLUfuncptr fn)
{
switch (which)
{
case GLU_ERROR:
qobj->errorCallback=(void(APIENTRY*)(GLint))fn;
break;
default:
gluQuadricError(qobj, GLU_INVALID_ENUM);
return;
}
}
GLAPI void APIENTRY gluQuadricNormals(GLUquadric* qobj, GLenum normals)
{
switch (normals)
{
case GLU_SMOOTH:
case GLU_FLAT:
case GLU_NONE:
break;
default:
gluQuadricError(qobj, GLU_INVALID_ENUM);
return;
}
qobj->normals=normals;
}
GLAPI void APIENTRY gluQuadricTexture(GLUquadric* qobj, GLboolean textureCoords)
{
qobj->textureCoords=textureCoords;
}
GLAPI void APIENTRY gluQuadricOrientation(GLUquadric* qobj, GLenum orientation)
{
switch(orientation)
{
case GLU_OUTSIDE:
case GLU_INSIDE:
break;
default:
gluQuadricError(qobj, GLU_INVALID_ENUM);
return;
}
qobj->orientation=orientation;
}
GLAPI void APIENTRY gluQuadricDrawStyle(GLUquadric* qobj, GLenum drawStyle)
{
switch(drawStyle)
{
case GLU_POINT:
case GLU_LINE:
case GLU_FILL:
case GLU_SILHOUETTE:
break;
default:
gluQuadricError(qobj, GLU_INVALID_ENUM);
return;
}
qobj->drawStyle=drawStyle;
}
GLAPI void APIENTRY gluCylinder(GLUquadric* qobj, GLfloat baseRadius,
GLfloat topRadius, GLfloat height,
GLint slices, GLint stacks)
{
GLint i, j;
GLfloat sinCache[CACHE_SIZE];
GLfloat cosCache[CACHE_SIZE];
GLfloat sinCache2[CACHE_SIZE];
GLfloat cosCache2[CACHE_SIZE];
GLfloat sinCache3[CACHE_SIZE];
GLfloat cosCache3[CACHE_SIZE];
GLfloat sintemp, costemp;
GLfloat vertices[(CACHE_SIZE+1)*2][3];
GLfloat texcoords[(CACHE_SIZE+1)*2][2];
GLfloat normals[(CACHE_SIZE+1)*2][3];
GLfloat angle;
GLfloat zLow, zHigh;
GLfloat length;
GLfloat deltaRadius;
GLfloat zNormal;
GLfloat xyNormalRatio;
GLfloat radiusLow, radiusHigh;
int needCache2, needCache3;
GLboolean texcoord_enabled;
GLboolean normal_enabled;
GLboolean vertex_enabled;
GLboolean color_enabled;
if (slices>=CACHE_SIZE)
{
slices=CACHE_SIZE-1;
}
/* Avoid vertex array overflow */
if (stacks>=CACHE_SIZE)
{
stacks=CACHE_SIZE-1;
}
if (slices<2 || stacks<1 || baseRadius<0.0 || topRadius<0.0 || height<0.0)
{
gluQuadricError(qobj, GLU_INVALID_VALUE);
return;
}
/* Compute length (needed for normal calculations) */
deltaRadius=baseRadius-topRadius;
length=(GLfloat)sqrt(deltaRadius*deltaRadius+height*height);
if (length==0.0)
{
gluQuadricError(qobj, GLU_INVALID_VALUE);
return;
}
/* Cache is the vertex locations cache */
/* Cache2 is the various normals at the vertices themselves */
/* Cache3 is the various normals for the faces */
needCache2=needCache3=0;
if (qobj->normals==GLU_SMOOTH)
{
needCache2=1;
}
if (qobj->normals==GLU_FLAT)
{
if (qobj->drawStyle!=GLU_POINT)
{
needCache3=1;
}
if (qobj->drawStyle==GLU_LINE)
{
needCache2=1;
}
}
zNormal=deltaRadius/length;
xyNormalRatio=height/length;
for (i=0; i<slices; i++)
{
angle=2.0f*PI*i/slices;
if (needCache2)
{
if (qobj->orientation==GLU_OUTSIDE)
{
sinCache2[i]=(GLfloat)(xyNormalRatio*sin(angle));
cosCache2[i]=(GLfloat)(xyNormalRatio*cos(angle));
}
else
{
sinCache2[i]=(GLfloat)(-xyNormalRatio*sin(angle));
cosCache2[i]=(GLfloat)(-xyNormalRatio*cos(angle));
}
}
sinCache[i]=(GLfloat)sin(angle);
cosCache[i]=(GLfloat)cos(angle);
}
if (needCache3)
{
for (i=0; i<slices; i++)
{
angle=2.0f*PI*(i-0.5f)/slices;
if (qobj->orientation==GLU_OUTSIDE)
{
sinCache3[i]=(GLfloat)(xyNormalRatio*sin(angle));
cosCache3[i]=(GLfloat)(xyNormalRatio*cos(angle));
}
else
{
sinCache3[i]=(GLfloat)(-xyNormalRatio*sin(angle));
cosCache3[i]=(GLfloat)(-xyNormalRatio*cos(angle));
}
}
}
sinCache[slices]=sinCache[0];
cosCache[slices]=cosCache[0];
if (needCache2)
{
sinCache2[slices]=sinCache2[0];
cosCache2[slices]=cosCache2[0];
}
if (needCache3)
{
sinCache3[slices]=sinCache3[0];
cosCache3[slices]=cosCache3[0];
}
/* Store status of enabled arrays */
texcoord_enabled=GL_FALSE; /* glIsEnabled(GL_TEXTURE_COORD_ARRAY); */
normal_enabled=GL_FALSE; /* glIsEnabled(GL_NORMAL_ARRAY); */
vertex_enabled=GL_FALSE; /* glIsEnabled(GL_VERTEX_ARRAY); */
color_enabled=GL_FALSE; /* glIsEnabled(GL_COLOR_ARRAY); */
/* Enable or disable arrays */
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, vertices);
if (qobj->textureCoords)
{
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glTexCoordPointer(2, GL_FLOAT, 0, texcoords);
}
else
{
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
}
if (qobj->normals!=GLU_NONE)
{
glEnableClientState(GL_NORMAL_ARRAY);
glNormalPointer(GL_FLOAT, 0, normals);
}
else
{
glDisableClientState(GL_NORMAL_ARRAY);
}
glDisableClientState(GL_COLOR_ARRAY);
switch (qobj->drawStyle)
{
case GLU_FILL:
for (j=0; j<stacks; j++)
{
zLow=j*height/stacks;
zHigh=(j+1)*height/stacks;
radiusLow=baseRadius-deltaRadius*((GLfloat)j/stacks);
radiusHigh=baseRadius-deltaRadius*((GLfloat)(j+1)/stacks);
for (i=0; i<=slices; i++)
{
switch(qobj->normals)
{
case GLU_FLAT:
/* per vertex normals */
normals[i*2][0]=sinCache3[i];
normals[i*2][1]=cosCache3[i];
normals[i*2][2]=zNormal;
normals[i*2+1][0]=sinCache3[i];
normals[i*2+1][1]=cosCache3[i];
normals[i*2+1][2]=zNormal;
break;
case GLU_SMOOTH:
/* per vertex normals */
normals[i*2][0]=sinCache2[i];
normals[i*2][1]=cosCache2[i];
normals[i*2][2]=zNormal;
normals[i*2+1][0]=sinCache2[i];
normals[i*2+1][1]=cosCache2[i];
normals[i*2+1][2]=zNormal;
break;
case GLU_NONE:
default:
break;
}
if (qobj->orientation==GLU_OUTSIDE)
{
if (qobj->textureCoords)
{
texcoords[i*2][0]=1-(GLfloat)i/slices;
texcoords[i*2][1]=(GLfloat)j/stacks;
}
vertices[i*2][0]=radiusLow*sinCache[i];
vertices[i*2][1]=radiusLow*cosCache[i];
vertices[i*2][2]=zLow;
if (qobj->textureCoords)
{
texcoords[i*2+1][0]=1-(GLfloat)i/slices;
texcoords[i*2+1][1]=(GLfloat)(j+1)/stacks;
}
vertices[i*2+1][0]=radiusHigh*sinCache[i];
vertices[i*2+1][1]=radiusHigh*cosCache[i];
vertices[i*2+1][2]=zHigh;
}
else
{
if (qobj->textureCoords)
{
texcoords[i*2][0]=1-(GLfloat)i/slices;
texcoords[i*2][1]=(GLfloat)(j+1)/ stacks;
}
vertices[i*2][0]=radiusHigh*sinCache[i];
vertices[i*2][1]=radiusHigh*cosCache[i];
vertices[i*2][2]=zHigh;
if (qobj->textureCoords)
{
texcoords[i*2+1][0]=1-(GLfloat)i/slices;
texcoords[i*2+1][1]=(GLfloat)j/stacks;
}
vertices[i*2+1][0]=radiusLow*sinCache[i];
vertices[i*2+1][1]=radiusLow*cosCache[i];
vertices[i*2+1][2]=zLow;
}
}
glDrawArrays(GL_TRIANGLE_STRIP, 0, 2*(slices+1));
}
break;
case GLU_POINT:
for (i=0; i<slices; i++)
{
sintemp=sinCache[i];
costemp=cosCache[i];
for (j=0; j<=stacks; j++)
{
switch(qobj->normals)
{
case GLU_FLAT:
case GLU_SMOOTH:
normals[j][0]=sinCache2[i];
normals[j][1]=cosCache2[i];
normals[j][2]=zNormal;
break;
case GLU_NONE:
default:
break;
}
zLow=j*height/stacks;
radiusLow=baseRadius-deltaRadius*((GLfloat)j/stacks);
if (qobj->textureCoords)
{
texcoords[j][0]=1-(GLfloat)i/slices;
texcoords[j][1]=(GLfloat)j/stacks;
}
vertices[j][0]=radiusLow*sintemp;
vertices[j][1]=radiusLow*costemp;
vertices[j][2]=zLow;
}
glDrawArrays(GL_POINTS, 0, (stacks+1));
}
break;
case GLU_LINE:
for (j=1; j<stacks; j++)
{
zLow=j*height/stacks;
radiusLow=baseRadius-deltaRadius*((GLfloat)j/stacks);
for (i=0; i<=slices; i++)
{
switch(qobj->normals)
{
case GLU_FLAT:
normals[i][0]=sinCache3[i];
normals[i][1]=cosCache3[i];
normals[i][2]=zNormal;
break;
case GLU_SMOOTH:
normals[i][0]=sinCache2[i];
normals[i][1]=cosCache2[i];
normals[i][2]=zNormal;
break;
case GLU_NONE:
default:
break;
}
if (qobj->textureCoords)
{
texcoords[i][0]=1-(GLfloat)i/slices;
texcoords[i][1]=(GLfloat)j/stacks;
}
vertices[i][0]=radiusLow*sinCache[i];
vertices[i][1]=radiusLow*cosCache[i];
vertices[i][2]=zLow;
}
glDrawArrays(GL_LINE_STRIP, 0, (slices+1));
}
/* Intentionally fall through here... */
case GLU_SILHOUETTE:
for (j=0; j<=stacks; j+=stacks)
{
zLow=j*height/stacks;
radiusLow=baseRadius-deltaRadius*((GLfloat)j/stacks);
for (i=0; i<=slices; i++)
{
switch(qobj->normals)
{
case GLU_FLAT:
normals[i][0]=sinCache3[i];
normals[i][1]=cosCache3[i];
normals[i][2]=zNormal;
break;
case GLU_SMOOTH:
normals[i][0]=sinCache2[i];
normals[i][1]=cosCache2[i];
normals[i][2]=zNormal;
break;
case GLU_NONE:
default:
break;
}
if (qobj->textureCoords)
{
texcoords[i][0]=1-(GLfloat)i/slices;
texcoords[i][1]=(GLfloat)j/stacks;
}
vertices[i][0]=radiusLow*sinCache[i];
vertices[i][1]=radiusLow*cosCache[i];
vertices[i][2]=zLow;
}
glDrawArrays(GL_LINE_STRIP, 0, (slices+1));
}
for (i=0; i<slices; i++)
{
sintemp=sinCache[i];
costemp=cosCache[i];
for (j=0; j<=stacks; j++)
{
switch(qobj->normals)
{
case GLU_FLAT:
case GLU_SMOOTH:
normals[j][0]=sinCache2[i];
normals[j][1]=cosCache2[i];
normals[j][2]=0.0f;
break;
case GLU_NONE:
default:
break;
}
zLow=j*height/stacks;
radiusLow=baseRadius-deltaRadius*((GLfloat)j/stacks);
if (qobj->textureCoords)
{
texcoords[j][0]=1-(GLfloat)i/slices;
texcoords[j][1]=(GLfloat)j/stacks;
}
vertices[j][0]=radiusLow*sintemp;
vertices[j][1]=radiusLow*costemp;
vertices[j][2]=zLow;
}
glDrawArrays(GL_LINE_STRIP, 0, (stacks+1));
}
break;
default:
break;
}
/* Disable or re-enable arrays */
if (vertex_enabled)
{
/* Re-enable vertex array */
glEnableClientState(GL_VERTEX_ARRAY);
}
else
{
glDisableClientState(GL_VERTEX_ARRAY);
}
if (texcoord_enabled)
{
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
}
else
{
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
}
if (normal_enabled)
{
glEnableClientState(GL_NORMAL_ARRAY);
}
else
{
glDisableClientState(GL_NORMAL_ARRAY);
}
if (color_enabled)
{
glEnableClientState(GL_COLOR_ARRAY);
}
else
{
glDisableClientState(GL_COLOR_ARRAY);
}
}
GLAPI void APIENTRY gluDisk(GLUquadric* qobj, GLfloat innerRadius,
GLfloat outerRadius, GLint slices, GLint loops)
{
gluPartialDisk(qobj, innerRadius, outerRadius, slices, loops, 0.0, 360.0);
}
GLAPI void APIENTRY gluPartialDisk(GLUquadric* qobj, GLfloat innerRadius,
GLfloat outerRadius, GLint slices,
GLint loops, GLfloat startAngle,
GLfloat sweepAngle)
{
GLint i, j;
GLfloat sinCache[CACHE_SIZE];
GLfloat cosCache[CACHE_SIZE];
GLfloat angle;
GLfloat sintemp, costemp;
GLfloat vertices[(CACHE_SIZE+1)*2][3];
GLfloat texcoords[(CACHE_SIZE+1)*2][2];
GLfloat deltaRadius;
GLfloat radiusLow, radiusHigh;
GLfloat texLow = 0.0, texHigh = 0.0;
GLfloat angleOffset;
GLint slices2;
GLint finish;
GLboolean texcoord_enabled;
GLboolean normal_enabled;
GLboolean vertex_enabled;
GLboolean color_enabled;
if (slices>=CACHE_SIZE)
{
slices=CACHE_SIZE-1;
}
if (slices<2 || loops<1 || outerRadius<=0.0 ||
innerRadius<0.0 ||innerRadius > outerRadius)
{
gluQuadricError(qobj, GLU_INVALID_VALUE);
return;
}
if (sweepAngle<-360.0)
{
sweepAngle=-360.0;
}
if (sweepAngle>360.0)
{
sweepAngle=360.0;
}
if (sweepAngle<0)
{
startAngle+=sweepAngle;
sweepAngle=-sweepAngle;
}
if (sweepAngle==360.0)
{
slices2=slices;
}
else
{
slices2=slices+1;
}
/* Compute length (needed for normal calculations) */
deltaRadius=outerRadius-innerRadius;
/* Cache is the vertex locations cache */
angleOffset=startAngle/180.0f*PI;
for (i=0; i<=slices; i++)
{
angle=angleOffset+((PI*sweepAngle)/180.0f)*i/slices;
sinCache[i]=(GLfloat)sin(angle);
cosCache[i]=(GLfloat)cos(angle);
}
if (sweepAngle==360.0)
{
sinCache[slices]=sinCache[0];
cosCache[slices]=cosCache[0];
}
switch(qobj->normals)
{
case GLU_FLAT:
case GLU_SMOOTH:
if (qobj->orientation==GLU_OUTSIDE)
{
glNormal3f(0.0f, 0.0f, 1.0f);
}
else
{
glNormal3f(0.0f, 0.0f, -1.0f);
}
break;
default:
case GLU_NONE:
break;
}
/* Store status of enabled arrays */
texcoord_enabled=GL_FALSE; //glIsEnabled(GL_TEXTURE_COORD_ARRAY);
normal_enabled=GL_FALSE; //glIsEnabled(GL_NORMAL_ARRAY);
vertex_enabled=GL_FALSE; //glIsEnabled(GL_VERTEX_ARRAY);
color_enabled=GL_FALSE; //glIsEnabled(GL_COLOR_ARRAY);
/* Enable arrays */
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, vertices);
if (qobj->textureCoords)
{
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glTexCoordPointer(2, GL_FLOAT, 0, texcoords);
}
else
{
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
}
glDisableClientState(GL_NORMAL_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);
switch (qobj->drawStyle)
{
case GLU_FILL:
if (innerRadius==0.0)
{
finish=loops-1;
/* Triangle strip for inner polygons */
if (qobj->textureCoords)
{
texcoords[0][0]=0.5f;
texcoords[0][1]=0.5f;
}
vertices[0][0]=0.0f;
vertices[0][1]=0.0f;
vertices[0][2]=0.0f;
radiusLow=outerRadius-deltaRadius*((GLfloat)(loops-1)/loops);
if (qobj->textureCoords)
{
texLow=radiusLow/outerRadius/2;
}
if (qobj->orientation==GLU_OUTSIDE)
{
for (i=slices; i>=0; i--)
{
if (qobj->textureCoords)
{
texcoords[slices-i+1][0]=texLow*sinCache[i]+0.5f;
texcoords[slices-i+1][1]=texLow*cosCache[i]+0.5f;
}
vertices[slices-i+1][0]=radiusLow*sinCache[i];
vertices[slices-i+1][1]=radiusLow*cosCache[i];
vertices[slices-i+1][2]=0.0f;
}
}
else
{
for (i=0; i<=slices; i++)
{
if (qobj->textureCoords)
{
texcoords[i+1][0]=texLow*sinCache[i]+0.5f;
texcoords[i+1][1]=texLow*cosCache[i]+0.5f;
}
vertices[i+1][0]=radiusLow*sinCache[i];
vertices[i+1][1]=radiusLow*cosCache[i];
vertices[i+1][2]=0.0f;
}
}
glDrawArrays(GL_TRIANGLE_FAN, 0, (slices+2));
}
else
{
finish=loops;
}
for (j=0; j<finish; j++)
{
radiusLow=outerRadius-deltaRadius*((GLfloat)j/loops);
radiusHigh=outerRadius-deltaRadius*((GLfloat)(j+1)/loops);
if (qobj->textureCoords)
{
texLow=radiusLow/outerRadius/2;
texHigh=radiusHigh/outerRadius/2;
}
for (i=0; i<=slices; i++)
{
if (qobj->orientation==GLU_OUTSIDE)
{
if (qobj->textureCoords)
{
texcoords[i*2][0]=texLow*sinCache[i]+0.5f;
texcoords[i*2][1]=texLow*cosCache[i]+0.5f;
}
vertices[i*2][0]=radiusLow*sinCache[i];
vertices[i*2][1]=radiusLow*cosCache[i];
vertices[i*2][2]=0.0;
if (qobj->textureCoords)
{
texcoords[i*2+1][0]=texHigh*sinCache[i]+0.5f;
texcoords[i*2+1][1]=texHigh*cosCache[i]+0.5f;
}
vertices[i*2+1][0]=radiusHigh*sinCache[i];
vertices[i*2+1][1]=radiusHigh*cosCache[i];
vertices[i*2+1][2]=0.0;
}
else
{
if (qobj->textureCoords)
{
texcoords[i*2][0]=texHigh*sinCache[i]+0.5f;
texcoords[i*2][1]=texHigh*cosCache[i]+0.5f;
}
vertices[i*2][0]=radiusHigh*sinCache[i];
vertices[i*2][1]=radiusHigh*cosCache[i];
vertices[i*2][2]=0.0;
if (qobj->textureCoords)
{
texcoords[i*2+1][0]=texLow*sinCache[i]+0.5f;
texcoords[i*2+1][1]=texLow*cosCache[i]+0.5f;
}
vertices[i*2+1][0]=radiusLow*sinCache[i];
vertices[i*2+1][1]=radiusLow*cosCache[i];
vertices[i*2+1][2]=0.0;
}
}
glDrawArrays(GL_TRIANGLE_STRIP, 0, ((slices+1)*2));
}
break;
case GLU_POINT:
for (j=0; j<=loops; j++)
{
radiusLow=outerRadius-deltaRadius*((GLfloat)j/loops);
for (i=0; i<slices2; i++)
{
sintemp=sinCache[i];
costemp=cosCache[i];
if (qobj->textureCoords)
{
texLow=radiusLow/outerRadius/2;
texcoords[i][0]=texLow*sinCache[i]+0.5f;
texcoords[i][1]=texLow*cosCache[i]+0.5f;
}
vertices[i][0]=radiusLow*sintemp;
vertices[i][1]=radiusLow*costemp;
vertices[i][2]=0.0f;
}
glDrawArrays(GL_POINTS, 0, slices2);
}
break;
case GLU_LINE:
if (innerRadius==outerRadius)
{
for (i=0; i<=slices; i++)
{
if (qobj->textureCoords)
{
texcoords[i][0]=sinCache[i]/2+0.5f;
texcoords[i][1]=cosCache[i]/2+0.5f;
}
vertices[i][0]=innerRadius*sinCache[i];
vertices[i][1]=innerRadius*cosCache[i];
vertices[i][2]=0.0f;
}
glDrawArrays(GL_LINE_STRIP, 0, slices+1);
break;
}
for (j=0; j<=loops; j++)
{
radiusLow=outerRadius-deltaRadius*((GLfloat)j/loops);
if (qobj->textureCoords)
{
texLow=radiusLow/outerRadius/2;
}
for (i=0; i<=slices; i++)
{
if (qobj->textureCoords)
{
texcoords[i][0]=texLow*sinCache[i]+0.5f;
texcoords[i][1]=texLow*cosCache[i]+0.5f;
}
vertices[i][0]=radiusLow*sinCache[i];
vertices[i][1]=radiusLow*cosCache[i];
vertices[i][2]=0.0f;
}
glDrawArrays(GL_LINE_STRIP, 0, slices+1);
}
for (i=0; i<slices2; i++)
{
sintemp=sinCache[i];
costemp=cosCache[i];
for (j=0; j<=loops; j++)
{
radiusLow=outerRadius-deltaRadius*((GLfloat)j/loops);
if (qobj->textureCoords)
{
texLow=radiusLow/outerRadius/2;
}
if (qobj->textureCoords)
{
texcoords[j][0]=texLow*sinCache[i]+0.5f;
texcoords[j][1]=texLow*cosCache[i]+0.5f;
}
vertices[j][0]=radiusLow*sintemp;
vertices[j][1]=radiusLow*costemp;
vertices[j][2]=0.0f;
}
glDrawArrays(GL_LINE_STRIP, 0, loops+1);
}
break;
case GLU_SILHOUETTE:
if (sweepAngle<360.0)
{
for (i=0; i<=slices; i+=slices)
{
sintemp=sinCache[i];
costemp=cosCache[i];
for (j=0; j<=loops; j++)
{
radiusLow=outerRadius-deltaRadius*((GLfloat)j/loops);
if (qobj->textureCoords)
{
texLow=radiusLow/outerRadius/2;
texcoords[j][0]=texLow*sinCache[i]+0.5f;
texcoords[j][1]=texLow*cosCache[i]+0.5f;
}
vertices[j][0]=radiusLow*sintemp;
vertices[j][1]=radiusLow*costemp;
vertices[j][2]=0.0f;
}
glDrawArrays(GL_LINE_STRIP, 0, loops+1);
}
}
for (j=0; j<=loops; j+=loops)
{
radiusLow=outerRadius-deltaRadius*((GLfloat)j/loops);
if (qobj->textureCoords)
{
texLow=radiusLow/outerRadius/2;
}
for (i=0; i<=slices; i++)
{
if (qobj->textureCoords)
{
texcoords[i][0]=texLow*sinCache[i]+0.5f;
texcoords[i][1]=texLow*cosCache[i]+0.5f;
}
vertices[i][0]=radiusLow*sinCache[i];
vertices[i][1]=radiusLow*cosCache[i];
vertices[i][2]=0.0f;
}
glDrawArrays(GL_LINE_STRIP, 0, slices+1);
if (innerRadius==outerRadius)
{
break;
}
}
break;
default:
break;
}
/* Disable or re-enable arrays */
if (vertex_enabled)
{
/* Re-enable vertex array */
glEnableClientState(GL_VERTEX_ARRAY);
}
else
{
glDisableClientState(GL_VERTEX_ARRAY);
}
if (texcoord_enabled)
{
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
}
else
{
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
}
if (normal_enabled)
{
glEnableClientState(GL_NORMAL_ARRAY);
}
else
{
glDisableClientState(GL_NORMAL_ARRAY);
}
if (color_enabled)
{
glEnableClientState(GL_COLOR_ARRAY);
}
else
{
glDisableClientState(GL_COLOR_ARRAY);
}
}
GLAPI void APIENTRY gluSphere(GLUquadric* qobj, GLfloat radius, GLint slices, GLint stacks)
{
GLint i, j;
GLfloat sinCache1a[CACHE_SIZE];
GLfloat cosCache1a[CACHE_SIZE];
GLfloat sinCache2a[CACHE_SIZE];
GLfloat cosCache2a[CACHE_SIZE];
GLfloat sinCache3a[CACHE_SIZE];
GLfloat cosCache3a[CACHE_SIZE];
GLfloat sinCache1b[CACHE_SIZE];
GLfloat cosCache1b[CACHE_SIZE];
GLfloat sinCache2b[CACHE_SIZE];
GLfloat cosCache2b[CACHE_SIZE];
GLfloat sinCache3b[CACHE_SIZE];
GLfloat cosCache3b[CACHE_SIZE];
GLfloat angle;
GLfloat zLow, zHigh;
GLfloat sintemp1 = 0.0, sintemp2 = 0.0, sintemp3 = 0.0, sintemp4 = 0.0;
GLfloat costemp1 = 0.0, costemp2 = 0.0, costemp3 = 0.0, costemp4 = 0.0;
GLfloat vertices[(CACHE_SIZE+1)*2][3];
GLfloat texcoords[(CACHE_SIZE+1)*2][2];
GLfloat normals[(CACHE_SIZE+1)*2][3];
GLboolean needCache2, needCache3;
GLint start, finish;
GLboolean texcoord_enabled;
GLboolean normal_enabled;
GLboolean vertex_enabled;
GLboolean color_enabled;
if (slices>=CACHE_SIZE)
{
slices=CACHE_SIZE-1;
}
if (stacks>=CACHE_SIZE)
{
stacks=CACHE_SIZE-1;
}
if (slices<2 || stacks<1 || radius<0.0)
{
gluQuadricError(qobj, GLU_INVALID_VALUE);
return;
}
/* Cache is the vertex locations cache */
/* Cache2 is the various normals at the vertices themselves */
/* Cache3 is the various normals for the faces */
needCache2=needCache3=GL_FALSE;
if (qobj->normals==GLU_SMOOTH)
{
needCache2=GL_TRUE;
}
if (qobj->normals==GLU_FLAT)
{
if (qobj->drawStyle!=GLU_POINT)
{
needCache3=GL_TRUE;
}
if (qobj->drawStyle==GLU_LINE)
{
needCache2=GL_TRUE;
}
}
for (i=0; i<slices; i++)
{
angle=2.0f*PI*i/slices;
sinCache1a[i]=(GLfloat)sin(angle);
cosCache1a[i]=(GLfloat)cos(angle);
if (needCache2)
{
sinCache2a[i] = sinCache1a[i];
cosCache2a[i] = cosCache1a[i];
}
}
for (j=0; j<=stacks; j++)
{
angle=PI*j/stacks;
if (needCache2)
{
if (qobj->orientation==GLU_OUTSIDE)
{
sinCache2b[j]=(GLfloat)sin(angle);
cosCache2b[j]=(GLfloat)cos(angle);
}
else
{
sinCache2b[j]=(GLfloat)-sin(angle);
cosCache2b[j]=(GLfloat)-cos(angle);
}
}
sinCache1b[j]=(GLfloat)(radius*sin(angle));
cosCache1b[j]=(GLfloat)(radius*cos(angle));
}
/* Make sure it comes to a point */
sinCache1b[0]=0;
sinCache1b[stacks]=0;
if (needCache3)
{
for (i=0; i<slices; i++)
{
angle=2.0f*PI*(i-0.5f)/slices;
sinCache3a[i]=(GLfloat)sin(angle);
cosCache3a[i]=(GLfloat)cos(angle);
}
for (j=0; j<=stacks; j++)
{
angle=PI*(j-0.5f)/stacks;
if (qobj->orientation==GLU_OUTSIDE)
{
sinCache3b[j]=(GLfloat)sin(angle);
cosCache3b[j]=(GLfloat)cos(angle);
}
else
{
sinCache3b[j]=(GLfloat)-sin(angle);
cosCache3b[j]=(GLfloat)-cos(angle);
}
}
}
sinCache1a[slices]=sinCache1a[0];
cosCache1a[slices]=cosCache1a[0];
if (needCache2)
{
sinCache2a[slices]=sinCache2a[0];
cosCache2a[slices]=cosCache2a[0];
}
if (needCache3)
{
sinCache3a[slices]=sinCache3a[0];
cosCache3a[slices]=cosCache3a[0];
}
/* Store status of enabled arrays */
texcoord_enabled=GL_FALSE; //glIsEnabled(GL_TEXTURE_COORD_ARRAY);
normal_enabled=GL_FALSE; //glIsEnabled(GL_NORMAL_ARRAY);
vertex_enabled=GL_FALSE; //glIsEnabled(GL_VERTEX_ARRAY);
color_enabled=GL_FALSE; //glIsEnabled(GL_COLOR_ARRAY);
/* Enable arrays */
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, vertices);
if (qobj->textureCoords)
{
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glTexCoordPointer(2, GL_FLOAT, 0, texcoords);
}
else
{
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
}
if (qobj->normals!=GLU_NONE)
{
glEnableClientState(GL_NORMAL_ARRAY);
glNormalPointer(GL_FLOAT, 0, normals);
}
else
{
glDisableClientState(GL_NORMAL_ARRAY);
}
glDisableClientState(GL_COLOR_ARRAY);
switch (qobj->drawStyle)
{
case GLU_FILL:
if (!(qobj->textureCoords))
{
start=1;
finish=stacks-1;
/* Low end first (j == 0 iteration) */
sintemp2=sinCache1b[1];
zHigh=cosCache1b[1];
switch(qobj->normals)
{
case GLU_FLAT:
sintemp3=sinCache3b[1];
costemp3=cosCache3b[1];
normals[0][0]=sinCache3a[0]*sinCache3b[0];
normals[0][1]=cosCache3a[0]*sinCache3b[0];
normals[0][2]=cosCache3b[0];
break;
case GLU_SMOOTH:
sintemp3=sinCache2b[1];
costemp3=cosCache2b[1];
normals[0][0]=sinCache2a[0]*sinCache2b[0];
normals[0][1]=cosCache2a[0]*sinCache2b[0];
normals[0][2]=cosCache2b[0];
break;
default:
break;
}
vertices[0][0]=0.0f;
vertices[0][1]=0.0f;
vertices[0][2]=radius;
if (qobj->orientation==GLU_OUTSIDE)
{
for (i=slices; i>=0; i--)
{
switch(qobj->normals)
{
case GLU_SMOOTH:
normals[slices-i+1][0]=sinCache2a[i]*sintemp3;
normals[slices-i+1][1]=cosCache2a[i]*sintemp3;
normals[slices-i+1][2]=costemp3;
break;
case GLU_FLAT:
if (i!=slices)
{
normals[slices-i+1][0]=sinCache3a[i+1]*sintemp3;
normals[slices-i+1][1]=cosCache3a[i+1]*sintemp3;
normals[slices-i+1][2]=costemp3;
}
else
{
/* We must add any normal here */
normals[slices-i+1][0]=sinCache3a[i]*sintemp3;
normals[slices-i+1][1]=cosCache3a[i]*sintemp3;
normals[slices-i+1][2]=costemp3;
}
break;
case GLU_NONE:
default:
break;
}
vertices[slices-i+1][0]=sintemp2*sinCache1a[i];
vertices[slices-i+1][1]=sintemp2*cosCache1a[i];
vertices[slices-i+1][2]=zHigh;
}
}
else
{
for (i=0; i<=slices; i++)
{
switch(qobj->normals)
{
case GLU_SMOOTH:
normals[i+1][0]=sinCache2a[i]*sintemp3;
normals[i+1][1]=cosCache2a[i]*sintemp3;
normals[i+1][2]=costemp3;
break;
case GLU_FLAT:
normals[i+1][0]=sinCache3a[i]*sintemp3;
normals[i+1][1]=cosCache3a[i]*sintemp3;
normals[i+1][2]=costemp3;
break;
case GLU_NONE:
default:
break;
}
vertices[i+1][0]=sintemp2*sinCache1a[i];
vertices[i+1][1]=sintemp2*cosCache1a[i];
vertices[i+1][2]=zHigh;
}
}
glDrawArrays(GL_TRIANGLE_FAN, 0, (slices+2));
/* High end next (j==stacks-1 iteration) */
sintemp2=sinCache1b[stacks-1];
zHigh=cosCache1b[stacks-1];
switch(qobj->normals)
{
case GLU_FLAT:
sintemp3=sinCache3b[stacks];
costemp3=cosCache3b[stacks];
normals[0][0]=sinCache3a[stacks]*sinCache3b[stacks];
normals[0][1]=cosCache3a[stacks]*sinCache3b[stacks];
normals[0][2]=cosCache3b[stacks];
break;
case GLU_SMOOTH:
sintemp3=sinCache2b[stacks-1];
costemp3=cosCache2b[stacks-1];
normals[0][0]=sinCache2a[stacks]*sinCache2b[stacks];
normals[0][1]=cosCache2a[stacks]*sinCache2b[stacks];
normals[0][2]=cosCache2b[stacks];
break;
default:
break;
}
vertices[0][0]=0.0f;
vertices[0][1]=0.0f;
vertices[0][2]=-radius;
if (qobj->orientation==GLU_OUTSIDE)
{
for (i=0; i<=slices; i++)
{
switch(qobj->normals)
{
case GLU_SMOOTH:
normals[i+1][0]=sinCache2a[i]*sintemp3;
normals[i+1][1]=cosCache2a[i]*sintemp3;
normals[i+1][2]=costemp3;
break;
case GLU_FLAT:
normals[i+1][0]=sinCache3a[i]*sintemp3;
normals[i+1][1]=cosCache3a[i]*sintemp3;
normals[i+1][2]=costemp3;
break;
case GLU_NONE:
default:
break;
}
vertices[i+1][0]=sintemp2*sinCache1a[i];
vertices[i+1][1]=sintemp2*cosCache1a[i];
vertices[i+1][2]=zHigh;
}
}
else
{
for (i=slices; i>=0; i--)
{
switch(qobj->normals)
{
case GLU_SMOOTH:
normals[slices-i+1][0]=sinCache2a[i]*sintemp3;
normals[slices-i+1][1]=cosCache2a[i]*sintemp3;
normals[slices-i+1][2]=costemp3;
break;
case GLU_FLAT:
if (i!=slices)
{
normals[slices-i+1][0]=sinCache3a[i+1]*sintemp3;
normals[slices-i+1][1]=cosCache3a[i+1]*sintemp3;
normals[slices-i+1][2]=costemp3;
}
else
{
normals[slices-i+1][0]=sinCache3a[i]*sintemp3;
normals[slices-i+1][1]=cosCache3a[i]*sintemp3;
normals[slices-i+1][2]=costemp3;
}
break;
case GLU_NONE:
default:
break;
}
vertices[slices-i+1][0]=sintemp2*sinCache1a[i];
vertices[slices-i+1][1]=sintemp2*cosCache1a[i];
vertices[slices-i+1][2]=zHigh;
}
}
glDrawArrays(GL_TRIANGLE_FAN, 0, (slices+2));
}
else
{
start=0;
finish=stacks;
}
for (j=start; j<finish; j++)
{
zLow=cosCache1b[j];
zHigh=cosCache1b[j+1];
sintemp1=sinCache1b[j];
sintemp2=sinCache1b[j+1];
switch(qobj->normals)
{
case GLU_FLAT:
sintemp4=sinCache3b[j+1];
costemp4=cosCache3b[j+1];
break;
case GLU_SMOOTH:
if (qobj->orientation==GLU_OUTSIDE)
{
sintemp3=sinCache2b[j+1];
costemp3=cosCache2b[j+1];
sintemp4=sinCache2b[j];
costemp4=cosCache2b[j];
}
else
{
sintemp3=sinCache2b[j];
costemp3=cosCache2b[j];
sintemp4=sinCache2b[j+1];
costemp4=cosCache2b[j+1];
}
break;
default:
break;
}
for (i=0; i<=slices; i++)
{
switch(qobj->normals)
{
case GLU_SMOOTH:
normals[i*2][0]=sinCache2a[i]*sintemp3;
normals[i*2][1]=cosCache2a[i]*sintemp3;
normals[i*2][2]=costemp3;
break;
case GLU_FLAT:
normals[i*2][0]=sinCache3a[i]*sintemp4;
normals[i*2][1]=cosCache3a[i]*sintemp4;
normals[i*2][2]=costemp4;
break;
case GLU_NONE:
default:
break;
}
if (qobj->orientation==GLU_OUTSIDE)
{
if (qobj->textureCoords)
{
texcoords[i*2][0]=1-(GLfloat)i/slices;
texcoords[i*2][1]=1-(GLfloat)(j+1)/stacks;
}
vertices[i*2][0]=sintemp2*sinCache1a[i];
vertices[i*2][1]=sintemp2*cosCache1a[i];
vertices[i*2][2]=zHigh;
}
else
{
if (qobj->textureCoords)
{
texcoords[i*2][0]=1-(GLfloat)i/slices;
texcoords[i*2][1]=1-(GLfloat)j/stacks;
}
vertices[i*2][0]=sintemp1*sinCache1a[i];
vertices[i*2][1]=sintemp1*cosCache1a[i];
vertices[i*2][2]=zLow;
}
switch(qobj->normals)
{
case GLU_SMOOTH:
normals[i*2+1][0]=sinCache2a[i]*sintemp4;
normals[i*2+1][1]=cosCache2a[i]*sintemp4;
normals[i*2+1][2]=costemp4;
break;
case GLU_FLAT:
normals[i*2+1][0]=sinCache3a[i]*sintemp4;
normals[i*2+1][1]=cosCache3a[i]*sintemp4;
normals[i*2+1][2]=costemp4;
break;
case GLU_NONE:
default:
break;
}
if (qobj->orientation==GLU_OUTSIDE)
{
if (qobj->textureCoords)
{
texcoords[i*2+1][0]=1-(GLfloat)i/slices;
texcoords[i*2+1][1]=1-(GLfloat)j/stacks;
}
vertices[i*2+1][0]=sintemp1*sinCache1a[i];
vertices[i*2+1][1]=sintemp1*cosCache1a[i];
vertices[i*2+1][2]=zLow;
}
else
{
if (qobj->textureCoords)
{
texcoords[i*2+1][0]=1-(GLfloat)i/slices;
texcoords[i*2+1][1]=1-(GLfloat)(j+1)/stacks;
}
vertices[i*2+1][0]=sintemp2*sinCache1a[i];
vertices[i*2+1][1]=sintemp2*cosCache1a[i];
vertices[i*2+1][2]=zHigh;
}
}
glDrawArrays(GL_TRIANGLE_STRIP, 0, (slices+1)*2);
}
break;
case GLU_POINT:
for (j=0; j<=stacks; j++)
{
sintemp1=sinCache1b[j];
costemp1=cosCache1b[j];
switch(qobj->normals)
{
case GLU_FLAT:
case GLU_SMOOTH:
sintemp2=sinCache2b[j];
costemp2=cosCache2b[j];
break;
default:
break;
}
for (i=0; i<slices; i++)
{
switch(qobj->normals)
{
case GLU_FLAT:
case GLU_SMOOTH:
normals[i][0]=sinCache2a[i]*sintemp2;
normals[i][1]=cosCache2a[i]*sintemp2;
normals[i][2]=costemp2;
break;
case GLU_NONE:
default:
break;
}
zLow=j*radius/stacks;
if (qobj->textureCoords)
{
texcoords[i][0]=1-(GLfloat)i/slices;
texcoords[i][1]=1-(GLfloat)j/stacks;
}
vertices[i][0]=sintemp1*sinCache1a[i];
vertices[i][1]=sintemp1*cosCache1a[i];
vertices[i][2]=costemp1;
}
glDrawArrays(GL_POINTS, 0, slices);
}
break;
case GLU_LINE:
case GLU_SILHOUETTE:
for (j=1; j<stacks; j++)
{
sintemp1=sinCache1b[j];
costemp1=cosCache1b[j];
switch(qobj->normals)
{
case GLU_FLAT:
case GLU_SMOOTH:
sintemp2=sinCache2b[j];
costemp2=cosCache2b[j];
break;
default:
break;
}
for (i=0; i<=slices; i++)
{
switch(qobj->normals)
{
case GLU_FLAT:
normals[i][0]=sinCache3a[i]*sintemp2;
normals[i][1]=cosCache3a[i]*sintemp2;
normals[i][2]=costemp2;
break;
case GLU_SMOOTH:
normals[i][0]=sinCache2a[i]*sintemp2;
normals[i][1]=cosCache2a[i]*sintemp2;
normals[i][2]=costemp2;
break;
case GLU_NONE:
default:
break;
}
if (qobj->textureCoords)
{
texcoords[i][0]=1-(GLfloat)i/slices;
texcoords[i][1]=1-(GLfloat)j/stacks;
}
vertices[i][0]=sintemp1*sinCache1a[i];
vertices[i][1]=sintemp1*cosCache1a[i];
vertices[i][2]=costemp1;
}
glDrawArrays(GL_LINE_STRIP, 0, slices+1);
}
for (i=0; i<slices; i++)
{
sintemp1=sinCache1a[i];
costemp1=cosCache1a[i];
switch(qobj->normals)
{
case GLU_FLAT:
case GLU_SMOOTH:
sintemp2=sinCache2a[i];
costemp2=cosCache2a[i];
break;
default:
break;
}
for (j=0; j<=stacks; j++)
{
switch(qobj->normals)
{
case GLU_FLAT:
normals[j][0]=sintemp2*sinCache3b[j];
normals[j][1]=costemp2*sinCache3b[j];
normals[j][2]=cosCache3b[j];
break;
case GLU_SMOOTH:
normals[j][0]=sintemp2*sinCache2b[j];
normals[j][1]=costemp2*sinCache2b[j];
normals[j][2]=cosCache2b[j];
break;
case GLU_NONE:
default:
break;
}
if (qobj->textureCoords)
{
texcoords[j][0]=1-(GLfloat)i/slices;
texcoords[j][1]=1-(GLfloat)j/stacks;
}
vertices[j][0]=sintemp1*sinCache1b[j];
vertices[j][1]=costemp1*sinCache1b[j];
vertices[j][2]=cosCache1b[j];
}
glDrawArrays(GL_LINE_STRIP, 0, stacks+1);
}
break;
default:
break;
}
/* Disable or re-enable arrays */
if (vertex_enabled)
{
/* Re-enable vertex array */
glEnableClientState(GL_VERTEX_ARRAY);
}
else
{
glDisableClientState(GL_VERTEX_ARRAY);
}
if (texcoord_enabled)
{
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
}
else
{
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
}
if (normal_enabled)
{
glEnableClientState(GL_NORMAL_ARRAY);
}
else
{
glDisableClientState(GL_NORMAL_ARRAY);
}
if (color_enabled)
{
glEnableClientState(GL_COLOR_ARRAY);
}
else
{
glDisableClientState(GL_COLOR_ARRAY);
}
}