Setting the line endings and keywords on a bunch of new text files
[freeglut] / src / Common / freeglut_geometry.c
index e102cba..0f9f5c5 100644 (file)
-/*\r
- * freeglut_geometry.c\r
- *\r
- * Freeglut geometry rendering methods.\r
- *\r
- * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved.\r
- * Written by Pawel W. Olszta, <olszta@sourceforge.net>\r
- * Creation date: Fri Dec 3 1999\r
- *\r
- * Permission is hereby granted, free of charge, to any person obtaining a\r
- * copy of this software and associated documentation files (the "Software"),\r
- * to deal in the Software without restriction, including without limitation\r
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,\r
- * and/or sell copies of the Software, and to permit persons to whom the\r
- * Software is furnished to do so, subject to the following conditions:\r
- *\r
- * The above copyright notice and this permission notice shall be included\r
- * in all copies or substantial portions of the Software.\r
- *\r
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS\r
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL\r
- * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\r
- * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
- */\r
-\r
-#include <GL/freeglut.h>\r
-#include "freeglut_internal.h"\r
-\r
-/*\r
- * TODO BEFORE THE STABLE RELEASE:\r
- *\r
- * Following functions have been contributed by Andreas Umbach.\r
- *\r
- *      glutWireCube()          -- looks OK\r
- *      glutSolidCube()         -- OK\r
- *\r
- * Those functions have been implemented by John Fay.\r
- *\r
- *      glutWireTorus()         -- looks OK\r
- *      glutSolidTorus()        -- looks OK\r
- *      glutWireDodecahedron()  -- looks OK\r
- *      glutSolidDodecahedron() -- looks OK\r
- *      glutWireOctahedron()    -- looks OK\r
- *      glutSolidOctahedron()   -- looks OK\r
- *      glutWireTetrahedron()   -- looks OK\r
- *      glutSolidTetrahedron()  -- looks OK\r
- *      glutWireIcosahedron()   -- looks OK\r
- *      glutSolidIcosahedron()  -- looks OK\r
- *\r
- *  The Following functions have been updated by Nigel Stewart, based\r
- *  on FreeGLUT 2.0.0 implementations:\r
- *\r
- *      glutWireSphere()        -- looks OK\r
- *      glutSolidSphere()       -- looks OK\r
- *      glutWireCone()          -- looks OK\r
- *      glutSolidCone()         -- looks OK\r
- */\r
-\r
-\r
-/* -- INTERFACE FUNCTIONS -------------------------------------------------- */\r
-\r
-/*\r
- * Draws a wireframed cube. Code contributed by Andreas Umbach <marvin@dataway.ch>\r
- */\r
-void FGAPIENTRY glutWireCube( GLdouble dSize )\r
-{\r
-    double size = dSize * 0.5;\r
-\r
-    FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutWireCube" );\r
-\r
-#   define V(a,b,c) glVertex3d( a size, b size, c size );\r
-#   define N(a,b,c) glNormal3d( a, b, c );\r
-\r
-    /* PWO: I dared to convert the code to use macros... */\r
-    glBegin( GL_LINE_LOOP ); N( 1.0, 0.0, 0.0); V(+,-,+); V(+,-,-); V(+,+,-); V(+,+,+); glEnd();\r
-    glBegin( GL_LINE_LOOP ); N( 0.0, 1.0, 0.0); V(+,+,+); V(+,+,-); V(-,+,-); V(-,+,+); glEnd();\r
-    glBegin( GL_LINE_LOOP ); N( 0.0, 0.0, 1.0); V(+,+,+); V(-,+,+); V(-,-,+); V(+,-,+); glEnd();\r
-    glBegin( GL_LINE_LOOP ); N(-1.0, 0.0, 0.0); V(-,-,+); V(-,+,+); V(-,+,-); V(-,-,-); glEnd();\r
-    glBegin( GL_LINE_LOOP ); N( 0.0,-1.0, 0.0); V(-,-,+); V(-,-,-); V(+,-,-); V(+,-,+); glEnd();\r
-    glBegin( GL_LINE_LOOP ); N( 0.0, 0.0,-1.0); V(-,-,-); V(-,+,-); V(+,+,-); V(+,-,-); glEnd();\r
-\r
-#   undef V\r
-#   undef N\r
-}\r
-\r
-/*\r
- * Draws a solid cube. Code contributed by Andreas Umbach <marvin@dataway.ch>\r
- */\r
-void FGAPIENTRY glutSolidCube( GLdouble dSize )\r
-{\r
-    double size = dSize * 0.5;\r
-\r
-    FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSolidCube" );\r
-\r
-#   define V(a,b,c) glVertex3d( a size, b size, c size );\r
-#   define N(a,b,c) glNormal3d( a, b, c );\r
-\r
-    /* PWO: Again, I dared to convert the code to use macros... */\r
-    glBegin( GL_QUADS );\r
-        N( 1.0, 0.0, 0.0); V(+,-,+); V(+,-,-); V(+,+,-); V(+,+,+);\r
-        N( 0.0, 1.0, 0.0); V(+,+,+); V(+,+,-); V(-,+,-); V(-,+,+);\r
-        N( 0.0, 0.0, 1.0); V(+,+,+); V(-,+,+); V(-,-,+); V(+,-,+);\r
-        N(-1.0, 0.0, 0.0); V(-,-,+); V(-,+,+); V(-,+,-); V(-,-,-);\r
-        N( 0.0,-1.0, 0.0); V(-,-,+); V(-,-,-); V(+,-,-); V(+,-,+);\r
-        N( 0.0, 0.0,-1.0); V(-,-,-); V(-,+,-); V(+,+,-); V(+,-,-);\r
-    glEnd();\r
-\r
-#   undef V\r
-#   undef N\r
-}\r
-\r
-/*\r
- * Compute lookup table of cos and sin values forming a cirle\r
- *\r
- * Notes:\r
- *    It is the responsibility of the caller to free these tables\r
- *    The size of the table is (n+1) to form a connected loop\r
- *    The last entry is exactly the same as the first\r
- *    The sign of n can be flipped to get the reverse loop\r
- */\r
-\r
-static void fghCircleTable(double **sint,double **cost,const int n)\r
-{\r
-    int i;\r
-\r
-    /* Table size, the sign of n flips the circle direction */\r
-\r
-    const int size = abs(n);\r
-\r
-    /* Determine the angle between samples */\r
-\r
-    const double angle = 2*M_PI/(double)( ( n == 0 ) ? 1 : n );\r
-\r
-    /* Allocate memory for n samples, plus duplicate of first entry at the end */\r
-\r
-    *sint = (double *) calloc(sizeof(double), size+1);\r
-    *cost = (double *) calloc(sizeof(double), size+1);\r
-\r
-    /* Bail out if memory allocation fails, fgError never returns */\r
-\r
-    if (!(*sint) || !(*cost))\r
-    {\r
-        free(*sint);\r
-        free(*cost);\r
-        fgError("Failed to allocate memory in fghCircleTable");\r
-    }\r
-\r
-    /* Compute cos and sin around the circle */\r
-\r
-    (*sint)[0] = 0.0;\r
-    (*cost)[0] = 1.0;\r
-\r
-    for (i=1; i<size; i++)\r
-    {\r
-        (*sint)[i] = sin(angle*i);\r
-        (*cost)[i] = cos(angle*i);\r
-    }\r
-\r
-    /* Last sample is duplicate of the first */\r
-\r
-    (*sint)[size] = (*sint)[0];\r
-    (*cost)[size] = (*cost)[0];\r
-}\r
-\r
-/*\r
- * Draws a solid sphere\r
- */\r
-void FGAPIENTRY glutSolidSphere(GLdouble radius, GLint slices, GLint stacks)\r
-{\r
-    int i,j;\r
-\r
-    /* Adjust z and radius as stacks are drawn. */\r
-\r
-    double z0,z1;\r
-    double r0,r1;\r
-\r
-    /* Pre-computed circle */\r
-\r
-    double *sint1,*cost1;\r
-    double *sint2,*cost2;\r
-\r
-    FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSolidSphere" );\r
-\r
-    fghCircleTable(&sint1,&cost1,-slices);\r
-    fghCircleTable(&sint2,&cost2,stacks*2);\r
-\r
-    /* The top stack is covered with a triangle fan */\r
-\r
-    z0 = 1.0;\r
-    z1 = cost2[(stacks>0)?1:0];\r
-    r0 = 0.0;\r
-    r1 = sint2[(stacks>0)?1:0];\r
-\r
-    glBegin(GL_TRIANGLE_FAN);\r
-\r
-        glNormal3d(0,0,1);\r
-        glVertex3d(0,0,radius);\r
-\r
-        for (j=slices; j>=0; j--)\r
-        {\r
-            glNormal3d(cost1[j]*r1,        sint1[j]*r1,        z1       );\r
-            glVertex3d(cost1[j]*r1*radius, sint1[j]*r1*radius, z1*radius);\r
-        }\r
-\r
-    glEnd();\r
-\r
-    /* Cover each stack with a quad strip, except the top and bottom stacks */\r
-\r
-    for( i=1; i<stacks-1; i++ )\r
-    {\r
-        z0 = z1; z1 = cost2[i+1];\r
-        r0 = r1; r1 = sint2[i+1];\r
-\r
-        glBegin(GL_QUAD_STRIP);\r
-\r
-            for(j=0; j<=slices; j++)\r
-            {\r
-                glNormal3d(cost1[j]*r1,        sint1[j]*r1,        z1       );\r
-                glVertex3d(cost1[j]*r1*radius, sint1[j]*r1*radius, z1*radius);\r
-                glNormal3d(cost1[j]*r0,        sint1[j]*r0,        z0       );\r
-                glVertex3d(cost1[j]*r0*radius, sint1[j]*r0*radius, z0*radius);\r
-            }\r
-\r
-        glEnd();\r
-    }\r
-\r
-    /* The bottom stack is covered with a triangle fan */\r
-\r
-    z0 = z1;\r
-    r0 = r1;\r
-\r
-    glBegin(GL_TRIANGLE_FAN);\r
-\r
-        glNormal3d(0,0,-1);\r
-        glVertex3d(0,0,-radius);\r
-\r
-        for (j=0; j<=slices; j++)\r
-        {\r
-            glNormal3d(cost1[j]*r0,        sint1[j]*r0,        z0       );\r
-            glVertex3d(cost1[j]*r0*radius, sint1[j]*r0*radius, z0*radius);\r
-        }\r
-\r
-    glEnd();\r
-\r
-    /* Release sin and cos tables */\r
-\r
-    free(sint1);\r
-    free(cost1);\r
-    free(sint2);\r
-    free(cost2);\r
-}\r
-\r
-/*\r
- * Draws a wire sphere\r
- */\r
-void FGAPIENTRY glutWireSphere(GLdouble radius, GLint slices, GLint stacks)\r
-{\r
-    int i,j;\r
-\r
-    /* Adjust z and radius as stacks and slices are drawn. */\r
-\r
-    double r;\r
-    double x,y,z;\r
-\r
-    /* Pre-computed circle */\r
-\r
-    double *sint1,*cost1;\r
-    double *sint2,*cost2;\r
-\r
-    FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutWireSphere" );\r
-\r
-    fghCircleTable(&sint1,&cost1,-slices  );\r
-    fghCircleTable(&sint2,&cost2, stacks*2);\r
-\r
-    /* Draw a line loop for each stack */\r
-\r
-    for (i=1; i<stacks; i++)\r
-    {\r
-        z = cost2[i];\r
-        r = sint2[i];\r
-\r
-        glBegin(GL_LINE_LOOP);\r
-\r
-            for(j=0; j<=slices; j++)\r
-            {\r
-                x = cost1[j];\r
-                y = sint1[j];\r
-\r
-                glNormal3d(x,y,z);\r
-                glVertex3d(x*r*radius,y*r*radius,z*radius);\r
-            }\r
-\r
-        glEnd();\r
-    }\r
-\r
-    /* Draw a line loop for each slice */\r
-\r
-    for (i=0; i<slices; i++)\r
-    {\r
-        glBegin(GL_LINE_STRIP);\r
-\r
-            for(j=0; j<=stacks; j++)\r
-            {\r
-                x = cost1[i]*sint2[j];\r
-                y = sint1[i]*sint2[j];\r
-                z = cost2[j];\r
-\r
-                glNormal3d(x,y,z);\r
-                glVertex3d(x*radius,y*radius,z*radius);\r
-            }\r
-\r
-        glEnd();\r
-    }\r
-\r
-    /* Release sin and cos tables */\r
-\r
-    free(sint1);\r
-    free(cost1);\r
-    free(sint2);\r
-    free(cost2);\r
-}\r
-\r
-/*\r
- * Draws a solid cone\r
- */\r
-void FGAPIENTRY glutSolidCone( GLdouble base, GLdouble height, GLint slices, GLint stacks )\r
-{\r
-    int i,j;\r
-\r
-    /* Step in z and radius as stacks are drawn. */\r
-\r
-    double z0,z1;\r
-    double r0,r1;\r
-\r
-    const double zStep = height / ( ( stacks > 0 ) ? stacks : 1 );\r
-    const double rStep = base / ( ( stacks > 0 ) ? stacks : 1 );\r
-\r
-    /* Scaling factors for vertex normals */\r
-\r
-    const double cosn = ( height / sqrt ( height * height + base * base ));\r
-    const double sinn = ( base   / sqrt ( height * height + base * base ));\r
-\r
-    /* Pre-computed circle */\r
-\r
-    double *sint,*cost;\r
-\r
-    FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSolidCone" );\r
-\r
-    fghCircleTable(&sint,&cost,-slices);\r
-\r
-    /* Cover the circular base with a triangle fan... */\r
-\r
-    z0 = 0.0;\r
-    z1 = zStep;\r
-\r
-    r0 = base;\r
-    r1 = r0 - rStep;\r
-\r
-    glBegin(GL_TRIANGLE_FAN);\r
-\r
-        glNormal3d(0.0,0.0,-1.0);\r
-        glVertex3d(0.0,0.0, z0 );\r
-\r
-        for (j=0; j<=slices; j++)\r
-            glVertex3d(cost[j]*r0, sint[j]*r0, z0);\r
-\r
-    glEnd();\r
-\r
-    /* Cover each stack with a quad strip, except the top stack */\r
-\r
-    for( i=0; i<stacks-1; i++ )\r
-    {\r
-        glBegin(GL_QUAD_STRIP);\r
-\r
-            for(j=0; j<=slices; j++)\r
-            {\r
-                glNormal3d(cost[j]*cosn, sint[j]*cosn, sinn);\r
-                glVertex3d(cost[j]*r0,   sint[j]*r0,   z0  );\r
-                glVertex3d(cost[j]*r1,   sint[j]*r1,   z1  );\r
-            }\r
-\r
-            z0 = z1; z1 += zStep;\r
-            r0 = r1; r1 -= rStep;\r
-\r
-        glEnd();\r
-    }\r
-\r
-    /* The top stack is covered with individual triangles */\r
-\r
-    glBegin(GL_TRIANGLES);\r
-\r
-        glNormal3d(cost[0]*sinn, sint[0]*sinn, cosn);\r
-\r
-        for (j=0; j<slices; j++)\r
-        {\r
-            glVertex3d(cost[j+0]*r0,   sint[j+0]*r0,   z0    );\r
-            glVertex3d(0,              0,              height);\r
-            glNormal3d(cost[j+1]*sinn, sint[j+1]*sinn, cosn  );\r
-            glVertex3d(cost[j+1]*r0,   sint[j+1]*r0,   z0    );\r
-        }\r
-\r
-    glEnd();\r
-\r
-    /* Release sin and cos tables */\r
-\r
-    free(sint);\r
-    free(cost);\r
-}\r
-\r
-/*\r
- * Draws a wire cone\r
- */\r
-void FGAPIENTRY glutWireCone( GLdouble base, GLdouble height, GLint slices, GLint stacks)\r
-{\r
-    int i,j;\r
-\r
-    /* Step in z and radius as stacks are drawn. */\r
-\r
-    double z = 0.0;\r
-    double r = base;\r
-\r
-    const double zStep = height / ( ( stacks > 0 ) ? stacks : 1 );\r
-    const double rStep = base / ( ( stacks > 0 ) ? stacks : 1 );\r
-\r
-    /* Scaling factors for vertex normals */\r
-\r
-    const double cosn = ( height / sqrt ( height * height + base * base ));\r
-    const double sinn = ( base   / sqrt ( height * height + base * base ));\r
-\r
-    /* Pre-computed circle */\r
-\r
-    double *sint,*cost;\r
-\r
-    FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutWireCone" );\r
-\r
-    fghCircleTable(&sint,&cost,-slices);\r
-\r
-    /* Draw the stacks... */\r
-\r
-    for (i=0; i<stacks; i++)\r
-    {\r
-        glBegin(GL_LINE_LOOP);\r
-\r
-            for( j=0; j<slices; j++ )\r
-            {\r
-                glNormal3d(cost[j]*sinn, sint[j]*sinn, cosn);\r
-                glVertex3d(cost[j]*r,    sint[j]*r,    z   );\r
-            }\r
-\r
-        glEnd();\r
-\r
-        z += zStep;\r
-        r -= rStep;\r
-    }\r
-\r
-    /* Draw the slices */\r
-\r
-    r = base;\r
-\r
-    glBegin(GL_LINES);\r
-\r
-        for (j=0; j<slices; j++)\r
-        {\r
-            glNormal3d(cost[j]*sinn, sint[j]*sinn, cosn  );\r
-            glVertex3d(cost[j]*r,    sint[j]*r,    0.0   );\r
-            glVertex3d(0.0,          0.0,          height);\r
-        }\r
-\r
-    glEnd();\r
-\r
-    /* Release sin and cos tables */\r
-\r
-    free(sint);\r
-    free(cost);\r
-}\r
-\r
-\r
-/*\r
- * Draws a solid cylinder\r
- */\r
-void FGAPIENTRY glutSolidCylinder(GLdouble radius, GLdouble height, GLint slices, GLint stacks)\r
-{\r
-    int i,j;\r
-\r
-    /* Step in z and radius as stacks are drawn. */\r
-\r
-    double z0,z1;\r
-    const double zStep = height / ( ( stacks > 0 ) ? stacks : 1 );\r
-\r
-    /* Pre-computed circle */\r
-\r
-    double *sint,*cost;\r
-\r
-    FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSolidCylinder" );\r
-\r
-    fghCircleTable(&sint,&cost,-slices);\r
-\r
-    /* Cover the base and top */\r
-\r
-    glBegin(GL_TRIANGLE_FAN);\r
-        glNormal3d(0.0, 0.0, -1.0 );\r
-        glVertex3d(0.0, 0.0,  0.0 );\r
-        for (j=0; j<=slices; j++)\r
-          glVertex3d(cost[j]*radius, sint[j]*radius, 0.0);\r
-    glEnd();\r
-\r
-    glBegin(GL_TRIANGLE_FAN);\r
-        glNormal3d(0.0, 0.0, 1.0   );\r
-        glVertex3d(0.0, 0.0, height);\r
-        for (j=slices; j>=0; j--)\r
-          glVertex3d(cost[j]*radius, sint[j]*radius, height);\r
-    glEnd();\r
-\r
-    /* Do the stacks */\r
-\r
-    z0 = 0.0;\r
-    z1 = zStep;\r
-\r
-    for (i=1; i<=stacks; i++)\r
-    {\r
-        if (i==stacks)\r
-            z1 = height;\r
-\r
-        glBegin(GL_QUAD_STRIP);\r
-            for (j=0; j<=slices; j++ )\r
-            {\r
-                glNormal3d(cost[j],        sint[j],        0.0 );\r
-                glVertex3d(cost[j]*radius, sint[j]*radius, z0  );\r
-                glVertex3d(cost[j]*radius, sint[j]*radius, z1  );\r
-            }\r
-        glEnd();\r
-\r
-        z0 = z1; z1 += zStep;\r
-    }\r
-\r
-    /* Release sin and cos tables */\r
-\r
-    free(sint);\r
-    free(cost);\r
-}\r
-\r
-/*\r
- * Draws a wire cylinder\r
- */\r
-void FGAPIENTRY glutWireCylinder(GLdouble radius, GLdouble height, GLint slices, GLint stacks)\r
-{\r
-    int i,j;\r
-\r
-    /* Step in z and radius as stacks are drawn. */\r
-\r
-          double z = 0.0;\r
-    const double zStep = height / ( ( stacks > 0 ) ? stacks : 1 );\r
-\r
-    /* Pre-computed circle */\r
-\r
-    double *sint,*cost;\r
-\r
-    FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutWireCylinder" );\r
-\r
-    fghCircleTable(&sint,&cost,-slices);\r
-\r
-    /* Draw the stacks... */\r
-\r
-    for (i=0; i<=stacks; i++)\r
-    {\r
-        if (i==stacks)\r
-            z = height;\r
-\r
-        glBegin(GL_LINE_LOOP);\r
-\r
-            for( j=0; j<slices; j++ )\r
-            {\r
-                glNormal3d(cost[j],        sint[j],        0.0);\r
-                glVertex3d(cost[j]*radius, sint[j]*radius, z  );\r
-            }\r
-\r
-        glEnd();\r
-\r
-        z += zStep;\r
-    }\r
-\r
-    /* Draw the slices */\r
-\r
-    glBegin(GL_LINES);\r
-\r
-        for (j=0; j<slices; j++)\r
-        {\r
-            glNormal3d(cost[j],        sint[j],        0.0   );\r
-            glVertex3d(cost[j]*radius, sint[j]*radius, 0.0   );\r
-            glVertex3d(cost[j]*radius, sint[j]*radius, height);\r
-        }\r
-\r
-    glEnd();\r
-\r
-    /* Release sin and cos tables */\r
-\r
-    free(sint);\r
-    free(cost);\r
-}\r
-\r
-/*\r
- * Draws a wire torus\r
- */\r
-void FGAPIENTRY glutWireTorus( GLdouble dInnerRadius, GLdouble dOuterRadius, GLint nSides, GLint nRings )\r
-{\r
-  double  iradius = dInnerRadius, oradius = dOuterRadius, phi, psi, dpsi, dphi;\r
-  double *vertex, *normal;\r
-  int    i, j;\r
-  double spsi, cpsi, sphi, cphi ;\r
-\r
-  FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutWireTorus" );\r
-\r
-  if ( nSides < 1 ) nSides = 1;\r
-  if ( nRings < 1 ) nRings = 1;\r
-\r
-  /* Allocate the vertices array */\r
-  vertex = (double *)calloc( sizeof(double), 3 * nSides * nRings );\r
-  normal = (double *)calloc( sizeof(double), 3 * nSides * nRings );\r
-\r
-  glPushMatrix();\r
-\r
-  dpsi =  2.0 * M_PI / (double)nRings ;\r
-  dphi = -2.0 * M_PI / (double)nSides ;\r
-  psi  = 0.0;\r
-\r
-  for( j=0; j<nRings; j++ )\r
-  {\r
-    cpsi = cos ( psi ) ;\r
-    spsi = sin ( psi ) ;\r
-    phi = 0.0;\r
-\r
-    for( i=0; i<nSides; i++ )\r
-    {\r
-      int offset = 3 * ( j * nSides + i ) ;\r
-      cphi = cos ( phi ) ;\r
-      sphi = sin ( phi ) ;\r
-      *(vertex + offset + 0) = cpsi * ( oradius + cphi * iradius ) ;\r
-      *(vertex + offset + 1) = spsi * ( oradius + cphi * iradius ) ;\r
-      *(vertex + offset + 2) =                    sphi * iradius  ;\r
-      *(normal + offset + 0) = cpsi * cphi ;\r
-      *(normal + offset + 1) = spsi * cphi ;\r
-      *(normal + offset + 2) =        sphi ;\r
-      phi += dphi;\r
-    }\r
-\r
-    psi += dpsi;\r
-  }\r
-\r
-  for( i=0; i<nSides; i++ )\r
-  {\r
-    glBegin( GL_LINE_LOOP );\r
-\r
-    for( j=0; j<nRings; j++ )\r
-    {\r
-      int offset = 3 * ( j * nSides + i ) ;\r
-      glNormal3dv( normal + offset );\r
-      glVertex3dv( vertex + offset );\r
-    }\r
-\r
-    glEnd();\r
-  }\r
-\r
-  for( j=0; j<nRings; j++ )\r
-  {\r
-    glBegin(GL_LINE_LOOP);\r
-\r
-    for( i=0; i<nSides; i++ )\r
-    {\r
-      int offset = 3 * ( j * nSides + i ) ;\r
-      glNormal3dv( normal + offset );\r
-      glVertex3dv( vertex + offset );\r
-    }\r
-\r
-    glEnd();\r
-  }\r
-\r
-  free ( vertex ) ;\r
-  free ( normal ) ;\r
-  glPopMatrix();\r
-}\r
-\r
-/*\r
- * Draws a solid torus\r
- */\r
-void FGAPIENTRY glutSolidTorus( GLdouble dInnerRadius, GLdouble dOuterRadius, GLint nSides, GLint nRings )\r
-{\r
-  double  iradius = dInnerRadius, oradius = dOuterRadius, phi, psi, dpsi, dphi;\r
-  double *vertex, *normal;\r
-  int    i, j;\r
-  double spsi, cpsi, sphi, cphi ;\r
-\r
-  FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSolidTorus" );\r
-\r
-  if ( nSides < 1 ) nSides = 1;\r
-  if ( nRings < 1 ) nRings = 1;\r
-\r
-  /* Increment the number of sides and rings to allow for one more point than surface */\r
-  nSides ++ ;\r
-  nRings ++ ;\r
-\r
-  /* Allocate the vertices array */\r
-  vertex = (double *)calloc( sizeof(double), 3 * nSides * nRings );\r
-  normal = (double *)calloc( sizeof(double), 3 * nSides * nRings );\r
-\r
-  glPushMatrix();\r
-\r
-  dpsi =  2.0 * M_PI / (double)(nRings - 1) ;\r
-  dphi = -2.0 * M_PI / (double)(nSides - 1) ;\r
-  psi  = 0.0;\r
-\r
-  for( j=0; j<nRings; j++ )\r
-  {\r
-    cpsi = cos ( psi ) ;\r
-    spsi = sin ( psi ) ;\r
-    phi = 0.0;\r
-\r
-    for( i=0; i<nSides; i++ )\r
-    {\r
-      int offset = 3 * ( j * nSides + i ) ;\r
-      cphi = cos ( phi ) ;\r
-      sphi = sin ( phi ) ;\r
-      *(vertex + offset + 0) = cpsi * ( oradius + cphi * iradius ) ;\r
-      *(vertex + offset + 1) = spsi * ( oradius + cphi * iradius ) ;\r
-      *(vertex + offset + 2) =                    sphi * iradius  ;\r
-      *(normal + offset + 0) = cpsi * cphi ;\r
-      *(normal + offset + 1) = spsi * cphi ;\r
-      *(normal + offset + 2) =        sphi ;\r
-      phi += dphi;\r
-    }\r
-\r
-    psi += dpsi;\r
-  }\r
-\r
-    glBegin( GL_QUADS );\r
-  for( i=0; i<nSides-1; i++ )\r
-  {\r
-    for( j=0; j<nRings-1; j++ )\r
-    {\r
-      int offset = 3 * ( j * nSides + i ) ;\r
-      glNormal3dv( normal + offset );\r
-      glVertex3dv( vertex + offset );\r
-      glNormal3dv( normal + offset + 3 );\r
-      glVertex3dv( vertex + offset + 3 );\r
-      glNormal3dv( normal + offset + 3 * nSides + 3 );\r
-      glVertex3dv( vertex + offset + 3 * nSides + 3 );\r
-      glNormal3dv( normal + offset + 3 * nSides );\r
-      glVertex3dv( vertex + offset + 3 * nSides );\r
-    }\r
-  }\r
-\r
-  glEnd();\r
-\r
-  free ( vertex ) ;\r
-  free ( normal ) ;\r
-  glPopMatrix();\r
-}\r
-\r
-/*\r
- *\r
- */\r
-void FGAPIENTRY glutWireDodecahedron( void )\r
-{\r
-  FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutWireDodecahedron" );\r
-\r
-  /* Magic Numbers:  It is possible to create a dodecahedron by attaching two pentagons to each face of\r
-   * of a cube.  The coordinates of the points are:\r
-   *   (+-x,0, z); (+-1, 1, 1); (0, z, x )\r
-   * where x = (-1 + sqrt(5))/2, z = (1 + sqrt(5))/2  or\r
-   *       x = 0.61803398875 and z = 1.61803398875.\r
-   */\r
-  glBegin ( GL_LINE_LOOP ) ;\r
-  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 ) ;\r
-  glEnd () ;\r
-  glBegin ( GL_LINE_LOOP ) ;\r
-  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 ) ;\r
-  glEnd () ;\r
-  glBegin ( GL_LINE_LOOP ) ;\r
-  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 ) ;\r
-  glEnd () ;\r
-  glBegin ( GL_LINE_LOOP ) ;\r
-  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 ) ;\r
-  glEnd () ;\r
-\r
-  glBegin ( GL_LINE_LOOP ) ;\r
-  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 ) ;\r
-  glEnd () ;\r
-  glBegin ( GL_LINE_LOOP ) ;\r
-  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 ) ;\r
-  glEnd () ;\r
-  glBegin ( GL_LINE_LOOP ) ;\r
-  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 ) ;\r
-  glEnd () ;\r
-  glBegin ( GL_LINE_LOOP ) ;\r
-  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 ) ;\r
-  glEnd () ;\r
-\r
-  glBegin ( GL_LINE_LOOP ) ;\r
-  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 ) ;\r
-  glEnd () ;\r
-  glBegin ( GL_LINE_LOOP ) ;\r
-  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 ) ;\r
-  glEnd () ;\r
-  glBegin ( GL_LINE_LOOP ) ;\r
-  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 ) ;\r
-  glEnd () ;\r
-  glBegin ( GL_LINE_LOOP ) ;\r
-  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 ) ;\r
-  glEnd () ;\r
-}\r
-\r
-/*\r
- *\r
- */\r
-void FGAPIENTRY glutSolidDodecahedron( void )\r
-{\r
-  FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSolidDodecahedron" );\r
-\r
-  /* Magic Numbers:  It is possible to create a dodecahedron by attaching two pentagons to each face of\r
-   * of a cube.  The coordinates of the points are:\r
-   *   (+-x,0, z); (+-1, 1, 1); (0, z, x )\r
-   * where x = (-1 + sqrt(5))/2, z = (1 + sqrt(5))/2 or\r
-   *       x = 0.61803398875 and z = 1.61803398875.\r
-   */\r
-  glBegin ( GL_POLYGON ) ;\r
-  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 ) ;\r
-  glEnd () ;\r
-  glBegin ( GL_POLYGON ) ;\r
-  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 ) ;\r
-  glEnd () ;\r
-  glBegin ( GL_POLYGON ) ;\r
-  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 ) ;\r
-  glEnd () ;\r
-  glBegin ( GL_POLYGON ) ;\r
-  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 ) ;\r
-  glEnd () ;\r
-\r
-  glBegin ( GL_POLYGON ) ;\r
-  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 ) ;\r
-  glEnd () ;\r
-  glBegin ( GL_POLYGON ) ;\r
-  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 ) ;\r
-  glEnd () ;\r
-  glBegin ( GL_POLYGON ) ;\r
-  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 ) ;\r
-  glEnd () ;\r
-  glBegin ( GL_POLYGON ) ;\r
-  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 ) ;\r
-  glEnd () ;\r
-\r
-  glBegin ( GL_POLYGON ) ;\r
-  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 ) ;\r
-  glEnd () ;\r
-  glBegin ( GL_POLYGON ) ;\r
-  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 ) ;\r
-  glEnd () ;\r
-  glBegin ( GL_POLYGON ) ;\r
-  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 ) ;\r
-  glEnd () ;\r
-  glBegin ( GL_POLYGON ) ;\r
-  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 ) ;\r
-  glEnd () ;\r
-}\r
-\r
-/*\r
- *\r
- */\r
-void FGAPIENTRY glutWireOctahedron( void )\r
-{\r
-  FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutWireOctahedron" );\r
-\r
-#define RADIUS    1.0f\r
-  glBegin( GL_LINE_LOOP );\r
-    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 );\r
-    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 );\r
-    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 );\r
-    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 );\r
-    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 );\r
-    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 );\r
-    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 );\r
-    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 );\r
-  glEnd();\r
-#undef RADIUS\r
-}\r
-\r
-/*\r
- *\r
- */\r
-void FGAPIENTRY glutSolidOctahedron( void )\r
-{\r
-  FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSolidOctahedron" );\r
-\r
-#define RADIUS    1.0f\r
-  glBegin( GL_TRIANGLES );\r
-    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 );\r
-    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 );\r
-    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 );\r
-    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 );\r
-    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 );\r
-    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 );\r
-    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 );\r
-    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 );\r
-  glEnd();\r
-#undef RADIUS\r
-}\r
-\r
-/* Magic Numbers:  r0 = ( 1, 0, 0 )\r
- *                 r1 = ( -1/3, 2 sqrt(2) / 3, 0 )\r
- *                 r2 = ( -1/3, -sqrt(2) / 3, sqrt(6) / 3 )\r
- *                 r3 = ( -1/3, -sqrt(2) / 3, -sqrt(6) / 3 )\r
- * |r0| = |r1| = |r2| = |r3| = 1\r
- * Distance between any two points is 2 sqrt(6) / 3\r
- *\r
- * Normals:  The unit normals are simply the negative of the coordinates of the point not on the surface.\r
- */\r
-\r
-#define NUM_TETR_FACES     4\r
-\r
-static GLdouble tet_r[4][3] = { {             1.0,             0.0,             0.0 },\r
-                                { -0.333333333333,  0.942809041582,             0.0 },\r
-                                { -0.333333333333, -0.471404520791,  0.816496580928 },\r
-                                { -0.333333333333, -0.471404520791, -0.816496580928 } } ;\r
-\r
-static GLint tet_i[4][3] =  /* Vertex indices */\r
-{\r
-  { 1, 3, 2 }, { 0, 2, 3 }, { 0, 3, 1 }, { 0, 1, 2 }\r
-} ;\r
-\r
-/*\r
- *\r
- */\r
-void FGAPIENTRY glutWireTetrahedron( void )\r
-{\r
-  FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutWireTetrahedron" );\r
-\r
-  glBegin( GL_LINE_LOOP ) ;\r
-    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] ) ;\r
-    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] ) ;\r
-    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] ) ;\r
-    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] ) ;\r
-  glEnd() ;\r
-}\r
-\r
-/*\r
- *\r
- */\r
-void FGAPIENTRY glutSolidTetrahedron( void )\r
-{\r
-  FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSolidTetrahedron" );\r
-\r
-  glBegin( GL_TRIANGLES ) ;\r
-    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] ) ;\r
-    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] ) ;\r
-    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] ) ;\r
-    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] ) ;\r
-  glEnd() ;\r
-}\r
-\r
-/*\r
- *\r
- */\r
-static double icos_r[12][3] = {\r
-    {  1.0,             0.0,             0.0            },\r
-    {  0.447213595500,  0.894427191000,  0.0            },\r
-    {  0.447213595500,  0.276393202252,  0.850650808354 },\r
-    {  0.447213595500, -0.723606797748,  0.525731112119 },\r
-    {  0.447213595500, -0.723606797748, -0.525731112119 },\r
-    {  0.447213595500,  0.276393202252, -0.850650808354 },\r
-    { -0.447213595500, -0.894427191000,  0.0 },\r
-    { -0.447213595500, -0.276393202252,  0.850650808354 },\r
-    { -0.447213595500,  0.723606797748,  0.525731112119 },\r
-    { -0.447213595500,  0.723606797748, -0.525731112119 },\r
-    { -0.447213595500, -0.276393202252, -0.850650808354 },\r
-    { -1.0,             0.0,             0.0            }\r
-};\r
-\r
-static int icos_v [20][3] = {\r
-    {  0,  1,  2 },\r
-    {  0,  2,  3 },\r
-    {  0,  3,  4 },\r
-    {  0,  4,  5 },\r
-    {  0,  5,  1 },\r
-    {  1,  8,  2 },\r
-    {  2,  7,  3 },\r
-    {  3,  6,  4 },\r
-    {  4, 10,  5 },\r
-    {  5,  9,  1 },\r
-    {  1,  9,  8 },\r
-    {  2,  8,  7 },\r
-    {  3,  7,  6 },\r
-    {  4,  6, 10 },\r
-    {  5, 10,  9 },\r
-    { 11,  9, 10 },\r
-    { 11,  8,  9 },\r
-    { 11,  7,  8 },\r
-    { 11,  6,  7 },\r
-    { 11, 10,  6 }\r
-};\r
-\r
-void FGAPIENTRY glutWireIcosahedron( void )\r
-{\r
-  int i ;\r
-\r
-  FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutWireIcosahedron" );\r
-\r
-  for ( i = 0; i < 20; i++ )\r
-  {\r
-    double normal[3] ;\r
-    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] ) ;\r
-    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] ) ;\r
-    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] ) ;\r
-    glBegin ( GL_LINE_LOOP ) ;\r
-      glNormal3dv ( normal ) ;\r
-      glVertex3dv ( icos_r[icos_v[i][0]] ) ;\r
-      glVertex3dv ( icos_r[icos_v[i][1]] ) ;\r
-      glVertex3dv ( icos_r[icos_v[i][2]] ) ;\r
-    glEnd () ;\r
-  }\r
-}\r
-\r
-/*\r
- *\r
- */\r
-void FGAPIENTRY glutSolidIcosahedron( void )\r
-{\r
-  int i ;\r
-\r
-  FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSolidIcosahedron" );\r
-\r
-  glBegin ( GL_TRIANGLES ) ;\r
-  for ( i = 0; i < 20; i++ )\r
-  {\r
-    double normal[3] ;\r
-    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] ) ;\r
-    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] ) ;\r
-    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] ) ;\r
-      glNormal3dv ( normal ) ;\r
-      glVertex3dv ( icos_r[icos_v[i][0]] ) ;\r
-      glVertex3dv ( icos_r[icos_v[i][1]] ) ;\r
-      glVertex3dv ( icos_r[icos_v[i][2]] ) ;\r
-  }\r
-\r
-  glEnd () ;\r
-}\r
-\r
-/*\r
- *\r
- */\r
-static double rdod_r[14][3] = {\r
-    {  0.0,             0.0,             1.0 },\r
-    {  0.707106781187,  0.000000000000,  0.5 },\r
-    {  0.000000000000,  0.707106781187,  0.5 },\r
-    { -0.707106781187,  0.000000000000,  0.5 },\r
-    {  0.000000000000, -0.707106781187,  0.5 },\r
-    {  0.707106781187,  0.707106781187,  0.0 },\r
-    { -0.707106781187,  0.707106781187,  0.0 },\r
-    { -0.707106781187, -0.707106781187,  0.0 },\r
-    {  0.707106781187, -0.707106781187,  0.0 },\r
-    {  0.707106781187,  0.000000000000, -0.5 },\r
-    {  0.000000000000,  0.707106781187, -0.5 },\r
-    { -0.707106781187,  0.000000000000, -0.5 },\r
-    {  0.000000000000, -0.707106781187, -0.5 },\r
-    {  0.0,             0.0,            -1.0 }\r
-} ;\r
-\r
-static int rdod_v [12][4] = {\r
-    { 0,  1,  5,  2 },\r
-    { 0,  2,  6,  3 },\r
-    { 0,  3,  7,  4 },\r
-    { 0,  4,  8,  1 },\r
-    { 5, 10,  6,  2 },\r
-    { 6, 11,  7,  3 },\r
-    { 7, 12,  8,  4 },\r
-    { 8,  9,  5,  1 },\r
-    { 5,  9, 13, 10 },\r
-    { 6, 10, 13, 11 },\r
-    { 7, 11, 13, 12 },\r
-    { 8, 12, 13,  9 }\r
-};\r
-\r
-static double rdod_n[12][3] = {\r
-    {  0.353553390594,  0.353553390594,  0.5 },\r
-    { -0.353553390594,  0.353553390594,  0.5 },\r
-    { -0.353553390594, -0.353553390594,  0.5 },\r
-    {  0.353553390594, -0.353553390594,  0.5 },\r
-    {  0.000000000000,  1.000000000000,  0.0 },\r
-    { -1.000000000000,  0.000000000000,  0.0 },\r
-    {  0.000000000000, -1.000000000000,  0.0 },\r
-    {  1.000000000000,  0.000000000000,  0.0 },\r
-    {  0.353553390594,  0.353553390594, -0.5 },\r
-    { -0.353553390594,  0.353553390594, -0.5 },\r
-    { -0.353553390594, -0.353553390594, -0.5 },\r
-    {  0.353553390594, -0.353553390594, -0.5 }\r
-};\r
-\r
-void FGAPIENTRY glutWireRhombicDodecahedron( void )\r
-{\r
-  int i ;\r
-\r
-  FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutWireRhombicDodecahedron" );\r
-\r
-  for ( i = 0; i < 12; i++ )\r
-  {\r
-    glBegin ( GL_LINE_LOOP ) ;\r
-      glNormal3dv ( rdod_n[i] ) ;\r
-      glVertex3dv ( rdod_r[rdod_v[i][0]] ) ;\r
-      glVertex3dv ( rdod_r[rdod_v[i][1]] ) ;\r
-      glVertex3dv ( rdod_r[rdod_v[i][2]] ) ;\r
-      glVertex3dv ( rdod_r[rdod_v[i][3]] ) ;\r
-    glEnd () ;\r
-  }\r
-}\r
-\r
-/*\r
- *\r
- */\r
-void FGAPIENTRY glutSolidRhombicDodecahedron( void )\r
-{\r
-  int i ;\r
-\r
-  FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSolidRhombicDodecahedron" );\r
-\r
-  glBegin ( GL_QUADS ) ;\r
-  for ( i = 0; i < 12; i++ )\r
-  {\r
-      glNormal3dv ( rdod_n[i] ) ;\r
-      glVertex3dv ( rdod_r[rdod_v[i][0]] ) ;\r
-      glVertex3dv ( rdod_r[rdod_v[i][1]] ) ;\r
-      glVertex3dv ( rdod_r[rdod_v[i][2]] ) ;\r
-      glVertex3dv ( rdod_r[rdod_v[i][3]] ) ;\r
-  }\r
-\r
-  glEnd () ;\r
-}\r
-\r
-void FGAPIENTRY glutWireSierpinskiSponge ( int num_levels, GLdouble offset[3], GLdouble scale )\r
-{\r
-  int i, j ;\r
-\r
-  FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutWireSierpinskiSponge" );\r
-\r
-  if ( num_levels == 0 )\r
-  {\r
-\r
-    for ( i = 0 ; i < NUM_TETR_FACES ; i++ )\r
-    {\r
-      glBegin ( GL_LINE_LOOP ) ;\r
-      glNormal3d ( -tet_r[i][0], -tet_r[i][1], -tet_r[i][2] ) ;\r
-      for ( j = 0; j < 3; j++ )\r
-      {\r
-        double x = offset[0] + scale * tet_r[tet_i[i][j]][0] ;\r
-        double y = offset[1] + scale * tet_r[tet_i[i][j]][1] ;\r
-        double z = offset[2] + scale * tet_r[tet_i[i][j]][2] ;\r
-        glVertex3d ( x, y, z ) ;\r
-      }\r
-\r
-      glEnd () ;\r
-    }\r
-  }\r
-  else if ( num_levels > 0 )\r
-  {\r
-    GLdouble local_offset[3] ;  /* Use a local variable to avoid buildup of roundoff errors */\r
-    num_levels -- ;\r
-    scale /= 2.0 ;\r
-    for ( i = 0 ; i < NUM_TETR_FACES ; i++ )\r
-    {\r
-      local_offset[0] = offset[0] + scale * tet_r[i][0] ;\r
-      local_offset[1] = offset[1] + scale * tet_r[i][1] ;\r
-      local_offset[2] = offset[2] + scale * tet_r[i][2] ;\r
-      glutWireSierpinskiSponge ( num_levels, local_offset, scale ) ;\r
-    }\r
-  }\r
-}\r
-\r
-void FGAPIENTRY glutSolidSierpinskiSponge ( int num_levels, GLdouble offset[3], GLdouble scale )\r
-{\r
-  int i, j ;\r
-\r
-  FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSolidSierpinskiSponge" );\r
-\r
-  if ( num_levels == 0 )\r
-  {\r
-    glBegin ( GL_TRIANGLES ) ;\r
-\r
-    for ( i = 0 ; i < NUM_TETR_FACES ; i++ )\r
-    {\r
-      glNormal3d ( -tet_r[i][0], -tet_r[i][1], -tet_r[i][2] ) ;\r
-      for ( j = 0; j < 3; j++ )\r
-      {\r
-        double x = offset[0] + scale * tet_r[tet_i[i][j]][0] ;\r
-        double y = offset[1] + scale * tet_r[tet_i[i][j]][1] ;\r
-        double z = offset[2] + scale * tet_r[tet_i[i][j]][2] ;\r
-        glVertex3d ( x, y, z ) ;\r
-      }\r
-    }\r
-\r
-    glEnd () ;\r
-  }\r
-  else if ( num_levels > 0 )\r
-  {\r
-    GLdouble local_offset[3] ;  /* Use a local variable to avoid buildup of roundoff errors */\r
-    num_levels -- ;\r
-    scale /= 2.0 ;\r
-    for ( i = 0 ; i < NUM_TETR_FACES ; i++ )\r
-    {\r
-      local_offset[0] = offset[0] + scale * tet_r[i][0] ;\r
-      local_offset[1] = offset[1] + scale * tet_r[i][1] ;\r
-      local_offset[2] = offset[2] + scale * tet_r[i][2] ;\r
-      glutSolidSierpinskiSponge ( num_levels, local_offset, scale ) ;\r
-    }\r
-  }\r
-}\r
-\r
-/*** END OF FILE ***/\r
+/*
+ * freeglut_geometry.c
+ *
+ * Freeglut geometry rendering methods.
+ *
+ * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved.
+ * Written by Pawel W. Olszta, <olszta@sourceforge.net>
+ * Creation date: Fri Dec 3 1999
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <GL/freeglut.h>
+#include "freeglut_internal.h"
+
+/*
+ * TODO BEFORE THE STABLE RELEASE:
+ *
+ * Following functions have been contributed by Andreas Umbach.
+ *
+ *      glutWireCube()          -- looks OK
+ *      glutSolidCube()         -- OK
+ *
+ * Those functions have been implemented by John Fay.
+ *
+ *      glutWireTorus()         -- looks OK
+ *      glutSolidTorus()        -- looks OK
+ *      glutWireDodecahedron()  -- looks OK
+ *      glutSolidDodecahedron() -- looks OK
+ *      glutWireOctahedron()    -- looks OK
+ *      glutSolidOctahedron()   -- looks OK
+ *      glutWireTetrahedron()   -- looks OK
+ *      glutSolidTetrahedron()  -- looks OK
+ *      glutWireIcosahedron()   -- looks OK
+ *      glutSolidIcosahedron()  -- looks OK
+ *
+ *  The Following functions have been updated by Nigel Stewart, based
+ *  on FreeGLUT 2.0.0 implementations:
+ *
+ *      glutWireSphere()        -- looks OK
+ *      glutSolidSphere()       -- looks OK
+ *      glutWireCone()          -- looks OK
+ *      glutSolidCone()         -- looks OK
+ */
+
+
+/* -- INTERFACE FUNCTIONS -------------------------------------------------- */
+
+/*
+ * Draws a wireframed cube. Code contributed by Andreas Umbach <marvin@dataway.ch>
+ */
+void FGAPIENTRY glutWireCube( GLdouble dSize )
+{
+    double size = dSize * 0.5;
+
+    FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutWireCube" );
+
+#   define V(a,b,c) glVertex3d( a size, b size, c size );
+#   define N(a,b,c) glNormal3d( a, b, c );
+
+    /* PWO: I dared to convert the code to use macros... */
+    glBegin( GL_LINE_LOOP ); N( 1.0, 0.0, 0.0); V(+,-,+); V(+,-,-); V(+,+,-); V(+,+,+); glEnd();
+    glBegin( GL_LINE_LOOP ); N( 0.0, 1.0, 0.0); V(+,+,+); V(+,+,-); V(-,+,-); V(-,+,+); glEnd();
+    glBegin( GL_LINE_LOOP ); N( 0.0, 0.0, 1.0); V(+,+,+); V(-,+,+); V(-,-,+); V(+,-,+); glEnd();
+    glBegin( GL_LINE_LOOP ); N(-1.0, 0.0, 0.0); V(-,-,+); V(-,+,+); V(-,+,-); V(-,-,-); glEnd();
+    glBegin( GL_LINE_LOOP ); N( 0.0,-1.0, 0.0); V(-,-,+); V(-,-,-); V(+,-,-); V(+,-,+); glEnd();
+    glBegin( GL_LINE_LOOP ); N( 0.0, 0.0,-1.0); V(-,-,-); V(-,+,-); V(+,+,-); V(+,-,-); glEnd();
+
+#   undef V
+#   undef N
+}
+
+/*
+ * Draws a solid cube. Code contributed by Andreas Umbach <marvin@dataway.ch>
+ */
+void FGAPIENTRY glutSolidCube( GLdouble dSize )
+{
+    double size = dSize * 0.5;
+
+    FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSolidCube" );
+
+#   define V(a,b,c) glVertex3d( a size, b size, c size );
+#   define N(a,b,c) glNormal3d( a, b, c );
+
+    /* PWO: Again, I dared to convert the code to use macros... */
+    glBegin( GL_QUADS );
+        N( 1.0, 0.0, 0.0); V(+,-,+); V(+,-,-); V(+,+,-); V(+,+,+);
+        N( 0.0, 1.0, 0.0); V(+,+,+); V(+,+,-); V(-,+,-); V(-,+,+);
+        N( 0.0, 0.0, 1.0); V(+,+,+); V(-,+,+); V(-,-,+); V(+,-,+);
+        N(-1.0, 0.0, 0.0); V(-,-,+); V(-,+,+); V(-,+,-); V(-,-,-);
+        N( 0.0,-1.0, 0.0); V(-,-,+); V(-,-,-); V(+,-,-); V(+,-,+);
+        N( 0.0, 0.0,-1.0); V(-,-,-); V(-,+,-); V(+,+,-); V(+,-,-);
+    glEnd();
+
+#   undef V
+#   undef N
+}
+
+/*
+ * Compute lookup table of cos and sin values forming a cirle
+ *
+ * Notes:
+ *    It is the responsibility of the caller to free these tables
+ *    The size of the table is (n+1) to form a connected loop
+ *    The last entry is exactly the same as the first
+ *    The sign of n can be flipped to get the reverse loop
+ */
+
+static void fghCircleTable(double **sint,double **cost,const int n)
+{
+    int i;
+
+    /* Table size, the sign of n flips the circle direction */
+
+    const int size = abs(n);
+
+    /* Determine the angle between samples */
+
+    const double angle = 2*M_PI/(double)( ( n == 0 ) ? 1 : n );
+
+    /* Allocate memory for n samples, plus duplicate of first entry at the end */
+
+    *sint = (double *) calloc(sizeof(double), size+1);
+    *cost = (double *) calloc(sizeof(double), size+1);
+
+    /* Bail out if memory allocation fails, fgError never returns */
+
+    if (!(*sint) || !(*cost))
+    {
+        free(*sint);
+        free(*cost);
+        fgError("Failed to allocate memory in fghCircleTable");
+    }
+
+    /* Compute cos and sin around the circle */
+
+    (*sint)[0] = 0.0;
+    (*cost)[0] = 1.0;
+
+    for (i=1; i<size; i++)
+    {
+        (*sint)[i] = sin(angle*i);
+        (*cost)[i] = cos(angle*i);
+    }
+
+    /* Last sample is duplicate of the first */
+
+    (*sint)[size] = (*sint)[0];
+    (*cost)[size] = (*cost)[0];
+}
+
+/*
+ * Draws a solid sphere
+ */
+void FGAPIENTRY glutSolidSphere(GLdouble radius, GLint slices, GLint stacks)
+{
+    int i,j;
+
+    /* Adjust z and radius as stacks are drawn. */
+
+    double z0,z1;
+    double r0,r1;
+
+    /* Pre-computed circle */
+
+    double *sint1,*cost1;
+    double *sint2,*cost2;
+
+    FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSolidSphere" );
+
+    fghCircleTable(&sint1,&cost1,-slices);
+    fghCircleTable(&sint2,&cost2,stacks*2);
+
+    /* The top stack is covered with a triangle fan */
+
+    z0 = 1.0;
+    z1 = cost2[(stacks>0)?1:0];
+    r0 = 0.0;
+    r1 = sint2[(stacks>0)?1:0];
+
+    glBegin(GL_TRIANGLE_FAN);
+
+        glNormal3d(0,0,1);
+        glVertex3d(0,0,radius);
+
+        for (j=slices; j>=0; j--)
+        {
+            glNormal3d(cost1[j]*r1,        sint1[j]*r1,        z1       );
+            glVertex3d(cost1[j]*r1*radius, sint1[j]*r1*radius, z1*radius);
+        }
+
+    glEnd();
+
+    /* Cover each stack with a quad strip, except the top and bottom stacks */
+
+    for( i=1; i<stacks-1; i++ )
+    {
+        z0 = z1; z1 = cost2[i+1];
+        r0 = r1; r1 = sint2[i+1];
+
+        glBegin(GL_QUAD_STRIP);
+
+            for(j=0; j<=slices; j++)
+            {
+                glNormal3d(cost1[j]*r1,        sint1[j]*r1,        z1       );
+                glVertex3d(cost1[j]*r1*radius, sint1[j]*r1*radius, z1*radius);
+                glNormal3d(cost1[j]*r0,        sint1[j]*r0,        z0       );
+                glVertex3d(cost1[j]*r0*radius, sint1[j]*r0*radius, z0*radius);
+            }
+
+        glEnd();
+    }
+
+    /* The bottom stack is covered with a triangle fan */
+
+    z0 = z1;
+    r0 = r1;
+
+    glBegin(GL_TRIANGLE_FAN);
+
+        glNormal3d(0,0,-1);
+        glVertex3d(0,0,-radius);
+
+        for (j=0; j<=slices; j++)
+        {
+            glNormal3d(cost1[j]*r0,        sint1[j]*r0,        z0       );
+            glVertex3d(cost1[j]*r0*radius, sint1[j]*r0*radius, z0*radius);
+        }
+
+    glEnd();
+
+    /* Release sin and cos tables */
+
+    free(sint1);
+    free(cost1);
+    free(sint2);
+    free(cost2);
+}
+
+/*
+ * Draws a wire sphere
+ */
+void FGAPIENTRY glutWireSphere(GLdouble radius, GLint slices, GLint stacks)
+{
+    int i,j;
+
+    /* Adjust z and radius as stacks and slices are drawn. */
+
+    double r;
+    double x,y,z;
+
+    /* Pre-computed circle */
+
+    double *sint1,*cost1;
+    double *sint2,*cost2;
+
+    FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutWireSphere" );
+
+    fghCircleTable(&sint1,&cost1,-slices  );
+    fghCircleTable(&sint2,&cost2, stacks*2);
+
+    /* Draw a line loop for each stack */
+
+    for (i=1; i<stacks; i++)
+    {
+        z = cost2[i];
+        r = sint2[i];
+
+        glBegin(GL_LINE_LOOP);
+
+            for(j=0; j<=slices; j++)
+            {
+                x = cost1[j];
+                y = sint1[j];
+
+                glNormal3d(x,y,z);
+                glVertex3d(x*r*radius,y*r*radius,z*radius);
+            }
+
+        glEnd();
+    }
+
+    /* Draw a line loop for each slice */
+
+    for (i=0; i<slices; i++)
+    {
+        glBegin(GL_LINE_STRIP);
+
+            for(j=0; j<=stacks; j++)
+            {
+                x = cost1[i]*sint2[j];
+                y = sint1[i]*sint2[j];
+                z = cost2[j];
+
+                glNormal3d(x,y,z);
+                glVertex3d(x*radius,y*radius,z*radius);
+            }
+
+        glEnd();
+    }
+
+    /* Release sin and cos tables */
+
+    free(sint1);
+    free(cost1);
+    free(sint2);
+    free(cost2);
+}
+
+/*
+ * Draws a solid cone
+ */
+void FGAPIENTRY glutSolidCone( GLdouble base, GLdouble height, GLint slices, GLint stacks )
+{
+    int i,j;
+
+    /* Step in z and radius as stacks are drawn. */
+
+    double z0,z1;
+    double r0,r1;
+
+    const double zStep = height / ( ( stacks > 0 ) ? stacks : 1 );
+    const double rStep = base / ( ( stacks > 0 ) ? stacks : 1 );
+
+    /* Scaling factors for vertex normals */
+
+    const double cosn = ( height / sqrt ( height * height + base * base ));
+    const double sinn = ( base   / sqrt ( height * height + base * base ));
+
+    /* Pre-computed circle */
+
+    double *sint,*cost;
+
+    FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSolidCone" );
+
+    fghCircleTable(&sint,&cost,-slices);
+
+    /* Cover the circular base with a triangle fan... */
+
+    z0 = 0.0;
+    z1 = zStep;
+
+    r0 = base;
+    r1 = r0 - rStep;
+
+    glBegin(GL_TRIANGLE_FAN);
+
+        glNormal3d(0.0,0.0,-1.0);
+        glVertex3d(0.0,0.0, z0 );
+
+        for (j=0; j<=slices; j++)
+            glVertex3d(cost[j]*r0, sint[j]*r0, z0);
+
+    glEnd();
+
+    /* Cover each stack with a quad strip, except the top stack */
+
+    for( i=0; i<stacks-1; i++ )
+    {
+        glBegin(GL_QUAD_STRIP);
+
+            for(j=0; j<=slices; j++)
+            {
+                glNormal3d(cost[j]*cosn, sint[j]*cosn, sinn);
+                glVertex3d(cost[j]*r0,   sint[j]*r0,   z0  );
+                glVertex3d(cost[j]*r1,   sint[j]*r1,   z1  );
+            }
+
+            z0 = z1; z1 += zStep;
+            r0 = r1; r1 -= rStep;
+
+        glEnd();
+    }
+
+    /* The top stack is covered with individual triangles */
+
+    glBegin(GL_TRIANGLES);
+
+        glNormal3d(cost[0]*sinn, sint[0]*sinn, cosn);
+
+        for (j=0; j<slices; j++)
+        {
+            glVertex3d(cost[j+0]*r0,   sint[j+0]*r0,   z0    );
+            glVertex3d(0,              0,              height);
+            glNormal3d(cost[j+1]*sinn, sint[j+1]*sinn, cosn  );
+            glVertex3d(cost[j+1]*r0,   sint[j+1]*r0,   z0    );
+        }
+
+    glEnd();
+
+    /* Release sin and cos tables */
+
+    free(sint);
+    free(cost);
+}
+
+/*
+ * Draws a wire cone
+ */
+void FGAPIENTRY glutWireCone( GLdouble base, GLdouble height, GLint slices, GLint stacks)
+{
+    int i,j;
+
+    /* Step in z and radius as stacks are drawn. */
+
+    double z = 0.0;
+    double r = base;
+
+    const double zStep = height / ( ( stacks > 0 ) ? stacks : 1 );
+    const double rStep = base / ( ( stacks > 0 ) ? stacks : 1 );
+
+    /* Scaling factors for vertex normals */
+
+    const double cosn = ( height / sqrt ( height * height + base * base ));
+    const double sinn = ( base   / sqrt ( height * height + base * base ));
+
+    /* Pre-computed circle */
+
+    double *sint,*cost;
+
+    FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutWireCone" );
+
+    fghCircleTable(&sint,&cost,-slices);
+
+    /* Draw the stacks... */
+
+    for (i=0; i<stacks; i++)
+    {
+        glBegin(GL_LINE_LOOP);
+
+            for( j=0; j<slices; j++ )
+            {
+                glNormal3d(cost[j]*sinn, sint[j]*sinn, cosn);
+                glVertex3d(cost[j]*r,    sint[j]*r,    z   );
+            }
+
+        glEnd();
+
+        z += zStep;
+        r -= rStep;
+    }
+
+    /* Draw the slices */
+
+    r = base;
+
+    glBegin(GL_LINES);
+
+        for (j=0; j<slices; j++)
+        {
+            glNormal3d(cost[j]*sinn, sint[j]*sinn, cosn  );
+            glVertex3d(cost[j]*r,    sint[j]*r,    0.0   );
+            glVertex3d(0.0,          0.0,          height);
+        }
+
+    glEnd();
+
+    /* Release sin and cos tables */
+
+    free(sint);
+    free(cost);
+}
+
+
+/*
+ * Draws a solid cylinder
+ */
+void FGAPIENTRY glutSolidCylinder(GLdouble radius, GLdouble height, GLint slices, GLint stacks)
+{
+    int i,j;
+
+    /* Step in z and radius as stacks are drawn. */
+
+    double z0,z1;
+    const double zStep = height / ( ( stacks > 0 ) ? stacks : 1 );
+
+    /* Pre-computed circle */
+
+    double *sint,*cost;
+
+    FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSolidCylinder" );
+
+    fghCircleTable(&sint,&cost,-slices);
+
+    /* Cover the base and top */
+
+    glBegin(GL_TRIANGLE_FAN);
+        glNormal3d(0.0, 0.0, -1.0 );
+        glVertex3d(0.0, 0.0,  0.0 );
+        for (j=0; j<=slices; j++)
+          glVertex3d(cost[j]*radius, sint[j]*radius, 0.0);
+    glEnd();
+
+    glBegin(GL_TRIANGLE_FAN);
+        glNormal3d(0.0, 0.0, 1.0   );
+        glVertex3d(0.0, 0.0, height);
+        for (j=slices; j>=0; j--)
+          glVertex3d(cost[j]*radius, sint[j]*radius, height);
+    glEnd();
+
+    /* Do the stacks */
+
+    z0 = 0.0;
+    z1 = zStep;
+
+    for (i=1; i<=stacks; i++)
+    {
+        if (i==stacks)
+            z1 = height;
+
+        glBegin(GL_QUAD_STRIP);
+            for (j=0; j<=slices; j++ )
+            {
+                glNormal3d(cost[j],        sint[j],        0.0 );
+                glVertex3d(cost[j]*radius, sint[j]*radius, z0  );
+                glVertex3d(cost[j]*radius, sint[j]*radius, z1  );
+            }
+        glEnd();
+
+        z0 = z1; z1 += zStep;
+    }
+
+    /* Release sin and cos tables */
+
+    free(sint);
+    free(cost);
+}
+
+/*
+ * Draws a wire cylinder
+ */
+void FGAPIENTRY glutWireCylinder(GLdouble radius, GLdouble height, GLint slices, GLint stacks)
+{
+    int i,j;
+
+    /* Step in z and radius as stacks are drawn. */
+
+          double z = 0.0;
+    const double zStep = height / ( ( stacks > 0 ) ? stacks : 1 );
+
+    /* Pre-computed circle */
+
+    double *sint,*cost;
+
+    FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutWireCylinder" );
+
+    fghCircleTable(&sint,&cost,-slices);
+
+    /* Draw the stacks... */
+
+    for (i=0; i<=stacks; i++)
+    {
+        if (i==stacks)
+            z = height;
+
+        glBegin(GL_LINE_LOOP);
+
+            for( j=0; j<slices; j++ )
+            {
+                glNormal3d(cost[j],        sint[j],        0.0);
+                glVertex3d(cost[j]*radius, sint[j]*radius, z  );
+            }
+
+        glEnd();
+
+        z += zStep;
+    }
+
+    /* Draw the slices */
+
+    glBegin(GL_LINES);
+
+        for (j=0; j<slices; j++)
+        {
+            glNormal3d(cost[j],        sint[j],        0.0   );
+            glVertex3d(cost[j]*radius, sint[j]*radius, 0.0   );
+            glVertex3d(cost[j]*radius, sint[j]*radius, height);
+        }
+
+    glEnd();
+
+    /* Release sin and cos tables */
+
+    free(sint);
+    free(cost);
+}
+
+/*
+ * Draws a wire torus
+ */
+void FGAPIENTRY glutWireTorus( GLdouble dInnerRadius, GLdouble dOuterRadius, GLint nSides, GLint nRings )
+{
+  double  iradius = dInnerRadius, oradius = dOuterRadius, phi, psi, dpsi, dphi;
+  double *vertex, *normal;
+  int    i, j;
+  double spsi, cpsi, sphi, cphi ;
+
+  FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutWireTorus" );
+
+  if ( nSides < 1 ) nSides = 1;
+  if ( nRings < 1 ) nRings = 1;
+
+  /* Allocate the vertices array */
+  vertex = (double *)calloc( sizeof(double), 3 * nSides * nRings );
+  normal = (double *)calloc( sizeof(double), 3 * nSides * nRings );
+
+  glPushMatrix();
+
+  dpsi =  2.0 * M_PI / (double)nRings ;
+  dphi = -2.0 * M_PI / (double)nSides ;
+  psi  = 0.0;
+
+  for( j=0; j<nRings; j++ )
+  {
+    cpsi = cos ( psi ) ;
+    spsi = sin ( psi ) ;
+    phi = 0.0;
+
+    for( i=0; i<nSides; i++ )
+    {
+      int offset = 3 * ( j * nSides + i ) ;
+      cphi = cos ( phi ) ;
+      sphi = sin ( phi ) ;
+      *(vertex + offset + 0) = cpsi * ( oradius + cphi * iradius ) ;
+      *(vertex + offset + 1) = spsi * ( oradius + cphi * iradius ) ;
+      *(vertex + offset + 2) =                    sphi * iradius  ;
+      *(normal + offset + 0) = cpsi * cphi ;
+      *(normal + offset + 1) = spsi * cphi ;
+      *(normal + offset + 2) =        sphi ;
+      phi += dphi;
+    }
+
+    psi += dpsi;
+  }
+
+  for( i=0; i<nSides; i++ )
+  {
+    glBegin( GL_LINE_LOOP );
+
+    for( j=0; j<nRings; j++ )
+    {
+      int offset = 3 * ( j * nSides + i ) ;
+      glNormal3dv( normal + offset );
+      glVertex3dv( vertex + offset );
+    }
+
+    glEnd();
+  }
+
+  for( j=0; j<nRings; j++ )
+  {
+    glBegin(GL_LINE_LOOP);
+
+    for( i=0; i<nSides; i++ )
+    {
+      int offset = 3 * ( j * nSides + i ) ;
+      glNormal3dv( normal + offset );
+      glVertex3dv( vertex + offset );
+    }
+
+    glEnd();
+  }
+
+  free ( vertex ) ;
+  free ( normal ) ;
+  glPopMatrix();
+}
+
+/*
+ * Draws a solid torus
+ */
+void FGAPIENTRY glutSolidTorus( GLdouble dInnerRadius, GLdouble dOuterRadius, GLint nSides, GLint nRings )
+{
+  double  iradius = dInnerRadius, oradius = dOuterRadius, phi, psi, dpsi, dphi;
+  double *vertex, *normal;
+  int    i, j;
+  double spsi, cpsi, sphi, cphi ;
+
+  FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSolidTorus" );
+
+  if ( nSides < 1 ) nSides = 1;
+  if ( nRings < 1 ) nRings = 1;
+
+  /* Increment the number of sides and rings to allow for one more point than surface */
+  nSides ++ ;
+  nRings ++ ;
+
+  /* Allocate the vertices array */
+  vertex = (double *)calloc( sizeof(double), 3 * nSides * nRings );
+  normal = (double *)calloc( sizeof(double), 3 * nSides * nRings );
+
+  glPushMatrix();
+
+  dpsi =  2.0 * M_PI / (double)(nRings - 1) ;
+  dphi = -2.0 * M_PI / (double)(nSides - 1) ;
+  psi  = 0.0;
+
+  for( j=0; j<nRings; j++ )
+  {
+    cpsi = cos ( psi ) ;
+    spsi = sin ( psi ) ;
+    phi = 0.0;
+
+    for( i=0; i<nSides; i++ )
+    {
+      int offset = 3 * ( j * nSides + i ) ;
+      cphi = cos ( phi ) ;
+      sphi = sin ( phi ) ;
+      *(vertex + offset + 0) = cpsi * ( oradius + cphi * iradius ) ;
+      *(vertex + offset + 1) = spsi * ( oradius + cphi * iradius ) ;
+      *(vertex + offset + 2) =                    sphi * iradius  ;
+      *(normal + offset + 0) = cpsi * cphi ;
+      *(normal + offset + 1) = spsi * cphi ;
+      *(normal + offset + 2) =        sphi ;
+      phi += dphi;
+    }
+
+    psi += dpsi;
+  }
+
+    glBegin( GL_QUADS );
+  for( i=0; i<nSides-1; i++ )
+  {
+    for( j=0; j<nRings-1; j++ )
+    {
+      int offset = 3 * ( j * nSides + i ) ;
+      glNormal3dv( normal + offset );
+      glVertex3dv( vertex + offset );
+      glNormal3dv( normal + offset + 3 );
+      glVertex3dv( vertex + offset + 3 );
+      glNormal3dv( normal + offset + 3 * nSides + 3 );
+      glVertex3dv( vertex + offset + 3 * nSides + 3 );
+      glNormal3dv( normal + offset + 3 * nSides );
+      glVertex3dv( vertex + offset + 3 * nSides );
+    }
+  }
+
+  glEnd();
+
+  free ( vertex ) ;
+  free ( normal ) ;
+  glPopMatrix();
+}
+
+/*
+ *
+ */
+void FGAPIENTRY glutWireDodecahedron( void )
+{
+  FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutWireDodecahedron" );
+
+  /* Magic Numbers:  It is possible to create a dodecahedron by attaching two pentagons to each face of
+   * of a cube.  The coordinates of the points are:
+   *   (+-x,0, z); (+-1, 1, 1); (0, z, x )
+   * where x = (-1 + sqrt(5))/2, z = (1 + sqrt(5))/2  or
+   *       x = 0.61803398875 and z = 1.61803398875.
+   */
+  glBegin ( GL_LINE_LOOP ) ;
+  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 ) ;
+  glEnd () ;
+  glBegin ( GL_LINE_LOOP ) ;
+  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 ) ;
+  glEnd () ;
+  glBegin ( GL_LINE_LOOP ) ;
+  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 ) ;
+  glEnd () ;
+  glBegin ( GL_LINE_LOOP ) ;
+  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 ) ;
+  glEnd () ;
+
+  glBegin ( GL_LINE_LOOP ) ;
+  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 ) ;
+  glEnd () ;
+  glBegin ( GL_LINE_LOOP ) ;
+  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 ) ;
+  glEnd () ;
+  glBegin ( GL_LINE_LOOP ) ;
+  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 ) ;
+  glEnd () ;
+  glBegin ( GL_LINE_LOOP ) ;
+  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 ) ;
+  glEnd () ;
+
+  glBegin ( GL_LINE_LOOP ) ;
+  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 ) ;
+  glEnd () ;
+  glBegin ( GL_LINE_LOOP ) ;
+  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 ) ;
+  glEnd () ;
+  glBegin ( GL_LINE_LOOP ) ;
+  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 ) ;
+  glEnd () ;
+  glBegin ( GL_LINE_LOOP ) ;
+  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 ) ;
+  glEnd () ;
+}
+
+/*
+ *
+ */
+void FGAPIENTRY glutSolidDodecahedron( void )
+{
+  FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSolidDodecahedron" );
+
+  /* Magic Numbers:  It is possible to create a dodecahedron by attaching two pentagons to each face of
+   * of a cube.  The coordinates of the points are:
+   *   (+-x,0, z); (+-1, 1, 1); (0, z, x )
+   * where x = (-1 + sqrt(5))/2, z = (1 + sqrt(5))/2 or
+   *       x = 0.61803398875 and z = 1.61803398875.
+   */
+  glBegin ( GL_POLYGON ) ;
+  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 ) ;
+  glEnd () ;
+  glBegin ( GL_POLYGON ) ;
+  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 ) ;
+  glEnd () ;
+  glBegin ( GL_POLYGON ) ;
+  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 ) ;
+  glEnd () ;
+  glBegin ( GL_POLYGON ) ;
+  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 ) ;
+  glEnd () ;
+
+  glBegin ( GL_POLYGON ) ;
+  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 ) ;
+  glEnd () ;
+  glBegin ( GL_POLYGON ) ;
+  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 ) ;
+  glEnd () ;
+  glBegin ( GL_POLYGON ) ;
+  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 ) ;
+  glEnd () ;
+  glBegin ( GL_POLYGON ) ;
+  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 ) ;
+  glEnd () ;
+
+  glBegin ( GL_POLYGON ) ;
+  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 ) ;
+  glEnd () ;
+  glBegin ( GL_POLYGON ) ;
+  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 ) ;
+  glEnd () ;
+  glBegin ( GL_POLYGON ) ;
+  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 ) ;
+  glEnd () ;
+  glBegin ( GL_POLYGON ) ;
+  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 ) ;
+  glEnd () ;
+}
+
+/*
+ *
+ */
+void FGAPIENTRY glutWireOctahedron( void )
+{
+  FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutWireOctahedron" );
+
+#define RADIUS    1.0f
+  glBegin( GL_LINE_LOOP );
+    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 );
+    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 );
+    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 );
+    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 );
+    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 );
+    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 );
+    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 );
+    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 );
+  glEnd();
+#undef RADIUS
+}
+
+/*
+ *
+ */
+void FGAPIENTRY glutSolidOctahedron( void )
+{
+  FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSolidOctahedron" );
+
+#define RADIUS    1.0f
+  glBegin( GL_TRIANGLES );
+    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 );
+    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 );
+    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 );
+    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 );
+    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 );
+    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 );
+    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 );
+    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 );
+  glEnd();
+#undef RADIUS
+}
+
+/* Magic Numbers:  r0 = ( 1, 0, 0 )
+ *                 r1 = ( -1/3, 2 sqrt(2) / 3, 0 )
+ *                 r2 = ( -1/3, -sqrt(2) / 3, sqrt(6) / 3 )
+ *                 r3 = ( -1/3, -sqrt(2) / 3, -sqrt(6) / 3 )
+ * |r0| = |r1| = |r2| = |r3| = 1
+ * Distance between any two points is 2 sqrt(6) / 3
+ *
+ * Normals:  The unit normals are simply the negative of the coordinates of the point not on the surface.
+ */
+
+#define NUM_TETR_FACES     4
+
+static GLdouble tet_r[4][3] = { {             1.0,             0.0,             0.0 },
+                                { -0.333333333333,  0.942809041582,             0.0 },
+                                { -0.333333333333, -0.471404520791,  0.816496580928 },
+                                { -0.333333333333, -0.471404520791, -0.816496580928 } } ;
+
+static GLint tet_i[4][3] =  /* Vertex indices */
+{
+  { 1, 3, 2 }, { 0, 2, 3 }, { 0, 3, 1 }, { 0, 1, 2 }
+} ;
+
+/*
+ *
+ */
+void FGAPIENTRY glutWireTetrahedron( void )
+{
+  FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutWireTetrahedron" );
+
+  glBegin( GL_LINE_LOOP ) ;
+    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] ) ;
+    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] ) ;
+    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] ) ;
+    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] ) ;
+  glEnd() ;
+}
+
+/*
+ *
+ */
+void FGAPIENTRY glutSolidTetrahedron( void )
+{
+  FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSolidTetrahedron" );
+
+  glBegin( GL_TRIANGLES ) ;
+    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] ) ;
+    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] ) ;
+    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] ) ;
+    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] ) ;
+  glEnd() ;
+}
+
+/*
+ *
+ */
+static double icos_r[12][3] = {
+    {  1.0,             0.0,             0.0            },
+    {  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 },
+    { -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 },
+    { -1.0,             0.0,             0.0            }
+};
+
+static int icos_v [20][3] = {
+    {  0,  1,  2 },
+    {  0,  2,  3 },
+    {  0,  3,  4 },
+    {  0,  4,  5 },
+    {  0,  5,  1 },
+    {  1,  8,  2 },
+    {  2,  7,  3 },
+    {  3,  6,  4 },
+    {  4, 10,  5 },
+    {  5,  9,  1 },
+    {  1,  9,  8 },
+    {  2,  8,  7 },
+    {  3,  7,  6 },
+    {  4,  6, 10 },
+    {  5, 10,  9 },
+    { 11,  9, 10 },
+    { 11,  8,  9 },
+    { 11,  7,  8 },
+    { 11,  6,  7 },
+    { 11, 10,  6 }
+};
+
+void FGAPIENTRY glutWireIcosahedron( void )
+{
+  int i ;
+
+  FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutWireIcosahedron" );
+
+  for ( i = 0; i < 20; i++ )
+  {
+    double normal[3] ;
+    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] ) ;
+    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] ) ;
+    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] ) ;
+    glBegin ( GL_LINE_LOOP ) ;
+      glNormal3dv ( normal ) ;
+      glVertex3dv ( icos_r[icos_v[i][0]] ) ;
+      glVertex3dv ( icos_r[icos_v[i][1]] ) ;
+      glVertex3dv ( icos_r[icos_v[i][2]] ) ;
+    glEnd () ;
+  }
+}
+
+/*
+ *
+ */
+void FGAPIENTRY glutSolidIcosahedron( void )
+{
+  int i ;
+
+  FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSolidIcosahedron" );
+
+  glBegin ( GL_TRIANGLES ) ;
+  for ( i = 0; i < 20; i++ )
+  {
+    double normal[3] ;
+    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] ) ;
+    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] ) ;
+    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] ) ;
+      glNormal3dv ( normal ) ;
+      glVertex3dv ( icos_r[icos_v[i][0]] ) ;
+      glVertex3dv ( icos_r[icos_v[i][1]] ) ;
+      glVertex3dv ( icos_r[icos_v[i][2]] ) ;
+  }
+
+  glEnd () ;
+}
+
+/*
+ *
+ */
+static double rdod_r[14][3] = {
+    {  0.0,             0.0,             1.0 },
+    {  0.707106781187,  0.000000000000,  0.5 },
+    {  0.000000000000,  0.707106781187,  0.5 },
+    { -0.707106781187,  0.000000000000,  0.5 },
+    {  0.000000000000, -0.707106781187,  0.5 },
+    {  0.707106781187,  0.707106781187,  0.0 },
+    { -0.707106781187,  0.707106781187,  0.0 },
+    { -0.707106781187, -0.707106781187,  0.0 },
+    {  0.707106781187, -0.707106781187,  0.0 },
+    {  0.707106781187,  0.000000000000, -0.5 },
+    {  0.000000000000,  0.707106781187, -0.5 },
+    { -0.707106781187,  0.000000000000, -0.5 },
+    {  0.000000000000, -0.707106781187, -0.5 },
+    {  0.0,             0.0,            -1.0 }
+} ;
+
+static int rdod_v [12][4] = {
+    { 0,  1,  5,  2 },
+    { 0,  2,  6,  3 },
+    { 0,  3,  7,  4 },
+    { 0,  4,  8,  1 },
+    { 5, 10,  6,  2 },
+    { 6, 11,  7,  3 },
+    { 7, 12,  8,  4 },
+    { 8,  9,  5,  1 },
+    { 5,  9, 13, 10 },
+    { 6, 10, 13, 11 },
+    { 7, 11, 13, 12 },
+    { 8, 12, 13,  9 }
+};
+
+static double rdod_n[12][3] = {
+    {  0.353553390594,  0.353553390594,  0.5 },
+    { -0.353553390594,  0.353553390594,  0.5 },
+    { -0.353553390594, -0.353553390594,  0.5 },
+    {  0.353553390594, -0.353553390594,  0.5 },
+    {  0.000000000000,  1.000000000000,  0.0 },
+    { -1.000000000000,  0.000000000000,  0.0 },
+    {  0.000000000000, -1.000000000000,  0.0 },
+    {  1.000000000000,  0.000000000000,  0.0 },
+    {  0.353553390594,  0.353553390594, -0.5 },
+    { -0.353553390594,  0.353553390594, -0.5 },
+    { -0.353553390594, -0.353553390594, -0.5 },
+    {  0.353553390594, -0.353553390594, -0.5 }
+};
+
+void FGAPIENTRY glutWireRhombicDodecahedron( void )
+{
+  int i ;
+
+  FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutWireRhombicDodecahedron" );
+
+  for ( i = 0; i < 12; i++ )
+  {
+    glBegin ( GL_LINE_LOOP ) ;
+      glNormal3dv ( rdod_n[i] ) ;
+      glVertex3dv ( rdod_r[rdod_v[i][0]] ) ;
+      glVertex3dv ( rdod_r[rdod_v[i][1]] ) ;
+      glVertex3dv ( rdod_r[rdod_v[i][2]] ) ;
+      glVertex3dv ( rdod_r[rdod_v[i][3]] ) ;
+    glEnd () ;
+  }
+}
+
+/*
+ *
+ */
+void FGAPIENTRY glutSolidRhombicDodecahedron( void )
+{
+  int i ;
+
+  FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSolidRhombicDodecahedron" );
+
+  glBegin ( GL_QUADS ) ;
+  for ( i = 0; i < 12; i++ )
+  {
+      glNormal3dv ( rdod_n[i] ) ;
+      glVertex3dv ( rdod_r[rdod_v[i][0]] ) ;
+      glVertex3dv ( rdod_r[rdod_v[i][1]] ) ;
+      glVertex3dv ( rdod_r[rdod_v[i][2]] ) ;
+      glVertex3dv ( rdod_r[rdod_v[i][3]] ) ;
+  }
+
+  glEnd () ;
+}
+
+void FGAPIENTRY glutWireSierpinskiSponge ( int num_levels, GLdouble offset[3], GLdouble scale )
+{
+  int i, j ;
+
+  FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutWireSierpinskiSponge" );
+
+  if ( num_levels == 0 )
+  {
+
+    for ( i = 0 ; i < NUM_TETR_FACES ; i++ )
+    {
+      glBegin ( GL_LINE_LOOP ) ;
+      glNormal3d ( -tet_r[i][0], -tet_r[i][1], -tet_r[i][2] ) ;
+      for ( j = 0; j < 3; j++ )
+      {
+        double x = offset[0] + scale * tet_r[tet_i[i][j]][0] ;
+        double y = offset[1] + scale * tet_r[tet_i[i][j]][1] ;
+        double z = offset[2] + scale * tet_r[tet_i[i][j]][2] ;
+        glVertex3d ( x, y, z ) ;
+      }
+
+      glEnd () ;
+    }
+  }
+  else if ( num_levels > 0 )
+  {
+    GLdouble local_offset[3] ;  /* Use a local variable to avoid buildup of roundoff errors */
+    num_levels -- ;
+    scale /= 2.0 ;
+    for ( i = 0 ; i < NUM_TETR_FACES ; i++ )
+    {
+      local_offset[0] = offset[0] + scale * tet_r[i][0] ;
+      local_offset[1] = offset[1] + scale * tet_r[i][1] ;
+      local_offset[2] = offset[2] + scale * tet_r[i][2] ;
+      glutWireSierpinskiSponge ( num_levels, local_offset, scale ) ;
+    }
+  }
+}
+
+void FGAPIENTRY glutSolidSierpinskiSponge ( int num_levels, GLdouble offset[3], GLdouble scale )
+{
+  int i, j ;
+
+  FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSolidSierpinskiSponge" );
+
+  if ( num_levels == 0 )
+  {
+    glBegin ( GL_TRIANGLES ) ;
+
+    for ( i = 0 ; i < NUM_TETR_FACES ; i++ )
+    {
+      glNormal3d ( -tet_r[i][0], -tet_r[i][1], -tet_r[i][2] ) ;
+      for ( j = 0; j < 3; j++ )
+      {
+        double x = offset[0] + scale * tet_r[tet_i[i][j]][0] ;
+        double y = offset[1] + scale * tet_r[tet_i[i][j]][1] ;
+        double z = offset[2] + scale * tet_r[tet_i[i][j]][2] ;
+        glVertex3d ( x, y, z ) ;
+      }
+    }
+
+    glEnd () ;
+  }
+  else if ( num_levels > 0 )
+  {
+    GLdouble local_offset[3] ;  /* Use a local variable to avoid buildup of roundoff errors */
+    num_levels -- ;
+    scale /= 2.0 ;
+    for ( i = 0 ; i < NUM_TETR_FACES ; i++ )
+    {
+      local_offset[0] = offset[0] + scale * tet_r[i][0] ;
+      local_offset[1] = offset[1] + scale * tet_r[i][1] ;
+      local_offset[2] = offset[2] + scale * tet_r[i][2] ;
+      glutSolidSierpinskiSponge ( num_levels, local_offset, scale ) ;
+    }
+  }
+}
+
+/*** END OF FILE ***/