aboutsummaryrefslogtreecommitdiffstats
path: root/src/glu/mesa/quadric.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/glu/mesa/quadric.c')
-rw-r--r--src/glu/mesa/quadric.c858
1 files changed, 858 insertions, 0 deletions
diff --git a/src/glu/mesa/quadric.c b/src/glu/mesa/quadric.c
new file mode 100644
index 00000000000..4698e795b15
--- /dev/null
+++ b/src/glu/mesa/quadric.c
@@ -0,0 +1,858 @@
+/* $Id: quadric.c,v 1.1 1999/08/19 00:55:42 jtg Exp $ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.1
+ * Copyright (C) 1995-1999 Brian Paul
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+
+/*
+ * $Log: quadric.c,v $
+ * Revision 1.1 1999/08/19 00:55:42 jtg
+ * Initial revision
+ *
+ * Revision 1.19 1999/02/27 13:55:31 brianp
+ * fixed BeOS-related GLU typedef problems
+ *
+ * Revision 1.18 1999/01/03 03:23:15 brianp
+ * now using GLAPIENTRY and GLCALLBACK keywords (Ted Jump)
+ *
+ * Revision 1.17 1999/01/03 03:19:15 brianp
+ * rewrote some of gluCylinder
+ *
+ * Revision 1.16 1998/06/01 01:08:36 brianp
+ * small update for Next/OpenStep from Alexander Mai
+ *
+ * Revision 1.15 1998/03/15 18:28:54 brianp
+ * reimplemented gluDisk() point and line mode
+ *
+ * Revision 1.14 1998/03/15 18:14:17 brianp
+ * fixed a compiler cast warning
+ *
+ * Revision 1.13 1998/02/07 14:28:34 brianp
+ * another change to gluQuadricCallback(), this time for StormC compiler
+ *
+ * Revision 1.12 1998/02/05 00:43:19 brianp
+ * Yes, still another change to gluQuadricCallback()!
+ *
+ * Revision 1.11 1998/02/04 00:27:43 brianp
+ * yet another change to gluQuadricCallback()!
+ *
+ * Revision 1.10 1998/02/04 00:23:23 brianp
+ * fixed CALLBACK problem in gluQuadricCallback() (Stephane Rehel)
+ *
+ * Revision 1.9 1998/02/04 00:20:09 brianp
+ * added missing (int) in ErrorFunc cast
+ *
+ * Revision 1.8 1998/01/16 03:37:51 brianp
+ * fixed another assignment warning in gluQuadricCallback()
+ *
+ * Revision 1.7 1998/01/16 03:35:26 brianp
+ * fixed Windows compilation warnings (Theodore Jump)
+ *
+ * Revision 1.6 1997/10/29 02:02:20 brianp
+ * various MS Windows compiler changes (David Bucciarelli, v20 3dfx driver)
+ *
+ * Revision 1.5 1997/09/17 01:51:48 brianp
+ * changed glu*Callback() functions to match prototype in glu.h
+ *
+ * Revision 1.4 1997/07/24 01:28:44 brianp
+ * changed precompiled header symbol from PCH to PC_HEADER
+ *
+ * Revision 1.3 1997/05/28 02:29:38 brianp
+ * added support for precompiled headers (PCH), inserted APIENTRY keyword
+ *
+ * Revision 1.2 1997/03/12 02:15:38 brianp
+ * fixed problem in gluPartialDisk() reported by Kenneth H. Carpenter
+ *
+ * Revision 1.1 1996/09/27 01:19:39 brianp
+ * Initial revision
+ *
+ */
+
+
+/* TODO:
+ * texture coordinate support
+ * flip normals according to orientation
+ * there's still some inside/outside orientation bugs in possibly all
+ * but the sphere function
+ */
+
+
+#ifdef PC_HEADER
+#include "all.h"
+#else
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "gluP.h"
+#endif
+
+
+
+#ifndef M_PI
+# define M_PI (3.1415926)
+#endif
+
+
+/*
+ * Convert degrees to radians:
+ */
+#define DEG_TO_RAD(A) ((A)*(M_PI/180.0))
+
+
+/*
+ * Sin and Cos for degree angles:
+ */
+#define SIND( A ) sin( (A)*(M_PI/180.0) )
+#define COSD( A) cos( (A)*(M_PI/180.0) )
+
+
+/*
+ * Texture coordinates if texture flag is set
+ */
+#define TXTR_COORD(x,y) if (qobj->TextureFlag) glTexCoord2f(x,y);
+
+
+
+struct GLUquadric {
+ GLenum DrawStyle; /* GLU_FILL, LINE, SILHOUETTE, or POINT */
+ GLenum Orientation; /* GLU_INSIDE or GLU_OUTSIDE */
+ GLboolean TextureFlag; /* Generate texture coords? */
+ GLenum Normals; /* GLU_NONE, GLU_FLAT, or GLU_SMOOTH */
+ void (GLCALLBACK *ErrorFunc)(GLenum err); /* Error handler callback function */
+};
+
+
+
+/*
+ * Process a GLU error.
+ */
+static void quadric_error( GLUquadricObj *qobj, GLenum error, const char *msg )
+{
+ /* Call the error call back function if any */
+ if (qobj->ErrorFunc) {
+ (*qobj->ErrorFunc)( error );
+ }
+ /* Print a message to stdout if MESA_DEBUG variable is defined */
+ if (getenv("MESA_DEBUG")) {
+ fprintf(stderr,"GLUError: %s: %s\n", (char*) gluErrorString(error), msg);
+ }
+}
+
+
+
+
+GLUquadricObj * GLAPIENTRY gluNewQuadric( void )
+{
+ GLUquadricObj *q;
+
+ q = (GLUquadricObj *) malloc( sizeof(struct GLUquadric) );
+ if (q) {
+ q->DrawStyle = GLU_FILL;
+ q->Orientation = GLU_OUTSIDE;
+ q->TextureFlag = GL_FALSE;
+ q->Normals = GLU_SMOOTH;
+ q->ErrorFunc = NULL;
+ }
+ return q;
+}
+
+
+
+void GLAPIENTRY gluDeleteQuadric( GLUquadricObj *state )
+{
+ if (state) {
+ free( (void *) state );
+ }
+}
+
+
+
+/*
+ * Set the drawing style to be GLU_FILL, GLU_LINE, GLU_SILHOUETTE,
+ * or GLU_POINT.
+ */
+void GLAPIENTRY gluQuadricDrawStyle( GLUquadricObj *quadObject, GLenum drawStyle )
+{
+ if (quadObject && (drawStyle==GLU_FILL || drawStyle==GLU_LINE
+ || drawStyle==GLU_SILHOUETTE || drawStyle==GLU_POINT)) {
+ quadObject->DrawStyle = drawStyle;
+ }
+ else {
+ quadric_error( quadObject, GLU_INVALID_ENUM, "qluQuadricDrawStyle" );
+ }
+}
+
+
+
+/*
+ * Set the orientation to GLU_INSIDE or GLU_OUTSIDE.
+ */
+void GLAPIENTRY gluQuadricOrientation( GLUquadricObj *quadObject,
+ GLenum orientation )
+{
+ if (quadObject && (orientation==GLU_INSIDE || orientation==GLU_OUTSIDE)) {
+ quadObject->Orientation = orientation;
+ }
+ else {
+ quadric_error( quadObject, GLU_INVALID_ENUM, "qluQuadricOrientation" );
+ }
+}
+
+
+
+/*
+ * Set the error handler callback function.
+ */
+void GLAPIENTRY gluQuadricCallback( GLUquadricObj *qobj,
+ GLenum which, void (GLCALLBACK *fn)() )
+{
+ /*
+ * UGH, this is a mess! I thought ANSI was a standard.
+ */
+ if (qobj && which==GLU_ERROR) {
+#ifdef __CYGWIN32__
+ qobj->ErrorFunc = (void(*)(int))fn;
+#elif defined(OPENSTEP)
+ qobj->ErrorFunc = (void(*)(GLenum))fn;
+#elif defined(_WIN32)
+ qobj->ErrorFunc = (void(GLCALLBACK*)(int))fn;
+#elif defined(__STORM__)
+ qobj->ErrorFunc = (void(GLCALLBACK*)(GLenum))fn;
+#elif defined(__BEOS__)
+ qobj->ErrorFunc = (void(*)(GLenum))fn;
+#else
+ qobj->ErrorFunc = (void(GLCALLBACK*)())fn;
+#endif
+ }
+}
+
+
+void GLAPIENTRY gluQuadricNormals( GLUquadricObj *quadObject, GLenum normals )
+{
+ if (quadObject
+ && (normals==GLU_NONE || normals==GLU_FLAT || normals==GLU_SMOOTH)) {
+ quadObject->Normals = normals;
+ }
+}
+
+
+void GLAPIENTRY gluQuadricTexture( GLUquadricObj *quadObject,
+ GLboolean textureCoords )
+{
+ if (quadObject) {
+ quadObject->TextureFlag = textureCoords;
+ }
+}
+
+
+
+
+/*
+ * Call glNormal3f after scaling normal to unit length.
+ */
+static void normal3f( GLfloat x, GLfloat y, GLfloat z )
+{
+ GLdouble mag;
+
+ mag = sqrt( x*x + y*y + z*z );
+ if (mag>0.00001F) {
+ x /= mag;
+ y /= mag;
+ z /= mag;
+ }
+ glNormal3f( x, y, z );
+}
+
+
+
+void GLAPIENTRY gluCylinder( GLUquadricObj *qobj,
+ GLdouble baseRadius, GLdouble topRadius,
+ GLdouble height, GLint slices, GLint stacks )
+{
+ GLdouble da, r, dr, dz;
+ GLfloat x, y, z, nz, nsign;
+ GLint i, j;
+
+ if (qobj->Orientation==GLU_INSIDE) {
+ nsign = -1.0;
+ }
+ else {
+ nsign = 1.0;
+ }
+
+ da = 2.0*M_PI / slices;
+ dr = (topRadius-baseRadius) / stacks;
+ dz = height / stacks;
+ nz = (baseRadius-topRadius) / height; /* Z component of normal vectors */
+
+ if (qobj->DrawStyle==GLU_POINT) {
+ glBegin( GL_POINTS );
+ for (i=0;i<slices;i++) {
+ x = cos(i*da);
+ y = sin(i*da);
+ normal3f( x*nsign, y*nsign, nz*nsign );
+
+ z = 0.0;
+ r = baseRadius;
+ for (j=0;j<=stacks;j++) {
+ glVertex3f( x*r, y*r, z );
+ z += dz;
+ r += dr;
+ }
+ }
+ glEnd();
+ }
+ else if (qobj->DrawStyle==GLU_LINE || qobj->DrawStyle==GLU_SILHOUETTE) {
+ /* Draw rings */
+ if (qobj->DrawStyle==GLU_LINE) {
+ z = 0.0;
+ r = baseRadius;
+ for (j=0;j<=stacks;j++) {
+ glBegin( GL_LINE_LOOP );
+ for (i=0;i<slices;i++) {
+ x = cos(i*da);
+ y = sin(i*da);
+ normal3f( x*nsign, y*nsign, nz*nsign );
+ glVertex3f( x*r, y*r, z );
+ }
+ glEnd();
+ z += dz;
+ r += dr;
+ }
+ }
+ else {
+ /* draw one ring at each end */
+ if (baseRadius!=0.0) {
+ glBegin( GL_LINE_LOOP );
+ for (i=0;i<slices;i++) {
+ x = cos(i*da);
+ y = sin(i*da);
+ normal3f( x*nsign, y*nsign, nz*nsign );
+ glVertex3f( x*baseRadius, y*baseRadius, 0.0 );
+ }
+ glEnd();
+ glBegin( GL_LINE_LOOP );
+ for (i=0;i<slices;i++) {
+ x = cos(i*da);
+ y = sin(i*da);
+ normal3f( x*nsign, y*nsign, nz*nsign );
+ glVertex3f( x*topRadius, y*topRadius, height );
+ }
+ glEnd();
+ }
+ }
+ /* draw length lines */
+ glBegin( GL_LINES );
+ for (i=0;i<slices;i++) {
+ x = cos(i*da);
+ y = sin(i*da);
+ normal3f( x*nsign, y*nsign, nz*nsign );
+ glVertex3f( x*baseRadius, y*baseRadius, 0.0 );
+ glVertex3f( x*topRadius, y*topRadius, height );
+ }
+ glEnd();
+ }
+ else if (qobj->DrawStyle==GLU_FILL) {
+ GLfloat ds = 1.0 / slices;
+ GLfloat dt = 1.0 / stacks;
+ GLfloat t = 0.0;
+ z = 0.0;
+ r = baseRadius;
+ for (j=0;j<stacks;j++) {
+ GLfloat s = 0.0;
+ glBegin( GL_QUAD_STRIP );
+ for (i=0;i<=slices;i++) {
+ GLfloat x, y;
+ if (i == slices) {
+ x = sin(0);
+ y = cos(0);
+ }
+ else {
+ x = sin(i * da);
+ y = cos(i * da);
+ }
+ if (nsign==1.0) {
+ normal3f( x*nsign, y*nsign, nz*nsign );
+ TXTR_COORD(s, t);
+ glVertex3f( x * r, y * r, z );
+ normal3f( x*nsign, y*nsign, nz*nsign );
+ TXTR_COORD(s, t + dt);
+ glVertex3f( x * (r + dr), y * (r + dr), z + dz);
+ }
+ else {
+ normal3f( x*nsign, y*nsign, nz*nsign );
+ TXTR_COORD(s, t);
+ glVertex3f( x * r, y * r, z );
+ normal3f( x*nsign, y*nsign, nz*nsign );
+ TXTR_COORD(s, t + dt);
+ glVertex3f( x * (r + dr), y * (r + dr), z + dz);
+ }
+ s += ds;
+ } /* for slices */
+ glEnd();
+ r += dr;
+ t += dt;
+ z += dz;
+ } /* for stacks */
+ }
+}
+
+
+
+
+
+void GLAPIENTRY gluSphere( GLUquadricObj *qobj,
+ GLdouble radius, GLint slices, GLint stacks )
+{
+ GLfloat rho, drho, theta, dtheta;
+ GLfloat x, y, z;
+ GLfloat s, t, ds, dt;
+ GLint i, j, imin, imax;
+ GLboolean normals;
+ GLfloat nsign;
+
+ if (qobj->Normals==GLU_NONE) {
+ normals = GL_FALSE;
+ }
+ else {
+ normals = GL_TRUE;
+ }
+ if (qobj->Orientation==GLU_INSIDE) {
+ nsign = -1.0;
+ }
+ else {
+ nsign = 1.0;
+ }
+
+ drho = M_PI / (GLfloat) stacks;
+ dtheta = 2.0 * M_PI / (GLfloat) slices;
+
+ /* texturing: s goes from 0.0/0.25/0.5/0.75/1.0 at +y/+x/-y/-x/+y axis */
+ /* t goes from -1.0/+1.0 at z = -radius/+radius (linear along longitudes) */
+ /* cannot use triangle fan on texturing (s coord. at top/bottom tip varies) */
+
+ if (qobj->DrawStyle==GLU_FILL) {
+ if (!qobj->TextureFlag) {
+ /* draw +Z end as a triangle fan */
+ glBegin( GL_TRIANGLE_FAN );
+ glNormal3f( 0.0, 0.0, 1.0 );
+ TXTR_COORD(0.5,1.0);
+ glVertex3f( 0.0, 0.0, nsign * radius );
+ for (j=0;j<=slices;j++) {
+ theta = (j==slices) ? 0.0 : j * dtheta;
+ x = -sin(theta) * sin(drho);
+ y = cos(theta) * sin(drho);
+ z = nsign * cos(drho);
+ if (normals) glNormal3f( x*nsign, y*nsign, z*nsign );
+ glVertex3f( x*radius, y*radius, z*radius );
+ }
+ glEnd();
+ }
+
+ ds = 1.0 / slices;
+ dt = 1.0 / stacks;
+ t = 1.0; /* because loop now runs from 0 */
+ if (qobj->TextureFlag) {
+ imin = 0;
+ imax = stacks;
+ }
+ else {
+ imin = 1;
+ imax = stacks-1;
+ }
+
+ /* draw intermediate stacks as quad strips */
+ for (i=imin;i<imax;i++) {
+ rho = i * drho;
+ glBegin( GL_QUAD_STRIP );
+ s = 0.0;
+ for (j=0;j<=slices;j++) {
+ theta = (j==slices) ? 0.0 : j * dtheta;
+ x = -sin(theta) * sin(rho);
+ y = cos(theta) * sin(rho);
+ z = nsign * cos(rho);
+ if (normals) glNormal3f( x*nsign, y*nsign, z*nsign );
+ TXTR_COORD(s,t);
+ glVertex3f( x*radius, y*radius, z*radius );
+ x = -sin(theta) * sin(rho+drho);
+ y = cos(theta) * sin(rho+drho);
+ z = nsign * cos(rho+drho);
+ if (normals) glNormal3f( x*nsign, y*nsign, z*nsign );
+ TXTR_COORD(s,t-dt);
+ s += ds;
+ glVertex3f( x*radius, y*radius, z*radius );
+ }
+ glEnd();
+ t -= dt;
+ }
+
+ if (!qobj->TextureFlag) {
+ /* draw -Z end as a triangle fan */
+ glBegin( GL_TRIANGLE_FAN );
+ glNormal3f( 0.0, 0.0, -1.0 );
+ TXTR_COORD(0.5,0.0);
+ glVertex3f( 0.0, 0.0, -radius*nsign );
+ rho = M_PI - drho;
+ s = 1.0;
+ t = dt;
+ for (j=slices;j>=0;j--) {
+ theta = (j==slices) ? 0.0 : j * dtheta;
+ x = -sin(theta) * sin(rho);
+ y = cos(theta) * sin(rho);
+ z = nsign * cos(rho);
+ if (normals) glNormal3f( x*nsign, y*nsign, z*nsign );
+ TXTR_COORD(s,t);
+ s -= ds;
+ glVertex3f( x*radius, y*radius, z*radius );
+ }
+ glEnd();
+ }
+ }
+ else if (qobj->DrawStyle==GLU_LINE || qobj->DrawStyle==GLU_SILHOUETTE) {
+ /* draw stack lines */
+ for (i=1;i<stacks;i++) { /* stack line at i==stacks-1 was missing here */
+ rho = i * drho;
+ glBegin( GL_LINE_LOOP );
+ for (j=0;j<slices;j++) {
+ theta = j * dtheta;
+ x = cos(theta) * sin(rho);
+ y = sin(theta) * sin(rho);
+ z = cos(rho);
+ if (normals) glNormal3f( x*nsign, y*nsign, z*nsign );
+ glVertex3f( x*radius, y*radius, z*radius );
+ }
+ glEnd();
+ }
+ /* draw slice lines */
+ for (j=0;j<slices;j++) {
+ theta = j * dtheta;
+ glBegin( GL_LINE_STRIP );
+ for (i=0;i<=stacks;i++) {
+ rho = i * drho;
+ x = cos(theta) * sin(rho);
+ y = sin(theta) * sin(rho);
+ z = cos(rho);
+ if (normals) glNormal3f( x*nsign, y*nsign, z*nsign );
+ glVertex3f( x*radius, y*radius, z*radius );
+ }
+ glEnd();
+ }
+ }
+ else if (qobj->DrawStyle==GLU_POINT) {
+ /* top and bottom-most points */
+ glBegin( GL_POINTS );
+ if (normals) glNormal3f( 0.0, 0.0, nsign );
+ glVertex3d( 0.0, 0.0, radius );
+ if (normals) glNormal3f( 0.0, 0.0, -nsign );
+ glVertex3d( 0.0, 0.0, -radius );
+
+ /* loop over stacks */
+ for (i=1;i<stacks-1;i++) {
+ rho = i * drho;
+ for (j=0;j<slices;j++) {
+ theta = j * dtheta;
+ x = cos(theta) * sin(rho);
+ y = sin(theta) * sin(rho);
+ z = cos(rho);
+ if (normals) glNormal3f( x*nsign, y*nsign, z*nsign );
+ glVertex3f( x*radius, y*radius, z*radius );
+ }
+ }
+ glEnd();
+ }
+
+}
+
+
+
+void GLAPIENTRY gluDisk( GLUquadricObj *qobj,
+ GLdouble innerRadius, GLdouble outerRadius,
+ GLint slices, GLint loops )
+{
+ GLfloat da, dr;
+#if 0
+ GLdouble a, da;
+ GLfloat r, dr;
+ GLfloat x, y;
+ GLfloat r1, r2, dtc;
+ GLint s, l;
+#endif
+
+ /* Normal vectors */
+ if (qobj->Normals!=GLU_NONE) {
+ if (qobj->Orientation==GLU_OUTSIDE) {
+ glNormal3f( 0.0, 0.0, +1.0 );
+ }
+ else {
+ glNormal3f( 0.0, 0.0, -1.0 );
+ }
+ }
+
+ da = 2.0*M_PI / slices;
+ dr = (outerRadius-innerRadius) / (GLfloat) loops;
+
+ switch (qobj->DrawStyle) {
+ case GLU_FILL:
+ {
+ /* texture of a gluDisk is a cut out of the texture unit square
+ * x, y in [-outerRadius, +outerRadius]; s, t in [0, 1]
+ * (linear mapping)
+ */
+ GLfloat dtc = 2.0f * outerRadius;
+ GLfloat sa,ca;
+ GLfloat r1 = innerRadius;
+ GLint l;
+ for (l=0; l<loops; l++) {
+ GLfloat r2 = r1 + dr;
+ if (qobj->Orientation==GLU_OUTSIDE) {
+ GLint s;
+ glBegin( GL_QUAD_STRIP );
+ for (s=0;s<=slices;s++) {
+ GLfloat a;
+ if (s==slices) a = 0.0;
+ else a = s * da;
+ sa = sin(a); ca = cos(a);
+ TXTR_COORD(0.5+sa*r2/dtc,0.5+ca*r2/dtc);
+ glVertex2f( r2*sa, r2*ca );
+ TXTR_COORD(0.5+sa*r1/dtc,0.5+ca*r1/dtc);
+ glVertex2f( r1*sa, r1*ca );
+ }
+ glEnd();
+ }
+ else {
+ GLint s;
+ glBegin( GL_QUAD_STRIP );
+ for (s=slices;s>=0;s--) {
+ GLfloat a;
+ if (s==slices) a = 0.0;
+ else a = s * da;
+ sa = sin(a); ca = cos(a);
+ TXTR_COORD(0.5-sa*r2/dtc,0.5+ca*r2/dtc);
+ glVertex2f( r2*sa, r2*ca );
+ TXTR_COORD(0.5-sa*r1/dtc,0.5+ca*r1/dtc);
+ glVertex2f( r1*sa, r1*ca );
+ }
+ glEnd();
+ }
+ r1 = r2;
+ }
+ break;
+ }
+ case GLU_LINE:
+ {
+ GLint l, s;
+ /* draw loops */
+ for (l=0; l<=loops; l++) {
+ GLfloat r = innerRadius + l * dr;
+ glBegin( GL_LINE_LOOP );
+ for (s=0; s<slices; s++) {
+ GLfloat a = s * da;
+ glVertex2f( r*sin(a), r*cos(a) );
+ }
+ glEnd();
+ }
+ /* draw spokes */
+ for (s=0; s<slices; s++) {
+ GLfloat a = s * da;
+ GLfloat x = sin(a);
+ GLfloat y = cos(a);
+ glBegin( GL_LINE_STRIP );
+ for (l=0; l<=loops; l++) {
+ GLfloat r = innerRadius + l * dr;
+ glVertex2f( r*x, r*y );
+ }
+ glEnd();
+ }
+ break;
+ }
+ case GLU_POINT:
+ {
+ GLint s;
+ glBegin( GL_POINTS );
+ for (s=0; s<slices; s++) {
+ GLfloat a = s * da;
+ GLfloat x = sin(a);
+ GLfloat y = cos(a);
+ GLint l;
+ for (l=0; l<=loops; l++) {
+ GLfloat r = innerRadius * l * dr;
+ glVertex2f( r*x, r*y );
+ }
+ }
+ glEnd();
+ break;
+ }
+ case GLU_SILHOUETTE:
+ {
+ if (innerRadius!=0.0) {
+ GLfloat a;
+ glBegin( GL_LINE_LOOP );
+ for (a=0.0; a<2.0*M_PI; a+=da) {
+ GLfloat x = innerRadius * sin(a);
+ GLfloat y = innerRadius * cos(a);
+ glVertex2f( x, y );
+ }
+ glEnd();
+ }
+ {
+ GLfloat a;
+ glBegin( GL_LINE_LOOP );
+ for (a=0; a<2.0*M_PI; a+=da) {
+ GLfloat x = outerRadius * sin(a);
+ GLfloat y = outerRadius * cos(a);
+ glVertex2f( x, y );
+ }
+ glEnd();
+ }
+ break;
+ }
+ default:
+ abort();
+ }
+}
+
+
+
+void GLAPIENTRY gluPartialDisk( GLUquadricObj *qobj, GLdouble innerRadius,
+ GLdouble outerRadius, GLint slices, GLint loops,
+ GLdouble startAngle, GLdouble sweepAngle )
+{
+ if (qobj->Normals!=GLU_NONE) {
+ if (qobj->Orientation==GLU_OUTSIDE) {
+ glNormal3f( 0.0, 0.0, +1.0 );
+ }
+ else {
+ glNormal3f( 0.0, 0.0, -1.0 );
+ }
+ }
+
+ if (qobj->DrawStyle==GLU_POINT) {
+ GLint loop, slice;
+ GLdouble radius, delta_radius;
+ GLdouble angle, delta_angle;
+ delta_radius = (outerRadius - innerRadius) / (loops-1);
+ delta_angle = DEG_TO_RAD((sweepAngle) / (slices-1));
+ glBegin( GL_POINTS );
+ radius = innerRadius;
+ for (loop=0; loop<loops; loop++) {
+ angle = DEG_TO_RAD(startAngle);
+ for (slice=0; slice<slices; slice++) {
+ glVertex2d( radius * sin(angle), radius * cos(angle) );
+ angle += delta_angle;
+ }
+ radius += delta_radius;
+ }
+ glEnd();
+ }
+ else if (qobj->DrawStyle==GLU_LINE) {
+ GLint loop, slice;
+ GLdouble radius, delta_radius;
+ GLdouble angle, delta_angle;
+ delta_radius = (outerRadius - innerRadius) / loops;
+ delta_angle = DEG_TO_RAD(sweepAngle / slices);
+ /* draw rings */
+ radius = innerRadius;
+ for (loop=0; loop<loops; loop++) {
+ angle = DEG_TO_RAD(startAngle);
+ glBegin( GL_LINE_STRIP );
+ for (slice=0; slice<slices; slice++) {
+ glVertex2d( radius * sin(angle), radius * cos(angle) );
+ angle += delta_angle;
+ }
+ glEnd();
+ radius += delta_radius;
+ }
+ /* draw spokes */
+ angle = DEG_TO_RAD(startAngle);
+ for (slice=0; slice<slices; slice++) {
+ radius = innerRadius;
+ glBegin( GL_LINE_STRIP );
+ for (loop=0; loop<loops; loop++) {
+ glVertex2d( radius * sin(angle), radius * cos(angle) );
+ radius += delta_radius;
+ }
+ glEnd();
+ angle += delta_angle;
+ }
+ }
+ else if (qobj->DrawStyle==GLU_SILHOUETTE) {
+ GLint slice;
+ GLdouble angle, delta_angle;
+ delta_angle = DEG_TO_RAD(sweepAngle / slices);
+ /* draw outer ring */
+ glBegin( GL_LINE_STRIP );
+ angle = DEG_TO_RAD(startAngle);
+ for (slice=0; slice<=slices; slice++) {
+ glVertex2d( outerRadius * sin(angle), outerRadius * cos(angle) );
+ angle += delta_angle;
+ }
+ glEnd();
+ /* draw inner ring */
+ if (innerRadius>0.0) {
+ glBegin( GL_LINE_STRIP );
+ angle = DEG_TO_RAD(startAngle);
+ for (slice=0; slice<slices; slice++) {
+ glVertex2d( innerRadius * sin(angle), innerRadius * cos(angle) );
+ angle += delta_angle;
+ }
+ glEnd();
+ }
+ /* draw spokes */
+ if (sweepAngle<360.0) {
+ GLdouble stopAngle = startAngle + sweepAngle;
+ glBegin( GL_LINES );
+ glVertex2d( innerRadius*SIND(startAngle), innerRadius*COSD(startAngle) );
+ glVertex2d( outerRadius*SIND(startAngle), outerRadius*COSD(startAngle) );
+ glVertex2d( innerRadius*SIND(stopAngle), innerRadius*COSD(stopAngle) );
+ glVertex2d( outerRadius*SIND(stopAngle), outerRadius*COSD(stopAngle) );
+ glEnd();
+ }
+ }
+ else if (qobj->DrawStyle==GLU_FILL) {
+ GLint loop, slice;
+ GLdouble radius, delta_radius;
+ GLdouble angle, delta_angle;
+ delta_radius = (outerRadius - innerRadius) / loops;
+ delta_angle = DEG_TO_RAD(sweepAngle / slices);
+ radius = innerRadius;
+ for (loop=0; loop<loops; loop++) {
+ glBegin( GL_QUAD_STRIP );
+ angle = DEG_TO_RAD(startAngle);
+ for (slice=0; slice<slices; slice++) {
+ if (qobj->Orientation==GLU_OUTSIDE) {
+ glVertex2d( (radius+delta_radius)*sin(angle),
+ (radius+delta_radius)*cos(angle) );
+ glVertex2d( radius * sin(angle), radius * cos(angle) );
+ }
+ else {
+ glVertex2d( radius * sin(angle), radius * cos(angle) );
+ glVertex2d( (radius+delta_radius)*sin(angle),
+ (radius+delta_radius)*cos(angle) );
+ }
+ angle += delta_angle;
+ }
+ glEnd();
+ radius += delta_radius;
+ }
+ }
+}
+
+
+