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