ed25bf1308b135da9e91f81a1416a3bbc42f20cf
[freeglut] / freeglut-1.3 / freeglut_geometry.c
1 /*
2  * freeglut_geometry.c
3  *
4  * Freeglut geometry rendering methods.
5  *
6  * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved.
7  * Written by Pawel W. Olszta, <olszta@sourceforge.net>
8  * Creation date: Fri Dec 3 1999
9  *
10  * Permission is hereby granted, free of charge, to any person obtaining a
11  * copy of this software and associated documentation files (the "Software"),
12  * to deal in the Software without restriction, including without limitation
13  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
14  * and/or sell copies of the Software, and to permit persons to whom the
15  * Software is furnished to do so, subject to the following conditions:
16  *
17  * The above copyright notice and this permission notice shall be included
18  * in all copies or substantial portions of the Software.
19  *
20  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
21  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
23  * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
24  * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
25  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26  */
27
28 #ifdef HAVE_CONFIG_H
29 #include "config.h"
30 #endif
31
32 #define  G_LOG_DOMAIN  "freeglut-geometry"
33
34 #include "../include/GL/freeglut.h"
35 #include "../include/GL/freeglut_internal.h"
36
37 /*
38  * TODO BEFORE THE STABLE RELEASE:
39  *
40  * Following functions have been contributed by Andreas Umbach. I modified
41  * them a bit to make them use GLib (for memory allocation).
42  *
43  *      glutWireCube()          -- could add normal vectors so that lighting works
44  *      glutSolidCube()         -- OK
45  *      glutWireSphere()        -- OK
46  *      glutSolidSphere()       -- OK
47  *
48  * Following functions have been implemented by me:
49  *
50  *      glutWireCone()          -- looks OK
51  *      glutSolidCone()         -- normals are missing, there are holes in the thing
52  *
53  * Those functions need to be implemented, as nothing has been done yet.
54  * For now all of them draw a wire or solid cube, just to mark their presence.
55  *
56  *      glutWireTorus()         --
57  *      glutSolidTorus()        --
58  *      glutWireDodecahedron()  --
59  *      glutSolidDodecahedron() --
60  *      glutWireOctahedron()    --
61  *      glutSolidOctahedron()   --
62  *      glutWireTetrahedron()   --
63  *      glutSolidTetrahedron()  --
64  *      glutWireIcosahedron()   --
65  *      glutSolidIcosahedron()  --
66  */
67
68
69 /* -- INTERFACE FUNCTIONS -------------------------------------------------- */
70
71 /*
72  * Draws a wireframed cube. Code contributed by Andreas Umbach <marvin@dataway.ch>
73  */
74 void FGAPIENTRY glutWireCube( GLdouble dSize )
75 {
76     float size = (float) dSize * 0.5f;
77
78 #   define V(a,b,c) glVertex3f( a size, b size, c size );
79
80     /*
81      * PWO: I dared to convert the code to use macros...
82      */
83     glBegin( GL_LINE_LOOP ); V(-,-,+); V(+,-,+); V(+,+,+); V(-,+,+); glEnd();
84     glBegin( GL_LINE_LOOP ); V(-,-,-); V(-,+,-); V(+,+,-); V(+,-,-); glEnd();
85     glBegin( GL_LINES );
86         V(-,-,+); V(-,-,-); V(-,+,+); V(-,+,-);
87         V(+,-,+); V(+,-,-); V(+,+,+); V(+,+,-);
88     glEnd();
89
90 #   undef V
91 }
92
93 /*
94  * Draws a solid cube. Code contributed by Andreas Umbach <marvin@dataway.ch>
95  */
96 void FGAPIENTRY glutSolidCube( GLdouble dSize )
97 {
98     float size = (float) dSize * 0.5f;
99
100 #   define V(a,b,c) glVertex3f( a size, b size, c size );
101 #   define N(a,b,c) glNormal3f( a, b, c );
102
103     /*
104      * PWO: Again, I dared to convert the code to use macros...
105      */
106     glBegin( GL_QUADS );
107         N( 1, 0, 0); V(+,-,+); V(+,-,-); V(+,+,-); V(+,+,+);
108         N( 0, 1, 0); V(+,+,+); V(+,+,-); V(-,+,-); V(-,+,+);
109         N( 0, 0, 1); V(+,+,+); V(-,+,+); V(-,-,+); V(+,-,+);
110         N(-1, 0, 0); V(-,-,+); V(-,+,+); V(-,+,-); V(-,-,-);
111         N( 0,-1, 0); V(-,-,+); V(-,-,-); V(+,-,-); V(+,-,+);
112         N( 0, 0,-1); V(-,-,-); V(-,+,-); V(+,+,-); V(+,-,-);
113     glEnd();
114
115 #   undef V
116 #   undef N
117 }
118
119 /*
120  * Draws a wire sphere. Code contributed by Andreas Umbach <marvin@dataway.ch>
121  */
122 void FGAPIENTRY glutWireSphere( GLdouble dRadius, GLint slices, GLint stacks )
123 {
124     float  radius = (float) dRadius, phi, psi, dpsi, dphi;
125     float* vertex;
126     int    i, j;
127
128     /*
129      * Allocate the vertices array
130      */
131     vertex = calloc( sizeof(float), 3 * slices * (stacks - 1) );
132
133     glPushMatrix();
134     glScalef( radius, radius, radius );
135
136     dpsi = M_PI / (stacks + 1);
137     dphi = 2 * M_PI / slices;
138     psi  = dpsi;
139
140     for( j=0; j<stacks-1; j++ )
141     {
142         phi = 0;
143
144         for( i=0; i<slices; i++ )
145         {
146             *(vertex + 3 * j * slices + 3 * i + 0) = sin( phi ) * sin( psi );
147             *(vertex + 3 * j * slices + 3 * i + 1) = cos( phi ) * sin( psi );
148             *(vertex + 3 * j * slices + 3 * i + 2) = cos( psi );
149             phi += dphi;
150             glVertex3fv( vertex + 3 * j * slices + 3 * i );
151         }
152
153         psi += dpsi;
154     }
155
156     for( i=0; i<slices; i++ )
157     {
158         glBegin( GL_LINE_STRIP );
159         glNormal3f( 0, 0, 1 );
160         glVertex3f( 0, 0, 1 );
161
162         for( j=0; j<stacks - 1; j++ )
163         {
164             glNormal3fv( vertex + 3 * j * slices + 3 * i );
165             glVertex3fv( vertex + 3 * j * slices + 3 * i );
166         }
167
168         glNormal3f(0, 0, -1);
169         glVertex3f(0, 0, -1);
170         glEnd();
171     }
172
173     for( j=0; j<stacks-1; j++ )
174     {
175         glBegin(GL_LINE_LOOP);
176
177         for( i=0; i<slices; i++ )
178         {
179             glNormal3fv( vertex + 3 * j * slices + 3 * i );
180             glVertex3fv( vertex + 3 * j * slices + 3 * i );
181         }
182
183         glEnd();
184     }
185
186     free( vertex );
187     glPopMatrix();
188 }
189
190 /*
191  * Draws a solid sphere. Code contributed by Andreas Umbach <marvin@dataway.ch>
192  */
193 void FGAPIENTRY glutSolidSphere( GLdouble dRadius, GLint slices, GLint stacks )
194 {
195     float  radius = (float) dRadius, phi, psi, dpsi, dphi;
196     float *next, *tmp, *row;
197     int    i, j;
198
199     glPushMatrix();
200     //glScalef( radius, radius, radius );
201
202     row  = calloc( sizeof(float), slices * 3 );
203     next = calloc( sizeof(float), slices * 3 );
204
205     dpsi = M_PI / (stacks + 1);
206     dphi = 2 * M_PI / slices;
207     psi  = dpsi;
208     phi  = 0;
209
210     /* init first line + do polar cap */
211     glBegin( GL_TRIANGLE_FAN );
212     glNormal3f( 0, 0, 1 );
213     glVertex3f( 0, 0, radius );
214
215     for( i=0; i<slices; i++ )
216     {
217         row[ i * 3 + 0 ] = sin( phi ) * sin( psi );
218         row[ i * 3 + 1 ] = cos( phi ) * sin( psi );
219         row[ i * 3 + 2 ] = cos( psi );
220
221         glNormal3fv( row + 3 * i );
222         glVertex3f(
223             radius * *(row + 3 * i + 0),
224             radius * *(row + 3 * i + 1),
225                 radius * *(row + 3 * i + 2)
226             );
227         
228         phi += dphi;
229     }
230
231     glNormal3fv( row );
232     glVertex3f( radius * *(row + 0), radius * *(row + 1), radius * *(row + 2) );
233     glEnd();
234
235     for( j=0; j<stacks-1; j++ )
236     {
237         phi = 0;
238         psi += dpsi;
239
240         /* get coords */
241         glBegin( GL_QUAD_STRIP );
242
243         /* glBegin(GL_LINE_LOOP); */
244         for( i=0; i<slices; i++ )
245         {
246             next[ i * 3 + 0 ] = sin( phi ) * sin( psi );
247             next[ i * 3 + 1 ] = cos( phi ) * sin( psi );
248             next[ i * 3 + 2 ] = cos( psi );
249
250             glNormal3fv( row + i * 3 );
251             glVertex3f(
252                 radius * *(row + 3 * i + 0),
253                 radius * *(row + 3 * i + 1),
254                         radius * *(row + 3 * i + 2)
255                     );
256
257             glNormal3fv( next + i * 3 );
258             glVertex3f(
259                 radius * *(next + 3 * i + 0),
260                 radius * *(next + 3 * i + 1),
261                 radius * *(next + 3 * i + 2)
262             );
263
264             phi += dphi;
265         }
266
267         glNormal3fv( row );
268         glVertex3f( radius * *(row + 0), radius * *(row + 1), radius * *(row + 2) );
269         glNormal3fv( next );
270         glVertex3f( radius * *(next + 0), radius * *(next + 1), radius * *(next + 2) );
271         glEnd();
272
273         tmp = row;
274         row = next;
275         next = tmp;
276     }
277
278     /* south pole */
279     glBegin( GL_TRIANGLE_FAN );
280     glNormal3f( 0, 0, -1 );
281     glVertex3f( 0, 0, -radius );
282     glNormal3fv( row );
283     glVertex3f( radius * *(row + 0), radius * *(row + 1), radius * *(row + 2) );
284
285     for( i=slices-1; i>=0; i-- )
286     {
287         glNormal3fv(row + 3 * i);
288         glVertex3f(
289             radius * *(row + 3 * i + 0),
290             radius * *(row + 3 * i + 1),
291                 radius * *(row + 3 * i + 2)
292            );
293     }
294
295     glEnd();
296
297     free(row);
298     free(next);
299     glPopMatrix();
300 }
301
302 /*
303  * Draws a wire cone
304  */
305 void FGAPIENTRY glutWireCone( GLdouble base, GLdouble height, GLint slices, GLint stacks )
306 {
307     float  alt   = (float) height / (float) (stacks + 1);
308     float  angle = (float) M_PI / (float) slices * 2.0f;
309     float  slope = (float) tan( height / base );
310     float* vertices = NULL;
311     int    i, j;
312
313     /*
314      * We need 'slices' points on a circle
315      */
316     vertices = calloc( sizeof(float), 2 * (slices + 1) );
317
318     for( i=0; i<slices+1; i++ )
319     {
320         vertices[ i*2 + 0 ] = cos( angle * i );
321         vertices[ i*2 + 1 ] = sin( angle * i );
322     }
323
324     /*
325      * First the cone's bottom...
326      */
327     for( i=0; i<slices; i++ )
328     {
329         float scl = height / slope;
330
331         glBegin( GL_LINE_LOOP );
332             glNormal3f( 0, 0, -1 );
333             glVertex3f( vertices[ (i+0)*2+0 ] * scl, vertices[ (i+0)*2+1 ] * scl, 0 );
334             glVertex3f( vertices[ (i+1)*2+0 ] * scl, vertices[ (i+1)*2+1 ] * scl, 0 );
335             glVertex3f( 0, 0, 0 );
336         glEnd();
337     }
338
339     /*
340      * Then all the stacks between the bottom and the top
341      *
342      * ekhm jak wektor normalny z trojkata?
343      */
344     for( i=0; i<stacks; i++ )
345     {
346         float alt_a = i * alt, alt_b = (i + 1) * alt;
347         float scl_a = (height - alt_a) / slope;
348         float scl_b = (height - alt_b) / slope;
349
350         for( j=0; j<slices; j++ )
351         {
352             glBegin( GL_LINE_LOOP );
353                 glVertex3f( vertices[(j+0)*2+0] * scl_a, vertices[(j+0)*2+1] * scl_a, alt_a );
354                 glVertex3f( vertices[(j+1)*2+0] * scl_a, vertices[(j+1)*2+1] * scl_a, alt_a );
355                 glVertex3f( vertices[(j+0)*2+0] * scl_b, vertices[(j+0)*2+1] * scl_b, alt_b );
356             glEnd();
357
358             glBegin( GL_LINE_LOOP );
359                 glVertex3f( vertices[(j+0)*2+0] * scl_b, vertices[(j+0)*2+1] * scl_b, alt_b );
360                 glVertex3f( vertices[(j+1)*2+0] * scl_b, vertices[(j+1)*2+1] * scl_b, alt_b );
361                 glVertex3f( vertices[(j+1)*2+0] * scl_a, vertices[(j+1)*2+1] * scl_a, alt_a );
362             glEnd();
363         }
364     }
365
366     /*
367      * Finally have the top part drawn...
368      */
369     for( i=0; i<slices; i++ )
370     {
371         float scl = alt / slope;
372
373         glBegin( GL_LINE_LOOP );
374             glVertex3f( vertices[ (i+0)*2+0 ] * scl, vertices[ (i+0)*2+1 ] * scl, height - alt );
375             glVertex3f( vertices[ (i+1)*2+0 ] * scl, vertices[ (i+1)*2+1 ] * scl, height - alt );
376             glVertex3f( 0, 0, height );
377         glEnd();
378     }
379 }
380
381 /*
382  * Draws a solid cone
383  */
384 void FGAPIENTRY glutSolidCone( GLdouble base, GLdouble height, GLint slices, GLint stacks )
385 {
386     float  alt   = (float) height / (float) (stacks + 1);
387     float  angle = (float) M_PI / (float) slices * 2.0f;
388     float  slope = (float) tan( height / base );
389     float* vertices = NULL;
390     int    i, j;
391
392     /*
393      * We need 'slices' points on a circle
394      */
395     vertices = calloc( sizeof(float), 2 * (slices + 1) );
396
397     for( i=0; i<slices+1; i++ )
398     {
399         vertices[ i*2 + 0 ] = cos( angle * i );
400         vertices[ i*2 + 1 ] = sin( angle * i );
401     }
402
403     /*
404      * First the cone's bottom...
405      */
406     for( i=0; i<slices; i++ )
407     {
408         float scl = height / slope;
409
410         glBegin( GL_TRIANGLES );
411             glNormal3f( 0, 0, -1 );
412             glVertex3f( vertices[ (i+0)*2+0 ] * scl, vertices[ (i+0)*2+1 ] * scl, 0 );
413             glVertex3f( vertices[ (i+1)*2+0 ] * scl, vertices[ (i+1)*2+1 ] * scl, 0 );
414             glVertex3f( 0, 0, 0 );
415         glEnd();
416     }
417
418     /*
419      * Then all the stacks between the bottom and the top
420      *
421      * ekhm jak wektor normalny z trojkata?
422      */
423     for( i=0; i<stacks; i++ )
424     {
425         float alt_a = i * alt, alt_b = (i + 1) * alt;
426         float scl_a = (height - alt_a) / slope;
427         float scl_b = (height - alt_b) / slope;
428
429         for( j=0; j<slices; j++ )
430         {
431             glBegin( GL_TRIANGLES );
432                 glVertex3f( vertices[(j+0)*2+0] * scl_a, vertices[(j+0)*2+1] * scl_a, alt_a );
433                 glVertex3f( vertices[(j+1)*2+0] * scl_a, vertices[(j+1)*2+1] * scl_a, alt_a );
434                 glVertex3f( vertices[(j+0)*2+0] * scl_b, vertices[(j+0)*2+1] * scl_b, alt_b );
435             glEnd();
436
437             glBegin( GL_TRIANGLES );
438                 glVertex3f( vertices[(j+1)*2+0] * scl_a, vertices[(j+1)*2+1] * scl_a, alt_a );
439                 glVertex3f( vertices[(j+1)*2+0] * scl_b, vertices[(j+1)*2+1] * scl_b, alt_b );
440                 glVertex3f( vertices[(j+0)*2+0] * scl_b, vertices[(j+0)*2+1] * scl_b, alt_b );
441             glEnd();
442         }
443     }
444
445     /*
446      * Finally have the top part drawn...
447      */
448     for( i=0; i<slices; i++ )
449     {
450         float scl = alt / slope;
451
452         glBegin( GL_TRIANGLES );
453             glVertex3f( vertices[ (i+0)*2+0 ] * scl, vertices[ (i+0)*2+1 ] * scl, height - alt );
454             glVertex3f( vertices[ (i+1)*2+0 ] * scl, vertices[ (i+1)*2+1 ] * scl, height - alt );
455             glVertex3f( 0, 0, height );
456         glEnd();
457     }
458 }
459
460 /*
461  *
462  */
463 void FGAPIENTRY glutWireTorus( GLdouble dInnerRadius, GLdouble dOuterRadius, GLint nSides, GLint nRings )
464 {
465     glutWireSphere( dOuterRadius, 5, 5 );
466 }
467
468 /*
469  *
470  */
471 void FGAPIENTRY glutSolidTorus( GLdouble dInnerRadius, GLdouble dOuterRadius, GLint nSides, GLint nRings )
472 {
473     glutSolidSphere( dOuterRadius, 5, 5 );
474 }
475
476 /*
477  *
478  */
479 void FGAPIENTRY glutWireDodecahedron( void )
480 {
481   /* Magic Numbers:  It is possible to create a dodecahedron by attaching two pentagons to each face of
482    * of a cube.  The coordinates of the points are:
483    *   (+-x,0, z); (+-1, 1, 1); (0, z, x )
484    * where x = 0.618033989 and z = 1.618033939.
485    */
486   glBegin ( GL_LINE_LOOP ) ;
487   glNormal3f (  0.000000f,  0.525731f,  0.850651f ) ; glVertex3f (  0.000000f,  1.618034f,  0.618034f ) ; glVertex3f ( -1.0f,  1.0f,  1.0f ) ; glVertex3f ( -0.618034f, 0.000000f,  1.618034f ) ; glVertex3f (  0.618034f, 0.000000f,  1.618034f ) ; glVertex3f (  1.0f,  1.0f,  1.0f ) ;
488   glEnd () ;
489   glBegin ( GL_LINE_LOOP ) ;
490   glNormal3f (  0.000000f,  0.525731f, -0.850651f ) ; glVertex3f (  0.000000f,  1.618034f, -0.618034f ) ; glVertex3f (  1.0f,  1.0f, -1.0f ) ; glVertex3f (  0.618034f, 0.000000f, -1.618034f ) ; glVertex3f ( -0.618034f, 0.000000f, -1.618034f ) ; glVertex3f ( -1.0f,  1.0f, -1.0f ) ;
491   glEnd () ;
492   glBegin ( GL_LINE_LOOP ) ;
493   glNormal3f (  0.000000f, -0.525731f,  0.850651f ) ; glVertex3f (  0.000000f, -1.618034f,  0.618034f ) ; glVertex3f (  1.0f, -1.0f,  1.0f ) ; glVertex3f (  0.618034f, 0.000000f,  1.618034f ) ; glVertex3f ( -0.618034f, 0.000000f,  1.618034f ) ; glVertex3f ( -1.0f, -1.0f,  1.0f ) ;
494   glEnd () ;
495   glBegin ( GL_LINE_LOOP ) ;
496   glNormal3f (  0.000000f, -0.525731f, -0.850651f ) ; glVertex3f (  0.000000f, -1.618034f, -0.618034f ) ; glVertex3f ( -1.0f, -1.0f, -1.0f ) ; glVertex3f ( -0.618034f, 0.000000f, -1.618034f ) ; glVertex3f (  0.618034f, 0.000000f, -1.618034f ) ; glVertex3f (  1.0f, -1.0f, -1.0f ) ;
497   glEnd () ;
498
499   glBegin ( GL_LINE_LOOP ) ;
500   glNormal3f (  0.850651f,  0.000000f,  0.525731f ) ; glVertex3f (  0.618034f,  0.000000f,  1.618034f ) ; glVertex3f (  1.0f, -1.0f,  1.0f ) ; glVertex3f (  1.618034f, -0.618034f, 0.000000f ) ; glVertex3f (  1.618034f,  0.618034f, 0.000000f ) ; glVertex3f (  1.0f,  1.0f,  1.0f ) ;
501   glEnd () ;
502   glBegin ( GL_LINE_LOOP ) ;
503   glNormal3f ( -0.850651f,  0.000000f,  0.525731f ) ; glVertex3f ( -0.618034f,  0.000000f,  1.618034f ) ; glVertex3f ( -1.0f,  1.0f,  1.0f ) ; glVertex3f ( -1.618034f,  0.618034f, 0.000000f ) ; glVertex3f ( -1.618034f, -0.618034f, 0.000000f ) ; glVertex3f ( -1.0f, -1.0f,  1.0f ) ;
504   glEnd () ;
505   glBegin ( GL_LINE_LOOP ) ;
506   glNormal3f (  0.850651f,  0.000000f, -0.525731f ) ; glVertex3f (  0.618034f,  0.000000f, -1.618034f ) ; glVertex3f (  1.0f,  1.0f, -1.0f ) ; glVertex3f (  1.618034f,  0.618034f, 0.000000f ) ; glVertex3f (  1.618034f, -0.618034f, 0.000000f ) ; glVertex3f (  1.0f, -1.0f, -1.0f ) ;
507   glEnd () ;
508   glBegin ( GL_LINE_LOOP ) ;
509   glNormal3f ( -0.850651f,  0.000000f, -0.525731f ) ; glVertex3f ( -0.618034f,  0.000000f, -1.618034f ) ; glVertex3f ( -1.0f, -1.0f, -1.0f ) ; glVertex3f ( -1.618034f, -0.618034f, 0.000000f ) ; glVertex3f ( -1.618034f,  0.618034f, 0.000000f ) ; glVertex3f ( -1.0f,  1.0f, -1.0f ) ;
510   glEnd () ;
511
512   glBegin ( GL_LINE_LOOP ) ;
513   glNormal3f (  0.525731f,  0.850651f,  0.000000f ) ; glVertex3f (  1.618034f,  0.618034f,  0.000000f ) ; glVertex3f (  1.0f,  1.0f, -1.0f ) ; glVertex3f ( 0.000000f,  1.618034f, -0.618034f ) ; glVertex3f ( 0.000000f,  1.618034f,  0.618034f ) ; glVertex3f (  1.0f,  1.0f,  1.0f ) ;
514   glEnd () ;
515   glBegin ( GL_LINE_LOOP ) ;
516   glNormal3f (  0.525731f, -0.850651f,  0.000000f ) ; glVertex3f (  1.618034f, -0.618034f,  0.000000f ) ; glVertex3f (  1.0f, -1.0f,  1.0f ) ; glVertex3f ( 0.000000f, -1.618034f,  0.618034f ) ; glVertex3f ( 0.000000f, -1.618034f, -0.618034f ) ; glVertex3f (  1.0f, -1.0f, -1.0f ) ;
517   glEnd () ;
518   glBegin ( GL_LINE_LOOP ) ;
519   glNormal3f ( -0.525731f,  0.850651f,  0.000000f ) ; glVertex3f ( -1.618034f,  0.618034f,  0.000000f ) ; glVertex3f ( -1.0f,  1.0f,  1.0f ) ; glVertex3f ( 0.000000f,  1.618034f,  0.618034f ) ; glVertex3f ( 0.000000f,  1.618034f, -0.618034f ) ; glVertex3f ( -1.0f,  1.0f, -1.0f ) ;
520   glEnd () ;
521   glBegin ( GL_LINE_LOOP ) ;
522   glNormal3f ( -0.525731f, -0.850651f,  0.000000f ) ; glVertex3f ( -1.618034f, -0.618034f,  0.000000f ) ; glVertex3f ( -1.0f, -1.0f, -1.0f ) ; glVertex3f ( 0.000000f, -1.618034f, -0.618034f ) ; glVertex3f ( 0.000000f, -1.618034f,  0.618034f ) ; glVertex3f ( -1.0f, -1.0f,  1.0f ) ;
523   glEnd () ;
524 }
525
526 /*
527  *
528  */
529 void FGAPIENTRY glutSolidDodecahedron( void )
530 {
531   /* Magic Numbers:  It is possible to create a dodecahedron by attaching two pentagons to each face of
532    * of a cube.  The coordinates of the points are:
533    *   (+-x,0, z); (+-1, 1, 1); (0, z, x )
534    * where x = 0.618033989 and z = 1.618033939.
535    */
536   glBegin ( GL_POLYGON ) ;
537   glNormal3f (  0.000000f,  0.525731f,  0.850651f ) ; glVertex3f (  0.000000f,  1.618034f,  0.618034f ) ; glVertex3f ( -1.0f,  1.0f,  1.0f ) ; glVertex3f ( -0.618034f, 0.000000f,  1.618034f ) ; glVertex3f (  0.618034f, 0.000000f,  1.618034f ) ; glVertex3f (  1.0f,  1.0f,  1.0f ) ;
538   glEnd () ;
539   glBegin ( GL_POLYGON ) ;
540   glNormal3f (  0.000000f,  0.525731f, -0.850651f ) ; glVertex3f (  0.000000f,  1.618034f, -0.618034f ) ; glVertex3f (  1.0f,  1.0f, -1.0f ) ; glVertex3f (  0.618034f, 0.000000f, -1.618034f ) ; glVertex3f ( -0.618034f, 0.000000f, -1.618034f ) ; glVertex3f ( -1.0f,  1.0f, -1.0f ) ;
541   glEnd () ;
542   glBegin ( GL_POLYGON ) ;
543   glNormal3f (  0.000000f, -0.525731f,  0.850651f ) ; glVertex3f (  0.000000f, -1.618034f,  0.618034f ) ; glVertex3f (  1.0f, -1.0f,  1.0f ) ; glVertex3f (  0.618034f, 0.000000f,  1.618034f ) ; glVertex3f ( -0.618034f, 0.000000f,  1.618034f ) ; glVertex3f ( -1.0f, -1.0f,  1.0f ) ;
544   glEnd () ;
545   glBegin ( GL_POLYGON ) ;
546   glNormal3f (  0.000000f, -0.525731f, -0.850651f ) ; glVertex3f (  0.000000f, -1.618034f, -0.618034f ) ; glVertex3f ( -1.0f, -1.0f, -1.0f ) ; glVertex3f ( -0.618034f, 0.000000f, -1.618034f ) ; glVertex3f (  0.618034f, 0.000000f, -1.618034f ) ; glVertex3f (  1.0f, -1.0f, -1.0f ) ;
547   glEnd () ;
548
549   glBegin ( GL_POLYGON ) ;
550   glNormal3f (  0.850651f,  0.000000f,  0.525731f ) ; glVertex3f (  0.618034f,  0.000000f,  1.618034f ) ; glVertex3f (  1.0f, -1.0f,  1.0f ) ; glVertex3f (  1.618034f, -0.618034f, 0.000000f ) ; glVertex3f (  1.618034f,  0.618034f, 0.000000f ) ; glVertex3f (  1.0f,  1.0f,  1.0f ) ;
551   glEnd () ;
552   glBegin ( GL_POLYGON ) ;
553   glNormal3f ( -0.850651f,  0.000000f,  0.525731f ) ; glVertex3f ( -0.618034f,  0.000000f,  1.618034f ) ; glVertex3f ( -1.0f,  1.0f,  1.0f ) ; glVertex3f ( -1.618034f,  0.618034f, 0.000000f ) ; glVertex3f ( -1.618034f, -0.618034f, 0.000000f ) ; glVertex3f ( -1.0f, -1.0f,  1.0f ) ;
554   glEnd () ;
555   glBegin ( GL_POLYGON ) ;
556   glNormal3f (  0.850651f,  0.000000f, -0.525731f ) ; glVertex3f (  0.618034f,  0.000000f, -1.618034f ) ; glVertex3f (  1.0f,  1.0f, -1.0f ) ; glVertex3f (  1.618034f,  0.618034f, 0.000000f ) ; glVertex3f (  1.618034f, -0.618034f, 0.000000f ) ; glVertex3f (  1.0f, -1.0f, -1.0f ) ;
557   glEnd () ;
558   glBegin ( GL_POLYGON ) ;
559   glNormal3f ( -0.850651f,  0.000000f, -0.525731f ) ; glVertex3f ( -0.618034f,  0.000000f, -1.618034f ) ; glVertex3f ( -1.0f, -1.0f, -1.0f ) ; glVertex3f ( -1.618034f, -0.618034f, 0.000000f ) ; glVertex3f ( -1.618034f,  0.618034f, 0.000000f ) ; glVertex3f ( -1.0f,  1.0f, -1.0f ) ;
560   glEnd () ;
561
562   glBegin ( GL_POLYGON ) ;
563   glNormal3f (  0.525731f,  0.850651f,  0.000000f ) ; glVertex3f (  1.618034f,  0.618034f,  0.000000f ) ; glVertex3f (  1.0f,  1.0f, -1.0f ) ; glVertex3f ( 0.000000f,  1.618034f, -0.618034f ) ; glVertex3f ( 0.000000f,  1.618034f,  0.618034f ) ; glVertex3f (  1.0f,  1.0f,  1.0f ) ;
564   glEnd () ;
565   glBegin ( GL_POLYGON ) ;
566   glNormal3f (  0.525731f, -0.850651f,  0.000000f ) ; glVertex3f (  1.618034f, -0.618034f,  0.000000f ) ; glVertex3f (  1.0f, -1.0f,  1.0f ) ; glVertex3f ( 0.000000f, -1.618034f,  0.618034f ) ; glVertex3f ( 0.000000f, -1.618034f, -0.618034f ) ; glVertex3f (  1.0f, -1.0f, -1.0f ) ;
567   glEnd () ;
568   glBegin ( GL_POLYGON ) ;
569   glNormal3f ( -0.525731f,  0.850651f,  0.000000f ) ; glVertex3f ( -1.618034f,  0.618034f,  0.000000f ) ; glVertex3f ( -1.0f,  1.0f,  1.0f ) ; glVertex3f ( 0.000000f,  1.618034f,  0.618034f ) ; glVertex3f ( 0.000000f,  1.618034f, -0.618034f ) ; glVertex3f ( -1.0f,  1.0f, -1.0f ) ;
570   glEnd () ;
571   glBegin ( GL_POLYGON ) ;
572   glNormal3f ( -0.525731f, -0.850651f,  0.000000f ) ; glVertex3f ( -1.618034f, -0.618034f,  0.000000f ) ; glVertex3f ( -1.0f, -1.0f, -1.0f ) ; glVertex3f ( 0.000000f, -1.618034f, -0.618034f ) ; glVertex3f ( 0.000000f, -1.618034f,  0.618034f ) ; glVertex3f ( -1.0f, -1.0f,  1.0f ) ;
573   glEnd () ;
574 }
575
576 /*
577  *
578  */
579 void FGAPIENTRY glutWireOctahedron( void )
580 {
581 #define RADIUS    1.0f
582   glBegin( GL_LINE_LOOP );
583     glNormal3f( 0.577350f, 0.577350f, 0.577350f); glVertex3f( RADIUS, 0.0f, 0.0f ); glVertex3f( 0.0f, RADIUS, 0.0f ); glVertex3f( 0.0f, 0.0f, RADIUS );
584     glNormal3f( 0.577350f, 0.577350f,-0.577350f); glVertex3f( RADIUS, 0.0f, 0.0f ); glVertex3f( 0.0f, RADIUS, 0.0f ); glVertex3f( 0.0f, 0.0f,-RADIUS );
585     glNormal3f( 0.577350f,-0.577350f, 0.577350f); glVertex3f( RADIUS, 0.0f, 0.0f ); glVertex3f( 0.0f,-RADIUS, 0.0f ); glVertex3f( 0.0f, 0.0f, RADIUS );
586     glNormal3f( 0.577350f,-0.577350f,-0.577350f); glVertex3f( RADIUS, 0.0f, 0.0f ); glVertex3f( 0.0f,-RADIUS, 0.0f ); glVertex3f( 0.0f, 0.0f,-RADIUS );
587     glNormal3f(-0.577350f, 0.577350f, 0.577350f); glVertex3f(-RADIUS, 0.0f, 0.0f ); glVertex3f( 0.0f, RADIUS, 0.0f ); glVertex3f( 0.0f, 0.0f, RADIUS );
588     glNormal3f(-0.577350f, 0.577350f,-0.577350f); glVertex3f(-RADIUS, 0.0f, 0.0f ); glVertex3f( 0.0f, RADIUS, 0.0f ); glVertex3f( 0.0f, 0.0f,-RADIUS );
589     glNormal3f(-0.577350f,-0.577350f, 0.577350f); glVertex3f(-RADIUS, 0.0f, 0.0f ); glVertex3f( 0.0f,-RADIUS, 0.0f ); glVertex3f( 0.0f, 0.0f, RADIUS );
590     glNormal3f(-0.577350f,-0.577350f,-0.577350f); glVertex3f(-RADIUS, 0.0f, 0.0f ); glVertex3f( 0.0f,-RADIUS, 0.0f ); glVertex3f( 0.0f, 0.0f,-RADIUS );
591   glEnd();
592 #undef RADIUS
593 }
594
595 /*
596  *
597  */
598 void FGAPIENTRY glutSolidOctahedron( void )
599 {
600 #define RADIUS    1.0f
601   glBegin( GL_TRIANGLES );
602     glNormal3f( 0.577350f, 0.577350f, 0.577350f); glVertex3f( RADIUS, 0.0f, 0.0f ); glVertex3f( 0.0f, RADIUS, 0.0f ); glVertex3f( 0.0f, 0.0f, RADIUS );
603     glNormal3f( 0.577350f, 0.577350f,-0.577350f); glVertex3f( RADIUS, 0.0f, 0.0f ); glVertex3f( 0.0f, RADIUS, 0.0f ); glVertex3f( 0.0f, 0.0f,-RADIUS );
604     glNormal3f( 0.577350f,-0.577350f, 0.577350f); glVertex3f( RADIUS, 0.0f, 0.0f ); glVertex3f( 0.0f,-RADIUS, 0.0f ); glVertex3f( 0.0f, 0.0f, RADIUS );
605     glNormal3f( 0.577350f,-0.577350f,-0.577350f); glVertex3f( RADIUS, 0.0f, 0.0f ); glVertex3f( 0.0f,-RADIUS, 0.0f ); glVertex3f( 0.0f, 0.0f,-RADIUS );
606     glNormal3f(-0.577350f, 0.577350f, 0.577350f); glVertex3f(-RADIUS, 0.0f, 0.0f ); glVertex3f( 0.0f, RADIUS, 0.0f ); glVertex3f( 0.0f, 0.0f, RADIUS );
607     glNormal3f(-0.577350f, 0.577350f,-0.577350f); glVertex3f(-RADIUS, 0.0f, 0.0f ); glVertex3f( 0.0f, RADIUS, 0.0f ); glVertex3f( 0.0f, 0.0f,-RADIUS );
608     glNormal3f(-0.577350f,-0.577350f, 0.577350f); glVertex3f(-RADIUS, 0.0f, 0.0f ); glVertex3f( 0.0f,-RADIUS, 0.0f ); glVertex3f( 0.0f, 0.0f, RADIUS );
609     glNormal3f(-0.577350f,-0.577350f,-0.577350f); glVertex3f(-RADIUS, 0.0f, 0.0f ); glVertex3f( 0.0f,-RADIUS, 0.0f ); glVertex3f( 0.0f, 0.0f,-RADIUS );
610   glEnd();
611 #undef RADIUS
612 }
613
614 /*
615  *
616  */
617 void FGAPIENTRY glutWireTetrahedron( void )
618 {
619   /* Magic Numbers:  r0 = ( 1, 0, 0 )
620    *                 r1 = ( -1/3, 2 sqrt(2) / 3, 0 )
621    *                 r2 = ( -1/3, -sqrt(2) / 3, sqrt(6) / 3 )
622    *                 r3 = ( -1/3, -sqrt(2) / 3, -sqrt(6) / 3 )
623    * |r0| = |r1| = |r2| = |r3| = 1
624    * Distance between any two points is 2 sqrt(6) / 3
625    *
626    * Normals:  The unit normals are simply the negative of the coordinates of the point not on the surface.
627    */
628
629   float r0[3] = {       1.0f,       0.0f,       0.0f } ;
630   float r1[3] = { -0.333333f,  0.942809f,       0.0f } ;
631   float r2[3] = { -0.333333f, -0.471405f,  0.816497f } ;
632   float r3[3] = { -0.333333f, -0.471405f, -0.816497f } ;
633
634   glBegin( GL_LINE_LOOP ) ;
635     glNormal3f (     -1.0f,       0.0f,       0.0f ) ; glVertex3fv ( r1 ) ; glVertex3fv ( r3 ) ; glVertex3fv ( r2 ) ;
636     glNormal3f ( 0.333333f, -0.942809f,       0.0f ) ; glVertex3fv ( r0 ) ; glVertex3fv ( r2 ) ; glVertex3fv ( r3 ) ;
637     glNormal3f ( 0.333333f,  0.471405f, -0.816497f ) ; glVertex3fv ( r0 ) ; glVertex3fv ( r3 ) ; glVertex3fv ( r1 ) ;
638     glNormal3f ( 0.333333f,  0.471405f,  0.816497f ) ; glVertex3fv ( r0 ) ; glVertex3fv ( r1 ) ; glVertex3fv ( r2 ) ;
639   glEnd() ;
640 }
641
642 /*
643  *
644  */
645 void FGAPIENTRY glutSolidTetrahedron( void )
646 {
647   /* Magic Numbers:  r0 = ( 1, 0, 0 )
648    *                 r1 = ( -1/3, 2 sqrt(2) / 3, 0 )
649    *                 r2 = ( -1/3, -sqrt(2) / 3, sqrt(6) / 3 )
650    *                 r3 = ( -1/3, -sqrt(2) / 3, -sqrt(6) / 3 )
651    * |r0| = |r1| = |r2| = |r3| = 1
652    * Distance between any two points is 2 sqrt(6) / 3
653    *
654    * Normals:  The unit normals are simply the negative of the coordinates of the point not on the surface.
655    */
656
657   float r0[3] = {       1.0f,       0.0f,       0.0f } ;
658   float r1[3] = { -0.333333f,  0.942809f,       0.0f } ;
659   float r2[3] = { -0.333333f, -0.471405f,  0.816497f } ;
660   float r3[3] = { -0.333333f, -0.471405f, -0.816497f } ;
661
662   glBegin( GL_TRIANGLES ) ;
663     glNormal3f (     -1.0f,       0.0f,       0.0f ) ; glVertex3fv ( r1 ) ; glVertex3fv ( r3 ) ; glVertex3fv ( r2 ) ;
664     glNormal3f ( 0.333333f, -0.942809f,       0.0f ) ; glVertex3fv ( r0 ) ; glVertex3fv ( r2 ) ; glVertex3fv ( r3 ) ;
665     glNormal3f ( 0.333333f,  0.471405f, -0.816497f ) ; glVertex3fv ( r0 ) ; glVertex3fv ( r3 ) ; glVertex3fv ( r1 ) ;
666     glNormal3f ( 0.333333f,  0.471405f,  0.816497f ) ; glVertex3fv ( r0 ) ; glVertex3fv ( r1 ) ; glVertex3fv ( r2 ) ;
667   glEnd() ;
668 }
669
670 /*
671  *
672  */
673   float r[12][3] = { { 1.0f, 0.0f, 0.0f },
674   {  0.447214f,  0.894427f, 0.0f }, {  0.447214f,  0.276393f, 0.850651f }, {  0.447214f, -0.723607f, 0.525731f }, {  0.447214f, -0.723607f, -0.525731f }, {  0.447214f,  0.276393f, -0.850651f },
675   { -0.447214f, -0.894427f, 0.0f }, { -0.447214f, -0.276393f, 0.850651f }, { -0.447214f,  0.723607f, 0.525731f }, { -0.447214f,  0.723607f, -0.525731f }, { -0.447214f, -0.276393f, -0.850651f },
676   { -1.0f, 0.0f, 0.0f } } ;
677   int v [20][3] = { { 0, 1, 2 }, { 0, 2, 3 }, { 0, 3, 4 }, { 0, 4, 5 }, { 0, 5, 1 },
678   { 1, 8, 2 }, { 2, 7, 3 }, { 3, 6, 4 }, { 4, 10, 5 }, { 5, 9, 1 },
679   { 1, 9, 8 }, { 2, 8, 7 }, { 3, 7, 6 }, { 4, 6, 10 }, { 5, 10, 9 },
680   { 11, 9, 10 }, { 11, 8, 9 }, { 11, 7, 8 }, { 11, 6, 7 }, { 11, 10, 6 } } ;
681
682 void FGAPIENTRY glutWireIcosahedron( void )
683 {
684   int i ;
685   for ( i = 0; i < 20; i++ )
686   {
687     float normal[3] ;
688     normal[0] = ( r[v[i][1]][1] - r[v[i][0]][1] ) * ( r[v[i][2]][2] - r[v[i][0]][2] ) - ( r[v[i][1]][2] - r[v[i][0]][2] ) * ( r[v[i][2]][1] - r[v[i][0]][1] ) ;
689     normal[1] = ( r[v[i][1]][2] - r[v[i][0]][2] ) * ( r[v[i][2]][0] - r[v[i][0]][0] ) - ( r[v[i][1]][0] - r[v[i][0]][0] ) * ( r[v[i][2]][2] - r[v[i][0]][2] ) ;
690     normal[2] = ( r[v[i][1]][0] - r[v[i][0]][0] ) * ( r[v[i][2]][1] - r[v[i][0]][1] ) - ( r[v[i][1]][1] - r[v[i][0]][1] ) * ( r[v[i][2]][0] - r[v[i][0]][0] ) ;
691     glBegin ( GL_LINE_LOOP ) ;
692       glNormal3fv ( normal ) ;
693       glVertex3fv ( r[v[i][0]] ) ;
694       glVertex3fv ( r[v[i][1]] ) ;
695       glVertex3fv ( r[v[i][2]] ) ;
696     glEnd () ;
697   }
698 }
699
700 /*
701  *
702  */
703 void FGAPIENTRY glutSolidIcosahedron( void )
704 {
705   int i ;
706
707   glBegin ( GL_TRIANGLES ) ;
708   for ( i = 0; i < 20; i++ )
709   {
710     float normal[3] ;
711     normal[0] = ( r[v[i][1]][1] - r[v[i][0]][1] ) * ( r[v[i][2]][2] - r[v[i][0]][2] ) - ( r[v[i][1]][2] - r[v[i][0]][2] ) * ( r[v[i][2]][1] - r[v[i][0]][1] ) ;
712     normal[1] = ( r[v[i][1]][2] - r[v[i][0]][2] ) * ( r[v[i][2]][0] - r[v[i][0]][0] ) - ( r[v[i][1]][0] - r[v[i][0]][0] ) * ( r[v[i][2]][2] - r[v[i][0]][2] ) ;
713     normal[2] = ( r[v[i][1]][0] - r[v[i][0]][0] ) * ( r[v[i][2]][1] - r[v[i][0]][1] ) - ( r[v[i][1]][1] - r[v[i][0]][1] ) * ( r[v[i][2]][0] - r[v[i][0]][0] ) ;
714       glNormal3fv ( normal ) ;
715       glVertex3fv ( r[v[i][0]] ) ;
716       glVertex3fv ( r[v[i][1]] ) ;
717       glVertex3fv ( r[v[i][2]] ) ;
718   }
719
720   glEnd () ;
721 }
722
723 /*** END OF FILE ***/