Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

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