1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225
|
#ifndef _VCG_GL_GEOMETRY_
#define _VCG_GL_GEOMETRY_
/* Portion of this file were more or less adapted from
* freeglut_geometry.c
*
* Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved.
* that was Written by Pawel W. Olszta, <olszta@sourceforge.net>
*/
#include<stdlib.h>
#include<math.h>
/*
* Compute lookup table of cos and sin values forming a cirle
*
* Notes:
* It is the responsibility of the caller to free these tables
* The size of the table is (n+1) to form a connected loop
* The last entry is exactly the same as the first
* The sign of n can be flipped to get the reverse loop
*/
static void fghCircleTable(double **sint,double **cost,const int n)
{
int i;
/* Table size, the sign of n flips the circle direction */
const int size = abs(n);
/* Determine the angle between samples */
const double angle = 2*M_PI/(double)( ( n == 0 ) ? 1 : n );
/* Allocate memory for n samples, plus duplicate of first entry at the end */
*sint = (double *) calloc(sizeof(double), size+1);
*cost = (double *) calloc(sizeof(double), size+1);
/* Bail out if memory allocation fails, fgError never returns */
if (!(*sint) || !(*cost))
{
free(*sint);
free(*cost);
abort(); //fgError("Failed to allocate memory in fghCircleTable");
}
/* Compute cos and sin around the circle */
(*sint)[0] = 0.0;
(*cost)[0] = 1.0;
for (i=1; i<size; i++)
{
(*sint)[i] = sin(angle*i);
(*cost)[i] = cos(angle*i);
}
/* Last sample is duplicate of the first */
(*sint)[size] = (*sint)[0];
(*cost)[size] = (*cost)[0];
}
/*
* Draws a solid sphere
*/
inline void glutSolidSphere(GLdouble radius, GLint slices, GLint stacks)
{
int i,j;
/* Adjust z and radius as stacks are drawn. */
double z0,z1;
double r0,r1;
/* Pre-computed circle */
double *sint1,*cost1;
double *sint2,*cost2;
// FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSolidSphere" );
fghCircleTable(&sint1,&cost1,-slices);
fghCircleTable(&sint2,&cost2,stacks*2);
/* The top stack is covered with a triangle fan */
z0 = 1.0;
z1 = cost2[(stacks>0)?1:0];
r0 = 0.0;
r1 = sint2[(stacks>0)?1:0];
glBegin(GL_TRIANGLE_FAN);
glNormal3d(0,0,1);
glVertex3d(0,0,radius);
for (j=slices; j>=0; j--)
{
glNormal3d(cost1[j]*r1, sint1[j]*r1, z1 );
glVertex3d(cost1[j]*r1*radius, sint1[j]*r1*radius, z1*radius);
}
glEnd();
/* Cover each stack with a quad strip, except the top and bottom stacks */
for( i=1; i<stacks-1; i++ )
{
z0 = z1; z1 = cost2[i+1];
r0 = r1; r1 = sint2[i+1];
glBegin(GL_QUAD_STRIP);
for(j=0; j<=slices; j++)
{
glNormal3d(cost1[j]*r1, sint1[j]*r1, z1 );
glVertex3d(cost1[j]*r1*radius, sint1[j]*r1*radius, z1*radius);
glNormal3d(cost1[j]*r0, sint1[j]*r0, z0 );
glVertex3d(cost1[j]*r0*radius, sint1[j]*r0*radius, z0*radius);
}
glEnd();
}
/* The bottom stack is covered with a triangle fan */
z0 = z1;
r0 = r1;
glBegin(GL_TRIANGLE_FAN);
glNormal3d(0,0,-1);
glVertex3d(0,0,-radius);
for (j=0; j<=slices; j++)
{
glNormal3d(cost1[j]*r0, sint1[j]*r0, z0 );
glVertex3d(cost1[j]*r0*radius, sint1[j]*r0*radius, z0*radius);
}
glEnd();
/* Release sin and cos tables */
free(sint1);
free(cost1);
free(sint2);
free(cost2);
}
/*
* Draws a wire sphere
*/
inline void glutWireSphere(GLdouble radius, GLint slices, GLint stacks)
{
int i,j;
/* Adjust z and radius as stacks and slices are drawn. */
double r;
double x,y,z;
/* Pre-computed circle */
double *sint1,*cost1;
double *sint2,*cost2;
//FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutWireSphere" );
fghCircleTable(&sint1,&cost1,-slices );
fghCircleTable(&sint2,&cost2, stacks*2);
/* Draw a line loop for each stack */
for (i=1; i<stacks; i++)
{
z = cost2[i];
r = sint2[i];
glBegin(GL_LINE_LOOP);
for(j=0; j<=slices; j++)
{
x = cost1[j];
y = sint1[j];
glNormal3d(x,y,z);
glVertex3d(x*r*radius,y*r*radius,z*radius);
}
glEnd();
}
/* Draw a line loop for each slice */
for (i=0; i<slices; i++)
{
glBegin(GL_LINE_STRIP);
for(j=0; j<=stacks; j++)
{
x = cost1[i]*sint2[j];
y = sint1[i]*sint2[j];
z = cost2[j];
glNormal3d(x,y,z);
glVertex3d(x*radius,y*radius,z*radius);
}
glEnd();
}
/* Release sin and cos tables */
free(sint1);
free(cost1);
free(sint2);
free(cost2);
}
#endif
|