fltk 1.3.0rc3
About: FLTK (Fast Light Tool Kit) is a cross-platform C++ GUI toolkit for UNIX/Linux (X11), Microsoft Windows, and MacOS X. Release candidate.
  SfR Fresh Dox: fltk-1.3.0rc3-source.tar.gz ("inofficial" and yet experimental doxygen-generated source code documentation)  

freeglut_geometry.cxx

Go to the documentation of this file.
00001 /*
00002  * freeglut_geometry.c
00003  *
00004  * Freeglut geometry rendering methods.
00005  *
00006  * Copyright (c) 1999-2010 Pawel W. Olszta. All Rights Reserved.
00007  * Written by Pawel W. Olszta, <olszta@sourceforge.net>
00008  * Creation date: Fri Dec 3 1999
00009  *
00010  * Permission is hereby granted, free of charge, to any person obtaining a
00011  * copy of this software and associated documentation files (the "Software"),
00012  * to deal in the Software without restriction, including without limitation
00013  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
00014  * and/or sell copies of the Software, and to permit persons to whom the
00015  * Software is furnished to do so, subject to the following conditions:
00016  *
00017  * The above copyright notice and this permission notice shall be included
00018  * in all copies or substantial portions of the Software.
00019  *
00020  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
00021  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00022  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
00023  * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
00024  * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
00025  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00026  */
00027 
00028 #include <FL/glut.H>
00029 #include <FL/math.h>
00030 #include <stdlib.h>
00031 
00032 /*
00033  * TODO BEFORE THE STABLE RELEASE:
00034  *
00035  * Following functions have been contributed by Andreas Umbach.
00036  *
00037  *      glutWireCube()          -- looks OK
00038  *      glutSolidCube()         -- OK
00039  *
00040  * Those functions have been implemented by John Fay.
00041  *
00042  *      glutWireTorus()         -- looks OK
00043  *      glutSolidTorus()        -- looks OK
00044  *      glutWireDodecahedron()  -- looks OK
00045  *      glutSolidDodecahedron() -- looks OK
00046  *      glutWireOctahedron()    -- looks OK
00047  *      glutSolidOctahedron()   -- looks OK
00048  *      glutWireTetrahedron()   -- looks OK
00049  *      glutSolidTetrahedron()  -- looks OK
00050  *      glutWireIcosahedron()   -- looks OK
00051  *      glutSolidIcosahedron()  -- looks OK
00052  *
00053  *  The Following functions have been updated by Nigel Stewart, based
00054  *  on FreeGLUT 2.0.0 implementations:
00055  *
00056  *      glutWireSphere()        -- looks OK
00057  *      glutSolidSphere()       -- looks OK
00058  *      glutWireCone()          -- looks OK
00059  *      glutSolidCone()         -- looks OK
00060  */
00061 
00062 
00063 /* -- INTERFACE FUNCTIONS -------------------------------------------------- */
00064 
00065 /*
00066  * Draws a wireframed cube. Code contributed by Andreas Umbach <marvin@dataway.ch>
00067  */
00068 void glutWireCube( GLdouble dSize )
00069 {
00070     double size = dSize * 0.5;
00071 
00072 #   define V(a,b,c) glVertex3d( a size, b size, c size );
00073 #   define N(a,b,c) glNormal3d( a, b, c );
00074 
00075     /* PWO: I dared to convert the code to use macros... */
00076     glBegin( GL_LINE_LOOP ); N( 1.0, 0.0, 0.0); V(+,-,+); V(+,-,-); V(+,+,-); V(+,+,+); glEnd();
00077     glBegin( GL_LINE_LOOP ); N( 0.0, 1.0, 0.0); V(+,+,+); V(+,+,-); V(-,+,-); V(-,+,+); glEnd();
00078     glBegin( GL_LINE_LOOP ); N( 0.0, 0.0, 1.0); V(+,+,+); V(-,+,+); V(-,-,+); V(+,-,+); glEnd();
00079     glBegin( GL_LINE_LOOP ); N(-1.0, 0.0, 0.0); V(-,-,+); V(-,+,+); V(-,+,-); V(-,-,-); glEnd();
00080     glBegin( GL_LINE_LOOP ); N( 0.0,-1.0, 0.0); V(-,-,+); V(-,-,-); V(+,-,-); V(+,-,+); glEnd();
00081     glBegin( GL_LINE_LOOP ); N( 0.0, 0.0,-1.0); V(-,-,-); V(-,+,-); V(+,+,-); V(+,-,-); glEnd();
00082 
00083 #   undef V
00084 #   undef N
00085 }
00086 
00087 /*
00088  * Draws a solid cube. Code contributed by Andreas Umbach <marvin@dataway.ch>
00089  */
00090 void glutSolidCube( GLdouble dSize )
00091 {
00092     double size = dSize * 0.5;
00093 
00094 #   define V(a,b,c) glVertex3d( a size, b size, c size );
00095 #   define N(a,b,c) glNormal3d( a, b, c );
00096 
00097     /* PWO: Again, I dared to convert the code to use macros... */
00098     glBegin( GL_QUADS );
00099         N( 1.0, 0.0, 0.0); V(+,-,+); V(+,-,-); V(+,+,-); V(+,+,+);
00100         N( 0.0, 1.0, 0.0); V(+,+,+); V(+,+,-); V(-,+,-); V(-,+,+);
00101         N( 0.0, 0.0, 1.0); V(+,+,+); V(-,+,+); V(-,-,+); V(+,-,+);
00102         N(-1.0, 0.0, 0.0); V(-,-,+); V(-,+,+); V(-,+,-); V(-,-,-);
00103         N( 0.0,-1.0, 0.0); V(-,-,+); V(-,-,-); V(+,-,-); V(+,-,+);
00104         N( 0.0, 0.0,-1.0); V(-,-,-); V(-,+,-); V(+,+,-); V(+,-,-);
00105     glEnd();
00106 
00107 #   undef V
00108 #   undef N
00109 }
00110 
00111 /*
00112  * Compute lookup table of cos and sin values forming a cirle
00113  *
00114  * Notes:
00115  *    It is the responsibility of the caller to free these tables
00116  *    The size of the table is (n+1) to form a connected loop
00117  *    The last entry is exactly the same as the first
00118  *    The sign of n can be flipped to get the reverse loop
00119  */
00120 
00121 static void fghCircleTable(double **sint,double **cost,const int n)
00122 {
00123     int i;
00124 
00125     /* Table size, the sign of n flips the circle direction */
00126 
00127     const int size = abs(n);
00128 
00129     /* Determine the angle between samples */
00130 
00131     const double angle = 2*M_PI/(double)( ( n == 0 ) ? 1 : n );
00132 
00133     /* Allocate memory for n samples, plus duplicate of first entry at the end */
00134 
00135     *sint = (double *) calloc(sizeof(double), size+1);
00136     *cost = (double *) calloc(sizeof(double), size+1);
00137 
00138     /* Bail out if memory allocation fails, fgError never returns */
00139 
00140     if (!(*sint) || !(*cost))
00141     {
00142       if (*sint) free(*sint);
00143       if (*cost) free(*cost);
00144       return;
00145     }
00146 
00147     /* Compute cos and sin around the circle */
00148 
00149     (*sint)[0] = 0.0;
00150     (*cost)[0] = 1.0;
00151 
00152     for (i=1; i<size; i++)
00153     {
00154         (*sint)[i] = sin(angle*i);
00155         (*cost)[i] = cos(angle*i);
00156     }
00157 
00158     /* Last sample is duplicate of the first */
00159 
00160     (*sint)[size] = (*sint)[0];
00161     (*cost)[size] = (*cost)[0];
00162 }
00163 
00164 /*
00165  * Draws a solid sphere
00166  */
00167 void glutSolidSphere(GLdouble radius, GLint slices, GLint stacks)
00168 {
00169     int i,j;
00170 
00171     /* Adjust z and radius as stacks are drawn. */
00172 
00173     double z0,z1;
00174     double r0,r1;
00175 
00176     /* Pre-computed circle */
00177 
00178     double *sint1,*cost1;
00179     double *sint2,*cost2;
00180 
00181     fghCircleTable(&sint1,&cost1,-slices);
00182     fghCircleTable(&sint2,&cost2,stacks*2);
00183 
00184     /* The top stack is covered with a triangle fan */
00185 
00186     z0 = 1.0;
00187     z1 = cost2[(stacks>0)?1:0];
00188     r0 = 0.0;
00189     r1 = sint2[(stacks>0)?1:0];
00190 
00191     glBegin(GL_TRIANGLE_FAN);
00192 
00193         glNormal3d(0,0,1);
00194         glVertex3d(0,0,radius);
00195 
00196         for (j=slices; j>=0; j--)
00197         {
00198             glNormal3d(cost1[j]*r1,        sint1[j]*r1,        z1       );
00199             glVertex3d(cost1[j]*r1*radius, sint1[j]*r1*radius, z1*radius);
00200         }
00201 
00202     glEnd();
00203 
00204     /* Cover each stack with a quad strip, except the top and bottom stacks */
00205 
00206     for( i=1; i<stacks-1; i++ )
00207     {
00208         z0 = z1; z1 = cost2[i+1];
00209         r0 = r1; r1 = sint2[i+1];
00210 
00211         glBegin(GL_QUAD_STRIP);
00212 
00213             for(j=0; j<=slices; j++)
00214             {
00215                 glNormal3d(cost1[j]*r1,        sint1[j]*r1,        z1       );
00216                 glVertex3d(cost1[j]*r1*radius, sint1[j]*r1*radius, z1*radius);
00217                 glNormal3d(cost1[j]*r0,        sint1[j]*r0,        z0       );
00218                 glVertex3d(cost1[j]*r0*radius, sint1[j]*r0*radius, z0*radius);
00219             }
00220 
00221         glEnd();
00222     }
00223 
00224     /* The bottom stack is covered with a triangle fan */
00225 
00226     z0 = z1;
00227     r0 = r1;
00228 
00229     glBegin(GL_TRIANGLE_FAN);
00230 
00231         glNormal3d(0,0,-1);
00232         glVertex3d(0,0,-radius);
00233 
00234         for (j=0; j<=slices; j++)
00235         {
00236             glNormal3d(cost1[j]*r0,        sint1[j]*r0,        z0       );
00237             glVertex3d(cost1[j]*r0*radius, sint1[j]*r0*radius, z0*radius);
00238         }
00239 
00240     glEnd();
00241 
00242     /* Release sin and cos tables */
00243 
00244     free(sint1);
00245     free(cost1);
00246     free(sint2);
00247     free(cost2);
00248 }
00249 
00250 /*
00251  * Draws a wire sphere
00252  */
00253 void glutWireSphere(GLdouble radius, GLint slices, GLint stacks)
00254 {
00255     int i,j;
00256 
00257     /* Adjust z and radius as stacks and slices are drawn. */
00258 
00259     double r;
00260     double x,y,z;
00261 
00262     /* Pre-computed circle */
00263 
00264     double *sint1,*cost1;
00265     double *sint2,*cost2;
00266 
00267     fghCircleTable(&sint1,&cost1,-slices  );
00268     fghCircleTable(&sint2,&cost2, stacks*2);
00269 
00270     /* Draw a line loop for each stack */
00271 
00272     for (i=1; i<stacks; i++)
00273     {
00274         z = cost2[i];
00275         r = sint2[i];
00276 
00277         glBegin(GL_LINE_LOOP);
00278 
00279             for(j=0; j<=slices; j++)
00280             {
00281                 x = cost1[j];
00282                 y = sint1[j];
00283 
00284                 glNormal3d(x,y,z);
00285                 glVertex3d(x*r*radius,y*r*radius,z*radius);
00286             }
00287 
00288         glEnd();
00289     }
00290 
00291     /* Draw a line loop for each slice */
00292 
00293     for (i=0; i<slices; i++)
00294     {
00295         glBegin(GL_LINE_STRIP);
00296 
00297             for(j=0; j<=stacks; j++)
00298             {
00299                 x = cost1[i]*sint2[j];
00300                 y = sint1[i]*sint2[j];
00301                 z = cost2[j];
00302 
00303                 glNormal3d(x,y,z);
00304                 glVertex3d(x*radius,y*radius,z*radius);
00305             }
00306 
00307         glEnd();
00308     }
00309 
00310     /* Release sin and cos tables */
00311 
00312     free(sint1);
00313     free(cost1);
00314     free(sint2);
00315     free(cost2);
00316 }
00317 
00318 /*
00319  * Draws a solid cone
00320  */
00321 void glutSolidCone( GLdouble base, GLdouble height, GLint slices, GLint stacks )
00322 {
00323     int i,j;
00324 
00325     /* Step in z and radius as stacks are drawn. */
00326 
00327     double z0,z1;
00328     double r0,r1;
00329 
00330     const double zStep = height / ( ( stacks > 0 ) ? stacks : 1 );
00331     const double rStep = base / ( ( stacks > 0 ) ? stacks : 1 );
00332 
00333     /* Scaling factors for vertex normals */
00334 
00335     const double cosn = ( height / sqrt ( height * height + base * base ));
00336     const double sinn = ( base   / sqrt ( height * height + base * base ));
00337 
00338     /* Pre-computed circle */
00339 
00340     double *sint,*cost;
00341 
00342     fghCircleTable(&sint,&cost,-slices);
00343 
00344     /* Cover the circular base with a triangle fan... */
00345 
00346     z0 = 0.0;
00347     z1 = zStep;
00348 
00349     r0 = base;
00350     r1 = r0 - rStep;
00351 
00352     glBegin(GL_TRIANGLE_FAN);
00353 
00354         glNormal3d(0.0,0.0,-1.0);
00355         glVertex3d(0.0,0.0, z0 );
00356 
00357         for (j=0; j<=slices; j++)
00358             glVertex3d(cost[j]*r0, sint[j]*r0, z0);
00359 
00360     glEnd();
00361 
00362     /* Cover each stack with a quad strip, except the top stack */
00363 
00364     for( i=0; i<stacks-1; i++ )
00365     {
00366         glBegin(GL_QUAD_STRIP);
00367 
00368             for(j=0; j<=slices; j++)
00369             {
00370                 glNormal3d(cost[j]*sinn, sint[j]*sinn, cosn);
00371                 glVertex3d(cost[j]*r0,   sint[j]*r0,   z0  );
00372                 glVertex3d(cost[j]*r1,   sint[j]*r1,   z1  );
00373             }
00374 
00375             z0 = z1; z1 += zStep;
00376             r0 = r1; r1 -= rStep;
00377 
00378         glEnd();
00379     }
00380 
00381     /* The top stack is covered with individual triangles */
00382 
00383     glBegin(GL_TRIANGLES);
00384 
00385         glNormal3d(cost[0]*sinn, sint[0]*sinn, cosn);
00386 
00387         for (j=0; j<slices; j++)
00388         {
00389             glVertex3d(cost[j+0]*r0,   sint[j+0]*r0,   z0    );
00390             glVertex3d(0,              0,              height);
00391             glNormal3d(cost[j+1]*sinn, sint[j+1]*sinn, cosn  );
00392             glVertex3d(cost[j+1]*r0,   sint[j+1]*r0,   z0    );
00393         }
00394 
00395     glEnd();
00396 
00397     /* Release sin and cos tables */
00398 
00399     free(sint);
00400     free(cost);
00401 }
00402 
00403 /*
00404  * Draws a wire cone
00405  */
00406 void glutWireCone( GLdouble base, GLdouble height, GLint slices, GLint stacks)
00407 {
00408     int i,j;
00409 
00410     /* Step in z and radius as stacks are drawn. */
00411 
00412     double z = 0.0;
00413     double r = base;
00414 
00415     const double zStep = height / ( ( stacks > 0 ) ? stacks : 1 );
00416     const double rStep = base / ( ( stacks > 0 ) ? stacks : 1 );
00417 
00418     /* Scaling factors for vertex normals */
00419 
00420     const double cosn = ( height / sqrt ( height * height + base * base ));
00421     const double sinn = ( base   / sqrt ( height * height + base * base ));
00422 
00423     /* Pre-computed circle */
00424 
00425     double *sint,*cost;
00426 
00427     fghCircleTable(&sint,&cost,-slices);
00428 
00429     /* Draw the stacks... */
00430 
00431     for (i=0; i<stacks; i++)
00432     {
00433         glBegin(GL_LINE_LOOP);
00434 
00435             for( j=0; j<slices; j++ )
00436             {
00437                 glNormal3d(cost[j]*sinn, sint[j]*sinn, cosn);
00438                 glVertex3d(cost[j]*r,    sint[j]*r,    z   );
00439             }
00440 
00441         glEnd();
00442 
00443         z += zStep;
00444         r -= rStep;
00445     }
00446 
00447     /* Draw the slices */
00448 
00449     r = base;
00450 
00451     glBegin(GL_LINES);
00452 
00453         for (j=0; j<slices; j++)
00454         {
00455             glNormal3d(cost[j]*sinn, sint[j]*sinn, cosn  );
00456             glVertex3d(cost[j]*r,    sint[j]*r,    0.0   );
00457             glVertex3d(0.0,          0.0,          height);
00458         }
00459 
00460     glEnd();
00461 
00462     /* Release sin and cos tables */
00463 
00464     free(sint);
00465     free(cost);
00466 }
00467 
00468 
00469 /*
00470  * Draws a solid cylinder
00471  */
00472 void glutSolidCylinder(GLdouble radius, GLdouble height, GLint slices, GLint stacks)
00473 {
00474     int i,j;
00475 
00476     /* Step in z and radius as stacks are drawn. */
00477 
00478     double z0,z1;
00479     const double zStep = height / ( ( stacks > 0 ) ? stacks : 1 );
00480 
00481     /* Pre-computed circle */
00482 
00483     double *sint,*cost;
00484 
00485     fghCircleTable(&sint,&cost,-slices);
00486 
00487     /* Cover the base and top */
00488 
00489     glBegin(GL_TRIANGLE_FAN);
00490         glNormal3d(0.0, 0.0, -1.0 );
00491         glVertex3d(0.0, 0.0,  0.0 );
00492         for (j=0; j<=slices; j++)
00493           glVertex3d(cost[j]*radius, sint[j]*radius, 0.0);
00494     glEnd();
00495 
00496     glBegin(GL_TRIANGLE_FAN);
00497         glNormal3d(0.0, 0.0, 1.0   );
00498         glVertex3d(0.0, 0.0, height);
00499         for (j=slices; j>=0; j--)
00500           glVertex3d(cost[j]*radius, sint[j]*radius, height);
00501     glEnd();
00502 
00503     /* Do the stacks */
00504 
00505     z0 = 0.0;
00506     z1 = zStep;
00507 
00508     for (i=1; i<=stacks; i++)
00509     {
00510         if (i==stacks)
00511             z1 = height;
00512 
00513         glBegin(GL_QUAD_STRIP);
00514             for (j=0; j<=slices; j++ )
00515             {
00516                 glNormal3d(cost[j],        sint[j],        0.0 );
00517                 glVertex3d(cost[j]*radius, sint[j]*radius, z0  );
00518                 glVertex3d(cost[j]*radius, sint[j]*radius, z1  );
00519             }
00520         glEnd();
00521 
00522         z0 = z1; z1 += zStep;
00523     }
00524 
00525     /* Release sin and cos tables */
00526 
00527     free(sint);
00528     free(cost);
00529 }
00530 
00531 /*
00532  * Draws a wire cylinder
00533  */
00534 void glutWireCylinder(GLdouble radius, GLdouble height, GLint slices, GLint stacks)
00535 {
00536     int i,j;
00537 
00538     /* Step in z and radius as stacks are drawn. */
00539 
00540           double z = 0.0;
00541     const double zStep = height / ( ( stacks > 0 ) ? stacks : 1 );
00542 
00543     /* Pre-computed circle */
00544 
00545     double *sint,*cost;
00546 
00547     fghCircleTable(&sint,&cost,-slices);
00548 
00549     /* Draw the stacks... */
00550 
00551     for (i=0; i<=stacks; i++)
00552     {
00553         if (i==stacks)
00554             z = height;
00555 
00556         glBegin(GL_LINE_LOOP);
00557 
00558             for( j=0; j<slices; j++ )
00559             {
00560                 glNormal3d(cost[j],        sint[j],        0.0);
00561                 glVertex3d(cost[j]*radius, sint[j]*radius, z  );
00562             }
00563 
00564         glEnd();
00565 
00566         z += zStep;
00567     }
00568 
00569     /* Draw the slices */
00570 
00571     glBegin(GL_LINES);
00572 
00573         for (j=0; j<slices; j++)
00574         {
00575             glNormal3d(cost[j],        sint[j],        0.0   );
00576             glVertex3d(cost[j]*radius, sint[j]*radius, 0.0   );
00577             glVertex3d(cost[j]*radius, sint[j]*radius, height);
00578         }
00579 
00580     glEnd();
00581 
00582     /* Release sin and cos tables */
00583 
00584     free(sint);
00585     free(cost);
00586 }
00587 
00588 /*
00589  * Draws a wire torus
00590  */
00591 void glutWireTorus( GLdouble dInnerRadius, GLdouble dOuterRadius, GLint nSides, GLint nRings )
00592 {
00593   double  iradius = dInnerRadius, oradius = dOuterRadius, phi, psi, dpsi, dphi;
00594   double *vertex, *normal;
00595   int    i, j;
00596   double spsi, cpsi, sphi, cphi ;
00597 
00598   if ( nSides < 1 ) nSides = 1;
00599   if ( nRings < 1 ) nRings = 1;
00600 
00601   /* Allocate the vertices array */
00602   vertex = (double *)calloc( sizeof(double), 3 * nSides * nRings );
00603   normal = (double *)calloc( sizeof(double), 3 * nSides * nRings );
00604 
00605   glPushMatrix();
00606 
00607   dpsi =  2.0 * M_PI / (double)nRings ;
00608   dphi = -2.0 * M_PI / (double)nSides ;
00609   psi  = 0.0;
00610 
00611   for( j=0; j<nRings; j++ )
00612   {
00613     cpsi = cos ( psi ) ;
00614     spsi = sin ( psi ) ;
00615     phi = 0.0;
00616 
00617     for( i=0; i<nSides; i++ )
00618     {
00619       int offset = 3 * ( j * nSides + i ) ;
00620       cphi = cos ( phi ) ;
00621       sphi = sin ( phi ) ;
00622       *(vertex + offset + 0) = cpsi * ( oradius + cphi * iradius ) ;
00623       *(vertex + offset + 1) = spsi * ( oradius + cphi * iradius ) ;
00624       *(vertex + offset + 2) =                    sphi * iradius  ;
00625       *(normal + offset + 0) = cpsi * cphi ;
00626       *(normal + offset + 1) = spsi * cphi ;
00627       *(normal + offset + 2) =        sphi ;
00628       phi += dphi;
00629     }
00630 
00631     psi += dpsi;
00632   }
00633 
00634   for( i=0; i<nSides; i++ )
00635   {
00636     glBegin( GL_LINE_LOOP );
00637 
00638     for( j=0; j<nRings; j++ )
00639     {
00640       int offset = 3 * ( j * nSides + i ) ;
00641       glNormal3dv( normal + offset );
00642       glVertex3dv( vertex + offset );
00643     }
00644 
00645     glEnd();
00646   }
00647 
00648   for( j=0; j<nRings; j++ )
00649   {
00650     glBegin(GL_LINE_LOOP);
00651 
00652     for( i=0; i<nSides; i++ )
00653     {
00654       int offset = 3 * ( j * nSides + i ) ;
00655       glNormal3dv( normal + offset );
00656       glVertex3dv( vertex + offset );
00657     }
00658 
00659     glEnd();
00660   }
00661 
00662   free ( vertex ) ;
00663   free ( normal ) ;
00664   glPopMatrix();
00665 }
00666 
00667 /*
00668  * Draws a solid torus
00669  */
00670 void glutSolidTorus( GLdouble dInnerRadius, GLdouble dOuterRadius, GLint nSides, GLint nRings )
00671 {
00672   double  iradius = dInnerRadius, oradius = dOuterRadius, phi, psi, dpsi, dphi;
00673   double *vertex, *normal;
00674   int    i, j;
00675   double spsi, cpsi, sphi, cphi ;
00676 
00677   if ( nSides < 1 ) nSides = 1;
00678   if ( nRings < 1 ) nRings = 1;
00679 
00680   /* Increment the number of sides and rings to allow for one more point than surface */
00681   nSides ++ ;
00682   nRings ++ ;
00683 
00684   /* Allocate the vertices array */
00685   vertex = (double *)calloc( sizeof(double), 3 * nSides * nRings );
00686   normal = (double *)calloc( sizeof(double), 3 * nSides * nRings );
00687 
00688   glPushMatrix();
00689 
00690   dpsi =  2.0 * M_PI / (double)(nRings - 1) ;
00691   dphi = -2.0 * M_PI / (double)(nSides - 1) ;
00692   psi  = 0.0;
00693 
00694   for( j=0; j<nRings; j++ )
00695   {
00696     cpsi = cos ( psi ) ;
00697     spsi = sin ( psi ) ;
00698     phi = 0.0;
00699 
00700     for( i=0; i<nSides; i++ )
00701     {
00702       int offset = 3 * ( j * nSides + i ) ;
00703       cphi = cos ( phi ) ;
00704       sphi = sin ( phi ) ;
00705       *(vertex + offset + 0) = cpsi * ( oradius + cphi * iradius ) ;
00706       *(vertex + offset + 1) = spsi * ( oradius + cphi * iradius ) ;
00707       *(vertex + offset + 2) =                    sphi * iradius  ;
00708       *(normal + offset + 0) = cpsi * cphi ;
00709       *(normal + offset + 1) = spsi * cphi ;
00710       *(normal + offset + 2) =        sphi ;
00711       phi += dphi;
00712     }
00713 
00714     psi += dpsi;
00715   }
00716 
00717     glBegin( GL_QUADS );
00718   for( i=0; i<nSides-1; i++ )
00719   {
00720     for( j=0; j<nRings-1; j++ )
00721     {
00722       int offset = 3 * ( j * nSides + i ) ;
00723       glNormal3dv( normal + offset );
00724       glVertex3dv( vertex + offset );
00725       glNormal3dv( normal + offset + 3 );
00726       glVertex3dv( vertex + offset + 3 );
00727       glNormal3dv( normal + offset + 3 * nSides + 3 );
00728       glVertex3dv( vertex + offset + 3 * nSides + 3 );
00729       glNormal3dv( normal + offset + 3 * nSides );
00730       glVertex3dv( vertex + offset + 3 * nSides );
00731     }
00732   }
00733 
00734   glEnd();
00735 
00736   free ( vertex ) ;
00737   free ( normal ) ;
00738   glPopMatrix();
00739 }
00740 
00741 /*
00742  *
00743  */
00744 void glutWireDodecahedron( void )
00745 {
00746   /* Magic Numbers:  It is possible to create a dodecahedron by attaching two pentagons to each face of
00747    * of a cube.  The coordinates of the points are:
00748    *   (+-x,0, z); (+-1, 1, 1); (0, z, x )
00749    * where x = (-1 + sqrt(5))/2, z = (1 + sqrt(5))/2  or
00750    *       x = 0.61803398875 and z = 1.61803398875.
00751    */
00752   glBegin ( GL_LINE_LOOP ) ;
00753   glNormal3d (  0.0,  0.525731112119,  0.850650808354 ) ; glVertex3d (  0.0,  1.61803398875,  0.61803398875 ) ; glVertex3d ( -1.0,  1.0,  1.0 ) ; glVertex3d ( -0.61803398875, 0.0,  1.61803398875 ) ; glVertex3d (  0.61803398875, 0.0,  1.61803398875 ) ; glVertex3d (  1.0,  1.0,  1.0 ) ;
00754   glEnd () ;
00755   glBegin ( GL_LINE_LOOP ) ;
00756   glNormal3d (  0.0,  0.525731112119, -0.850650808354 ) ; glVertex3d (  0.0,  1.61803398875, -0.61803398875 ) ; glVertex3d (  1.0,  1.0, -1.0 ) ; glVertex3d (  0.61803398875, 0.0, -1.61803398875 ) ; glVertex3d ( -0.61803398875, 0.0, -1.61803398875 ) ; glVertex3d ( -1.0,  1.0, -1.0 ) ;
00757   glEnd () ;
00758   glBegin ( GL_LINE_LOOP ) ;
00759   glNormal3d (  0.0, -0.525731112119,  0.850650808354 ) ; glVertex3d (  0.0, -1.61803398875,  0.61803398875 ) ; glVertex3d (  1.0, -1.0,  1.0 ) ; glVertex3d (  0.61803398875, 0.0,  1.61803398875 ) ; glVertex3d ( -0.61803398875, 0.0,  1.61803398875 ) ; glVertex3d ( -1.0, -1.0,  1.0 ) ;
00760   glEnd () ;
00761   glBegin ( GL_LINE_LOOP ) ;
00762   glNormal3d (  0.0, -0.525731112119, -0.850650808354 ) ; glVertex3d (  0.0, -1.61803398875, -0.61803398875 ) ; glVertex3d ( -1.0, -1.0, -1.0 ) ; glVertex3d ( -0.61803398875, 0.0, -1.61803398875 ) ; glVertex3d (  0.61803398875, 0.0, -1.61803398875 ) ; glVertex3d (  1.0, -1.0, -1.0 ) ;
00763   glEnd () ;
00764 
00765   glBegin ( GL_LINE_LOOP ) ;
00766   glNormal3d (  0.850650808354,  0.0,  0.525731112119 ) ; glVertex3d (  0.61803398875,  0.0,  1.61803398875 ) ; glVertex3d (  1.0, -1.0,  1.0 ) ; glVertex3d (  1.61803398875, -0.61803398875, 0.0 ) ; glVertex3d (  1.61803398875,  0.61803398875, 0.0 ) ; glVertex3d (  1.0,  1.0,  1.0 ) ;
00767   glEnd () ;
00768   glBegin ( GL_LINE_LOOP ) ;
00769   glNormal3d ( -0.850650808354,  0.0,  0.525731112119 ) ; glVertex3d ( -0.61803398875,  0.0,  1.61803398875 ) ; glVertex3d ( -1.0,  1.0,  1.0 ) ; glVertex3d ( -1.61803398875,  0.61803398875, 0.0 ) ; glVertex3d ( -1.61803398875, -0.61803398875, 0.0 ) ; glVertex3d ( -1.0, -1.0,  1.0 ) ;
00770   glEnd () ;
00771   glBegin ( GL_LINE_LOOP ) ;
00772   glNormal3d (  0.850650808354,  0.0, -0.525731112119 ) ; glVertex3d (  0.61803398875,  0.0, -1.61803398875 ) ; glVertex3d (  1.0,  1.0, -1.0 ) ; glVertex3d (  1.61803398875,  0.61803398875, 0.0 ) ; glVertex3d (  1.61803398875, -0.61803398875, 0.0 ) ; glVertex3d (  1.0, -1.0, -1.0 ) ;
00773   glEnd () ;
00774   glBegin ( GL_LINE_LOOP ) ;
00775   glNormal3d ( -0.850650808354,  0.0, -0.525731112119 ) ; glVertex3d ( -0.61803398875,  0.0, -1.61803398875 ) ; glVertex3d ( -1.0, -1.0, -1.0 ) ; glVertex3d ( -1.61803398875, -0.61803398875, 0.0 ) ; glVertex3d ( -1.61803398875,  0.61803398875, 0.0 ) ; glVertex3d ( -1.0,  1.0, -1.0 ) ;
00776   glEnd () ;
00777 
00778   glBegin ( GL_LINE_LOOP ) ;
00779   glNormal3d (  0.525731112119,  0.850650808354,  0.0 ) ; glVertex3d (  1.61803398875,  0.61803398875,  0.0 ) ; glVertex3d (  1.0,  1.0, -1.0 ) ; glVertex3d ( 0.0,  1.61803398875, -0.61803398875 ) ; glVertex3d ( 0.0,  1.61803398875,  0.61803398875 ) ; glVertex3d (  1.0,  1.0,  1.0 ) ;
00780   glEnd () ;
00781   glBegin ( GL_LINE_LOOP ) ;
00782   glNormal3d (  0.525731112119, -0.850650808354,  0.0 ) ; glVertex3d (  1.61803398875, -0.61803398875,  0.0 ) ; glVertex3d (  1.0, -1.0,  1.0 ) ; glVertex3d ( 0.0, -1.61803398875,  0.61803398875 ) ; glVertex3d ( 0.0, -1.61803398875, -0.61803398875 ) ; glVertex3d (  1.0, -1.0, -1.0 ) ;
00783   glEnd () ;
00784   glBegin ( GL_LINE_LOOP ) ;
00785   glNormal3d ( -0.525731112119,  0.850650808354,  0.0 ) ; glVertex3d ( -1.61803398875,  0.61803398875,  0.0 ) ; glVertex3d ( -1.0,  1.0,  1.0 ) ; glVertex3d ( 0.0,  1.61803398875,  0.61803398875 ) ; glVertex3d ( 0.0,  1.61803398875, -0.61803398875 ) ; glVertex3d ( -1.0,  1.0, -1.0 ) ;
00786   glEnd () ;
00787   glBegin ( GL_LINE_LOOP ) ;
00788   glNormal3d ( -0.525731112119, -0.850650808354,  0.0 ) ; glVertex3d ( -1.61803398875, -0.61803398875,  0.0 ) ; glVertex3d ( -1.0, -1.0, -1.0 ) ; glVertex3d ( 0.0, -1.61803398875, -0.61803398875 ) ; glVertex3d ( 0.0, -1.61803398875,  0.61803398875 ) ; glVertex3d ( -1.0, -1.0,  1.0 ) ;
00789   glEnd () ;
00790 }
00791 
00792 /*
00793  *
00794  */
00795 void glutSolidDodecahedron( void )
00796 {
00797   /* Magic Numbers:  It is possible to create a dodecahedron by attaching two pentagons to each face of
00798    * of a cube.  The coordinates of the points are:
00799    *   (+-x,0, z); (+-1, 1, 1); (0, z, x )
00800    * where x = (-1 + sqrt(5))/2, z = (1 + sqrt(5))/2 or
00801    *       x = 0.61803398875 and z = 1.61803398875.
00802    */
00803   glBegin ( GL_POLYGON ) ;
00804   glNormal3d (  0.0,  0.525731112119,  0.850650808354 ) ; glVertex3d (  0.0,  1.61803398875,  0.61803398875 ) ; glVertex3d ( -1.0,  1.0,  1.0 ) ; glVertex3d ( -0.61803398875, 0.0,  1.61803398875 ) ; glVertex3d (  0.61803398875, 0.0,  1.61803398875 ) ; glVertex3d (  1.0,  1.0,  1.0 ) ;
00805   glEnd () ;
00806   glBegin ( GL_POLYGON ) ;
00807   glNormal3d (  0.0,  0.525731112119, -0.850650808354 ) ; glVertex3d (  0.0,  1.61803398875, -0.61803398875 ) ; glVertex3d (  1.0,  1.0, -1.0 ) ; glVertex3d (  0.61803398875, 0.0, -1.61803398875 ) ; glVertex3d ( -0.61803398875, 0.0, -1.61803398875 ) ; glVertex3d ( -1.0,  1.0, -1.0 ) ;
00808   glEnd () ;
00809   glBegin ( GL_POLYGON ) ;
00810   glNormal3d (  0.0, -0.525731112119,  0.850650808354 ) ; glVertex3d (  0.0, -1.61803398875,  0.61803398875 ) ; glVertex3d (  1.0, -1.0,  1.0 ) ; glVertex3d (  0.61803398875, 0.0,  1.61803398875 ) ; glVertex3d ( -0.61803398875, 0.0,  1.61803398875 ) ; glVertex3d ( -1.0, -1.0,  1.0 ) ;
00811   glEnd () ;
00812   glBegin ( GL_POLYGON ) ;
00813   glNormal3d (  0.0, -0.525731112119, -0.850650808354 ) ; glVertex3d (  0.0, -1.61803398875, -0.61803398875 ) ; glVertex3d ( -1.0, -1.0, -1.0 ) ; glVertex3d ( -0.61803398875, 0.0, -1.61803398875 ) ; glVertex3d (  0.61803398875, 0.0, -1.61803398875 ) ; glVertex3d (  1.0, -1.0, -1.0 ) ;
00814   glEnd () ;
00815 
00816   glBegin ( GL_POLYGON ) ;
00817   glNormal3d (  0.850650808354,  0.0,  0.525731112119 ) ; glVertex3d (  0.61803398875,  0.0,  1.61803398875 ) ; glVertex3d (  1.0, -1.0,  1.0 ) ; glVertex3d (  1.61803398875, -0.61803398875, 0.0 ) ; glVertex3d (  1.61803398875,  0.61803398875, 0.0 ) ; glVertex3d (  1.0,  1.0,  1.0 ) ;
00818   glEnd () ;
00819   glBegin ( GL_POLYGON ) ;
00820   glNormal3d ( -0.850650808354,  0.0,  0.525731112119 ) ; glVertex3d ( -0.61803398875,  0.0,  1.61803398875 ) ; glVertex3d ( -1.0,  1.0,  1.0 ) ; glVertex3d ( -1.61803398875,  0.61803398875, 0.0 ) ; glVertex3d ( -1.61803398875, -0.61803398875, 0.0 ) ; glVertex3d ( -1.0, -1.0,  1.0 ) ;
00821   glEnd () ;
00822   glBegin ( GL_POLYGON ) ;
00823   glNormal3d (  0.850650808354,  0.0, -0.525731112119 ) ; glVertex3d (  0.61803398875,  0.0, -1.61803398875 ) ; glVertex3d (  1.0,  1.0, -1.0 ) ; glVertex3d (  1.61803398875,  0.61803398875, 0.0 ) ; glVertex3d (  1.61803398875, -0.61803398875, 0.0 ) ; glVertex3d (  1.0, -1.0, -1.0 ) ;
00824   glEnd () ;
00825   glBegin ( GL_POLYGON ) ;
00826   glNormal3d ( -0.850650808354,  0.0, -0.525731112119 ) ; glVertex3d ( -0.61803398875,  0.0, -1.61803398875 ) ; glVertex3d ( -1.0, -1.0, -1.0 ) ; glVertex3d ( -1.61803398875, -0.61803398875, 0.0 ) ; glVertex3d ( -1.61803398875,  0.61803398875, 0.0 ) ; glVertex3d ( -1.0,  1.0, -1.0 ) ;
00827   glEnd () ;
00828 
00829   glBegin ( GL_POLYGON ) ;
00830   glNormal3d (  0.525731112119,  0.850650808354,  0.0 ) ; glVertex3d (  1.61803398875,  0.61803398875,  0.0 ) ; glVertex3d (  1.0,  1.0, -1.0 ) ; glVertex3d ( 0.0,  1.61803398875, -0.61803398875 ) ; glVertex3d ( 0.0,  1.61803398875,  0.61803398875 ) ; glVertex3d (  1.0,  1.0,  1.0 ) ;
00831   glEnd () ;
00832   glBegin ( GL_POLYGON ) ;
00833   glNormal3d (  0.525731112119, -0.850650808354,  0.0 ) ; glVertex3d (  1.61803398875, -0.61803398875,  0.0 ) ; glVertex3d (  1.0, -1.0,  1.0 ) ; glVertex3d ( 0.0, -1.61803398875,  0.61803398875 ) ; glVertex3d ( 0.0, -1.61803398875, -0.61803398875 ) ; glVertex3d (  1.0, -1.0, -1.0 ) ;
00834   glEnd () ;
00835   glBegin ( GL_POLYGON ) ;
00836   glNormal3d ( -0.525731112119,  0.850650808354,  0.0 ) ; glVertex3d ( -1.61803398875,  0.61803398875,  0.0 ) ; glVertex3d ( -1.0,  1.0,  1.0 ) ; glVertex3d ( 0.0,  1.61803398875,  0.61803398875 ) ; glVertex3d ( 0.0,  1.61803398875, -0.61803398875 ) ; glVertex3d ( -1.0,  1.0, -1.0 ) ;
00837   glEnd () ;
00838   glBegin ( GL_POLYGON ) ;
00839   glNormal3d ( -0.525731112119, -0.850650808354,  0.0 ) ; glVertex3d ( -1.61803398875, -0.61803398875,  0.0 ) ; glVertex3d ( -1.0, -1.0, -1.0 ) ; glVertex3d ( 0.0, -1.61803398875, -0.61803398875 ) ; glVertex3d ( 0.0, -1.61803398875,  0.61803398875 ) ; glVertex3d ( -1.0, -1.0,  1.0 ) ;
00840   glEnd () ;
00841 }
00842 
00843 /*
00844  *
00845  */
00846 void glutWireOctahedron( void )
00847 {
00848 #define RADIUS    1.0f
00849   glBegin( GL_LINE_LOOP );
00850     glNormal3d( 0.577350269189, 0.577350269189, 0.577350269189); glVertex3d( RADIUS, 0.0, 0.0 ); glVertex3d( 0.0, RADIUS, 0.0 ); glVertex3d( 0.0, 0.0, RADIUS );
00851     glNormal3d( 0.577350269189, 0.577350269189,-0.577350269189); glVertex3d( RADIUS, 0.0, 0.0 ); glVertex3d( 0.0, 0.0,-RADIUS ); glVertex3d( 0.0, RADIUS, 0.0 );
00852     glNormal3d( 0.577350269189,-0.577350269189, 0.577350269189); glVertex3d( RADIUS, 0.0, 0.0 ); glVertex3d( 0.0, 0.0, RADIUS ); glVertex3d( 0.0,-RADIUS, 0.0 );
00853     glNormal3d( 0.577350269189,-0.577350269189,-0.577350269189); glVertex3d( RADIUS, 0.0, 0.0 ); glVertex3d( 0.0,-RADIUS, 0.0 ); glVertex3d( 0.0, 0.0,-RADIUS );
00854     glNormal3d(-0.577350269189, 0.577350269189, 0.577350269189); glVertex3d(-RADIUS, 0.0, 0.0 ); glVertex3d( 0.0, 0.0, RADIUS ); glVertex3d( 0.0, RADIUS, 0.0 );
00855     glNormal3d(-0.577350269189, 0.577350269189,-0.577350269189); glVertex3d(-RADIUS, 0.0, 0.0 ); glVertex3d( 0.0, RADIUS, 0.0 ); glVertex3d( 0.0, 0.0,-RADIUS );
00856     glNormal3d(-0.577350269189,-0.577350269189, 0.577350269189); glVertex3d(-RADIUS, 0.0, 0.0 ); glVertex3d( 0.0,-RADIUS, 0.0 ); glVertex3d( 0.0, 0.0, RADIUS );
00857     glNormal3d(-0.577350269189,-0.577350269189,-0.577350269189); glVertex3d(-RADIUS, 0.0, 0.0 ); glVertex3d( 0.0, 0.0,-RADIUS ); glVertex3d( 0.0,-RADIUS, 0.0 );
00858   glEnd();
00859 #undef RADIUS
00860 }
00861 
00862 /*
00863  *
00864  */
00865 void glutSolidOctahedron( void )
00866 {
00867 #define RADIUS    1.0f
00868   glBegin( GL_TRIANGLES );
00869     glNormal3d( 0.577350269189, 0.577350269189, 0.577350269189); glVertex3d( RADIUS, 0.0, 0.0 ); glVertex3d( 0.0, RADIUS, 0.0 ); glVertex3d( 0.0, 0.0, RADIUS );
00870     glNormal3d( 0.577350269189, 0.577350269189,-0.577350269189); glVertex3d( RADIUS, 0.0, 0.0 ); glVertex3d( 0.0, 0.0,-RADIUS ); glVertex3d( 0.0, RADIUS, 0.0 );
00871     glNormal3d( 0.577350269189,-0.577350269189, 0.577350269189); glVertex3d( RADIUS, 0.0, 0.0 ); glVertex3d( 0.0, 0.0, RADIUS ); glVertex3d( 0.0,-RADIUS, 0.0 );
00872     glNormal3d( 0.577350269189,-0.577350269189,-0.577350269189); glVertex3d( RADIUS, 0.0, 0.0 ); glVertex3d( 0.0,-RADIUS, 0.0 ); glVertex3d( 0.0, 0.0,-RADIUS );
00873     glNormal3d(-0.577350269189, 0.577350269189, 0.577350269189); glVertex3d(-RADIUS, 0.0, 0.0 ); glVertex3d( 0.0, 0.0, RADIUS ); glVertex3d( 0.0, RADIUS, 0.0 );
00874     glNormal3d(-0.577350269189, 0.577350269189,-0.577350269189); glVertex3d(-RADIUS, 0.0, 0.0 ); glVertex3d( 0.0, RADIUS, 0.0 ); glVertex3d( 0.0, 0.0,-RADIUS );
00875     glNormal3d(-0.577350269189,-0.577350269189, 0.577350269189); glVertex3d(-RADIUS, 0.0, 0.0 ); glVertex3d( 0.0,-RADIUS, 0.0 ); glVertex3d( 0.0, 0.0, RADIUS );
00876     glNormal3d(-0.577350269189,-0.577350269189,-0.577350269189); glVertex3d(-RADIUS, 0.0, 0.0 ); glVertex3d( 0.0, 0.0,-RADIUS ); glVertex3d( 0.0,-RADIUS, 0.0 );
00877   glEnd();
00878 #undef RADIUS
00879 }
00880 
00881 /* Magic Numbers:  r0 = ( 1, 0, 0 )
00882  *                 r1 = ( -1/3, 2 sqrt(2) / 3, 0 )
00883  *                 r2 = ( -1/3, -sqrt(2) / 3, sqrt(6) / 3 )
00884  *                 r3 = ( -1/3, -sqrt(2) / 3, -sqrt(6) / 3 )
00885  * |r0| = |r1| = |r2| = |r3| = 1
00886  * Distance between any two points is 2 sqrt(6) / 3
00887  *
00888  * Normals:  The unit normals are simply the negative of the coordinates of the point not on the surface.
00889  */
00890 
00891 #define NUM_TETR_FACES     4
00892 
00893 static GLdouble tet_r[4][3] = { {             1.0,             0.0,             0.0 },
00894                                 { -0.333333333333,  0.942809041582,             0.0 },
00895                                 { -0.333333333333, -0.471404520791,  0.816496580928 },
00896                                 { -0.333333333333, -0.471404520791, -0.816496580928 } } ;
00897 
00898 static GLint tet_i[4][3] =  /* Vertex indices */
00899 {
00900   { 1, 3, 2 }, { 0, 2, 3 }, { 0, 3, 1 }, { 0, 1, 2 }
00901 } ;
00902 
00903 /*
00904  *
00905  */
00906 void glutWireTetrahedron( void )
00907 {
00908   glBegin( GL_LINE_LOOP ) ;
00909     glNormal3d ( -tet_r[0][0], -tet_r[0][1], -tet_r[0][2] ) ; glVertex3dv ( tet_r[1] ) ; glVertex3dv ( tet_r[3] ) ; glVertex3dv ( tet_r[2] ) ;
00910     glNormal3d ( -tet_r[1][0], -tet_r[1][1], -tet_r[1][2] ) ; glVertex3dv ( tet_r[0] ) ; glVertex3dv ( tet_r[2] ) ; glVertex3dv ( tet_r[3] ) ;
00911     glNormal3d ( -tet_r[2][0], -tet_r[2][1], -tet_r[2][2] ) ; glVertex3dv ( tet_r[0] ) ; glVertex3dv ( tet_r[3] ) ; glVertex3dv ( tet_r[1] ) ;
00912     glNormal3d ( -tet_r[3][0], -tet_r[3][1], -tet_r[3][2] ) ; glVertex3dv ( tet_r[0] ) ; glVertex3dv ( tet_r[1] ) ; glVertex3dv ( tet_r[2] ) ;
00913   glEnd() ;
00914 }
00915 
00916 /*
00917  *
00918  */
00919 void glutSolidTetrahedron( void )
00920 {
00921   glBegin( GL_TRIANGLES ) ;
00922     glNormal3d ( -tet_r[0][0], -tet_r[0][1], -tet_r[0][2] ) ; glVertex3dv ( tet_r[1] ) ; glVertex3dv ( tet_r[3] ) ; glVertex3dv ( tet_r[2] ) ;
00923     glNormal3d ( -tet_r[1][0], -tet_r[1][1], -tet_r[1][2] ) ; glVertex3dv ( tet_r[0] ) ; glVertex3dv ( tet_r[2] ) ; glVertex3dv ( tet_r[3] ) ;
00924     glNormal3d ( -tet_r[2][0], -tet_r[2][1], -tet_r[2][2] ) ; glVertex3dv ( tet_r[0] ) ; glVertex3dv ( tet_r[3] ) ; glVertex3dv ( tet_r[1] ) ;
00925     glNormal3d ( -tet_r[3][0], -tet_r[3][1], -tet_r[3][2] ) ; glVertex3dv ( tet_r[0] ) ; glVertex3dv ( tet_r[1] ) ; glVertex3dv ( tet_r[2] ) ;
00926   glEnd() ;
00927 }
00928 
00929 /*
00930  *
00931  */
00932 double icos_r[12][3] = { { 1.0, 0.0, 0.0 },
00933   {  0.447213595500,  0.894427191000, 0.0 }, {  0.447213595500,  0.276393202252, 0.850650808354 }, {  0.447213595500, -0.723606797748, 0.525731112119 }, {  0.447213595500, -0.723606797748, -0.525731112119 }, {  0.447213595500,  0.276393202252, -0.850650808354 },
00934   { -0.447213595500, -0.894427191000, 0.0 }, { -0.447213595500, -0.276393202252, 0.850650808354 }, { -0.447213595500,  0.723606797748, 0.525731112119 }, { -0.447213595500,  0.723606797748, -0.525731112119 }, { -0.447213595500, -0.276393202252, -0.850650808354 },
00935   { -1.0, 0.0, 0.0 } } ;
00936 int icos_v [20][3] = { { 0, 1, 2 }, { 0, 2, 3 }, { 0, 3, 4 }, { 0, 4, 5 }, { 0, 5, 1 },
00937                        { 1, 8, 2 }, { 2, 7, 3 }, { 3, 6, 4 }, { 4, 10, 5 }, { 5, 9, 1 },
00938                        { 1, 9, 8 }, { 2, 8, 7 }, { 3, 7, 6 }, { 4, 6, 10 }, { 5, 10, 9 },
00939                        { 11, 9, 10 }, { 11, 8, 9 }, { 11, 7, 8 }, { 11, 6, 7 }, { 11, 10, 6 } } ;
00940 
00941 void glutWireIcosahedron( void )
00942 {
00943   int i ;
00944 
00945   for ( i = 0; i < 20; i++ )
00946   {
00947     double normal[3] ;
00948     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] ) ;
00949     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] ) ;
00950     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] ) ;
00951     glBegin ( GL_LINE_LOOP ) ;
00952       glNormal3dv ( normal ) ;
00953       glVertex3dv ( icos_r[icos_v[i][0]] ) ;
00954       glVertex3dv ( icos_r[icos_v[i][1]] ) ;
00955       glVertex3dv ( icos_r[icos_v[i][2]] ) ;
00956     glEnd () ;
00957   }
00958 }
00959 
00960 /*
00961  *
00962  */
00963 void glutSolidIcosahedron( void )
00964 {
00965   int i ;
00966 
00967   glBegin ( GL_TRIANGLES ) ;
00968   for ( i = 0; i < 20; i++ )
00969   {
00970     double normal[3] ;
00971     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] ) ;
00972     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] ) ;
00973     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] ) ;
00974       glNormal3dv ( normal ) ;
00975       glVertex3dv ( icos_r[icos_v[i][0]] ) ;
00976       glVertex3dv ( icos_r[icos_v[i][1]] ) ;
00977       glVertex3dv ( icos_r[icos_v[i][2]] ) ;
00978   }
00979 
00980   glEnd () ;
00981 }
00982 
00983 /*
00984  *
00985  */
00986 double rdod_r[14][3] = { { 0.0, 0.0, 1.0 },
00987   {  0.707106781187,  0.000000000000,  0.5 }, {  0.000000000000,  0.707106781187,  0.5 }, { -0.707106781187,  0.000000000000,  0.5 }, {  0.000000000000, -0.707106781187,  0.5 },
00988   {  0.707106781187,  0.707106781187,  0.0 }, { -0.707106781187,  0.707106781187,  0.0 }, { -0.707106781187, -0.707106781187,  0.0 }, {  0.707106781187, -0.707106781187,  0.0 },
00989   {  0.707106781187,  0.000000000000, -0.5 }, {  0.000000000000,  0.707106781187, -0.5 }, { -0.707106781187,  0.000000000000, -0.5 }, {  0.000000000000, -0.707106781187, -0.5 },
00990   {  0.0, 0.0, -1.0 } } ;
00991 int rdod_v [12][4] = { { 0,  1,  5,  2 }, { 0,  2,  6,  3 }, { 0,  3,  7,  4 }, { 0,  4,  8, 1 },
00992                        { 5, 10,  6,  2 }, { 6, 11,  7,  3 }, { 7, 12,  8,  4 }, { 8,  9,  5, 1 },
00993                        { 5,  9, 13, 10 }, { 6, 10, 13, 11 }, { 7, 11, 13, 12 }, { 8, 12, 13, 9 } } ;
00994 double rdod_n[12][3] = {
00995   {  0.353553390594,  0.353553390594,  0.5 }, { -0.353553390594,  0.353553390594,  0.5 }, { -0.353553390594, -0.353553390594,  0.5 }, {  0.353553390594, -0.353553390594,  0.5 },
00996   {  0.000000000000,  1.000000000000,  0.0 }, { -1.000000000000,  0.000000000000,  0.0 }, {  0.000000000000, -1.000000000000,  0.0 }, {  1.000000000000,  0.000000000000,  0.0 },
00997   {  0.353553390594,  0.353553390594, -0.5 }, { -0.353553390594,  0.353553390594, -0.5 }, { -0.353553390594, -0.353553390594, -0.5 }, {  0.353553390594, -0.353553390594, -0.5 }
00998   } ;
00999 
01000 void glutWireRhombicDodecahedron( void )
01001 {
01002   int i ;
01003 
01004   for ( i = 0; i < 12; i++ )
01005   {
01006     glBegin ( GL_LINE_LOOP ) ;
01007       glNormal3dv ( rdod_n[i] ) ;
01008       glVertex3dv ( rdod_r[rdod_v[i][0]] ) ;
01009       glVertex3dv ( rdod_r[rdod_v[i][1]] ) ;
01010       glVertex3dv ( rdod_r[rdod_v[i][2]] ) ;
01011       glVertex3dv ( rdod_r[rdod_v[i][3]] ) ;
01012     glEnd () ;
01013   }
01014 }
01015 
01016 /*
01017  *
01018  */
01019 void glutSolidRhombicDodecahedron( void )
01020 {
01021   int i ;
01022 
01023   glBegin ( GL_QUADS ) ;
01024   for ( i = 0; i < 12; i++ )
01025   {
01026       glNormal3dv ( rdod_n[i] ) ;
01027       glVertex3dv ( rdod_r[rdod_v[i][0]] ) ;
01028       glVertex3dv ( rdod_r[rdod_v[i][1]] ) ;
01029       glVertex3dv ( rdod_r[rdod_v[i][2]] ) ;
01030       glVertex3dv ( rdod_r[rdod_v[i][3]] ) ;
01031   }
01032 
01033   glEnd () ;
01034 }
01035 
01036 void glutWireSierpinskiSponge ( int num_levels, GLdouble offset[3], GLdouble scale )
01037 {
01038   int i, j ;
01039 
01040   if ( num_levels == 0 )
01041   {
01042 
01043     for ( i = 0 ; i < NUM_TETR_FACES ; i++ )
01044     {
01045       glBegin ( GL_LINE_LOOP ) ;
01046       glNormal3d ( -tet_r[i][0], -tet_r[i][1], -tet_r[i][2] ) ;
01047       for ( j = 0; j < 3; j++ )
01048       {
01049         double x = offset[0] + scale * tet_r[tet_i[i][j]][0] ;
01050         double y = offset[1] + scale * tet_r[tet_i[i][j]][1] ;
01051         double z = offset[2] + scale * tet_r[tet_i[i][j]][2] ;
01052         glVertex3d ( x, y, z ) ;
01053       }
01054 
01055       glEnd () ;
01056     }
01057   }
01058   else
01059   {
01060     GLdouble local_offset[3] ;  /* Use a local variable to avoid buildup of roundoff errors */
01061     num_levels -- ;
01062     scale /= 2.0 ;
01063     for ( i = 0 ; i < NUM_TETR_FACES ; i++ )
01064     {
01065       local_offset[0] = offset[0] + scale * tet_r[i][0] ;
01066       local_offset[1] = offset[1] + scale * tet_r[i][1] ;
01067       local_offset[2] = offset[2] + scale * tet_r[i][2] ;
01068       glutWireSierpinskiSponge ( num_levels, local_offset, scale ) ;
01069     }
01070   }
01071 }
01072 
01073 void glutSolidSierpinskiSponge ( int num_levels, GLdouble offset[3], GLdouble scale )
01074 {
01075   int i, j ;
01076 
01077   if ( num_levels == 0 )
01078   {
01079     glBegin ( GL_TRIANGLES ) ;
01080 
01081     for ( i = 0 ; i < NUM_TETR_FACES ; i++ )
01082     {
01083       glNormal3d ( -tet_r[i][0], -tet_r[i][1], -tet_r[i][2] ) ;
01084       for ( j = 0; j < 3; j++ )
01085       {
01086         double x = offset[0] + scale * tet_r[tet_i[i][j]][0] ;
01087         double y = offset[1] + scale * tet_r[tet_i[i][j]][1] ;
01088         double z = offset[2] + scale * tet_r[tet_i[i][j]][2] ;
01089         glVertex3d ( x, y, z ) ;
01090       }
01091     }
01092 
01093     glEnd () ;
01094   }
01095   else
01096   {
01097     GLdouble local_offset[3] ;  /* Use a local variable to avoid buildup of roundoff errors */
01098     num_levels -- ;
01099     scale /= 2.0 ;
01100     for ( i = 0 ; i < NUM_TETR_FACES ; i++ )
01101     {
01102       local_offset[0] = offset[0] + scale * tet_r[i][0] ;
01103       local_offset[1] = offset[1] + scale * tet_r[i][1] ;
01104       local_offset[2] = offset[2] + scale * tet_r[i][2] ;
01105       glutSolidSierpinskiSponge ( num_levels, local_offset, scale ) ;
01106     }
01107   }
01108 }
01109 
01110 /*** END OF FILE ***/