home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 6 / AACD06.ISO / AACD / System / Mesa-3.1 / src-glu / quadric.c < prev    next >
C/C++ Source or Header  |  2000-01-05  |  23KB  |  862 lines

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