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