SubWindow border thickness fix. Overlay changes in glutGet.
[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.
41  *
42  *      glutWireCube()          -- looks OK
43  *      glutSolidCube()         -- OK
44  *      glutWireSphere()        -- OK
45  *      glutSolidSphere()       -- OK
46  *
47  * Following functions have been implemented by Pawel and modified by John Fay:
48  *
49  *      glutWireCone()          -- looks OK
50  *      glutSolidCone()         -- looks OK
51  *
52  * Those functions have been implemented by John Fay.
53  *
54  *      glutWireTorus()         -- looks OK
55  *      glutSolidTorus()        -- looks OK
56  *      glutWireDodecahedron()  -- looks OK
57  *      glutSolidDodecahedron() -- looks OK
58  *      glutWireOctahedron()    -- looks OK
59  *      glutSolidOctahedron()   -- looks OK
60  *      glutWireTetrahedron()   -- looks OK
61  *      glutSolidTetrahedron()  -- looks OK
62  *      glutWireIcosahedron()   -- looks OK
63  *      glutSolidIcosahedron()  -- looks OK
64  */
65
66
67 /* -- INTERFACE FUNCTIONS -------------------------------------------------- */
68
69 /*
70  * Draws a wireframed cube. Code contributed by Andreas Umbach <marvin@dataway.ch>
71  */
72 void FGAPIENTRY glutWireCube( GLdouble dSize )
73 {
74     float size = (float) dSize * 0.5f;
75
76 #   define V(a,b,c) glVertex3f( a size, b size, c size );
77 #   define N(a,b,c) glNormal3f( a, b, c );
78
79     /*
80      * PWO: I dared to convert the code to use macros...
81      */
82     glBegin( GL_LINE_LOOP ); N( 1.0, 0.0, 0.0); V(+,-,+); V(+,-,-); V(+,+,-); V(+,+,+); glEnd();
83     glBegin( GL_LINE_LOOP ); N( 0.0, 1.0, 0.0); V(+,+,+); V(+,+,-); V(-,+,-); V(-,+,+); glEnd();
84     glBegin( GL_LINE_LOOP ); N( 0.0, 0.0, 1.0); V(+,+,+); V(-,+,+); V(-,-,+); V(+,-,+); glEnd();
85     glBegin( GL_LINE_LOOP ); N(-1.0, 0.0, 0.0); V(-,-,+); V(-,+,+); V(-,+,-); V(-,-,-); glEnd();
86     glBegin( GL_LINE_LOOP ); N( 0.0,-1.0, 0.0); V(-,-,+); V(-,-,-); V(+,-,-); V(+,-,+); glEnd();
87     glBegin( GL_LINE_LOOP ); N( 0.0, 0.0,-1.0); V(-,-,-); V(-,+,-); V(+,+,-); V(+,-,-); glEnd();
88
89 #   undef V
90 #   undef N
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.0, 0.0); V(+,-,+); V(+,-,-); V(+,+,-); V(+,+,+);
108         N( 0.0, 1.0, 0.0); V(+,+,+); V(+,+,-); V(-,+,-); V(-,+,+);
109         N( 0.0, 0.0, 1.0); V(+,+,+); V(-,+,+); V(-,-,+); V(+,-,+);
110         N(-1.0, 0.0, 0.0); V(-,-,+); V(-,+,+); V(-,+,-); V(-,-,-);
111         N( 0.0,-1.0, 0.0); V(-,-,+); V(-,-,-); V(+,-,-); V(+,-,+);
112         N( 0.0, 0.0,-1.0); 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     float cphi, sphi, cpsi, spsi ;
128
129     /*
130      * Allocate the vertices array
131      */
132     vertex = calloc( sizeof(float), 3 * slices * (stacks - 1) );
133
134     glPushMatrix();
135     glScalef( radius, radius, radius );
136
137     dpsi = M_PI / (stacks + 1);
138     dphi = 2 * M_PI / slices;
139     psi  = dpsi;
140
141     for( j=0; j<stacks-1; j++ )
142     {
143         cpsi = (float)cos ( psi ) ;
144         spsi = (float)sin ( psi ) ;
145         phi = 0;
146
147         for( i=0; i<slices; i++ )
148         {
149           int offset = 3 * ( j * slices + i ) ;
150           cphi = (float)cos ( phi ) ;
151           sphi = (float)sin ( phi ) ;
152             *(vertex + offset + 0) = sphi * spsi ;
153             *(vertex + offset + 1) = cphi * spsi ;
154             *(vertex + offset + 2) = cpsi ;
155             phi += dphi;
156         }
157
158         psi += dpsi;
159     }
160
161     for( i=0; i<slices; i++ )
162     {
163         glBegin( GL_LINE_STRIP );
164         glNormal3f( 0, 0, 1 );
165         glVertex3f( 0, 0, 1 );
166
167         for( j=0; j<stacks - 1; j++ )
168         {
169           int offset = 3 * ( j * slices + i ) ;
170             glNormal3fv( vertex + offset );
171             glVertex3fv( vertex + offset );
172         }
173
174         glNormal3f(0, 0, -1);
175         glVertex3f(0, 0, -1);
176         glEnd();
177     }
178
179     for( j=0; j<stacks-1; j++ )
180     {
181         glBegin(GL_LINE_LOOP);
182
183         for( i=0; i<slices; i++ )
184         {
185           int offset = 3 * ( j * slices + i ) ;
186             glNormal3fv( vertex + offset );
187             glVertex3fv( vertex + offset );
188         }
189
190         glEnd();
191     }
192
193     free( vertex );
194     glPopMatrix();
195 }
196
197 /*
198  * Draws a solid sphere. Code contributed by Andreas Umbach <marvin@dataway.ch>
199  */
200 void FGAPIENTRY glutSolidSphere( GLdouble dRadius, GLint slices, GLint stacks )
201 {
202     float  radius = (float) dRadius, phi, psi, dpsi, dphi;
203     float *next, *tmp, *row;
204     int    i, j;
205     float cphi, sphi, cpsi, spsi ;
206
207     glPushMatrix();
208     //glScalef( radius, radius, radius );
209
210     row  = calloc( sizeof(float), slices * 3 );
211     next = calloc( sizeof(float), slices * 3 );
212
213     dpsi = M_PI / (stacks + 1);
214     dphi = 2 * M_PI / slices;
215     psi  = dpsi;
216     phi  = 0;
217
218     /* init first line + do polar cap */
219     glBegin( GL_TRIANGLE_FAN );
220     glNormal3f( 0, 0, 1 );
221     glVertex3f( 0, 0, radius );
222
223     for( i=0; i<slices; i++ )
224     {
225         row[ i * 3 + 0 ] = sin( phi ) * sin( psi );
226         row[ i * 3 + 1 ] = cos( phi ) * sin( psi );
227         row[ i * 3 + 2 ] = cos( psi );
228
229         glNormal3fv( row + 3 * i );
230         glVertex3f(
231             radius * *(row + 3 * i + 0),
232             radius * *(row + 3 * i + 1),
233                 radius * *(row + 3 * i + 2)
234             );
235         
236         phi += dphi;
237     }
238
239     glNormal3fv( row );
240     glVertex3f( radius * *(row + 0), radius * *(row + 1), radius * *(row + 2) );
241     glEnd();
242
243     for( j=0; j<stacks-1; j++ )
244     {
245         phi = 0;
246         psi += dpsi;
247         cpsi = (float)cos ( psi ) ;
248         spsi = (float)sin ( psi ) ;
249
250         /* get coords */
251         glBegin( GL_QUAD_STRIP );
252
253         /* glBegin(GL_LINE_LOOP); */
254         for( i=0; i<slices; i++ )
255         {
256           cphi = (float)cos ( phi ) ;
257           sphi = (float)sin ( phi ) ;
258             next[ i * 3 + 0 ] = sphi * spsi ;
259             next[ i * 3 + 1 ] = cphi * spsi ;
260             next[ i * 3 + 2 ] = cpsi ;
261
262             glNormal3fv( row + i * 3 );
263             glVertex3f(
264                 radius * *(row + 3 * i + 0),
265                 radius * *(row + 3 * i + 1),
266                         radius * *(row + 3 * i + 2)
267                     );
268
269             glNormal3fv( next + i * 3 );
270             glVertex3f(
271                 radius * *(next + 3 * i + 0),
272                 radius * *(next + 3 * i + 1),
273                 radius * *(next + 3 * i + 2)
274             );
275
276             phi += dphi;
277         }
278
279         glNormal3fv( row );
280         glVertex3f( radius * *(row + 0), radius * *(row + 1), radius * *(row + 2) );
281         glNormal3fv( next );
282         glVertex3f( radius * *(next + 0), radius * *(next + 1), radius * *(next + 2) );
283         glEnd();
284
285         tmp = row;
286         row = next;
287         next = tmp;
288     }
289
290     /* south pole */
291     glBegin( GL_TRIANGLE_FAN );
292     glNormal3f( 0, 0, -1 );
293     glVertex3f( 0, 0, -radius );
294     glNormal3fv( row );
295     glVertex3f( radius * *(row + 0), radius * *(row + 1), radius * *(row + 2) );
296
297     for( i=slices-1; i>=0; i-- )
298     {
299         glNormal3fv(row + 3 * i);
300         glVertex3f(
301             radius * *(row + 3 * i + 0),
302             radius * *(row + 3 * i + 1),
303                 radius * *(row + 3 * i + 2)
304            );
305     }
306
307     glEnd();
308
309     free(row);
310     free(next);
311     glPopMatrix();
312 }
313
314 /*
315  * Draws a wire cone
316  */
317 void FGAPIENTRY glutWireCone( GLdouble base, GLdouble height, GLint slices, GLint stacks )
318 {
319   float  alt   = (float) height / (float) (stacks + 1);
320   float  angle = (float) M_PI / (float) slices * 2.0f;
321   float  slope = (float) ( height / base );
322   float  sBase = (float)base ;
323   float  sinNormal = (float)( base   / sqrt ( height * height + base * base )) ;
324   float  cosNormal = (float)( height / sqrt ( height * height + base * base )) ;
325
326   float* vertices = NULL;
327   int    i, j;
328
329   /*
330    * We need 'slices' points on a circle
331    */
332   vertices = calloc( sizeof(float), 2 * (slices + 1) );
333
334   for( j=0; j<slices+1; j++ )
335   {
336     vertices[ j*2 + 0 ] = cos( angle * j );
337     vertices[ j*2 + 1 ] = sin( angle * j );
338   }
339
340   /*
341    * First the cone's bottom...
342    */
343   for( j=0; j<slices; j++ )
344   {
345     glBegin( GL_LINE_LOOP );
346       glNormal3f( 0, 0, -1 );
347       glVertex3f( vertices[ (j+0)*2+0 ] * sBase, vertices[ (j+0)*2+1 ] * sBase, 0 );
348       glVertex3f( vertices[ (j+1)*2+0 ] * sBase, vertices[ (j+1)*2+1 ] * sBase, 0 );
349       glVertex3f( 0, 0, 0 );
350     glEnd();
351   }
352
353   /*
354    * Then all the stacks between the bottom and the top
355    */
356   for( i=0; i<stacks; i++ )
357   {
358     float alt_a = i * alt, alt_b = (i + 1) * alt;
359     float scl_a = (height - alt_a) / slope;
360     float scl_b = (height - alt_b) / slope;
361
362     for( j=0; j<slices; j++ )
363     {
364       glBegin( GL_LINE_LOOP );
365         glNormal3f( sinNormal * vertices[(j+0)*2+0], sinNormal * vertices[(j+0)*2+1], cosNormal ) ;
366         glVertex3f( vertices[(j+0)*2+0] * scl_a, vertices[(j+0)*2+1] * scl_a, alt_a );
367         glNormal3f( sinNormal * vertices[(j+1)*2+0], sinNormal * vertices[(j+1)*2+1], cosNormal ) ;
368         glVertex3f( vertices[(j+1)*2+0] * scl_a, vertices[(j+1)*2+1] * scl_a, alt_a );
369         glNormal3f( sinNormal * vertices[(j+0)*2+0], sinNormal * vertices[(j+0)*2+1], cosNormal ) ;
370         glVertex3f( vertices[(j+0)*2+0] * scl_b, vertices[(j+0)*2+1] * scl_b, alt_b );
371       glEnd();
372
373       glBegin( GL_LINE_LOOP );
374         glNormal3f( sinNormal * vertices[(j+0)*2+0], sinNormal * vertices[(j+0)*2+1], cosNormal ) ;
375         glVertex3f( vertices[(j+0)*2+0] * scl_b, vertices[(j+0)*2+1] * scl_b, alt_b );
376         glNormal3f( sinNormal * vertices[(j+1)*2+0], sinNormal * vertices[(j+1)*2+1], cosNormal ) ;
377         glVertex3f( vertices[(j+1)*2+0] * scl_b, vertices[(j+1)*2+1] * scl_b, alt_b );
378         glVertex3f( vertices[(j+1)*2+0] * scl_a, vertices[(j+1)*2+1] * scl_a, alt_a );
379       glEnd();
380     }
381   }
382
383   /*
384    * Finally have the top part drawn...
385    */
386   for( j=0; j<slices; j++ )
387   {
388     float scl = alt / slope;
389
390     glBegin( GL_LINE_LOOP );
391       glNormal3f( sinNormal * vertices[(j+0)*2+0], sinNormal * vertices[(j+0)*2+1], cosNormal ) ;
392       glVertex3f( vertices[ (j+0)*2+0 ] * scl, vertices[ (j+0)*2+1 ] * scl, height - alt );
393       glNormal3f( sinNormal * vertices[(j+1)*2+0], sinNormal * vertices[(j+1)*2+1], cosNormal ) ;
394       glVertex3f( vertices[ (j+1)*2+0 ] * scl, vertices[ (j+1)*2+1 ] * scl, height - alt );
395       glVertex3f( 0, 0, height );
396     glEnd();
397   }
398 }
399
400 /*
401  * Draws a solid cone
402  */
403 void FGAPIENTRY glutSolidCone( GLdouble base, GLdouble height, GLint slices, GLint stacks )
404 {
405   float  alt   = (float) height / (float) (stacks + 1);
406   float  angle = (float) M_PI / (float) slices * 2.0f;
407   float  slope = (float) ( height / base );
408   float  sBase = (float)base ;
409   float  sinNormal = (float)( base   / sqrt ( height * height + base * base )) ;
410   float  cosNormal = (float)( height / sqrt ( height * height + base * base )) ;
411
412   float* vertices = NULL;
413   int    i, j;
414
415   /*
416    * We need 'slices' points on a circle
417    */
418   vertices = calloc( sizeof(float), 2 * (slices + 1) );
419
420   for( j=0; j<slices+1; j++ )
421   {
422     vertices[ j*2 + 0 ] = cos( angle * j );
423     vertices[ j*2 + 1 ] = sin( angle * j );
424   }
425
426   /*
427    * First the cone's bottom...
428    */
429   for( j=0; j<slices; j++ )
430   {
431     float scl = height / slope;
432
433     glBegin( GL_TRIANGLES );
434       glNormal3f( 0, 0, -1 );
435       glVertex3f( vertices[ (j+0)*2+0 ] * sBase, vertices[ (j+0)*2+1 ] * sBase, 0 );
436       glVertex3f( vertices[ (j+1)*2+0 ] * sBase, vertices[ (j+1)*2+1 ] * sBase, 0 );
437       glVertex3f( 0, 0, 0 );
438     glEnd();
439   }
440
441   /*
442    * Then all the stacks between the bottom and the top
443    */
444   for( i=0; i<stacks; i++ )
445   {
446     float alt_a = i * alt, alt_b = (i + 1) * alt;
447     float scl_a = (height - alt_a) / slope;
448     float scl_b = (height - alt_b) / slope;
449
450     for( j=0; j<slices; j++ )
451     {
452       glBegin( GL_TRIANGLES );
453         glNormal3f( sinNormal * vertices[(j+0)*2+0], sinNormal * vertices[(j+0)*2+1], cosNormal ) ;
454         glVertex3f( vertices[(j+0)*2+0] * scl_a, vertices[(j+0)*2+1] * scl_a, alt_a );
455         glNormal3f( sinNormal * vertices[(j+1)*2+0], sinNormal * vertices[(j+1)*2+1], cosNormal ) ;
456         glVertex3f( vertices[(j+1)*2+0] * scl_a, vertices[(j+1)*2+1] * scl_a, alt_a );
457         glNormal3f( sinNormal * vertices[(j+0)*2+0], sinNormal * vertices[(j+0)*2+1], cosNormal ) ;
458         glVertex3f( vertices[(j+0)*2+0] * scl_b, vertices[(j+0)*2+1] * scl_b, alt_b );
459       glEnd();
460
461       glBegin( GL_TRIANGLES );
462         glNormal3f( sinNormal * vertices[(j+0)*2+0], sinNormal * vertices[(j+0)*2+1], cosNormal ) ;
463         glVertex3f( vertices[(j+0)*2+0] * scl_b, vertices[(j+0)*2+1] * scl_b, alt_b );
464         glNormal3f( sinNormal * vertices[(j+1)*2+0], sinNormal * vertices[(j+1)*2+1], cosNormal ) ;
465         glVertex3f( vertices[(j+1)*2+0] * scl_b, vertices[(j+1)*2+1] * scl_b, alt_b );
466         glVertex3f( vertices[(j+1)*2+0] * scl_a, vertices[(j+1)*2+1] * scl_a, alt_a );
467       glEnd();
468     }
469   }
470
471   /*
472    * Finally have the top part drawn...
473    */
474   for( j=0; j<slices; j++ )
475   {
476     float scl = alt / slope;
477
478     glBegin( GL_TRIANGLES );
479       glNormal3f( sinNormal * vertices[(j+0)*2+0], sinNormal * vertices[(j+0)*2+1], cosNormal ) ;
480       glVertex3f( vertices[ (j+0)*2+0 ] * scl, vertices[ (j+0)*2+1 ] * scl, height - alt );
481       glNormal3f( sinNormal * vertices[(j+1)*2+0], sinNormal * vertices[(j+1)*2+1], cosNormal ) ;
482       glVertex3f( vertices[ (j+1)*2+0 ] * scl, vertices[ (j+1)*2+1 ] * scl, height - alt );
483       glVertex3f( 0, 0, height );
484     glEnd();
485   }
486 }
487
488 /*
489  *
490  */
491 void FGAPIENTRY glutWireTorus( GLdouble dInnerRadius, GLdouble dOuterRadius, GLint nSides, GLint nRings )
492 {
493   float  iradius = (float) dInnerRadius, oradius = (float)dOuterRadius, phi, psi, dpsi, dphi;
494   float* vertex, *normal;
495   int    i, j;
496   float spsi, cpsi, sphi, cphi ;
497
498   /*
499    * Allocate the vertices array
500    */
501   vertex = calloc( sizeof(float), 3 * nSides * nRings );
502   normal = calloc( sizeof(float), 3 * nSides * nRings );
503
504   glPushMatrix();
505
506   dpsi = 2.0 * M_PI / (float)nRings ;
507   dphi = 2.0 * M_PI / (float)nSides ;
508   psi  = 0.0;
509
510   for( j=0; j<nRings; j++ )
511   {
512     cpsi = (float)cos ( psi ) ;
513     spsi = (float)sin ( psi ) ;
514     phi = 0.0;
515
516     for( i=0; i<nSides; i++ )
517     {
518       int offset = 3 * ( j * nSides + i ) ;
519       cphi = (float)cos ( phi ) ;
520       sphi = (float)sin ( phi ) ;
521       *(vertex + offset + 0) = cpsi * ( oradius + cphi * iradius ) ;
522       *(vertex + offset + 1) = spsi * ( oradius + cphi * iradius ) ;
523       *(vertex + offset + 2) =                    sphi * iradius   ;
524       *(normal + offset + 0) = cpsi * cphi ;
525       *(normal + offset + 1) = spsi * cphi ;
526       *(normal + offset + 2) =        sphi ;
527       phi += dphi;
528     }
529
530     psi += dpsi;
531   }
532
533   for( i=0; i<nSides; i++ )
534   {
535     glBegin( GL_LINE_LOOP );
536
537     for( j=0; j<nRings; j++ )
538     {
539       int offset = 3 * ( j * nSides + i ) ;
540       glNormal3fv( normal + offset );
541       glVertex3fv( vertex + offset );
542     }
543
544     glEnd();
545   }
546
547   for( j=0; j<nRings; j++ )
548   {
549     glBegin(GL_LINE_LOOP);
550
551     for( i=0; i<nSides; i++ )
552     {
553       int offset = 3 * ( j * nSides + i ) ;
554       glNormal3fv( normal + offset );
555       glVertex3fv( vertex + offset );
556     }
557
558     glEnd();
559   }
560
561   free ( vertex ) ;
562   free ( normal ) ;
563   glPopMatrix();
564 }
565
566 /*
567  *
568  */
569 void FGAPIENTRY glutSolidTorus( GLdouble dInnerRadius, GLdouble dOuterRadius, GLint nSides, GLint nRings )
570 {
571   float  iradius = (float) dInnerRadius, oradius = (float)dOuterRadius, phi, psi, dpsi, dphi;
572   float* vertex, *normal;
573   int    i, j;
574   float spsi, cpsi, sphi, cphi ;
575
576   /*
577    * Increment the number of sides and rings to allow for one more point than surface
578    */
579   nSides ++ ;
580   nRings ++ ;
581
582   /*
583    * Allocate the vertices array
584    */
585   vertex = calloc( sizeof(float), 3 * nSides * nRings );
586   normal = calloc( sizeof(float), 3 * nSides * nRings );
587
588   glPushMatrix();
589
590   dpsi = 2.0 * M_PI / (float)(nRings - 1) ;
591   dphi = 2.0 * M_PI / (float)(nSides - 1) ;
592   psi  = 0.0;
593
594   for( j=0; j<nRings; j++ )
595   {
596     cpsi = (float)cos ( psi ) ;
597     spsi = (float)sin ( psi ) ;
598     phi = 0.0;
599
600     for( i=0; i<nSides; i++ )
601     {
602       int offset = 3 * ( j * nSides + i ) ;
603       cphi = (float)cos ( phi ) ;
604       sphi = (float)sin ( phi ) ;
605       *(vertex + offset + 0) = cpsi * ( oradius + cphi * iradius ) ;
606       *(vertex + offset + 1) = spsi * ( oradius + cphi * iradius ) ;
607       *(vertex + offset + 2) =                    sphi * iradius   ;
608       *(normal + offset + 0) = cpsi * cphi ;
609       *(normal + offset + 1) = spsi * cphi ;
610       *(normal + offset + 2) =        sphi ;
611       phi += dphi;
612     }
613
614     psi += dpsi;
615   }
616
617     glBegin( GL_QUADS );
618   for( i=0; i<nSides-1; i++ )
619   {
620     for( j=0; j<nRings-1; j++ )
621     {
622       int offset = 3 * ( j * nSides + i ) ;
623       glNormal3fv( normal + offset );
624       glVertex3fv( vertex + offset );
625       glNormal3fv( normal + offset + 3 );
626       glVertex3fv( vertex + offset + 3 );
627       glNormal3fv( normal + offset + 3 * nSides + 3 );
628       glVertex3fv( vertex + offset + 3 * nSides + 3 );
629       glNormal3fv( normal + offset + 3 * nSides );
630       glVertex3fv( vertex + offset + 3 * nSides );
631     }
632   }
633
634   glEnd();
635
636   free ( vertex ) ;
637   free ( normal ) ;
638   glPopMatrix();
639 }
640
641 /*
642  *
643  */
644 void FGAPIENTRY glutWireDodecahedron( void )
645 {
646   /* Magic Numbers:  It is possible to create a dodecahedron by attaching two pentagons to each face of
647    * of a cube.  The coordinates of the points are:
648    *   (+-x,0, z); (+-1, 1, 1); (0, z, x )
649    * where x = 0.618033989 and z = 1.618033939.
650    */
651   glBegin ( GL_LINE_LOOP ) ;
652   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 ) ;
653   glEnd () ;
654   glBegin ( GL_LINE_LOOP ) ;
655   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 ) ;
656   glEnd () ;
657   glBegin ( GL_LINE_LOOP ) ;
658   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 ) ;
659   glEnd () ;
660   glBegin ( GL_LINE_LOOP ) ;
661   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 ) ;
662   glEnd () ;
663
664   glBegin ( GL_LINE_LOOP ) ;
665   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 ) ;
666   glEnd () ;
667   glBegin ( GL_LINE_LOOP ) ;
668   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 ) ;
669   glEnd () ;
670   glBegin ( GL_LINE_LOOP ) ;
671   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 ) ;
672   glEnd () ;
673   glBegin ( GL_LINE_LOOP ) ;
674   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 ) ;
675   glEnd () ;
676
677   glBegin ( GL_LINE_LOOP ) ;
678   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 ) ;
679   glEnd () ;
680   glBegin ( GL_LINE_LOOP ) ;
681   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 ) ;
682   glEnd () ;
683   glBegin ( GL_LINE_LOOP ) ;
684   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 ) ;
685   glEnd () ;
686   glBegin ( GL_LINE_LOOP ) ;
687   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 ) ;
688   glEnd () ;
689 }
690
691 /*
692  *
693  */
694 void FGAPIENTRY glutSolidDodecahedron( void )
695 {
696   /* Magic Numbers:  It is possible to create a dodecahedron by attaching two pentagons to each face of
697    * of a cube.  The coordinates of the points are:
698    *   (+-x,0, z); (+-1, 1, 1); (0, z, x )
699    * where x = 0.618033989 and z = 1.618033939.
700    */
701   glBegin ( GL_POLYGON ) ;
702   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 ) ;
703   glEnd () ;
704   glBegin ( GL_POLYGON ) ;
705   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 ) ;
706   glEnd () ;
707   glBegin ( GL_POLYGON ) ;
708   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 ) ;
709   glEnd () ;
710   glBegin ( GL_POLYGON ) ;
711   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 ) ;
712   glEnd () ;
713
714   glBegin ( GL_POLYGON ) ;
715   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 ) ;
716   glEnd () ;
717   glBegin ( GL_POLYGON ) ;
718   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 ) ;
719   glEnd () ;
720   glBegin ( GL_POLYGON ) ;
721   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 ) ;
722   glEnd () ;
723   glBegin ( GL_POLYGON ) ;
724   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 ) ;
725   glEnd () ;
726
727   glBegin ( GL_POLYGON ) ;
728   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 ) ;
729   glEnd () ;
730   glBegin ( GL_POLYGON ) ;
731   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 ) ;
732   glEnd () ;
733   glBegin ( GL_POLYGON ) ;
734   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 ) ;
735   glEnd () ;
736   glBegin ( GL_POLYGON ) ;
737   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 ) ;
738   glEnd () ;
739 }
740
741 /*
742  *
743  */
744 void FGAPIENTRY glutWireOctahedron( void )
745 {
746 #define RADIUS    1.0f
747   glBegin( GL_LINE_LOOP );
748     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 );
749     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 );
750     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 );
751     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 );
752     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 );
753     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 );
754     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 );
755     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 );
756   glEnd();
757 #undef RADIUS
758 }
759
760 /*
761  *
762  */
763 void FGAPIENTRY glutSolidOctahedron( void )
764 {
765 #define RADIUS    1.0f
766   glBegin( GL_TRIANGLES );
767     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 );
768     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 );
769     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 );
770     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 );
771     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 );
772     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 );
773     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 );
774     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 );
775   glEnd();
776 #undef RADIUS
777 }
778
779 /*
780  *
781  */
782 void FGAPIENTRY glutWireTetrahedron( void )
783 {
784   /* Magic Numbers:  r0 = ( 1, 0, 0 )
785    *                 r1 = ( -1/3, 2 sqrt(2) / 3, 0 )
786    *                 r2 = ( -1/3, -sqrt(2) / 3, sqrt(6) / 3 )
787    *                 r3 = ( -1/3, -sqrt(2) / 3, -sqrt(6) / 3 )
788    * |r0| = |r1| = |r2| = |r3| = 1
789    * Distance between any two points is 2 sqrt(6) / 3
790    *
791    * Normals:  The unit normals are simply the negative of the coordinates of the point not on the surface.
792    */
793
794   float r0[3] = {       1.0f,       0.0f,       0.0f } ;
795   float r1[3] = { -0.333333f,  0.942809f,       0.0f } ;
796   float r2[3] = { -0.333333f, -0.471405f,  0.816497f } ;
797   float r3[3] = { -0.333333f, -0.471405f, -0.816497f } ;
798
799   glBegin( GL_LINE_LOOP ) ;
800     glNormal3f (     -1.0f,       0.0f,       0.0f ) ; glVertex3fv ( r1 ) ; glVertex3fv ( r3 ) ; glVertex3fv ( r2 ) ;
801     glNormal3f ( 0.333333f, -0.942809f,       0.0f ) ; glVertex3fv ( r0 ) ; glVertex3fv ( r2 ) ; glVertex3fv ( r3 ) ;
802     glNormal3f ( 0.333333f,  0.471405f, -0.816497f ) ; glVertex3fv ( r0 ) ; glVertex3fv ( r3 ) ; glVertex3fv ( r1 ) ;
803     glNormal3f ( 0.333333f,  0.471405f,  0.816497f ) ; glVertex3fv ( r0 ) ; glVertex3fv ( r1 ) ; glVertex3fv ( r2 ) ;
804   glEnd() ;
805 }
806
807 /*
808  *
809  */
810 void FGAPIENTRY glutSolidTetrahedron( void )
811 {
812   /* Magic Numbers:  r0 = ( 1, 0, 0 )
813    *                 r1 = ( -1/3, 2 sqrt(2) / 3, 0 )
814    *                 r2 = ( -1/3, -sqrt(2) / 3, sqrt(6) / 3 )
815    *                 r3 = ( -1/3, -sqrt(2) / 3, -sqrt(6) / 3 )
816    * |r0| = |r1| = |r2| = |r3| = 1
817    * Distance between any two points is 2 sqrt(6) / 3
818    *
819    * Normals:  The unit normals are simply the negative of the coordinates of the point not on the surface.
820    */
821
822   float r0[3] = {       1.0f,       0.0f,       0.0f } ;
823   float r1[3] = { -0.333333f,  0.942809f,       0.0f } ;
824   float r2[3] = { -0.333333f, -0.471405f,  0.816497f } ;
825   float r3[3] = { -0.333333f, -0.471405f, -0.816497f } ;
826
827   glBegin( GL_TRIANGLES ) ;
828     glNormal3f (     -1.0f,       0.0f,       0.0f ) ; glVertex3fv ( r1 ) ; glVertex3fv ( r3 ) ; glVertex3fv ( r2 ) ;
829     glNormal3f ( 0.333333f, -0.942809f,       0.0f ) ; glVertex3fv ( r0 ) ; glVertex3fv ( r2 ) ; glVertex3fv ( r3 ) ;
830     glNormal3f ( 0.333333f,  0.471405f, -0.816497f ) ; glVertex3fv ( r0 ) ; glVertex3fv ( r3 ) ; glVertex3fv ( r1 ) ;
831     glNormal3f ( 0.333333f,  0.471405f,  0.816497f ) ; glVertex3fv ( r0 ) ; glVertex3fv ( r1 ) ; glVertex3fv ( r2 ) ;
832   glEnd() ;
833 }
834
835 /*
836  *
837  */
838 float icos_r[12][3] = { { 1.0f, 0.0f, 0.0f },
839   {  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 },
840   { -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 },
841   { -1.0f, 0.0f, 0.0f } } ;
842 int icos_v [20][3] = { { 0, 1, 2 }, { 0, 2, 3 }, { 0, 3, 4 }, { 0, 4, 5 }, { 0, 5, 1 },
843                        { 1, 8, 2 }, { 2, 7, 3 }, { 3, 6, 4 }, { 4, 10, 5 }, { 5, 9, 1 },
844                        { 1, 9, 8 }, { 2, 8, 7 }, { 3, 7, 6 }, { 4, 6, 10 }, { 5, 10, 9 },
845                        { 11, 9, 10 }, { 11, 8, 9 }, { 11, 7, 8 }, { 11, 6, 7 }, { 11, 10, 6 } } ;
846
847 void FGAPIENTRY glutWireIcosahedron( void )
848 {
849   int i ;
850   for ( i = 0; i < 20; i++ )
851   {
852     float normal[3] ;
853     normal[0] = ( icos_r[icos_v[i][1]][1] - icos_r[icos_v[i][0]][1] ) * ( icos_r[icos_v[i][2]][2] - icos_r[icos_v[i][0]][2] ) - ( icos_r[icos_v[i][1]][2] - icos_r[icos_v[i][0]][2] ) * ( icos_r[icos_v[i][2]][1] - icos_r[icos_v[i][0]][1] ) ;
854     normal[1] = ( icos_r[icos_v[i][1]][2] - icos_r[icos_v[i][0]][2] ) * ( icos_r[icos_v[i][2]][0] - icos_r[icos_v[i][0]][0] ) - ( icos_r[icos_v[i][1]][0] - icos_r[icos_v[i][0]][0] ) * ( icos_r[icos_v[i][2]][2] - icos_r[icos_v[i][0]][2] ) ;
855     normal[2] = ( icos_r[icos_v[i][1]][0] - icos_r[icos_v[i][0]][0] ) * ( icos_r[icos_v[i][2]][1] - icos_r[icos_v[i][0]][1] ) - ( icos_r[icos_v[i][1]][1] - icos_r[icos_v[i][0]][1] ) * ( icos_r[icos_v[i][2]][0] - icos_r[icos_v[i][0]][0] ) ;
856     glBegin ( GL_LINE_LOOP ) ;
857       glNormal3fv ( normal ) ;
858       glVertex3fv ( icos_r[icos_v[i][0]] ) ;
859       glVertex3fv ( icos_r[icos_v[i][1]] ) ;
860       glVertex3fv ( icos_r[icos_v[i][2]] ) ;
861     glEnd () ;
862   }
863 }
864
865 /*
866  *
867  */
868 void FGAPIENTRY glutSolidIcosahedron( void )
869 {
870   int i ;
871
872   glBegin ( GL_TRIANGLES ) ;
873   for ( i = 0; i < 20; i++ )
874   {
875     float normal[3] ;
876     normal[0] = ( icos_r[icos_v[i][1]][1] - icos_r[icos_v[i][0]][1] ) * ( icos_r[icos_v[i][2]][2] - icos_r[icos_v[i][0]][2] ) - ( icos_r[icos_v[i][1]][2] - icos_r[icos_v[i][0]][2] ) * ( icos_r[icos_v[i][2]][1] - icos_r[icos_v[i][0]][1] ) ;
877     normal[1] = ( icos_r[icos_v[i][1]][2] - icos_r[icos_v[i][0]][2] ) * ( icos_r[icos_v[i][2]][0] - icos_r[icos_v[i][0]][0] ) - ( icos_r[icos_v[i][1]][0] - icos_r[icos_v[i][0]][0] ) * ( icos_r[icos_v[i][2]][2] - icos_r[icos_v[i][0]][2] ) ;
878     normal[2] = ( icos_r[icos_v[i][1]][0] - icos_r[icos_v[i][0]][0] ) * ( icos_r[icos_v[i][2]][1] - icos_r[icos_v[i][0]][1] ) - ( icos_r[icos_v[i][1]][1] - icos_r[icos_v[i][0]][1] ) * ( icos_r[icos_v[i][2]][0] - icos_r[icos_v[i][0]][0] ) ;
879       glNormal3fv ( normal ) ;
880       glVertex3fv ( icos_r[icos_v[i][0]] ) ;
881       glVertex3fv ( icos_r[icos_v[i][1]] ) ;
882       glVertex3fv ( icos_r[icos_v[i][2]] ) ;
883   }
884
885   glEnd () ;
886 }
887
888 /*
889  *
890  */
891 float rdod_r[14][3] = { { 0.0f, 0.0f, 1.0f },
892   {  0.707107f,  0.000000f,  0.5f }, {  0.000000f,  0.707107f,  0.5f }, { -0.707107f,  0.000000f,  0.5f }, {  0.000000f, -0.707107f,  0.5f },
893   {  0.707107f,  0.707107f,  0.0f }, { -0.707107f,  0.707107f,  0.0f }, { -0.707107f, -0.707107f,  0.0f }, {  0.707107f, -0.707107f,  0.0f },
894   {  0.707107f,  0.000000f, -0.5f }, {  0.000000f,  0.707107f, -0.5f }, { -0.707107f,  0.000000f, -0.5f }, {  0.000000f, -0.707107f, -0.5f },
895   {  0.0f, 0.0f, -1.0f } } ;
896 int rdod_v [12][4] = { { 0,  1,  5,  2 }, { 0,  2,  6,  3 }, { 0,  3,  7,  4 }, { 0,  4,  8, 1 },
897                        { 5, 10,  6,  2 }, { 6, 11,  7,  3 }, { 7, 12,  8,  4 }, { 8,  9,  5, 1 },
898                        { 5,  9, 13, 10 }, { 6, 10, 13, 11 }, { 7, 11, 13, 12 }, { 8, 12, 13, 9 } } ;
899 float rdod_n[12][3] = {
900   {  0.353553f,  0.353553f,  0.5f }, { -0.353553f,  0.353553f,  0.5f }, { -0.353553f, -0.353553f,  0.5f }, {  0.353553f, -0.353553f,  0.5f },
901   {  0.000000f,  1.000000f,  0.0f }, { -1.000000f,  0.000000f,  0.0f }, {  0.000000f, -1.000000f,  0.0f }, {  1.000000f,  0.000000f,  0.0f },
902   {  0.353553f,  0.353553f, -0.5f }, { -0.353553f,  0.353553f, -0.5f }, { -0.353553f, -0.353553f, -0.5f }, {  0.353553f, -0.353553f, -0.5f }
903   } ;
904
905 void FGAPIENTRY glutWireRhombicDodecahedron( void )
906 {
907   int i ;
908   for ( i = 0; i < 12; i++ )
909   {
910     glBegin ( GL_LINE_LOOP ) ;
911       glNormal3fv ( rdod_n[i] ) ;
912       glVertex3fv ( rdod_r[rdod_v[i][0]] ) ;
913       glVertex3fv ( rdod_r[rdod_v[i][1]] ) ;
914       glVertex3fv ( rdod_r[rdod_v[i][2]] ) ;
915       glVertex3fv ( rdod_r[rdod_v[i][3]] ) ;
916     glEnd () ;
917   }
918 }
919
920 /*
921  *
922  */
923 void FGAPIENTRY glutSolidRhombicDodecahedron( void )
924 {
925   int i ;
926
927   glBegin ( GL_QUADS ) ;
928   for ( i = 0; i < 12; i++ )
929   {
930       glNormal3fv ( rdod_n[i] ) ;
931       glVertex3fv ( rdod_r[rdod_v[i][0]] ) ;
932       glVertex3fv ( rdod_r[rdod_v[i][1]] ) ;
933       glVertex3fv ( rdod_r[rdod_v[i][2]] ) ;
934       glVertex3fv ( rdod_r[rdod_v[i][3]] ) ;
935   }
936
937   glEnd () ;
938 }
939
940 #define NUM_FACES     4
941
942 static GLfloat tetrahedron_v[4][3] =  /* Vertices */
943 {
944   { -0.5, -0.288675134, -0.144337567 },
945   {  0.5, -0.288675134, -0.144337567 },
946   {  0.0,  0.577350269, -0.144337567 },
947   {  0.0,  0.0,          0.672159013 }
948 } ;
949
950 static GLint tetrahedron_i[4][3] =  /* Vertex indices */
951 {
952   { 0, 1, 2 }, { 0, 2, 3 }, { 0, 3, 1 }, { 1, 3, 2 }
953 } ;
954
955 static GLfloat tetrahedron_n[4][3] =  /* Normals */
956 {
957   {  0.0,          0.0,         -1.0 },
958   { -0.816496581,  0.471404521,  0.333333333 },
959   {  0.0,         -0.942809042,  0.333333333 },
960   {  0.816496581,  0.471404521,  0.333333333 }
961 } ;
962
963 void FGAPIENTRY glutWireSierpinskiSponge ( int num_levels, GLfloat offset[3], GLfloat scale )
964 {
965   int i, j ;
966
967   if ( num_levels == 0 )
968   {
969
970     for ( i = 0 ; i < NUM_FACES ; i++ )
971     {
972       glBegin ( GL_LINE_LOOP ) ;
973       glNormal3fv ( tetrahedron_n[i] ) ;
974       for ( j = 0; j < 3; j++ )
975       {
976         float x = offset[0] + scale * tetrahedron_v[tetrahedron_i[i][j]][0] ;
977         float y = offset[1] + scale * tetrahedron_v[tetrahedron_i[i][j]][1] ;
978         float z = offset[2] + scale * tetrahedron_v[tetrahedron_i[i][j]][2] ;
979         glVertex3f ( x, y, z ) ;
980       }
981
982       glEnd () ;
983     }
984   }
985   else
986   {
987     GLfloat local_offset[3] ;  // Use a local variable to avoid buildup of roundoff errors
988     num_levels -- ;
989     scale /= 2.0 ;
990     local_offset[0] = offset[0] + scale * tetrahedron_v[0][0] ;
991     local_offset[1] = offset[1] + scale * tetrahedron_v[0][1] ;
992     local_offset[2] = offset[2] + scale * tetrahedron_v[0][2] ;
993     glutWireSierpinskiSponge ( num_levels, local_offset, scale ) ;
994     local_offset[0] += scale ;
995     glutWireSierpinskiSponge ( num_levels, local_offset, scale ) ;
996     local_offset[0] -= 0.5         * scale ;
997     local_offset[1] += 0.866025403 * scale ;
998     glutWireSierpinskiSponge ( num_levels, local_offset, scale ) ;
999     local_offset[1] -= 0.577350269 * scale ;
1000     local_offset[2] += 0.816496581 * scale ;
1001     glutWireSierpinskiSponge ( num_levels, local_offset, scale ) ;
1002   }
1003 }
1004
1005 void FGAPIENTRY glutSolidSierpinskiSponge ( int num_levels, GLfloat offset[3], GLfloat scale )
1006 {
1007   int i, j ;
1008
1009   if ( num_levels == 0 )
1010   {
1011     glBegin ( GL_TRIANGLES ) ;
1012
1013     for ( i = 0 ; i < NUM_FACES ; i++ )
1014     {
1015       glNormal3fv ( tetrahedron_n[i] ) ;
1016       for ( j = 0; j < 3; j++ )
1017       {
1018         float x = offset[0] + scale * tetrahedron_v[tetrahedron_i[i][j]][0] ;
1019         float y = offset[1] + scale * tetrahedron_v[tetrahedron_i[i][j]][1] ;
1020         float z = offset[2] + scale * tetrahedron_v[tetrahedron_i[i][j]][2] ;
1021         glVertex3f ( x, y, z ) ;
1022       }
1023     }
1024
1025     glEnd () ;
1026   }
1027   else
1028   {
1029     GLfloat local_offset[3] ;  // Use a local variable to avoid buildup of roundoff errors
1030     num_levels -- ;
1031     scale /= 2.0 ;
1032     local_offset[0] = offset[0] + scale * tetrahedron_v[0][0] ;
1033     local_offset[1] = offset[1] + scale * tetrahedron_v[0][1] ;
1034     local_offset[2] = offset[2] + scale * tetrahedron_v[0][2] ;
1035     glutSolidSierpinskiSponge ( num_levels, local_offset, scale ) ;
1036     local_offset[0] += scale ;
1037     glutSolidSierpinskiSponge ( num_levels, local_offset, scale ) ;
1038     local_offset[0] -= 0.5         * scale ;
1039     local_offset[1] += 0.866025403 * scale ;
1040     glutSolidSierpinskiSponge ( num_levels, local_offset, scale ) ;
1041     local_offset[1] -= 0.577350269 * scale ;
1042     local_offset[2] += 0.816496581 * scale ;
1043     glutSolidSierpinskiSponge ( num_levels, local_offset, scale ) ;
1044   }
1045 }
1046
1047 #undef NUM_FACES
1048
1049 /*** END OF FILE ***/