freeglut_geometry.c
上传用户:gb3593
上传日期:2022-01-07
资源大小:3028k
文件大小:40k
源码类别:

游戏引擎

开发平台:

Visual C++

  1. /*
  2.  * freeglut_geometry.c
  3.  *
  4.  * Freeglut geometry rendering methods.
  5.  *
  6.  * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved.
  7.  * Written by Pawel W. Olszta, <olszta@sourceforge.net>
  8.  * Creation date: Fri Dec 3 1999
  9.  *
  10.  * Permission is hereby granted, free of charge, to any person obtaining a
  11.  * copy of this software and associated documentation files (the "Software"),
  12.  * to deal in the Software without restriction, including without limitation
  13.  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  14.  * and/or sell copies of the Software, and to permit persons to whom the
  15.  * Software is furnished to do so, subject to the following conditions:
  16.  *
  17.  * The above copyright notice and this permission notice shall be included
  18.  * in all copies or substantial portions of the Software.
  19.  *
  20.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  21.  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  22.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  23.  * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
  24.  * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  25.  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  26.  */
  27. #include <GL/freeglut.h>
  28. #include "freeglut_internal.h"
  29. /*
  30.  * TODO BEFORE THE STABLE RELEASE:
  31.  *
  32.  * Following functions have been contributed by Andreas Umbach.
  33.  *
  34.  *      glutWireCube()          -- looks OK
  35.  *      glutSolidCube()         -- OK
  36.  *
  37.  * Those functions have been implemented by John Fay.
  38.  *
  39.  *      glutWireTorus()         -- looks OK
  40.  *      glutSolidTorus()        -- looks OK
  41.  *      glutWireDodecahedron()  -- looks OK
  42.  *      glutSolidDodecahedron() -- looks OK
  43.  *      glutWireOctahedron()    -- looks OK
  44.  *      glutSolidOctahedron()   -- looks OK
  45.  *      glutWireTetrahedron()   -- looks OK
  46.  *      glutSolidTetrahedron()  -- looks OK
  47.  *      glutWireIcosahedron()   -- looks OK
  48.  *      glutSolidIcosahedron()  -- looks OK
  49.  *
  50.  *  The Following functions have been updated by Nigel Stewart, based
  51.  *  on FreeGLUT 2.0.0 implementations:
  52.  *
  53.  *      glutWireSphere()        -- looks OK
  54.  *      glutSolidSphere()       -- looks OK
  55.  *      glutWireCone()          -- looks OK
  56.  *      glutSolidCone()         -- looks OK
  57.  */
  58. /* -- INTERFACE FUNCTIONS -------------------------------------------------- */
  59. /*
  60.  * Draws a wireframed cube. Code contributed by Andreas Umbach <marvin@dataway.ch>
  61.  */
  62. void FGAPIENTRY glutWireCube( GLdouble dSize )
  63. {
  64.     double size = dSize * 0.5;
  65.     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutWireCube" );
  66. #   define V(a,b,c) glVertex3d( a size, b size, c size );
  67. #   define N(a,b,c) glNormal3d( a, b, c );
  68.     /* PWO: I dared to convert the code to use macros... */
  69.     glBegin( GL_LINE_LOOP ); N( 1.0, 0.0, 0.0); V(+,-,+); V(+,-,-); V(+,+,-); V(+,+,+); glEnd();
  70.     glBegin( GL_LINE_LOOP ); N( 0.0, 1.0, 0.0); V(+,+,+); V(+,+,-); V(-,+,-); V(-,+,+); glEnd();
  71.     glBegin( GL_LINE_LOOP ); N( 0.0, 0.0, 1.0); V(+,+,+); V(-,+,+); V(-,-,+); V(+,-,+); glEnd();
  72.     glBegin( GL_LINE_LOOP ); N(-1.0, 0.0, 0.0); V(-,-,+); V(-,+,+); V(-,+,-); V(-,-,-); glEnd();
  73.     glBegin( GL_LINE_LOOP ); N( 0.0,-1.0, 0.0); V(-,-,+); V(-,-,-); V(+,-,-); V(+,-,+); glEnd();
  74.     glBegin( GL_LINE_LOOP ); N( 0.0, 0.0,-1.0); V(-,-,-); V(-,+,-); V(+,+,-); V(+,-,-); glEnd();
  75. #   undef V
  76. #   undef N
  77. }
  78. /*
  79.  * Draws a solid cube. Code contributed by Andreas Umbach <marvin@dataway.ch>
  80.  */
  81. void FGAPIENTRY glutSolidCube( GLdouble dSize )
  82. {
  83.     double size = dSize * 0.5;
  84.     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSolidCube" );
  85. #   define V(a,b,c) glVertex3d( a size, b size, c size );
  86. #   define N(a,b,c) glNormal3d( a, b, c );
  87.     /* PWO: Again, I dared to convert the code to use macros... */
  88.     glBegin( GL_QUADS );
  89.         N( 1.0, 0.0, 0.0); V(+,-,+); V(+,-,-); V(+,+,-); V(+,+,+);
  90.         N( 0.0, 1.0, 0.0); V(+,+,+); V(+,+,-); V(-,+,-); V(-,+,+);
  91.         N( 0.0, 0.0, 1.0); V(+,+,+); V(-,+,+); V(-,-,+); V(+,-,+);
  92.         N(-1.0, 0.0, 0.0); V(-,-,+); V(-,+,+); V(-,+,-); V(-,-,-);
  93.         N( 0.0,-1.0, 0.0); V(-,-,+); V(-,-,-); V(+,-,-); V(+,-,+);
  94.         N( 0.0, 0.0,-1.0); V(-,-,-); V(-,+,-); V(+,+,-); V(+,-,-);
  95.     glEnd();
  96. #   undef V
  97. #   undef N
  98. }
  99. /*
  100.  * Compute lookup table of cos and sin values forming a cirle
  101.  *
  102.  * Notes:
  103.  *    It is the responsibility of the caller to free these tables
  104.  *    The size of the table is (n+1) to form a connected loop
  105.  *    The last entry is exactly the same as the first
  106.  *    The sign of n can be flipped to get the reverse loop
  107.  */
  108. static void fghCircleTable(double **sint,double **cost,const int n)
  109. {
  110.     int i;
  111.     /* Table size, the sign of n flips the circle direction */
  112.     const int size = abs(n);
  113.     /* Determine the angle between samples */
  114.     const double angle = 2*M_PI/(double)( ( n == 0 ) ? 1 : n );
  115.     /* Allocate memory for n samples, plus duplicate of first entry at the end */
  116.     *sint = (double *) calloc(sizeof(double), size+1);
  117.     *cost = (double *) calloc(sizeof(double), size+1);
  118.     /* Bail out if memory allocation fails, fgError never returns */
  119.     if (!(*sint) || !(*cost))
  120.     {
  121.         free(*sint);
  122.         free(*cost);
  123.         fgError("Failed to allocate memory in fghCircleTable");
  124.     }
  125.     /* Compute cos and sin around the circle */
  126.     (*sint)[0] = 0.0;
  127.     (*cost)[0] = 1.0;
  128.     for (i=1; i<size; i++)
  129.     {
  130.         (*sint)[i] = sin(angle*i);
  131.         (*cost)[i] = cos(angle*i);
  132.     }
  133.     /* Last sample is duplicate of the first */
  134.     (*sint)[size] = (*sint)[0];
  135.     (*cost)[size] = (*cost)[0];
  136. }
  137. /*
  138.  * Draws a solid sphere
  139.  */
  140. void FGAPIENTRY glutSolidSphere(GLdouble radius, GLint slices, GLint stacks)
  141. {
  142.     int i,j;
  143.     /* Adjust z and radius as stacks are drawn. */
  144.     double z0,z1;
  145.     double r0,r1;
  146.     /* Pre-computed circle */
  147.     double *sint1,*cost1;
  148.     double *sint2,*cost2;
  149.     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSolidSphere" );
  150.     fghCircleTable(&sint1,&cost1,-slices);
  151.     fghCircleTable(&sint2,&cost2,stacks*2);
  152.     /* The top stack is covered with a triangle fan */
  153.     z0 = 1.0;
  154.     z1 = cost2[(stacks>0)?1:0];
  155.     r0 = 0.0;
  156.     r1 = sint2[(stacks>0)?1:0];
  157.     glBegin(GL_TRIANGLE_FAN);
  158.         glNormal3d(0,0,1);
  159.         glVertex3d(0,0,radius);
  160.         for (j=slices; j>=0; j--)
  161.         {
  162.             glNormal3d(cost1[j]*r1,        sint1[j]*r1,        z1       );
  163.             glVertex3d(cost1[j]*r1*radius, sint1[j]*r1*radius, z1*radius);
  164.         }
  165.     glEnd();
  166.     /* Cover each stack with a quad strip, except the top and bottom stacks */
  167.     for( i=1; i<stacks-1; i++ )
  168.     {
  169.         z0 = z1; z1 = cost2[i+1];
  170.         r0 = r1; r1 = sint2[i+1];
  171.         glBegin(GL_QUAD_STRIP);
  172.             for(j=0; j<=slices; j++)
  173.             {
  174.                 glNormal3d(cost1[j]*r1,        sint1[j]*r1,        z1       );
  175.                 glVertex3d(cost1[j]*r1*radius, sint1[j]*r1*radius, z1*radius);
  176.                 glNormal3d(cost1[j]*r0,        sint1[j]*r0,        z0       );
  177.                 glVertex3d(cost1[j]*r0*radius, sint1[j]*r0*radius, z0*radius);
  178.             }
  179.         glEnd();
  180.     }
  181.     /* The bottom stack is covered with a triangle fan */
  182.     z0 = z1;
  183.     r0 = r1;
  184.     glBegin(GL_TRIANGLE_FAN);
  185.         glNormal3d(0,0,-1);
  186.         glVertex3d(0,0,-radius);
  187.         for (j=0; j<=slices; j++)
  188.         {
  189.             glNormal3d(cost1[j]*r0,        sint1[j]*r0,        z0       );
  190.             glVertex3d(cost1[j]*r0*radius, sint1[j]*r0*radius, z0*radius);
  191.         }
  192.     glEnd();
  193.     /* Release sin and cos tables */
  194.     free(sint1);
  195.     free(cost1);
  196.     free(sint2);
  197.     free(cost2);
  198. }
  199. /*
  200.  * Draws a wire sphere
  201.  */
  202. void FGAPIENTRY glutWireSphere(GLdouble radius, GLint slices, GLint stacks)
  203. {
  204.     int i,j;
  205.     /* Adjust z and radius as stacks and slices are drawn. */
  206.     double r;
  207.     double x,y,z;
  208.     /* Pre-computed circle */
  209.     double *sint1,*cost1;
  210.     double *sint2,*cost2;
  211.     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutWireSphere" );
  212.     fghCircleTable(&sint1,&cost1,-slices  );
  213.     fghCircleTable(&sint2,&cost2, stacks*2);
  214.     /* Draw a line loop for each stack */
  215.     for (i=1; i<stacks; i++)
  216.     {
  217.         z = cost2[i];
  218.         r = sint2[i];
  219.         glBegin(GL_LINE_LOOP);
  220.             for(j=0; j<=slices; j++)
  221.             {
  222.                 x = cost1[j];
  223.                 y = sint1[j];
  224.                 glNormal3d(x,y,z);
  225.                 glVertex3d(x*r*radius,y*r*radius,z*radius);
  226.             }
  227.         glEnd();
  228.     }
  229.     /* Draw a line loop for each slice */
  230.     for (i=0; i<slices; i++)
  231.     {
  232.         glBegin(GL_LINE_STRIP);
  233.             for(j=0; j<=stacks; j++)
  234.             {
  235.                 x = cost1[i]*sint2[j];
  236.                 y = sint1[i]*sint2[j];
  237.                 z = cost2[j];
  238.                 glNormal3d(x,y,z);
  239.                 glVertex3d(x*radius,y*radius,z*radius);
  240.             }
  241.         glEnd();
  242.     }
  243.     /* Release sin and cos tables */
  244.     free(sint1);
  245.     free(cost1);
  246.     free(sint2);
  247.     free(cost2);
  248. }
  249. /*
  250.  * Draws a solid cone
  251.  */
  252. void FGAPIENTRY glutSolidCone( GLdouble base, GLdouble height, GLint slices, GLint stacks )
  253. {
  254.     int i,j;
  255.     /* Step in z and radius as stacks are drawn. */
  256.     double z0,z1;
  257.     double r0,r1;
  258.     const double zStep = height / ( ( stacks > 0 ) ? stacks : 1 );
  259.     const double rStep = base / ( ( stacks > 0 ) ? stacks : 1 );
  260.     /* Scaling factors for vertex normals */
  261.     const double cosn = ( height / sqrt ( height * height + base * base ));
  262.     const double sinn = ( base   / sqrt ( height * height + base * base ));
  263.     /* Pre-computed circle */
  264.     double *sint,*cost;
  265.     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSolidCone" );
  266.     fghCircleTable(&sint,&cost,-slices);
  267.     /* Cover the circular base with a triangle fan... */
  268.     z0 = 0.0;
  269.     z1 = zStep;
  270.     r0 = base;
  271.     r1 = r0 - rStep;
  272.     glBegin(GL_TRIANGLE_FAN);
  273.         glNormal3d(0.0,0.0,-1.0);
  274.         glVertex3d(0.0,0.0, z0 );
  275.         for (j=0; j<=slices; j++)
  276.             glVertex3d(cost[j]*r0, sint[j]*r0, z0);
  277.     glEnd();
  278.     /* Cover each stack with a quad strip, except the top stack */
  279.     for( i=0; i<stacks-1; i++ )
  280.     {
  281.         glBegin(GL_QUAD_STRIP);
  282.             for(j=0; j<=slices; j++)
  283.             {
  284.                 glNormal3d(cost[j]*sinn, sint[j]*sinn, cosn);
  285.                 glVertex3d(cost[j]*r0,   sint[j]*r0,   z0  );
  286.                 glVertex3d(cost[j]*r1,   sint[j]*r1,   z1  );
  287.             }
  288.             z0 = z1; z1 += zStep;
  289.             r0 = r1; r1 -= rStep;
  290.         glEnd();
  291.     }
  292.     /* The top stack is covered with individual triangles */
  293.     glBegin(GL_TRIANGLES);
  294.         glNormal3d(cost[0]*sinn, sint[0]*sinn, cosn);
  295.         for (j=0; j<slices; j++)
  296.         {
  297.             glVertex3d(cost[j+0]*r0,   sint[j+0]*r0,   z0    );
  298.             glVertex3d(0,              0,              height);
  299.             glNormal3d(cost[j+1]*sinn, sint[j+1]*sinn, cosn  );
  300.             glVertex3d(cost[j+1]*r0,   sint[j+1]*r0,   z0    );
  301.         }
  302.     glEnd();
  303.     /* Release sin and cos tables */
  304.     free(sint);
  305.     free(cost);
  306. }
  307. /*
  308.  * Draws a wire cone
  309.  */
  310. void FGAPIENTRY glutWireCone( GLdouble base, GLdouble height, GLint slices, GLint stacks)
  311. {
  312.     int i,j;
  313.     /* Step in z and radius as stacks are drawn. */
  314.     double z = 0.0;
  315.     double r = base;
  316.     const double zStep = height / ( ( stacks > 0 ) ? stacks : 1 );
  317.     const double rStep = base / ( ( stacks > 0 ) ? stacks : 1 );
  318.     /* Scaling factors for vertex normals */
  319.     const double cosn = ( height / sqrt ( height * height + base * base ));
  320.     const double sinn = ( base   / sqrt ( height * height + base * base ));
  321.     /* Pre-computed circle */
  322.     double *sint,*cost;
  323.     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutWireCone" );
  324.     fghCircleTable(&sint,&cost,-slices);
  325.     /* Draw the stacks... */
  326.     for (i=0; i<stacks; i++)
  327.     {
  328.         glBegin(GL_LINE_LOOP);
  329.             for( j=0; j<slices; j++ )
  330.             {
  331.                 glNormal3d(cost[j]*sinn, sint[j]*sinn, cosn);
  332.                 glVertex3d(cost[j]*r,    sint[j]*r,    z   );
  333.             }
  334.         glEnd();
  335.         z += zStep;
  336.         r -= rStep;
  337.     }
  338.     /* Draw the slices */
  339.     r = base;
  340.     glBegin(GL_LINES);
  341.         for (j=0; j<slices; j++)
  342.         {
  343.             glNormal3d(cost[j]*sinn, sint[j]*sinn, cosn  );
  344.             glVertex3d(cost[j]*r,    sint[j]*r,    0.0   );
  345.             glVertex3d(0.0,          0.0,          height);
  346.         }
  347.     glEnd();
  348.     /* Release sin and cos tables */
  349.     free(sint);
  350.     free(cost);
  351. }
  352. /*
  353.  * Draws a solid cylinder
  354.  */
  355. void FGAPIENTRY glutSolidCylinder(GLdouble radius, GLdouble height, GLint slices, GLint stacks)
  356. {
  357.     int i,j;
  358.     /* Step in z and radius as stacks are drawn. */
  359.     double z0,z1;
  360.     const double zStep = height / ( ( stacks > 0 ) ? stacks : 1 );
  361.     /* Pre-computed circle */
  362.     double *sint,*cost;
  363.     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSolidCylinder" );
  364.     fghCircleTable(&sint,&cost,-slices);
  365.     /* Cover the base and top */
  366.     glBegin(GL_TRIANGLE_FAN);
  367.         glNormal3d(0.0, 0.0, -1.0 );
  368.         glVertex3d(0.0, 0.0,  0.0 );
  369.         for (j=0; j<=slices; j++)
  370.           glVertex3d(cost[j]*radius, sint[j]*radius, 0.0);
  371.     glEnd();
  372.     glBegin(GL_TRIANGLE_FAN);
  373.         glNormal3d(0.0, 0.0, 1.0   );
  374.         glVertex3d(0.0, 0.0, height);
  375.         for (j=slices; j>=0; j--)
  376.           glVertex3d(cost[j]*radius, sint[j]*radius, height);
  377.     glEnd();
  378.     /* Do the stacks */
  379.     z0 = 0.0;
  380.     z1 = zStep;
  381.     for (i=1; i<=stacks; i++)
  382.     {
  383.         if (i==stacks)
  384.             z1 = height;
  385.         glBegin(GL_QUAD_STRIP);
  386.             for (j=0; j<=slices; j++ )
  387.             {
  388.                 glNormal3d(cost[j],        sint[j],        0.0 );
  389.                 glVertex3d(cost[j]*radius, sint[j]*radius, z0  );
  390.                 glVertex3d(cost[j]*radius, sint[j]*radius, z1  );
  391.             }
  392.         glEnd();
  393.         z0 = z1; z1 += zStep;
  394.     }
  395.     /* Release sin and cos tables */
  396.     free(sint);
  397.     free(cost);
  398. }
  399. /*
  400.  * Draws a wire cylinder
  401.  */
  402. void FGAPIENTRY glutWireCylinder(GLdouble radius, GLdouble height, GLint slices, GLint stacks)
  403. {
  404.     int i,j;
  405.     /* Step in z and radius as stacks are drawn. */
  406.           double z = 0.0;
  407.     const double zStep = height / ( ( stacks > 0 ) ? stacks : 1 );
  408.     /* Pre-computed circle */
  409.     double *sint,*cost;
  410.     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutWireCylinder" );
  411.     fghCircleTable(&sint,&cost,-slices);
  412.     /* Draw the stacks... */
  413.     for (i=0; i<=stacks; i++)
  414.     {
  415.         if (i==stacks)
  416.             z = height;
  417.         glBegin(GL_LINE_LOOP);
  418.             for( j=0; j<slices; j++ )
  419.             {
  420.                 glNormal3d(cost[j],        sint[j],        0.0);
  421.                 glVertex3d(cost[j]*radius, sint[j]*radius, z  );
  422.             }
  423.         glEnd();
  424.         z += zStep;
  425.     }
  426.     /* Draw the slices */
  427.     glBegin(GL_LINES);
  428.         for (j=0; j<slices; j++)
  429.         {
  430.             glNormal3d(cost[j],        sint[j],        0.0   );
  431.             glVertex3d(cost[j]*radius, sint[j]*radius, 0.0   );
  432.             glVertex3d(cost[j]*radius, sint[j]*radius, height);
  433.         }
  434.     glEnd();
  435.     /* Release sin and cos tables */
  436.     free(sint);
  437.     free(cost);
  438. }
  439. /*
  440.  * Draws a wire torus
  441.  */
  442. void FGAPIENTRY glutWireTorus( GLdouble dInnerRadius, GLdouble dOuterRadius, GLint nSides, GLint nRings )
  443. {
  444.   double  iradius = dInnerRadius, oradius = dOuterRadius, phi, psi, dpsi, dphi;
  445.   double *vertex, *normal;
  446.   int    i, j;
  447.   double spsi, cpsi, sphi, cphi ;
  448.   FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutWireTorus" );
  449.   if ( nSides < 1 ) nSides = 1;
  450.   if ( nRings < 1 ) nRings = 1;
  451.   /* Allocate the vertices array */
  452.   vertex = (double *)calloc( sizeof(double), 3 * nSides * nRings );
  453.   normal = (double *)calloc( sizeof(double), 3 * nSides * nRings );
  454.   glPushMatrix();
  455.   dpsi =  2.0 * M_PI / (double)nRings ;
  456.   dphi = -2.0 * M_PI / (double)nSides ;
  457.   psi  = 0.0;
  458.   for( j=0; j<nRings; j++ )
  459.   {
  460.     cpsi = cos ( psi ) ;
  461.     spsi = sin ( psi ) ;
  462.     phi = 0.0;
  463.     for( i=0; i<nSides; i++ )
  464.     {
  465.       int offset = 3 * ( j * nSides + i ) ;
  466.       cphi = cos ( phi ) ;
  467.       sphi = sin ( phi ) ;
  468.       *(vertex + offset + 0) = cpsi * ( oradius + cphi * iradius ) ;
  469.       *(vertex + offset + 1) = spsi * ( oradius + cphi * iradius ) ;
  470.       *(vertex + offset + 2) =                    sphi * iradius  ;
  471.       *(normal + offset + 0) = cpsi * cphi ;
  472.       *(normal + offset + 1) = spsi * cphi ;
  473.       *(normal + offset + 2) =        sphi ;
  474.       phi += dphi;
  475.     }
  476.     psi += dpsi;
  477.   }
  478.   for( i=0; i<nSides; i++ )
  479.   {
  480.     glBegin( GL_LINE_LOOP );
  481.     for( j=0; j<nRings; j++ )
  482.     {
  483.       int offset = 3 * ( j * nSides + i ) ;
  484.       glNormal3dv( normal + offset );
  485.       glVertex3dv( vertex + offset );
  486.     }
  487.     glEnd();
  488.   }
  489.   for( j=0; j<nRings; j++ )
  490.   {
  491.     glBegin(GL_LINE_LOOP);
  492.     for( i=0; i<nSides; i++ )
  493.     {
  494.       int offset = 3 * ( j * nSides + i ) ;
  495.       glNormal3dv( normal + offset );
  496.       glVertex3dv( vertex + offset );
  497.     }
  498.     glEnd();
  499.   }
  500.   free ( vertex ) ;
  501.   free ( normal ) ;
  502.   glPopMatrix();
  503. }
  504. /*
  505.  * Draws a solid torus
  506.  */
  507. void FGAPIENTRY glutSolidTorus( GLdouble dInnerRadius, GLdouble dOuterRadius, GLint nSides, GLint nRings )
  508. {
  509.   double  iradius = dInnerRadius, oradius = dOuterRadius, phi, psi, dpsi, dphi;
  510.   double *vertex, *normal;
  511.   int    i, j;
  512.   double spsi, cpsi, sphi, cphi ;
  513.   FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSolidTorus" );
  514.   if ( nSides < 1 ) nSides = 1;
  515.   if ( nRings < 1 ) nRings = 1;
  516.   /* Increment the number of sides and rings to allow for one more point than surface */
  517.   nSides ++ ;
  518.   nRings ++ ;
  519.   /* Allocate the vertices array */
  520.   vertex = (double *)calloc( sizeof(double), 3 * nSides * nRings );
  521.   normal = (double *)calloc( sizeof(double), 3 * nSides * nRings );
  522.   glPushMatrix();
  523.   dpsi =  2.0 * M_PI / (double)(nRings - 1) ;
  524.   dphi = -2.0 * M_PI / (double)(nSides - 1) ;
  525.   psi  = 0.0;
  526.   for( j=0; j<nRings; j++ )
  527.   {
  528.     cpsi = cos ( psi ) ;
  529.     spsi = sin ( psi ) ;
  530.     phi = 0.0;
  531.     for( i=0; i<nSides; i++ )
  532.     {
  533.       int offset = 3 * ( j * nSides + i ) ;
  534.       cphi = cos ( phi ) ;
  535.       sphi = sin ( phi ) ;
  536.       *(vertex + offset + 0) = cpsi * ( oradius + cphi * iradius ) ;
  537.       *(vertex + offset + 1) = spsi * ( oradius + cphi * iradius ) ;
  538.       *(vertex + offset + 2) =                    sphi * iradius  ;
  539.       *(normal + offset + 0) = cpsi * cphi ;
  540.       *(normal + offset + 1) = spsi * cphi ;
  541.       *(normal + offset + 2) =        sphi ;
  542.       phi += dphi;
  543.     }
  544.     psi += dpsi;
  545.   }
  546.     glBegin( GL_QUADS );
  547.   for( i=0; i<nSides-1; i++ )
  548.   {
  549.     for( j=0; j<nRings-1; j++ )
  550.     {
  551.       int offset = 3 * ( j * nSides + i ) ;
  552.       glNormal3dv( normal + offset );
  553.       glVertex3dv( vertex + offset );
  554.       glNormal3dv( normal + offset + 3 );
  555.       glVertex3dv( vertex + offset + 3 );
  556.       glNormal3dv( normal + offset + 3 * nSides + 3 );
  557.       glVertex3dv( vertex + offset + 3 * nSides + 3 );
  558.       glNormal3dv( normal + offset + 3 * nSides );
  559.       glVertex3dv( vertex + offset + 3 * nSides );
  560.     }
  561.   }
  562.   glEnd();
  563.   free ( vertex ) ;
  564.   free ( normal ) ;
  565.   glPopMatrix();
  566. }
  567. /*
  568.  *
  569.  */
  570. void FGAPIENTRY glutWireDodecahedron( void )
  571. {
  572.   FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutWireDodecahedron" );
  573.   /* Magic Numbers:  It is possible to create a dodecahedron by attaching two pentagons to each face of
  574.    * of a cube.  The coordinates of the points are:
  575.    *   (+-x,0, z); (+-1, 1, 1); (0, z, x )
  576.    * where x = (-1 + sqrt(5))/2, z = (1 + sqrt(5))/2  or
  577.    *       x = 0.61803398875 and z = 1.61803398875.
  578.    */
  579.   glBegin ( GL_LINE_LOOP ) ;
  580.   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 ) ;
  581.   glEnd () ;
  582.   glBegin ( GL_LINE_LOOP ) ;
  583.   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 ) ;
  584.   glEnd () ;
  585.   glBegin ( GL_LINE_LOOP ) ;
  586.   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 ) ;
  587.   glEnd () ;
  588.   glBegin ( GL_LINE_LOOP ) ;
  589.   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 ) ;
  590.   glEnd () ;
  591.   glBegin ( GL_LINE_LOOP ) ;
  592.   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 ) ;
  593.   glEnd () ;
  594.   glBegin ( GL_LINE_LOOP ) ;
  595.   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 ) ;
  596.   glEnd () ;
  597.   glBegin ( GL_LINE_LOOP ) ;
  598.   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 ) ;
  599.   glEnd () ;
  600.   glBegin ( GL_LINE_LOOP ) ;
  601.   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 ) ;
  602.   glEnd () ;
  603.   glBegin ( GL_LINE_LOOP ) ;
  604.   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 ) ;
  605.   glEnd () ;
  606.   glBegin ( GL_LINE_LOOP ) ;
  607.   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 ) ;
  608.   glEnd () ;
  609.   glBegin ( GL_LINE_LOOP ) ;
  610.   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 ) ;
  611.   glEnd () ;
  612.   glBegin ( GL_LINE_LOOP ) ;
  613.   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 ) ;
  614.   glEnd () ;
  615. }
  616. /*
  617.  *
  618.  */
  619. void FGAPIENTRY glutSolidDodecahedron( void )
  620. {
  621.   FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSolidDodecahedron" );
  622.   /* Magic Numbers:  It is possible to create a dodecahedron by attaching two pentagons to each face of
  623.    * of a cube.  The coordinates of the points are:
  624.    *   (+-x,0, z); (+-1, 1, 1); (0, z, x )
  625.    * where x = (-1 + sqrt(5))/2, z = (1 + sqrt(5))/2 or
  626.    *       x = 0.61803398875 and z = 1.61803398875.
  627.    */
  628.   glBegin ( GL_POLYGON ) ;
  629.   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 ) ;
  630.   glEnd () ;
  631.   glBegin ( GL_POLYGON ) ;
  632.   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 ) ;
  633.   glEnd () ;
  634.   glBegin ( GL_POLYGON ) ;
  635.   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 ) ;
  636.   glEnd () ;
  637.   glBegin ( GL_POLYGON ) ;
  638.   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 ) ;
  639.   glEnd () ;
  640.   glBegin ( GL_POLYGON ) ;
  641.   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 ) ;
  642.   glEnd () ;
  643.   glBegin ( GL_POLYGON ) ;
  644.   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 ) ;
  645.   glEnd () ;
  646.   glBegin ( GL_POLYGON ) ;
  647.   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 ) ;
  648.   glEnd () ;
  649.   glBegin ( GL_POLYGON ) ;
  650.   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 ) ;
  651.   glEnd () ;
  652.   glBegin ( GL_POLYGON ) ;
  653.   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 ) ;
  654.   glEnd () ;
  655.   glBegin ( GL_POLYGON ) ;
  656.   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 ) ;
  657.   glEnd () ;
  658.   glBegin ( GL_POLYGON ) ;
  659.   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 ) ;
  660.   glEnd () ;
  661.   glBegin ( GL_POLYGON ) ;
  662.   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 ) ;
  663.   glEnd () ;
  664. }
  665. /*
  666.  *
  667.  */
  668. void FGAPIENTRY glutWireOctahedron( void )
  669. {
  670.   FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutWireOctahedron" );
  671. #define RADIUS    1.0f
  672.   glBegin( GL_LINE_LOOP );
  673.     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 );
  674.     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 );
  675.     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 );
  676.     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 );
  677.     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 );
  678.     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 );
  679.     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 );
  680.     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 );
  681.   glEnd();
  682. #undef RADIUS
  683. }
  684. /*
  685.  *
  686.  */
  687. void FGAPIENTRY glutSolidOctahedron( void )
  688. {
  689.   FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSolidOctahedron" );
  690. #define RADIUS    1.0f
  691.   glBegin( GL_TRIANGLES );
  692.     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 );
  693.     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 );
  694.     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 );
  695.     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 );
  696.     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 );
  697.     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 );
  698.     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 );
  699.     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 );
  700.   glEnd();
  701. #undef RADIUS
  702. }
  703. /* Magic Numbers:  r0 = ( 1, 0, 0 )
  704.  *                 r1 = ( -1/3, 2 sqrt(2) / 3, 0 )
  705.  *                 r2 = ( -1/3, -sqrt(2) / 3, sqrt(6) / 3 )
  706.  *                 r3 = ( -1/3, -sqrt(2) / 3, -sqrt(6) / 3 )
  707.  * |r0| = |r1| = |r2| = |r3| = 1
  708.  * Distance between any two points is 2 sqrt(6) / 3
  709.  *
  710.  * Normals:  The unit normals are simply the negative of the coordinates of the point not on the surface.
  711.  */
  712. #define NUM_TETR_FACES     4
  713. static GLdouble tet_r[4][3] = { {             1.0,             0.0,             0.0 },
  714.                                 { -0.333333333333,  0.942809041582,             0.0 },
  715.                                 { -0.333333333333, -0.471404520791,  0.816496580928 },
  716.                                 { -0.333333333333, -0.471404520791, -0.816496580928 } } ;
  717. static GLint tet_i[4][3] =  /* Vertex indices */
  718. {
  719.   { 1, 3, 2 }, { 0, 2, 3 }, { 0, 3, 1 }, { 0, 1, 2 }
  720. } ;
  721. /*
  722.  *
  723.  */
  724. void FGAPIENTRY glutWireTetrahedron( void )
  725. {
  726.   FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutWireTetrahedron" );
  727.   glBegin( GL_LINE_LOOP ) ;
  728.     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] ) ;
  729.     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] ) ;
  730.     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] ) ;
  731.     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] ) ;
  732.   glEnd() ;
  733. }
  734. /*
  735.  *
  736.  */
  737. void FGAPIENTRY glutSolidTetrahedron( void )
  738. {
  739.   FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSolidTetrahedron" );
  740.   glBegin( GL_TRIANGLES ) ;
  741.     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] ) ;
  742.     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] ) ;
  743.     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] ) ;
  744.     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] ) ;
  745.   glEnd() ;
  746. }
  747. /*
  748.  *
  749.  */
  750. static double icos_r[12][3] = {
  751.     {  1.0,             0.0,             0.0            },
  752.     {  0.447213595500,  0.894427191000,  0.0            },
  753.     {  0.447213595500,  0.276393202252,  0.850650808354 },
  754.     {  0.447213595500, -0.723606797748,  0.525731112119 },
  755.     {  0.447213595500, -0.723606797748, -0.525731112119 },
  756.     {  0.447213595500,  0.276393202252, -0.850650808354 },
  757.     { -0.447213595500, -0.894427191000,  0.0 },
  758.     { -0.447213595500, -0.276393202252,  0.850650808354 },
  759.     { -0.447213595500,  0.723606797748,  0.525731112119 },
  760.     { -0.447213595500,  0.723606797748, -0.525731112119 },
  761.     { -0.447213595500, -0.276393202252, -0.850650808354 },
  762.     { -1.0,             0.0,             0.0            }
  763. };
  764. static int icos_v [20][3] = {
  765.     {  0,  1,  2 },
  766.     {  0,  2,  3 },
  767.     {  0,  3,  4 },
  768.     {  0,  4,  5 },
  769.     {  0,  5,  1 },
  770.     {  1,  8,  2 },
  771.     {  2,  7,  3 },
  772.     {  3,  6,  4 },
  773.     {  4, 10,  5 },
  774.     {  5,  9,  1 },
  775.     {  1,  9,  8 },
  776.     {  2,  8,  7 },
  777.     {  3,  7,  6 },
  778.     {  4,  6, 10 },
  779.     {  5, 10,  9 },
  780.     { 11,  9, 10 },
  781.     { 11,  8,  9 },
  782.     { 11,  7,  8 },
  783.     { 11,  6,  7 },
  784.     { 11, 10,  6 }
  785. };
  786. void FGAPIENTRY glutWireIcosahedron( void )
  787. {
  788.   int i ;
  789.   FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutWireIcosahedron" );
  790.   for ( i = 0; i < 20; i++ )
  791.   {
  792.     double normal[3] ;
  793.     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] ) ;
  794.     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] ) ;
  795.     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] ) ;
  796.     glBegin ( GL_LINE_LOOP ) ;
  797.       glNormal3dv ( normal ) ;
  798.       glVertex3dv ( icos_r[icos_v[i][0]] ) ;
  799.       glVertex3dv ( icos_r[icos_v[i][1]] ) ;
  800.       glVertex3dv ( icos_r[icos_v[i][2]] ) ;
  801.     glEnd () ;
  802.   }
  803. }
  804. /*
  805.  *
  806.  */
  807. void FGAPIENTRY glutSolidIcosahedron( void )
  808. {
  809.   int i ;
  810.   FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSolidIcosahedron" );
  811.   glBegin ( GL_TRIANGLES ) ;
  812.   for ( i = 0; i < 20; i++ )
  813.   {
  814.     double normal[3] ;
  815.     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] ) ;
  816.     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] ) ;
  817.     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] ) ;
  818.       glNormal3dv ( normal ) ;
  819.       glVertex3dv ( icos_r[icos_v[i][0]] ) ;
  820.       glVertex3dv ( icos_r[icos_v[i][1]] ) ;
  821.       glVertex3dv ( icos_r[icos_v[i][2]] ) ;
  822.   }
  823.   glEnd () ;
  824. }
  825. /*
  826.  *
  827.  */
  828. static double rdod_r[14][3] = {
  829.     {  0.0,             0.0,             1.0 },
  830.     {  0.707106781187,  0.000000000000,  0.5 },
  831.     {  0.000000000000,  0.707106781187,  0.5 },
  832.     { -0.707106781187,  0.000000000000,  0.5 },
  833.     {  0.000000000000, -0.707106781187,  0.5 },
  834.     {  0.707106781187,  0.707106781187,  0.0 },
  835.     { -0.707106781187,  0.707106781187,  0.0 },
  836.     { -0.707106781187, -0.707106781187,  0.0 },
  837.     {  0.707106781187, -0.707106781187,  0.0 },
  838.     {  0.707106781187,  0.000000000000, -0.5 },
  839.     {  0.000000000000,  0.707106781187, -0.5 },
  840.     { -0.707106781187,  0.000000000000, -0.5 },
  841.     {  0.000000000000, -0.707106781187, -0.5 },
  842.     {  0.0,             0.0,            -1.0 }
  843. } ;
  844. static int rdod_v [12][4] = {
  845.     { 0,  1,  5,  2 },
  846.     { 0,  2,  6,  3 },
  847.     { 0,  3,  7,  4 },
  848.     { 0,  4,  8,  1 },
  849.     { 5, 10,  6,  2 },
  850.     { 6, 11,  7,  3 },
  851.     { 7, 12,  8,  4 },
  852.     { 8,  9,  5,  1 },
  853.     { 5,  9, 13, 10 },
  854.     { 6, 10, 13, 11 },
  855.     { 7, 11, 13, 12 },
  856.     { 8, 12, 13,  9 }
  857. };
  858. static double rdod_n[12][3] = {
  859.     {  0.353553390594,  0.353553390594,  0.5 },
  860.     { -0.353553390594,  0.353553390594,  0.5 },
  861.     { -0.353553390594, -0.353553390594,  0.5 },
  862.     {  0.353553390594, -0.353553390594,  0.5 },
  863.     {  0.000000000000,  1.000000000000,  0.0 },
  864.     { -1.000000000000,  0.000000000000,  0.0 },
  865.     {  0.000000000000, -1.000000000000,  0.0 },
  866.     {  1.000000000000,  0.000000000000,  0.0 },
  867.     {  0.353553390594,  0.353553390594, -0.5 },
  868.     { -0.353553390594,  0.353553390594, -0.5 },
  869.     { -0.353553390594, -0.353553390594, -0.5 },
  870.     {  0.353553390594, -0.353553390594, -0.5 }
  871. };
  872. void FGAPIENTRY glutWireRhombicDodecahedron( void )
  873. {
  874.   int i ;
  875.   FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutWireRhombicDodecahedron" );
  876.   for ( i = 0; i < 12; i++ )
  877.   {
  878.     glBegin ( GL_LINE_LOOP ) ;
  879.       glNormal3dv ( rdod_n[i] ) ;
  880.       glVertex3dv ( rdod_r[rdod_v[i][0]] ) ;
  881.       glVertex3dv ( rdod_r[rdod_v[i][1]] ) ;
  882.       glVertex3dv ( rdod_r[rdod_v[i][2]] ) ;
  883.       glVertex3dv ( rdod_r[rdod_v[i][3]] ) ;
  884.     glEnd () ;
  885.   }
  886. }
  887. /*
  888.  *
  889.  */
  890. void FGAPIENTRY glutSolidRhombicDodecahedron( void )
  891. {
  892.   int i ;
  893.   FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSolidRhombicDodecahedron" );
  894.   glBegin ( GL_QUADS ) ;
  895.   for ( i = 0; i < 12; i++ )
  896.   {
  897.       glNormal3dv ( rdod_n[i] ) ;
  898.       glVertex3dv ( rdod_r[rdod_v[i][0]] ) ;
  899.       glVertex3dv ( rdod_r[rdod_v[i][1]] ) ;
  900.       glVertex3dv ( rdod_r[rdod_v[i][2]] ) ;
  901.       glVertex3dv ( rdod_r[rdod_v[i][3]] ) ;
  902.   }
  903.   glEnd () ;
  904. }
  905. void FGAPIENTRY glutWireSierpinskiSponge ( int num_levels, GLdouble offset[3], GLdouble scale )
  906. {
  907.   int i, j ;
  908.   FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutWireSierpinskiSponge" );
  909.   if ( num_levels == 0 )
  910.   {
  911.     for ( i = 0 ; i < NUM_TETR_FACES ; i++ )
  912.     {
  913.       glBegin ( GL_LINE_LOOP ) ;
  914.       glNormal3d ( -tet_r[i][0], -tet_r[i][1], -tet_r[i][2] ) ;
  915.       for ( j = 0; j < 3; j++ )
  916.       {
  917.         double x = offset[0] + scale * tet_r[tet_i[i][j]][0] ;
  918.         double y = offset[1] + scale * tet_r[tet_i[i][j]][1] ;
  919.         double z = offset[2] + scale * tet_r[tet_i[i][j]][2] ;
  920.         glVertex3d ( x, y, z ) ;
  921.       }
  922.       glEnd () ;
  923.     }
  924.   }
  925.   else if ( num_levels > 0 )
  926.   {
  927.     GLdouble local_offset[3] ;  /* Use a local variable to avoid buildup of roundoff errors */
  928.     num_levels -- ;
  929.     scale /= 2.0 ;
  930.     for ( i = 0 ; i < NUM_TETR_FACES ; i++ )
  931.     {
  932.       local_offset[0] = offset[0] + scale * tet_r[i][0] ;
  933.       local_offset[1] = offset[1] + scale * tet_r[i][1] ;
  934.       local_offset[2] = offset[2] + scale * tet_r[i][2] ;
  935.       glutWireSierpinskiSponge ( num_levels, local_offset, scale ) ;
  936.     }
  937.   }
  938. }
  939. void FGAPIENTRY glutSolidSierpinskiSponge ( int num_levels, GLdouble offset[3], GLdouble scale )
  940. {
  941.   int i, j ;
  942.   FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSolidSierpinskiSponge" );
  943.   if ( num_levels == 0 )
  944.   {
  945.     glBegin ( GL_TRIANGLES ) ;
  946.     for ( i = 0 ; i < NUM_TETR_FACES ; i++ )
  947.     {
  948.       glNormal3d ( -tet_r[i][0], -tet_r[i][1], -tet_r[i][2] ) ;
  949.       for ( j = 0; j < 3; j++ )
  950.       {
  951.         double x = offset[0] + scale * tet_r[tet_i[i][j]][0] ;
  952.         double y = offset[1] + scale * tet_r[tet_i[i][j]][1] ;
  953.         double z = offset[2] + scale * tet_r[tet_i[i][j]][2] ;
  954.         glVertex3d ( x, y, z ) ;
  955.       }
  956.     }
  957.     glEnd () ;
  958.   }
  959.   else if ( num_levels > 0 )
  960.   {
  961.     GLdouble local_offset[3] ;  /* Use a local variable to avoid buildup of roundoff errors */
  962.     num_levels -- ;
  963.     scale /= 2.0 ;
  964.     for ( i = 0 ; i < NUM_TETR_FACES ; i++ )
  965.     {
  966.       local_offset[0] = offset[0] + scale * tet_r[i][0] ;
  967.       local_offset[1] = offset[1] + scale * tet_r[i][1] ;
  968.       local_offset[2] = offset[2] + scale * tet_r[i][2] ;
  969.       glutSolidSierpinskiSponge ( num_levels, local_offset, scale ) ;
  970.     }
  971.   }
  972. }
  973. /*** END OF FILE ***/