home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / mesa5.zip / mesa5src.zip / MesaDLL / quadric.cpp < prev    next >
C/C++ Source or Header  |  2002-12-18  |  24KB  |  823 lines

  1. /* $Id: quadric.c,v 1.9 2001/01/15 20:04:28 brianp Exp $ */
  2.  
  3. /*
  4.  * Mesa 3-D graphics library
  5.  * Version:  3.3
  6.  * Copyright (C) 1999-2000  Brian Paul
  7.  *
  8.  * This library is free software; you can redistribute it and/or
  9.  * modify it under the terms of the GNU Library General Public
  10.  * License as published by the Free Software Foundation; either
  11.  * version 2 of the License, or (at your option) any later version.
  12.  *
  13.  * This library is distributed in the hope that it will be useful,
  14.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  16.  * Library General Public License for more details.
  17.  *
  18.  * You should have received a copy of the GNU Library General Public
  19.  * License along with this library; if not, write to the Free
  20.  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  21.  */
  22.  
  23.  
  24. /* TODO:
  25.  *   texture coordinate support
  26.  *   flip normals according to orientation
  27.  *   there's still some inside/outside orientation bugs in possibly all
  28.  *     but the sphere function
  29.  */
  30.  
  31.  
  32. #ifdef PC_HEADER
  33. #include "all.h"
  34. #else
  35. #include <math.h>
  36. #include <stdio.h>
  37. #include <stdlib.h>
  38. #include "gluP.h"
  39. #endif
  40.  
  41.  
  42.  
  43. #ifndef M_PI
  44. #  define M_PI (3.1415926)
  45. #endif
  46.  
  47.  
  48. /*
  49.  * Convert degrees to radians:
  50.  */
  51. #define DEG_TO_RAD(A)   ((A)*(M_PI/180.0))
  52.  
  53.  
  54. /*
  55.  * Sin and Cos for degree angles:
  56.  */
  57. #define SIND( A )   sin( (A)*(M_PI/180.0) )
  58. #define COSD( A)    cos( (A)*(M_PI/180.0) )
  59.  
  60.  
  61. /*
  62.  * Texture coordinates if texture flag is set
  63.  */
  64. #define TXTR_COORD(x,y)    if (qobj->TextureFlag) glTexCoord2f(x,y);
  65.  
  66.  
  67.  
  68. struct GLUquadric
  69. {
  70.    GLenum DrawStyle;           /* GLU_FILL, LINE, SILHOUETTE, or POINT */
  71.    GLenum Orientation;         /* GLU_INSIDE or GLU_OUTSIDE */
  72.    GLboolean TextureFlag;      /* Generate texture coords? */
  73.    GLenum Normals;             /* GLU_NONE, GLU_FLAT, or GLU_SMOOTH */
  74.    void (GLCALLBACK * ErrorFunc) (GLenum err); /* Error handler callback function */
  75. };
  76.  
  77.  
  78.  
  79. /*
  80.  * Process a GLU error.
  81.  */
  82. static void
  83. quadric_error(GLUquadricObj * qobj, GLenum error, const char *msg)
  84. {
  85.    /* Call the error call back function if any */
  86.    if (qobj->ErrorFunc) {
  87.       (*qobj->ErrorFunc) (error);
  88.    }
  89.    /* Print a message to stdout if MESA_DEBUG variable is defined */
  90.    if (getenv("MESA_DEBUG")) {
  91.       fprintf(stderr, "GLUError: %s: %s\n", (char *) gluErrorString(error),
  92.              msg);
  93.    }
  94. }
  95.  
  96.  
  97.  
  98.  
  99. GLUquadricObj *GLAPIENTRY
  100. gluNewQuadric(void)
  101. {
  102.    GLUquadricObj *q;
  103.  
  104.    q = (GLUquadricObj *) malloc(sizeof(struct GLUquadric));
  105.    if (q) {
  106.       q->DrawStyle = GLU_FILL;
  107.       q->Orientation = GLU_OUTSIDE;
  108.       q->TextureFlag = GL_FALSE;
  109.       q->Normals = GLU_SMOOTH;
  110.       q->ErrorFunc = NULL;
  111.    }
  112.    return q;
  113. }
  114.  
  115.  
  116.  
  117. void GLAPIENTRY
  118. gluDeleteQuadric(GLUquadricObj * state)
  119. {
  120.    if (state) {
  121.       free((void *) state);
  122.    }
  123. }
  124.  
  125.  
  126.  
  127. /*
  128.  * Set the drawing style to be GLU_FILL, GLU_LINE, GLU_SILHOUETTE,
  129.  * or GLU_POINT.
  130.  */
  131. void GLAPIENTRY
  132. gluQuadricDrawStyle(GLUquadricObj * quadObject, GLenum drawStyle)
  133. {
  134.    if (quadObject && (drawStyle == GLU_FILL || drawStyle == GLU_LINE
  135.                      || drawStyle == GLU_SILHOUETTE
  136.                      || drawStyle == GLU_POINT)) {
  137.       quadObject->DrawStyle = drawStyle;
  138.    }
  139.    else {
  140.       quadric_error(quadObject, GLU_INVALID_ENUM, "qluQuadricDrawStyle");
  141.    }
  142. }
  143.  
  144.  
  145.  
  146. /*
  147.  * Set the orientation to GLU_INSIDE or GLU_OUTSIDE.
  148.  */
  149. void GLAPIENTRY
  150. gluQuadricOrientation(GLUquadricObj * quadObject, GLenum orientation)
  151. {
  152.    if (quadObject
  153.        && (orientation == GLU_INSIDE || orientation == GLU_OUTSIDE)) {
  154.       quadObject->Orientation = orientation;
  155.    }
  156.    else {
  157.       quadric_error(quadObject, GLU_INVALID_ENUM, "qluQuadricOrientation");
  158.    }
  159. }
  160.  
  161.  
  162.  
  163. /*
  164.  * Set the error handler callback function.
  165.  */
  166. void GLAPIENTRY
  167. gluQuadricCallback(GLUquadricObj * qobj,
  168.                   GLenum which, void (GLCALLBACK * fn) ())
  169. {
  170.    /*
  171.     * UGH, this is a mess!  I thought ANSI was a standard.
  172.     */
  173.    if (qobj && which == GLU_ERROR) {
  174. #ifdef __CYGWIN32__
  175.       qobj->ErrorFunc = (void (GLCALLBACKPCAST) (GLenum)) fn;
  176. #elif defined(OPENSTEP)
  177.       qobj->ErrorFunc = (void (*)(GLenum)) fn;
  178. #elif defined(_WIN32) || defined(__OS2__)
  179.  
  180.       qobj->ErrorFunc = (void(GLCALLBACK *)(GLenum)) fn;
  181. //    qobj->ErrorFunc = (void (GLCALLBACK *) (int)) fn;
  182. #elif defined(__STORM__)
  183.       qobj->ErrorFunc = (void (GLCALLBACK *) (GLenum)) fn;
  184. #elif defined(__BEOS__)
  185.       qobj->ErrorFunc = (void (*)(GLenum)) fn;
  186. #else
  187.       qobj->ErrorFunc = (void (GLCALLBACK *) ()) fn;
  188. #endif
  189.    }
  190. }
  191.  
  192.  
  193. void GLAPIENTRY
  194. gluQuadricNormals(GLUquadricObj * quadObject, GLenum normals)
  195. {
  196.    if (quadObject
  197.        && (normals == GLU_NONE || normals == GLU_FLAT
  198.           || normals == GLU_SMOOTH)) {
  199.       quadObject->Normals = normals;
  200.    }
  201. }
  202.  
  203.  
  204. void GLAPIENTRY
  205. gluQuadricTexture(GLUquadricObj * quadObject, GLboolean textureCoords)
  206. {
  207.    if (quadObject) {
  208.       quadObject->TextureFlag = textureCoords;
  209.    }
  210. }
  211.  
  212.  
  213.  
  214.  
  215. /*
  216.  * Call glNormal3f after scaling normal to unit length.
  217.  */
  218. static void
  219. normal3f(GLfloat x, GLfloat y, GLfloat z)
  220. {
  221.    GLdouble mag;
  222.  
  223.    mag = sqrt(x * x + y * y + z * z);
  224.    if (mag > 0.00001F) {
  225.       x /= mag;
  226.       y /= mag;
  227.       z /= mag;
  228.    }
  229.    glNormal3f(x, y, z);
  230. }
  231.  
  232.  
  233.  
  234. void GLAPIENTRY
  235. gluCylinder(GLUquadricObj * qobj,
  236.            GLdouble baseRadius, GLdouble topRadius,
  237.            GLdouble height, GLint slices, GLint stacks)
  238. {
  239.    GLdouble da, r, dr, dz;
  240.    GLfloat x, y, z, nz, nsign;
  241.    GLint i, j;
  242.  
  243.    if (qobj->Orientation == GLU_INSIDE) {
  244.       nsign = -1.0;
  245.    }
  246.    else {
  247.       nsign = 1.0;
  248.    }
  249.  
  250.    da = 2.0 * M_PI / slices;
  251.    dr = (topRadius - baseRadius) / stacks;
  252.    dz = height / stacks;
  253.    nz = (baseRadius - topRadius) / height;     /* Z component of normal vectors */
  254.  
  255.    if (qobj->DrawStyle == GLU_POINT) {
  256.       glBegin(GL_POINTS);
  257.       for (i = 0; i < slices; i++) {
  258.         x = cos(i * da);
  259.         y = sin(i * da);
  260.         normal3f(x * nsign, y * nsign, nz * nsign);
  261.  
  262.         z = 0.0;
  263.         r = baseRadius;
  264.         for (j = 0; j <= stacks; j++) {
  265.            glVertex3f(x * r, y * r, z);
  266.            z += dz;
  267.            r += dr;
  268.         }
  269.       }
  270.       glEnd();
  271.    }
  272.    else if (qobj->DrawStyle == GLU_LINE || qobj->DrawStyle == GLU_SILHOUETTE) {
  273.       /* Draw rings */
  274.       if (qobj->DrawStyle == GLU_LINE) {
  275.         z = 0.0;
  276.         r = baseRadius;
  277.         for (j = 0; j <= stacks; j++) {
  278.            glBegin(GL_LINE_LOOP);
  279.            for (i = 0; i < slices; i++) {
  280.               x = cos(i * da);
  281.               y = sin(i * da);
  282.               normal3f(x * nsign, y * nsign, nz * nsign);
  283.               glVertex3f(x * r, y * r, z);
  284.            }
  285.            glEnd();
  286.            z += dz;
  287.            r += dr;
  288.         }
  289.       }
  290.       else {
  291.         /* draw one ring at each end */
  292.         if (baseRadius != 0.0) {
  293.            glBegin(GL_LINE_LOOP);
  294.            for (i = 0; i < slices; i++) {
  295.               x = cos(i * da);
  296.               y = sin(i * da);
  297.               normal3f(x * nsign, y * nsign, nz * nsign);
  298.               glVertex3f(x * baseRadius, y * baseRadius, 0.0);
  299.            }
  300.            glEnd();
  301.            glBegin(GL_LINE_LOOP);
  302.            for (i = 0; i < slices; i++) {
  303.               x = cos(i * da);
  304.               y = sin(i * da);
  305.               normal3f(x * nsign, y * nsign, nz * nsign);
  306.               glVertex3f(x * topRadius, y * topRadius, height);
  307.            }
  308.            glEnd();
  309.         }
  310.       }
  311.       /* draw length lines */
  312.       glBegin(GL_LINES);
  313.       for (i = 0; i < slices; i++) {
  314.         x = cos(i * da);
  315.         y = sin(i * da);
  316.         normal3f(x * nsign, y * nsign, nz * nsign);
  317.         glVertex3f(x * baseRadius, y * baseRadius, 0.0);
  318.         glVertex3f(x * topRadius, y * topRadius, height);
  319.       }
  320.       glEnd();
  321.    }
  322.    else if (qobj->DrawStyle == GLU_FILL) {
  323.       GLfloat ds = 1.0 / slices;
  324.       GLfloat dt = 1.0 / stacks;
  325.       GLfloat t = 0.0;
  326.       z = 0.0;
  327.       r = baseRadius;
  328.       for (j = 0; j < stacks; j++) {
  329.         GLfloat s = 0.0;
  330.         glBegin(GL_QUAD_STRIP);
  331.         for (i = 0; i <= slices; i++) {
  332.            GLfloat x, y;
  333.            if (i == slices) {
  334.               x = sin(0.0);
  335.               y = cos(0.0);
  336.            }
  337.            else {
  338.               x = sin(i * da);
  339.               y = cos(i * da);
  340.            }
  341.            if (nsign == 1.0) {
  342.               normal3f(x * nsign, y * nsign, nz * nsign);
  343.               TXTR_COORD(s, t);
  344.               glVertex3f(x * r, y * r, z);
  345.               normal3f(x * nsign, y * nsign, nz * nsign);
  346.               TXTR_COORD(s, t + dt);
  347.               glVertex3f(x * (r + dr), y * (r + dr), z + dz);
  348.            }
  349.            else {
  350.               normal3f(x * nsign, y * nsign, nz * nsign);
  351.               TXTR_COORD(s, t);
  352.               glVertex3f(x * r, y * r, z);
  353.               normal3f(x * nsign, y * nsign, nz * nsign);
  354.               TXTR_COORD(s, t + dt);
  355.               glVertex3f(x * (r + dr), y * (r + dr), z + dz);
  356.            }
  357.            s += ds;
  358.         }                      /* for slices */
  359.         glEnd();
  360.         r += dr;
  361.         t += dt;
  362.         z += dz;
  363.       }                                /* for stacks */
  364.    }
  365. }
  366.  
  367.  
  368.  
  369.  
  370.  
  371. void GLAPIENTRY
  372. gluSphere(GLUquadricObj * qobj, GLdouble radius, GLint slices, GLint stacks)
  373. {
  374.    GLfloat rho, drho, theta, dtheta;
  375.    GLfloat x, y, z;
  376.    GLfloat s, t, ds, dt;
  377.    GLint i, j, imin, imax;
  378.    GLboolean normals;
  379.    GLfloat nsign;
  380.  
  381.    if (qobj->Normals == GLU_NONE) {
  382.       normals = GL_FALSE;
  383.    }
  384.    else {
  385.       normals = GL_TRUE;
  386.    }
  387.    if (qobj->Orientation == GLU_INSIDE) {
  388.       nsign = -1.0;
  389.    }
  390.    else {
  391.       nsign = 1.0;
  392.    }
  393.  
  394.    drho = M_PI / (GLfloat) stacks;
  395.    dtheta = 2.0 * M_PI / (GLfloat) slices;
  396.  
  397.    /* texturing: s goes from 0.0/0.25/0.5/0.75/1.0 at +y/+x/-y/-x/+y axis */
  398.    /* t goes from -1.0/+1.0 at z = -radius/+radius (linear along longitudes) */
  399.    /* cannot use triangle fan on texturing (s coord. at top/bottom tip varies) */
  400.  
  401.    if (qobj->DrawStyle == GLU_FILL) {
  402.       if (!qobj->TextureFlag) {
  403.         /* draw +Z end as a triangle fan */
  404.         glBegin(GL_TRIANGLE_FAN);
  405.         glNormal3f(0.0, 0.0, 1.0);
  406.         glVertex3f(0.0, 0.0, nsign * radius);
  407.         for (j = 0; j <= slices; j++) {
  408.            theta = (j == slices) ? 0.0 : j * dtheta;
  409.            x = -sin(theta) * sin(drho);
  410.            y = cos(theta) * sin(drho);
  411.            z = nsign * cos(drho);
  412.            if (normals)
  413.               glNormal3f(x * nsign, y * nsign, z * nsign);
  414.            glVertex3f(x * radius, y * radius, z * radius);
  415.         }
  416.         glEnd();
  417.       }
  418.  
  419.       ds = 1.0 / slices;
  420.       dt = 1.0 / stacks;
  421.       t = 1.0;                 /* because loop now runs from 0 */
  422.       if (qobj->TextureFlag) {
  423.         imin = 0;
  424.         imax = stacks;
  425.       }
  426.       else {
  427.         imin = 1;
  428.         imax = stacks - 1;
  429.       }
  430.  
  431.       /* draw intermediate stacks as quad strips */
  432.       for (i = imin; i < imax; i++) {
  433.         rho = i * drho;
  434.         glBegin(GL_QUAD_STRIP);
  435.         s = 0.0;
  436.         for (j = 0; j <= slices; j++) {
  437.            theta = (j == slices) ? 0.0 : j * dtheta;
  438.            x = -sin(theta) * sin(rho);
  439.            y = cos(theta) * sin(rho);
  440.            z = nsign * cos(rho);
  441.            if (normals)
  442.               glNormal3f(x * nsign, y * nsign, z * nsign);
  443.            TXTR_COORD(s, t);
  444.            glVertex3f(x * radius, y * radius, z * radius);
  445.            x = -sin(theta) * sin(rho + drho);
  446.            y = cos(theta) * sin(rho + drho);
  447.            z = nsign * cos(rho + drho);
  448.            if (normals)
  449.               glNormal3f(x * nsign, y * nsign, z * nsign);
  450.            TXTR_COORD(s, t - dt);
  451.            s += ds;
  452.            glVertex3f(x * radius, y * radius, z * radius);
  453.         }
  454.         glEnd();
  455.         t -= dt;
  456.       }
  457.  
  458.       if (!qobj->TextureFlag) {
  459.         /* draw -Z end as a triangle fan */
  460.         glBegin(GL_TRIANGLE_FAN);
  461.         glNormal3f(0.0, 0.0, -1.0);
  462.         glVertex3f(0.0, 0.0, -radius * nsign);
  463.         rho = M_PI - drho;
  464.         s = 1.0;
  465.         t = dt;
  466.         for (j = slices; j >= 0; j--) {
  467.            theta = (j == slices) ? 0.0 : j * dtheta;
  468.            x = -sin(theta) * sin(rho);
  469.            y = cos(theta) * sin(rho);
  470.            z = nsign * cos(rho);
  471.            if (normals)
  472.               glNormal3f(x * nsign, y * nsign, z * nsign);
  473.            s -= ds;
  474.            glVertex3f(x * radius, y * radius, z * radius);
  475.         }
  476.         glEnd();
  477.       }
  478.    }
  479.    else if (qobj->DrawStyle == GLU_LINE || qobj->DrawStyle == GLU_SILHOUETTE) {
  480.       /* draw stack lines */
  481.       for (i = 1; i < stacks; i++) {   /* stack line at i==stacks-1 was missing here */
  482.         rho = i * drho;
  483.         glBegin(GL_LINE_LOOP);
  484.         for (j = 0; j < slices; j++) {
  485.            theta = j * dtheta;
  486.            x = cos(theta) * sin(rho);
  487.            y = sin(theta) * sin(rho);
  488.            z = cos(rho);
  489.            if (normals)
  490.               glNormal3f(x * nsign, y * nsign, z * nsign);
  491.            glVertex3f(x * radius, y * radius, z * radius);
  492.         }
  493.         glEnd();
  494.       }
  495.       /* draw slice lines */
  496.       for (j = 0; j < slices; j++) {
  497.         theta = j * dtheta;
  498.         glBegin(GL_LINE_STRIP);
  499.         for (i = 0; i <= stacks; i++) {
  500.            rho = i * drho;
  501.            x = cos(theta) * sin(rho);
  502.            y = sin(theta) * sin(rho);
  503.            z = cos(rho);
  504.            if (normals)
  505.               glNormal3f(x * nsign, y * nsign, z * nsign);
  506.            glVertex3f(x * radius, y * radius, z * radius);
  507.         }
  508.         glEnd();
  509.       }
  510.    }
  511.    else if (qobj->DrawStyle == GLU_POINT) {
  512.       /* top and bottom-most points */
  513.       glBegin(GL_POINTS);
  514.       if (normals)
  515.         glNormal3f(0.0, 0.0, nsign);
  516.       glVertex3d(0.0, 0.0, radius);
  517.       if (normals)
  518.         glNormal3f(0.0, 0.0, -nsign);
  519.       glVertex3d(0.0, 0.0, -radius);
  520.  
  521.       /* loop over stacks */
  522.       for (i = 1; i < stacks - 1; i++) {
  523.         rho = i * drho;
  524.         for (j = 0; j < slices; j++) {
  525.            theta = j * dtheta;
  526.            x = cos(theta) * sin(rho);
  527.            y = sin(theta) * sin(rho);
  528.            z = cos(rho);
  529.            if (normals)
  530.               glNormal3f(x * nsign, y * nsign, z * nsign);
  531.            glVertex3f(x * radius, y * radius, z * radius);
  532.         }
  533.       }
  534.       glEnd();
  535.    }
  536.  
  537. }
  538.  
  539.  
  540.  
  541. void GLAPIENTRY
  542. gluDisk(GLUquadricObj * qobj,
  543.        GLdouble innerRadius, GLdouble outerRadius, GLint slices, GLint loops)
  544. {
  545.    GLfloat da, dr;
  546. #if 0
  547.    GLdouble a, da;
  548.    GLfloat r, dr;
  549.    GLfloat x, y;
  550.    GLfloat r1, r2, dtc;
  551.    GLint s, l;
  552. #endif
  553.  
  554.    /* Normal vectors */
  555.    if (qobj->Normals != GLU_NONE) {
  556.       if (qobj->Orientation == GLU_OUTSIDE) {
  557.         glNormal3f(0.0, 0.0, +1.0);
  558.       }
  559.       else {
  560.         glNormal3f(0.0, 0.0, -1.0);
  561.       }
  562.    }
  563.  
  564.    da = 2.0 * M_PI / slices;
  565.    dr = (outerRadius - innerRadius) / (GLfloat) loops;
  566.  
  567.    switch (qobj->DrawStyle) {
  568.    case GLU_FILL:
  569.       {
  570.         /* texture of a gluDisk is a cut out of the texture unit square
  571.          * x, y in [-outerRadius, +outerRadius]; s, t in [0, 1]
  572.          * (linear mapping)
  573.          */
  574.         GLfloat dtc = 2.0f * outerRadius;
  575.         GLfloat sa, ca;
  576.         GLfloat r1 = innerRadius;
  577.         GLint l;
  578.         for (l = 0; l < loops; l++) {
  579.            GLfloat r2 = r1 + dr;
  580.            if (qobj->Orientation == GLU_OUTSIDE) {
  581.               GLint s;
  582.               glBegin(GL_QUAD_STRIP);
  583.               for (s = 0; s <= slices; s++) {
  584.                  GLfloat a;
  585.                  if (s == slices)
  586.                     a = 0.0;
  587.                  else
  588.                     a = s * da;
  589.                  sa = sin(a);
  590.                  ca = cos(a);
  591.                  TXTR_COORD(0.5 + sa * r2 / dtc, 0.5 + ca * r2 / dtc);
  592.                  glVertex2f(r2 * sa, r2 * ca);
  593.                  TXTR_COORD(0.5 + sa * r1 / dtc, 0.5 + ca * r1 / dtc);
  594.                  glVertex2f(r1 * sa, r1 * ca);
  595.               }
  596.               glEnd();
  597.            }
  598.            else {
  599.               GLint s;
  600.               glBegin(GL_QUAD_STRIP);
  601.               for (s = slices; s >= 0; s--) {
  602.                  GLfloat a;
  603.                  if (s == slices)
  604.                     a = 0.0;
  605.                  else
  606.                     a = s * da;
  607.                  sa = sin(a);
  608.                  ca = cos(a);
  609.                  TXTR_COORD(0.5 - sa * r2 / dtc, 0.5 + ca * r2 / dtc);
  610.                  glVertex2f(r2 * sa, r2 * ca);
  611.                  TXTR_COORD(0.5 - sa * r1 / dtc, 0.5 + ca * r1 / dtc);
  612.                  glVertex2f(r1 * sa, r1 * ca);
  613.               }
  614.               glEnd();
  615.            }
  616.            r1 = r2;
  617.         }
  618.         break;
  619.       }
  620.    case GLU_LINE:
  621.       {
  622.         GLint l, s;
  623.         /* draw loops */
  624.         for (l = 0; l <= loops; l++) {
  625.            GLfloat r = innerRadius + l * dr;
  626.            glBegin(GL_LINE_LOOP);
  627.            for (s = 0; s < slices; s++) {
  628.               GLfloat a = s * da;
  629.               glVertex2f(r * sin(a), r * cos(a));
  630.            }
  631.            glEnd();
  632.         }
  633.         /* draw spokes */
  634.         for (s = 0; s < slices; s++) {
  635.            GLfloat a = s * da;
  636.            GLfloat x = sin(a);
  637.            GLfloat y = cos(a);
  638.            glBegin(GL_LINE_STRIP);
  639.            for (l = 0; l <= loops; l++) {
  640.               GLfloat r = innerRadius + l * dr;
  641.               glVertex2f(r * x, r * y);
  642.            }
  643.            glEnd();
  644.         }
  645.         break;
  646.       }
  647.    case GLU_POINT:
  648.       {
  649.         GLint s;
  650.         glBegin(GL_POINTS);
  651.         for (s = 0; s < slices; s++) {
  652.            GLfloat a = s * da;
  653.            GLfloat x = sin(a);
  654.            GLfloat y = cos(a);
  655.            GLint l;
  656.            for (l = 0; l <= loops; l++) {
  657.               GLfloat r = innerRadius * l * dr;
  658.               glVertex2f(r * x, r * y);
  659.            }
  660.         }
  661.         glEnd();
  662.         break;
  663.       }
  664.    case GLU_SILHOUETTE:
  665.       {
  666.         if (innerRadius != 0.0) {
  667.            GLfloat a;
  668.            glBegin(GL_LINE_LOOP);
  669.            for (a = 0.0; a < 2.0 * M_PI; a += da) {
  670.               GLfloat x = innerRadius * sin(a);
  671.               GLfloat y = innerRadius * cos(a);
  672.               glVertex2f(x, y);
  673.            }
  674.            glEnd();
  675.         }
  676.         {
  677.            GLfloat a;
  678.            glBegin(GL_LINE_LOOP);
  679.            for (a = 0; a < 2.0 * M_PI; a += da) {
  680.               GLfloat x = outerRadius * sin(a);
  681.               GLfloat y = outerRadius * cos(a);
  682.               glVertex2f(x, y);
  683.            }
  684.            glEnd();
  685.         }
  686.         break;
  687.       }
  688.    default:
  689.       abort();
  690.    }
  691. }
  692.  
  693.  
  694.  
  695. void GLAPIENTRY
  696. gluPartialDisk(GLUquadricObj * qobj, GLdouble innerRadius,
  697.               GLdouble outerRadius, GLint slices, GLint loops,
  698.               GLdouble startAngle, GLdouble sweepAngle)
  699. {
  700.    if (qobj->Normals != GLU_NONE) {
  701.       if (qobj->Orientation == GLU_OUTSIDE) {
  702.         glNormal3f(0.0, 0.0, +1.0);
  703.       }
  704.       else {
  705.         glNormal3f(0.0, 0.0, -1.0);
  706.       }
  707.    }
  708.  
  709.    if (qobj->DrawStyle == GLU_POINT) {
  710.       GLint loop, slice;
  711.       GLdouble radius, delta_radius;
  712.       GLdouble angle, delta_angle;
  713.       delta_radius = (outerRadius - innerRadius) / (loops - 1);
  714.       delta_angle = DEG_TO_RAD((sweepAngle) / (slices - 1));
  715.       glBegin(GL_POINTS);
  716.       radius = innerRadius;
  717.       for (loop = 0; loop < loops; loop++) {
  718.         angle = DEG_TO_RAD(startAngle);
  719.         for (slice = 0; slice < slices; slice++) {
  720.            glVertex2d(radius * sin(angle), radius * cos(angle));
  721.            angle += delta_angle;
  722.         }
  723.         radius += delta_radius;
  724.       }
  725.       glEnd();
  726.    }
  727.    else if (qobj->DrawStyle == GLU_LINE) {
  728.       GLint loop, slice;
  729.       GLdouble radius, delta_radius;
  730.       GLdouble angle, delta_angle;
  731.       delta_radius = (outerRadius - innerRadius) / loops;
  732.       delta_angle = DEG_TO_RAD(sweepAngle / slices);
  733.       /* draw rings */
  734.       radius = innerRadius;
  735.       for (loop = 0; loop < loops; loop++) {
  736.         angle = DEG_TO_RAD(startAngle);
  737.         glBegin(GL_LINE_STRIP);
  738.         for (slice = 0; slice <= slices; slice++) {
  739.            glVertex2d(radius * sin(angle), radius * cos(angle));
  740.            angle += delta_angle;
  741.         }
  742.         glEnd();
  743.         radius += delta_radius;
  744.       }
  745.       /* draw spokes */
  746.       angle = DEG_TO_RAD(startAngle);
  747.       for (slice = 0; slice <= slices; slice++) {
  748.         radius = innerRadius;
  749.         glBegin(GL_LINE_STRIP);
  750.         for (loop = 0; loop < loops; loop++) {
  751.            glVertex2d(radius * sin(angle), radius * cos(angle));
  752.            radius += delta_radius;
  753.         }
  754.         glEnd();
  755.         angle += delta_angle;
  756.       }
  757.    }
  758.    else if (qobj->DrawStyle == GLU_SILHOUETTE) {
  759.       GLint slice;
  760.       GLdouble angle, delta_angle;
  761.       delta_angle = DEG_TO_RAD(sweepAngle / slices);
  762.       /* draw outer ring */
  763.       glBegin(GL_LINE_STRIP);
  764.       angle = DEG_TO_RAD(startAngle);
  765.       for (slice = 0; slice <= slices; slice++) {
  766.         glVertex2d(outerRadius * sin(angle), outerRadius * cos(angle));
  767.         angle += delta_angle;
  768.       }
  769.       glEnd();
  770.       /* draw inner ring */
  771.       if (innerRadius > 0.0) {
  772.         glBegin(GL_LINE_STRIP);
  773.         angle = DEG_TO_RAD(startAngle);
  774.         for (slice = 0; slice < slices; slice++) {
  775.            glVertex2d(innerRadius * sin(angle), innerRadius * cos(angle));
  776.            angle += delta_angle;
  777.         }
  778.         glEnd();
  779.       }
  780.       /* draw spokes */
  781.       if (sweepAngle < 360.0) {
  782.         GLdouble stopAngle = startAngle + sweepAngle;
  783.         glBegin(GL_LINES);
  784.         glVertex2d(innerRadius * SIND(startAngle),
  785.                    innerRadius * COSD(startAngle));
  786.         glVertex2d(outerRadius * SIND(startAngle),
  787.                    outerRadius * COSD(startAngle));
  788.         glVertex2d(innerRadius * SIND(stopAngle),
  789.                    innerRadius * COSD(stopAngle));
  790.         glVertex2d(outerRadius * SIND(stopAngle),
  791.                    outerRadius * COSD(stopAngle));
  792.         glEnd();
  793.       }
  794.    }
  795.    else if (qobj->DrawStyle == GLU_FILL) {
  796.       GLint loop, slice;
  797.       GLdouble radius, delta_radius;
  798.       GLdouble angle, delta_angle;
  799.       delta_radius = (outerRadius - innerRadius) / loops;
  800.       delta_angle = DEG_TO_RAD(sweepAngle / slices);
  801.       radius = innerRadius;
  802.       for (loop = 0; loop < loops; loop++) {
  803.         glBegin(GL_QUAD_STRIP);
  804.         angle = DEG_TO_RAD(startAngle);
  805.         for (slice = 0; slice <= slices; slice++) {
  806.            if (qobj->Orientation == GLU_OUTSIDE) {
  807.               glVertex2d((radius + delta_radius) * sin(angle),
  808.                          (radius + delta_radius) * cos(angle));
  809.               glVertex2d(radius * sin(angle), radius * cos(angle));
  810.            }
  811.            else {
  812.               glVertex2d(radius * sin(angle), radius * cos(angle));
  813.               glVertex2d((radius + delta_radius) * sin(angle),
  814.                          (radius + delta_radius) * cos(angle));
  815.            }
  816.            angle += delta_angle;
  817.         }
  818.         glEnd();
  819.         radius += delta_radius;
  820.       }
  821.    }
  822. }
  823.