home *** CD-ROM | disk | FTP | other *** search
- /* quadric.c */
-
- /*
- * Mesa 3-D graphics library
- * Version: 1.2
- * Copyright (C) 1995 Brian Paul (brianp@ssec.wisc.edu)
- *
- * 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.
- */
-
-
- /*
- $Id: quadric.c,v 1.6 1995/05/22 16:56:20 brianp Exp $
-
- $Log: quadric.c,v $
- * Revision 1.6 1995/05/22 16:56:20 brianp
- * Release 1.2
- *
- * Revision 1.5 1995/05/16 19:17:21 brianp
- * minor changes to allow compilation with real OpenGL headers
- *
- * Revision 1.4 1995/04/28 14:38:15 brianp
- * moved GLUquadricObj struct from .h to .c file
- *
- * Revision 1.3 1995/04/18 15:51:41 brianp
- * implemented gluPartialDisk()
- * implemented quadric error handler
- *
- * Revision 1.2 1995/03/04 19:39:18 brianp
- * version 1.1 beta
- *
- * Revision 1.1 1995/02/24 15:45:01 brianp
- * Initial revision
- *
- */
-
-
- #include <math.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include "gluP.h"
-
-
-
- #define PI 3.14159
-
-
- /*
- * Convert degrees to radians:
- */
- #define DEG_TO_RAD(A) ((A)*(PI/180.0))
-
-
- /*
- * Sin and Cos for degree angles:
- */
- #define SIND( A ) sin( (A)*(PI/180.0) )
- #define COSD( A) cos( (A)*(PI/180.0) )
-
-
-
- struct GLUquadricObj {
- GLUenum DrawStyle; /* GLU_FILL, LINE, SILHOUETTE, or POINT */
- GLUenum Orientation; /* GLU_INSIDE or GLU_OUTSIDE */
- GLboolean TextureFlag; /* Generate texture coords? */
- GLUenum Normals; /* GLU_NONE, GLU_FLAT, or GLU_SMOOTH */
- void (*ErrorFunc)(GLUenum err); /* Error handler callback function */
- };
-
-
-
- /*
- * Process a GLU error.
- */
- static void quadric_error( GLUquadricObj *qobj, GLUenum 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", gluErrorString(error), msg );
- }
- }
-
-
-
-
- GLUquadricObj *gluNewQuadric( void )
- {
- GLUquadricObj *q;
-
- q = (GLUquadricObj *) malloc( sizeof(struct GLUquadricObj) );
- if (q) {
- q->DrawStyle = GLU_FILL;
- q->Orientation = GLU_OUTSIDE;
- }
- return q;
- }
-
-
-
- void gluDeleteQuadric( GLUquadricObj *state )
- {
- if (state) {
- free( (void *) state );
- }
- }
-
-
-
- /*
- * Set the drawing style to be GLU_FILL, GLU_LINE, GLU_SILHOUETTE, or GLU_POINT.
- */
- void gluQuadricDrawStyle( GLUquadricObj *quadObject, GLUenum 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 gluQuadricOrientation( GLUquadricObj *quadObject, GLUenum 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 gluQuadricCallback( GLUquadricObj *qobj,
- GLUenum which, void (*fn)() )
- {
- if (qobj && fn && which==GLU_ERROR) {
- qobj->ErrorFunc = fn;
- }
- }
-
-
- void gluQuadricNormals( GLUquadricObj *quadObject, GLUenum normals )
- {
- if (quadObject
- && (normals==GLU_NONE || normals==GLU_FLAT || normals==GLU_SMOOTH)) {
- quadObject->Normals = normals;
- }
- }
-
-
- void gluQuadricTexture( GLUquadricObj *quadObject,
- GLboolean textureCoords )
- {
- if (quadObject) {
- quadObject->TextureFlag = textureCoords;
- }
- }
-
-
- void gluCylinder( GLUquadricObj *qobj,
- GLdouble baseRadius, GLdouble topRadius, GLdouble height,
- GLint slices, GLint stacks )
- {
- GLdouble a, da;
- GLfloat x, y, nz;
-
- da = 2.0*PI / slices;
-
- if (qobj->DrawStyle==GLU_FILL) {
- glBegin( GL_QUAD_STRIP );
- }
- else if (qobj->DrawStyle==GLU_LINE) {
- glBegin( GL_LINES );
- }
- else if (qobj->DrawStyle==GLU_SILHOUETTE) {
- glBegin( GL_LINES );
- }
- else if (qobj->DrawStyle==GLU_POINT) {
- glBegin( GL_POINTS );
- }
-
- nz = (baseRadius-topRadius) / height;
- for (a=0.0; a<2.0*PI; a+=da) {
- x = cos(a);
- y = sin(a);
-
- glNormal3f( x, y, nz );
- glVertex3f( x*topRadius, y*topRadius, height );
- glVertex3f( x*baseRadius, y*baseRadius, 0.0 );
- }
- glNormal3f( 1.0, 0.0, nz );
- glVertex3f( topRadius, 0.0, height );
- glVertex3f( baseRadius, 0.0, 0.0 );
- glEnd();
-
- if (qobj->DrawStyle==GLU_LINE || qobj->DrawStyle==GLU_SILHOUETTE) {
- /* Draw end circles */
- glBegin( GL_LINE_LOOP );
- for (a=0.0; a<2.0*PI; a+=da) {
- x = cos(a) * topRadius;
- y = sin(a) * topRadius;
- glVertex3f( x, y, height );
- }
- glEnd();
- glBegin( GL_LINE_LOOP );
- for (a=0.0; a<2.0*PI; a+=da) {
- x = cos(a) * baseRadius;
- y = sin(a) * baseRadius;
- glVertex3f( x, y, 0.0 );
- }
- glEnd();
- }
- }
-
-
-
-
- void gluSphere( GLUquadricObj *qobj,
- GLdouble radius, GLint slices, GLint stacks )
- {
- /* TODO: implement GLU_LINE, GLU_SILHOUETTE, etc. */
-
- GLfloat rho, drho, theta, dtheta;
- GLfloat x, y, z;
- GLint i, j;
-
- drho = PI / (GLfloat) stacks;
- dtheta = 2.0 * PI / (GLfloat) slices;
-
- /* loop over stacks */
- rho = -PI/2.0;
- for (i=0;i<stacks;i++) {
- glBegin( GL_QUAD_STRIP );
-
- /* loop over slices */
- theta = 0.0;
- for (j=0;j<slices+1;j++) {
-
- if (j==slices) {
- theta = 0.0;
- }
-
- x = cos(theta) * cos(rho+drho);
- y = sin(theta) * cos(rho+drho);
- z = sin(rho+drho);
- glNormal3f( x, y, z );
- glVertex3f( x*radius, y*radius, z*radius );
-
- x = cos(theta) * cos(rho);
- y = sin(theta) * cos(rho);
- z = sin(rho);
- glNormal3f( x, y, z );
- glVertex3f( x*radius, y*radius, z*radius );
-
- theta += dtheta;
- }
- glEnd();
- rho += drho;
- }
- }
-
-
-
- void gluDisk( GLUquadricObj *qobj,
- GLdouble innerRadius, GLdouble outerRadius,
- GLint slices, GLint loops )
- {
- GLdouble a, da;
- GLfloat r, dr;
- GLfloat x, y;
- GLfloat r1, r2;
- GLint s, l;
-
- /* 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*PI / slices;
- dr = (outerRadius-innerRadius) / (GLfloat) loops;
-
- switch (qobj->DrawStyle) {
- case GLU_FILL:
- r1 = innerRadius;
- for (l=0;l<loops;l++) {
- r2 = r1 + dr;
- glBegin( GL_QUAD_STRIP );
- a = 0.0;
- for (s=0;s<slices-1;s++) {
- glVertex2f( r1*sin(a), r1*cos(a) );
- glVertex2f( r2*sin(a), r2*cos(a) );
- a += da;
- }
- glVertex2f( 0.0, r1 );
- glVertex2f( 0.0, r2 );
- glEnd();
- r1 = r2;
- }
- break;
- case GLU_LINE:
- /* draw rings */
- for (r=innerRadius; r<=outerRadius; r+=dr) {
- glBegin( GL_LINE_LOOP );
- for (a=0.0; a<2.0*PI; a+=da) {
- glVertex2f( r*sin(a), r*cos(a) );
- }
- glEnd();
- }
- /* draw spokes */
- for (a=0.0; a<2.0*PI; a+=da) {
- x = sin(a);
- y = cos(a);
- glBegin( GL_LINE_STRIP );
- for (r=innerRadius; r<=outerRadius; r+=dr) {
- glVertex2f( r*x, r*y );
- }
- glEnd();
- }
- break;
- case GLU_POINT:
- glBegin( GL_POINTS );
- for (a=0.0; a<2.0*PI; a+=da) {
- x = sin(a);
- y = cos(a);
- for (r=innerRadius; r<=outerRadius; r+=dr) {
- glVertex2f( r*x, r*y );
- }
- }
- glEnd();
- break;
- case GLU_SILHOUETTE:
- if (innerRadius!=0.0) {
- glBegin( GL_LINE_LOOP );
- for (a=0.0; a<2.0*PI; a+=da) {
- x = innerRadius * sin(a);
- y = innerRadius * cos(a);
- glVertex2f( x, y );
- }
- glEnd();
- }
- glBegin( GL_LINE_LOOP );
- for (a=0; a<2.0*PI; a+=da) {
- x = outerRadius * sin(a);
- y = outerRadius * cos(a);
- glVertex2f( x, y );
- }
- glEnd();
- break;
- }
-
- /* Draw interior */
- if (qobj->DrawStyle!=GLU_SILHOUETTE) {
- if (qobj->DrawStyle==GLU_FILL) {
- glBegin( GL_QUAD_STRIP );
- }
- else if (qobj->DrawStyle==GLU_LINE) {
- glBegin( GL_LINES );
- }
- else if (qobj->DrawStyle==GLU_POINT) {
- glBegin( GL_POINTS );
- }
- for (a=0.0; a<2.0*PI; a+=da) {
- x = sin(a);
- y = cos(a);
-
- glVertex2f( x*innerRadius, y*innerRadius );
- glVertex2f( x*outerRadius, y*outerRadius );
- }
- glVertex2f( 0.0, innerRadius );
- glVertex2f( 0.0, outerRadius );
- glEnd();
- }
-
- /* Draw circles */
- if (qobj->DrawStyle==GLU_LINE || qobj->DrawStyle==GLU_SILHOUETTE) {
- if (innerRadius!=0.0) {
- /* Draw inner circle */
- glBegin( GL_LINE_LOOP );
- for (a=0.0; a<2.0*PI; a+=da) {
- x = sin(a) * innerRadius;
- y = cos(a) * innerRadius;
- glVertex2f( x, y );
- }
- glEnd();
- }
- /* Draw outer circle */
- glBegin( GL_LINE_LOOP );
- for (a=0.0; a<2.0*PI; a+=da) {
- x = sin(a) * outerRadius;
- y = cos(a) * outerRadius;
- glVertex2f( x, y );
- }
- glEnd();
- }
-
- }
-
-
-
- void 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-1);
- delta_angle = DEG_TO_RAD((sweepAngle) / (slices-1));
- /* 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-1));
- /* 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-1);
- delta_angle = DEG_TO_RAD((sweepAngle) / (slices-1));
- radius = innerRadius;
- for (loop=0; loop<loops-1; loop++) {
- glBegin( GL_QUAD_STRIP );
- angle = DEG_TO_RAD(startAngle);
- for (slice=0; slice<slices; slice++) {
- 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;
- }
-
-
- }
- }
-
-