home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / src / exampleCode / opengl / siggraphCD / lib / libaux / shapes.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-08-02  |  29.0 KB  |  1,093 lines

  1. /*
  2.  * (c) Copyright 1993, 1994, Silicon Graphics, Inc.
  3.  * ALL RIGHTS RESERVED 
  4.  * Permission to use, copy, modify, and distribute this software for 
  5.  * any purpose and without fee is hereby granted, provided that the above
  6.  * copyright notice appear in all copies and that both the copyright notice
  7.  * and this permission notice appear in supporting documentation, and that 
  8.  * the name of Silicon Graphics, Inc. not be used in advertising
  9.  * or publicity pertaining to distribution of the software without specific,
  10.  * written prior permission. 
  11.  *
  12.  * THE MATERIAL EMBODIED ON THIS SOFTWARE IS PROVIDED TO YOU "AS-IS"
  13.  * AND WITHOUT WARRANTY OF ANY KIND, EXPRESS, IMPLIED OR OTHERWISE,
  14.  * INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY OR
  15.  * FITNESS FOR A PARTICULAR PURPOSE.  IN NO EVENT SHALL SILICON
  16.  * GRAPHICS, INC.  BE LIABLE TO YOU OR ANYONE ELSE FOR ANY DIRECT,
  17.  * SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY
  18.  * KIND, OR ANY DAMAGES WHATSOEVER, INCLUDING WITHOUT LIMITATION,
  19.  * LOSS OF PROFIT, LOSS OF USE, SAVINGS OR REVENUE, OR THE CLAIMS OF
  20.  * THIRD PARTIES, WHETHER OR NOT SILICON GRAPHICS, INC.  HAS BEEN
  21.  * ADVISED OF THE POSSIBILITY OF SUCH LOSS, HOWEVER CAUSED AND ON
  22.  * ANY THEORY OF LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE
  23.  * POSSESSION, USE OR PERFORMANCE OF THIS SOFTWARE.
  24.  * 
  25.  * US Government Users Restricted Rights 
  26.  * Use, duplication, or disclosure by the Government is subject to
  27.  * restrictions set forth in FAR 52.227.19(c)(2) or subparagraph
  28.  * (c)(1)(ii) of the Rights in Technical Data and Computer Software
  29.  * clause at DFARS 252.227-7013 and/or in similar or successor
  30.  * clauses in the FAR or the DOD or NASA FAR Supplement.
  31.  * Unpublished-- rights reserved under the copyright laws of the
  32.  * United States.  Contractor/manufacturer is Silicon Graphics,
  33.  * Inc., 2011 N.  Shoreline Blvd., Mountain View, CA 94039-7311.
  34.  *
  35.  * OpenGL(TM) is a trademark of Silicon Graphics, Inc.
  36.  */
  37. #include <stdio.h>
  38. #include <math.h>
  39. #include <GL/gl.h>
  40. #include <GL/glu.h>
  41. #include "aux.h"
  42. #include "3d.h"
  43.  
  44. #if defined(__cplusplus) || defined(c_plusplus)
  45. #define class c_class
  46. #endif
  47.  
  48. #define SPHEREWIRE    0
  49. #define CUBEWIRE    1
  50. #define BOXWIRE        2
  51. #define TORUSWIRE    3
  52. #define CYLINDERWIRE    4
  53. #define ICOSAWIRE    5
  54. #define OCTAWIRE    6
  55. #define TETRAWIRE    7
  56. #define DODECAWIRE    8
  57. #define CONEWIRE    9
  58. #define SPHERESOLID    10
  59. #define CUBESOLID    11
  60. #define BOXSOLID    12
  61. #define TORUSSOLID    13
  62. #define CYLINDERSOLID    14
  63. #define ICOSASOLID    15
  64. #define OCTASOLID    16
  65. #define TETRASOLID    17
  66. #define DODECASOLID    18
  67. #define CONESOLID    19
  68.  
  69. #define PI 3.1415926535897
  70.  
  71. /*    structure for each geometric object    */
  72. typedef struct model {
  73.     GLuint list;    /*  display list to render object   */
  74.     struct model *ptr;    /*  pointer to next object    */
  75.     int numParam;    /*  # of parameters        */
  76.     GLdouble *params;    /*  array with parameters    */
  77. } MODEL, *MODELPTR;
  78.  
  79. /*    array of linked lists--used to keep track of display lists 
  80.  *    for each different type of geometric object.
  81.  */
  82. static MODELPTR lists[25] = {
  83.     NULL, NULL, NULL, NULL, NULL,
  84.     NULL, NULL, NULL, NULL, NULL,
  85.     NULL, NULL, NULL, NULL, NULL,
  86.     NULL, NULL, NULL, NULL, NULL,
  87.     NULL, NULL, NULL, NULL, NULL
  88. };
  89.  
  90. GLuint findList (int index, GLdouble *paramArray, int size);
  91. int compareParams (GLdouble *oneArray, GLdouble *twoArray, int size);
  92. GLuint makeModelPtr (int index, GLdouble *sizeArray, int count);
  93.  
  94. static void drawbox(GLdouble, GLdouble, GLdouble, 
  95.     GLdouble, GLdouble, GLdouble, GLenum);
  96. static void doughnut(GLdouble, GLdouble, GLint, GLint, GLenum);
  97. static void icosahedron(GLdouble *, GLdouble, GLenum);
  98. static void octahedron(GLdouble *, GLdouble, GLenum);
  99. static void tetrahedron(GLdouble *, GLdouble, GLenum);
  100. static void subdivide(int, GLdouble *, GLdouble *, GLdouble *,
  101.     GLdouble *, GLdouble, GLenum, int);
  102. static void drawtriangle(int, int, int,
  103.     GLdouble *, GLdouble, GLenum, int);
  104. static void recorditem(GLdouble *, GLdouble *, GLdouble *,
  105.     GLdouble *, GLdouble, GLenum, int);
  106. static void initdodec(void);
  107. static void dodecahedron(GLdouble *, GLdouble, GLenum);
  108. static void pentagon(int, int, int, int, int, GLenum);
  109.  
  110.  
  111. /*  Render wire frame or solid sphere.  If no display list with
  112.  *  the current model size exists, create a new display list.
  113.  */
  114. void auxWireSphere (GLdouble radius)
  115. {
  116.     GLUquadricObj *quadObj;
  117.     GLdouble *sizeArray;
  118.     GLuint displayList;
  119.  
  120.     sizeArray = (GLdouble *) malloc (sizeof (GLdouble) * 1);
  121.     *sizeArray = radius;
  122.     displayList = findList (SPHEREWIRE, sizeArray, 1);
  123.  
  124.     if (displayList == 0) {
  125.     glNewList(makeModelPtr (SPHEREWIRE, sizeArray, 1),
  126.         GL_COMPILE_AND_EXECUTE);
  127.         quadObj = gluNewQuadric ();
  128.         gluQuadricDrawStyle (quadObj, GLU_LINE);
  129.         gluSphere (quadObj, radius, 16, 16);
  130.     glEndList();
  131.     }
  132.     else {
  133.     glCallList(displayList);
  134.     free (sizeArray);
  135.     }
  136. }
  137.  
  138. void auxSolidSphere (GLdouble radius)
  139. {
  140.     GLUquadricObj *quadObj;
  141.     GLdouble *sizeArray;
  142.     GLuint displayList;
  143.  
  144.     sizeArray = (GLdouble *) malloc (sizeof (GLdouble) * 1);
  145.     *sizeArray = radius;
  146.     displayList = findList (SPHERESOLID, sizeArray, 1);
  147.  
  148.     if (displayList == 0) {
  149.     glNewList(makeModelPtr (SPHERESOLID, sizeArray, 1),
  150.         GL_COMPILE_AND_EXECUTE);
  151.         quadObj = gluNewQuadric ();
  152.         gluQuadricDrawStyle (quadObj, GLU_FILL);
  153.         gluQuadricNormals (quadObj, GLU_SMOOTH);
  154.         gluSphere (quadObj, radius, 16, 16);
  155.     glEndList();
  156.     }
  157.     else {
  158.     glCallList(displayList);
  159.     free (sizeArray);
  160.     }
  161. }
  162.  
  163. /*  Render wire frame or solid cube.  If no display list with
  164.  *  the current model size exists, create a new display list.
  165.  */
  166. void auxWireCube (GLdouble size)
  167. {
  168.     GLdouble *sizeArray;
  169.     GLuint displayList;
  170.  
  171.     sizeArray = (GLdouble *) malloc (sizeof (GLdouble) * 1);
  172.     *sizeArray = size;
  173.     displayList = findList (CUBEWIRE, sizeArray, 1);
  174.  
  175.     if (displayList == 0) {
  176.     glNewList(makeModelPtr (CUBEWIRE, sizeArray, 1),
  177.         GL_COMPILE_AND_EXECUTE);
  178.         drawbox(-size/2., size/2., -size/2., size/2., 
  179.         -size/2., size/2., GL_LINE_LOOP);
  180.     glEndList();
  181.     }
  182.     else {
  183.     glCallList(displayList);
  184.     free (sizeArray);
  185.     }
  186. }
  187.  
  188. void auxSolidCube (GLdouble size)
  189. {
  190.     GLdouble *sizeArray;
  191.     GLuint displayList;
  192.  
  193.     sizeArray = (GLdouble *) malloc (sizeof (GLdouble) * 1);
  194.     *sizeArray = size;
  195.     displayList = findList (CUBESOLID, sizeArray, 1);
  196.  
  197.     if (displayList == 0) {
  198.     glNewList(makeModelPtr (CUBESOLID, sizeArray, 1),
  199.         GL_COMPILE_AND_EXECUTE);
  200.         drawbox(-size/2., size/2., -size/2., size/2., 
  201.         -size/2., size/2., GL_QUADS);
  202.     glEndList();
  203.     }
  204.     else {
  205.     glCallList(displayList);
  206.     free (sizeArray);
  207.     }
  208. }
  209.  
  210. /*  Render wire frame or solid cube.  If no display list with
  211.  *  the current model size exists, create a new display list.
  212.  */
  213. void auxWireBox (GLdouble width, GLdouble height, GLdouble depth)
  214. {
  215.     GLdouble *sizeArray, *tmp;
  216.     GLuint displayList;
  217.  
  218.     sizeArray = (GLdouble *) malloc (sizeof (GLdouble) * 3);
  219.     tmp = sizeArray;
  220.     *tmp++ = width;
  221.     *tmp++ = height;
  222.     *tmp++ = depth;
  223.     displayList = findList (BOXWIRE, sizeArray, 3);
  224.  
  225.     if (displayList == 0) {
  226.     glNewList(makeModelPtr (BOXWIRE, sizeArray, 3),
  227.         GL_COMPILE_AND_EXECUTE);
  228.         drawbox(-width/2., width/2., -height/2., height/2., 
  229.         -depth/2., depth/2., GL_LINE_LOOP);
  230.     glEndList();
  231.     }
  232.     else {
  233.     glCallList(displayList);
  234.     free (sizeArray);
  235.     }
  236. }
  237.  
  238. void auxSolidBox (GLdouble width, GLdouble height, GLdouble depth)
  239. {
  240.     GLdouble *sizeArray, *tmp;
  241.     GLuint displayList;
  242.  
  243.     sizeArray = (GLdouble *) malloc (sizeof (GLdouble) * 3);
  244.     tmp = sizeArray;
  245.     *tmp++ = width;
  246.     *tmp++ = height;
  247.     *tmp++ = depth;
  248.     displayList = findList (BOXSOLID, sizeArray, 3);
  249.  
  250.     if (displayList == 0) {
  251.     glNewList(makeModelPtr (BOXSOLID, sizeArray, 3),
  252.         GL_COMPILE_AND_EXECUTE);
  253.         drawbox(-width/2., width/2., -height/2., height/2., 
  254.         -depth/2., depth/2., GL_QUADS);
  255.     glEndList();
  256.     }
  257.     else {
  258.     glCallList(displayList);
  259.     free (sizeArray);
  260.     }
  261. }
  262.  
  263. /*  Render wire frame or solid tori.  If no display list with
  264.  *  the current model size exists, create a new display list.
  265.  */
  266. void auxWireTorus (GLdouble innerRadius, GLdouble outerRadius)
  267. {
  268.     GLdouble *sizeArray, *tmp;
  269.     GLuint displayList;
  270.  
  271.     sizeArray = (GLdouble *) malloc (sizeof (GLdouble) * 2);
  272.     tmp = sizeArray;
  273.     *tmp++ = innerRadius;
  274.     *tmp++ = outerRadius;
  275.     displayList = findList (TORUSWIRE, sizeArray, 2);
  276.  
  277.     if (displayList == 0) {
  278.     glNewList(makeModelPtr (TORUSWIRE, sizeArray, 2),
  279.         GL_COMPILE_AND_EXECUTE);
  280.         doughnut(innerRadius, outerRadius, 5, 10, GL_LINE_LOOP);
  281.     glEndList();
  282.     }
  283.     else {
  284.     glCallList(displayList);
  285.     free (sizeArray);
  286.     }
  287. }
  288.  
  289. void auxSolidTorus (GLdouble innerRadius, GLdouble outerRadius)
  290. {
  291.     GLdouble *sizeArray, *tmp;
  292.     GLuint displayList;
  293.  
  294.     sizeArray = (GLdouble *) malloc (sizeof (GLdouble) * 2);
  295.     tmp = sizeArray;
  296.     *tmp++ = innerRadius;
  297.     *tmp++ = outerRadius;
  298.     displayList = findList (TORUSSOLID, sizeArray, 2);
  299.  
  300.     if (displayList == 0) {
  301.     glNewList(makeModelPtr (TORUSSOLID, sizeArray, 2),
  302.         GL_COMPILE_AND_EXECUTE);
  303.         doughnut(innerRadius, outerRadius, 8, 15, GL_QUADS);
  304.     glEndList();
  305.     }
  306.     else {
  307.     glCallList(displayList);
  308.     free (sizeArray);
  309.     }
  310. }
  311.  
  312. /*  Render wire frame or solid cylinders.  If no display list with
  313.  *  the current model size exists, create a new display list.
  314.  */
  315. void auxWireCylinder (GLdouble radius, GLdouble height)
  316. {
  317.     GLUquadricObj *quadObj;
  318.     GLdouble *sizeArray, *tmp;
  319.     GLuint displayList;
  320.  
  321.     sizeArray = (GLdouble *) malloc (sizeof (GLdouble) * 2);
  322.     tmp = sizeArray;
  323.     *tmp++ = radius;
  324.     *tmp++ = height;
  325.     displayList = findList (CYLINDERWIRE, sizeArray, 2);
  326.  
  327.     if (displayList == 0) {
  328.     glNewList(makeModelPtr (CYLINDERWIRE, sizeArray, 2),
  329.         GL_COMPILE_AND_EXECUTE);
  330.         glPushMatrix ();
  331.         glRotatef (90.0, 1.0, 0.0, 0.0);
  332.         glTranslatef (0.0, 0.0, -1.0);
  333.         quadObj = gluNewQuadric ();
  334.         gluQuadricDrawStyle (quadObj, GLU_LINE);
  335.         gluCylinder (quadObj, radius, radius, height, 12, 2);
  336.         glPopMatrix ();
  337.     glEndList();
  338.     }
  339.     else {
  340.     glCallList(displayList);
  341.     free (sizeArray);
  342.     }
  343. }
  344.  
  345. void auxSolidCylinder (GLdouble radius, GLdouble height)
  346. {
  347.     GLUquadricObj *quadObj;
  348.     GLdouble *sizeArray, *tmp;
  349.     GLuint displayList;
  350.  
  351.     sizeArray = (GLdouble *) malloc (sizeof (GLdouble) * 2);
  352.     tmp = sizeArray;
  353.     *tmp++ = radius;
  354.     *tmp++ = height;
  355.     displayList = findList (CYLINDERWIRE, sizeArray, 2);
  356.  
  357.     if (displayList == 0) {
  358.     glNewList(makeModelPtr (CYLINDERWIRE, sizeArray, 2),
  359.         GL_COMPILE_AND_EXECUTE);
  360.         glPushMatrix ();
  361.         glRotatef (90.0, 1.0, 0.0, 0.0);
  362.         glTranslatef (0.0, 0.0, -1.0);
  363.         quadObj = gluNewQuadric ();
  364.         gluQuadricDrawStyle (quadObj, GLU_FILL);
  365.         gluQuadricNormals (quadObj, GLU_SMOOTH);
  366.         gluCylinder (quadObj, radius, radius, height, 12, 2);
  367.         glPopMatrix ();
  368.     glEndList();
  369.     }
  370.     else {
  371.     glCallList(displayList);
  372.     free (sizeArray);
  373.     }
  374. }
  375.  
  376. /*  Render wire frame or solid icosahedra.  If no display list with
  377.  *  the current model size exists, create a new display list.
  378.  */
  379. void auxWireIcosahedron (GLdouble radius)
  380. {
  381.     GLdouble *sizeArray;
  382.     GLuint displayList;
  383.     GLdouble center[3] = {0.0, 0.0, 0.0};
  384.  
  385.     sizeArray = (GLdouble *) malloc (sizeof (GLdouble) * 1);
  386.     *sizeArray = radius;
  387.     displayList = findList (ICOSAWIRE, sizeArray, 1);
  388.  
  389.     if (displayList == 0) {
  390.     glNewList(makeModelPtr (ICOSAWIRE, sizeArray, 1),
  391.         GL_COMPILE_AND_EXECUTE);
  392.         icosahedron (center, radius, GL_LINE_LOOP);
  393.     glEndList();
  394.     }
  395.     else {
  396.     glCallList(displayList);
  397.     free (sizeArray);
  398.     }
  399. }
  400.  
  401. void auxSolidIcosahedron (GLdouble radius)
  402. {
  403.     GLdouble *sizeArray;
  404.     GLuint displayList;
  405.     GLdouble center[3] = {0.0, 0.0, 0.0};
  406.  
  407.     sizeArray = (GLdouble *) malloc (sizeof (GLdouble) * 1);
  408.     *sizeArray = radius;
  409.     displayList = findList (ICOSASOLID, sizeArray, 1);
  410.  
  411.     if (displayList == 0) {
  412.     glNewList(makeModelPtr (ICOSASOLID, sizeArray, 1),
  413.         GL_COMPILE_AND_EXECUTE);
  414.         icosahedron (center, radius, GL_TRIANGLES);
  415.     glEndList();
  416.     }
  417.     else {
  418.     glCallList(displayList);
  419.     free (sizeArray);
  420.     }
  421. }
  422.  
  423. /*  Render wire frame or solid octahedra.  If no display list with
  424.  *  the current model size exists, create a new display list.
  425.  */
  426. void auxWireOctahedron (GLdouble radius)
  427. {
  428.     GLdouble *sizeArray;
  429.     GLuint displayList;
  430.     GLdouble center[3] = {0.0, 0.0, 0.0};
  431.  
  432.     sizeArray = (GLdouble *) malloc (sizeof (GLdouble) * 1);
  433.     *sizeArray = radius;
  434.     displayList = findList (OCTAWIRE, sizeArray, 1);
  435.  
  436.     if (displayList == 0) {
  437.     glNewList(makeModelPtr (OCTAWIRE, sizeArray, 1),
  438.         GL_COMPILE_AND_EXECUTE);
  439.         octahedron (center, radius, GL_LINE_LOOP);
  440.     glEndList();
  441.     }
  442.     else {
  443.     glCallList(displayList);
  444.     free (sizeArray);
  445.     }
  446. }
  447.  
  448. void auxSolidOctahedron (GLdouble radius)
  449. {
  450.     GLdouble *sizeArray;
  451.     GLuint displayList;
  452.     GLdouble center[3] = {0.0, 0.0, 0.0};
  453.  
  454.     sizeArray = (GLdouble *) malloc (sizeof (GLdouble) * 1);
  455.     *sizeArray = radius;
  456.     displayList = findList (OCTASOLID, sizeArray, 1);
  457.  
  458.     if (displayList == 0) {
  459.     glNewList(makeModelPtr (OCTASOLID, sizeArray, 1),
  460.         GL_COMPILE_AND_EXECUTE);
  461.         octahedron (center, radius, GL_TRIANGLES);
  462.     glEndList();
  463.     }
  464.     else {
  465.     glCallList(displayList);
  466.     free (sizeArray);
  467.     }
  468. }
  469.  
  470. /*  Render wire frame or solid tetrahedra.  If no display list with
  471.  *  the current model size exists, create a new display list.
  472.  */
  473. void auxWireTetrahedron (GLdouble radius)
  474. {
  475.     GLdouble *sizeArray;
  476.     GLuint displayList;
  477.     GLdouble center[3] = {0.0, 0.0, 0.0};
  478.  
  479.     sizeArray = (GLdouble *) malloc (sizeof (GLdouble) * 1);
  480.     *sizeArray = radius;
  481.     displayList = findList (TETRAWIRE, sizeArray, 1);
  482.  
  483.     if (displayList == 0) {
  484.     glNewList(makeModelPtr (TETRAWIRE, sizeArray, 1),
  485.         GL_COMPILE_AND_EXECUTE);
  486.         tetrahedron (center, radius, GL_LINE_LOOP);
  487.     glEndList();
  488.     }
  489.     else {
  490.     glCallList(displayList);
  491.     free (sizeArray);
  492.     }
  493. }
  494.  
  495. void auxSolidTetrahedron (GLdouble radius)
  496. {
  497.     GLdouble *sizeArray;
  498.     GLuint displayList;
  499.     GLdouble center[3] = {0.0, 0.0, 0.0};
  500.  
  501.     sizeArray = (GLdouble *) malloc (sizeof (GLdouble) * 1);
  502.     *sizeArray = radius;
  503.     displayList = findList (TETRASOLID, sizeArray, 1);
  504.  
  505.     if (displayList == 0) {
  506.     glNewList(makeModelPtr (TETRASOLID, sizeArray, 1),
  507.         GL_COMPILE_AND_EXECUTE);
  508.         tetrahedron (center, radius, GL_TRIANGLES);
  509.     glEndList();
  510.     }
  511.     else {
  512.     glCallList(displayList);
  513.     free (sizeArray);
  514.     }
  515. }
  516.  
  517. /*  Render wire frame or solid dodecahedra.  If no display list with
  518.  *  the current model size exists, create a new display list.
  519.  */
  520. void auxWireDodecahedron (GLdouble radius)
  521. {
  522.     GLdouble *sizeArray;
  523.     GLuint displayList;
  524.     GLdouble center[3] = {0.0, 0.0, 0.0};
  525.  
  526.     sizeArray = (GLdouble *) malloc (sizeof (GLdouble) * 1);
  527.     *sizeArray = radius;
  528.     displayList = findList (DODECAWIRE, sizeArray, 1);
  529.  
  530.     if (displayList == 0) {
  531.     glNewList(makeModelPtr (DODECAWIRE, sizeArray, 1),
  532.         GL_COMPILE_AND_EXECUTE);
  533.         dodecahedron (center, radius/1.73, GL_LINE_LOOP);
  534.     glEndList();
  535.     }
  536.     else {
  537.     glCallList(displayList);
  538.     free (sizeArray);
  539.     }
  540. }
  541.  
  542. void auxSolidDodecahedron (GLdouble radius)
  543. {
  544.     GLdouble *sizeArray;
  545.     GLuint displayList;
  546.     GLdouble center[3] = {0.0, 0.0, 0.0};
  547.  
  548.     sizeArray = (GLdouble *) malloc (sizeof (GLdouble) * 1);
  549.     *sizeArray = radius;
  550.     displayList = findList (DODECASOLID, sizeArray, 1);
  551.  
  552.     if (displayList == 0) {
  553.     glNewList(makeModelPtr (DODECASOLID, sizeArray, 1),
  554.         GL_COMPILE_AND_EXECUTE);
  555.         dodecahedron (center, radius/1.73, GL_TRIANGLE_FAN);
  556.     glEndList();
  557.     }
  558.     else {
  559.     glCallList(displayList);
  560.     free (sizeArray);
  561.     }
  562. }
  563.  
  564. /*  Render wire frame or solid cones.  If no display list with
  565.  *  the current model size exists, create a new display list.
  566.  */
  567. void auxWireCone (GLdouble base, GLdouble height)
  568. {
  569.     GLUquadricObj *quadObj;
  570.     GLdouble *sizeArray, *tmp;
  571.     GLuint displayList;
  572.  
  573.     sizeArray = (GLdouble *) malloc (sizeof (GLdouble) * 2);
  574.     tmp = sizeArray;
  575.     *tmp++ = base;
  576.     *tmp++ = height;
  577.     displayList = findList (CONEWIRE, sizeArray, 2);
  578.  
  579.     if (displayList == 0) {
  580.     glNewList(makeModelPtr (CONEWIRE, sizeArray, 2),
  581.         GL_COMPILE_AND_EXECUTE);
  582.         quadObj = gluNewQuadric ();
  583.         gluQuadricDrawStyle (quadObj, GLU_LINE);
  584.         gluCylinder (quadObj, base, 0.0, height, 15, 10);
  585.     glEndList();
  586.     }
  587.     else {
  588.     glCallList(displayList);
  589.     free (sizeArray);
  590.     }
  591. }
  592.  
  593. void auxSolidCone (GLdouble base, GLdouble height)
  594. {
  595.     GLUquadricObj *quadObj;
  596.     GLdouble *sizeArray, *tmp;
  597.     GLuint displayList;
  598.  
  599.     sizeArray = (GLdouble *) malloc (sizeof (GLdouble) * 2);
  600.     tmp = sizeArray;
  601.     *tmp++ = base;
  602.     *tmp++ = height;
  603.     displayList = findList (CONEWIRE, sizeArray, 2);
  604.  
  605.     if (displayList == 0) {
  606.     glNewList(makeModelPtr (CONEWIRE, sizeArray, 2),
  607.         GL_COMPILE_AND_EXECUTE);
  608.         quadObj = gluNewQuadric ();
  609.         gluQuadricDrawStyle (quadObj, GLU_FILL);
  610.         gluQuadricNormals (quadObj, GLU_SMOOTH);
  611.         gluCylinder (quadObj, base, 0.0, height, 15, 10);
  612.     glEndList();
  613.     }
  614.     else {
  615.     glCallList(displayList);
  616.     free (sizeArray);
  617.     }
  618. }
  619.  
  620. /* Routines to build 3 dimensional solids, including:
  621.  *
  622.  * drawbox, doughnut, icosahedron, 
  623.  * octahedron, tetrahedron, dodecahedron.
  624.  */
  625.  
  626. /* drawbox:
  627.  *
  628.  * draws a rectangular box with the given x, y, and z ranges.  
  629.  * The box is axis-aligned.
  630.  */
  631. void drawbox(GLdouble x0, GLdouble x1, GLdouble y0, GLdouble y1,
  632.     GLdouble z0, GLdouble z1, GLenum type)
  633. {
  634.     static GLdouble n[6][3] = {
  635.     {-1.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {1.0, 0.0, 0.0},
  636.     {0.0, -1.0, 0.0}, {0.0, 0.0, 1.0}, {0.0, 0.0, -1.0}
  637.     };
  638.     static GLint faces[6][4] = {
  639.     { 0, 1, 2, 3 }, { 3, 2, 6, 7 }, { 7, 6, 5, 4 },
  640.     { 4, 5, 1, 0 }, { 5, 6, 2, 1 }, { 7, 4, 0, 3 }
  641.     };
  642.     GLdouble v[8][3], tmp;
  643.     GLint i;
  644.  
  645.     if (x0 > x1) {
  646.     tmp = x0; x0 = x1; x1 = tmp;
  647.     }
  648.     if (y0 > y1) {
  649.     tmp = y0; y0 = y1; y1 = tmp; 
  650.     }
  651.     if (z0 > z1) {
  652.     tmp = z0; z0 = z1; z1 = tmp; 
  653.     }
  654.     v[0][0] = v[1][0] = v[2][0] = v[3][0] = x0;
  655.     v[4][0] = v[5][0] = v[6][0] = v[7][0] = x1;
  656.     v[0][1] = v[1][1] = v[4][1] = v[5][1] = y0;
  657.     v[2][1] = v[3][1] = v[6][1] = v[7][1] = y1;
  658.     v[0][2] = v[3][2] = v[4][2] = v[7][2] = z0;
  659.     v[1][2] = v[2][2] = v[5][2] = v[6][2] = z1;
  660.  
  661.     for (i = 0; i < 6; i++) {
  662.     glBegin(type);
  663.     glNormal3dv(&n[i][0]);
  664.     glVertex3dv(&v[faces[i][0]][0]);
  665.     glNormal3dv(&n[i][0]);
  666.     glVertex3dv(&v[faces[i][1]][0]);
  667.     glNormal3dv(&n[i][0]);
  668.     glVertex3dv(&v[faces[i][2]][0]);
  669.     glNormal3dv(&n[i][0]);
  670.     glVertex3dv(&v[faces[i][3]][0]);
  671.     glEnd();
  672.     }
  673. }
  674.  
  675. /* doughnut:
  676.  *
  677.  * draws a doughnut, centered at (0, 0, 0) whose axis is aligned with
  678.  * the z-axis.  The doughnut's major radius is R, and minor radius is r.
  679.  */
  680.  
  681. void doughnut(GLdouble r, GLdouble R, GLint nsides, GLint rings, GLenum type)
  682. {
  683.     int    i, j;
  684.     GLdouble    theta, phi, theta1, phi1;
  685.     GLdouble    p0[03], p1[3], p2[3], p3[3];
  686.     GLdouble    n0[3], n1[3], n2[3], n3[3];
  687.  
  688.     for (i = 0; i < rings; i++) {
  689.     theta = (GLdouble)i*2.0*PI/rings;
  690.     theta1 = (GLdouble)(i+1)*2.0*PI/rings;
  691.     for (j = 0; j < nsides; j++) {
  692.         phi = (GLdouble)j*2.0*PI/nsides;
  693.         phi1 = (GLdouble)(j+1)*2.0*PI/nsides;
  694.  
  695.         p0[0] = cos(theta)*(R + r*cos(phi));
  696.         p0[1] = -sin(theta)*(R + r*cos(phi));
  697.         p0[2] = r*sin(phi);
  698.  
  699.         p1[0] = cos(theta1)*(R + r*cos(phi));
  700.         p1[1] = -sin(theta1)*(R + r*cos(phi));
  701.         p1[2] = r*sin(phi);
  702.  
  703.         p2[0] = cos(theta1)*(R + r*cos(phi1));
  704.         p2[1] = -sin(theta1)*(R + r*cos(phi1));
  705.         p2[2] = r*sin(phi1);
  706.  
  707.         p3[0] = cos(theta)*(R + r*cos(phi1));
  708.         p3[1] = -sin(theta)*(R + r*cos(phi1));
  709.         p3[2] = r*sin(phi1);
  710.  
  711.         n0[0] = cos(theta)*(cos(phi));
  712.         n0[1] = -sin(theta)*(cos(phi));
  713.         n0[2] = sin(phi);
  714.  
  715.         n1[0] = cos(theta1)*(cos(phi));
  716.         n1[1] = -sin(theta1)*(cos(phi));
  717.         n1[2] = sin(phi);
  718.  
  719.         n2[0] = cos(theta1)*(cos(phi1));
  720.         n2[1] = -sin(theta1)*(cos(phi1));
  721.         n2[2] = sin(phi1);
  722.  
  723.         n3[0] = cos(theta)*(cos(phi1));
  724.         n3[1] = -sin(theta)*(cos(phi1));
  725.         n3[2] = sin(phi1);
  726.  
  727.         m_xformpt(p0, p0, n0, n0);
  728.         m_xformpt(p1, p1, n1, n1);
  729.         m_xformpt(p2, p2, n2, n2);
  730.         m_xformpt(p3, p3, n3, n3);
  731.  
  732.         glBegin(type);
  733.         glNormal3dv(n3);
  734.         glVertex3dv(p3);
  735.         glNormal3dv(n2);
  736.         glVertex3dv(p2);
  737.         glNormal3dv(n1);
  738.         glVertex3dv(p1);
  739.         glNormal3dv(n0);
  740.         glVertex3dv(p0);
  741.         glEnd();
  742.     }
  743.     }
  744. }
  745.  
  746. /* octahedron data: The octahedron produced is centered 
  747.  * at the origin and has radius 1.0 
  748.  */
  749. static GLdouble odata[6][3] = {
  750.   {1.0, 0.0, 0.0},
  751.   {-1.0, 0.0, 0.0},
  752.   {0.0, 1.0, 0.0},
  753.   {0.0, -1.0, 0.0},
  754.   {0.0, 0.0, 1.0},
  755.   {0.0, 0.0, -1.0}
  756. };
  757.  
  758. static int ondex[8][3] = {
  759.     {0, 4, 2}, {1, 2, 4}, {0, 3, 4}, {1, 4, 3},
  760.     {0, 2, 5}, {1, 5, 2}, {0, 5, 3}, {1, 3, 5}
  761. };
  762.  
  763. /* tetrahedron data: */
  764.  
  765. #define T    1.73205080756887729
  766.  
  767. static GLdouble tdata[4][3] = {
  768.     {T, T, T}, {T, -T, -T}, {-T, T, -T}, {-T, -T, T}
  769. };
  770.  
  771. static int tndex[4][3] = {
  772.     {0, 1, 3}, {2, 1, 0}, {3, 2, 0}, {1, 2, 3}
  773. };
  774.  
  775. /* icosahedron data: These numbers are rigged to 
  776.  * make an icosahedron of radius 1.0 
  777.  */
  778.  
  779. #define X .525731112119133606
  780. #define Z .850650808352039932
  781.  
  782. static GLdouble idata[12][3] = {
  783.   {-X, 0, Z},
  784.   {X, 0, Z},
  785.   {-X, 0, -Z},
  786.   {X, 0, -Z},
  787.   {0, Z, X},
  788.   {0, Z, -X},
  789.   {0, -Z, X},
  790.   {0, -Z, -X},
  791.   {Z, X, 0},
  792.   {-Z, X, 0},
  793.   {Z, -X, 0},
  794.   {-Z, -X, 0}
  795. };
  796.  
  797. static int index[20][3] = {
  798.     {0, 4, 1},    {0, 9, 4},
  799.     {9, 5, 4},    {4, 5, 8},
  800.     {4, 8, 1},    {8, 10, 1},
  801.     {8, 3, 10},    {5, 3, 8},
  802.     {5, 2, 3},    {2, 7, 3},
  803.     {7, 10, 3},    {7, 6, 10},
  804.     {7, 11, 6},    {11, 0, 6},
  805.     {0, 1, 6},    {6, 1, 10},
  806.     {9, 0, 11},    {9, 11, 2},
  807.     {9, 2, 5},    {7, 2, 11},
  808. };
  809.  
  810. /* icosahedron:
  811.  *
  812.  * Draws an icosahedron with center at p0 having the
  813.  * given radius.
  814.  */
  815.  
  816. static void icosahedron(GLdouble p0[3], GLdouble radius, GLenum shadeType)
  817. {
  818.     int i;
  819.  
  820.     for (i = 0; i < 20; i++)
  821.     drawtriangle(i, 0, 1, p0, radius, shadeType, 0);
  822. }
  823.  
  824. /* octahedron:
  825.  *
  826.  * Draws an octahedron with center at p0 having the
  827.  * given radius.
  828.  */
  829. static void octahedron(GLdouble p0[3], GLdouble radius, GLenum shadeType)
  830. {
  831.     int i;
  832.  
  833.     for (i = 0; i < 8; i++)
  834.     drawtriangle(i, 1, 1, p0, radius, shadeType, 0);
  835. }
  836.  
  837. /* tetrahedron:
  838.  *
  839.  * Draws an tetrahedron with center at p0 having the
  840.  * given radius.
  841.  */
  842.  
  843. static void tetrahedron(GLdouble p0[3], GLdouble radius, GLenum shadeType)
  844. {
  845.     int i;
  846.  
  847.     for (i = 0; i < 4; i++)
  848.     drawtriangle(i, 2, 1, p0, radius, shadeType, 0);
  849. }
  850.  
  851. static void subdivide(int depth, GLdouble *v0, GLdouble *v1, GLdouble *v2,
  852.     GLdouble p0[3], GLdouble radius, GLenum shadeType, int avnormal)
  853. {
  854.     GLdouble w0[3], w1[3], w2[3];
  855.     GLdouble l;
  856.     int i, j, k, n;
  857.  
  858.     for (i = 0; i < depth; i++)
  859.     for (j = 0; i + j < depth; j++) {
  860.         k = depth - i - j;
  861.         for (n = 0; n < 3; n++) {
  862.         w0[n] = (i*v0[n] + j*v1[n] + k*v2[n])/depth;
  863.         w1[n] = ((i+1)*v0[n] + j*v1[n] + (k-1)*v2[n])/depth;
  864.         w2[n] = (i*v0[n] + (j+1)*v1[n] + (k-1)*v2[n])/depth;
  865.         }
  866.         l = sqrt(w0[0]*w0[0] + w0[1]*w0[1] + w0[2]*w0[2]);
  867.         w0[0] /= l; w0[1] /= l; w0[2] /= l;
  868.         l = sqrt(w1[0]*w1[0] + w1[1]*w1[1] + w1[2]*w1[2]);
  869.         w1[0] /= l; w1[1] /= l; w1[2] /= l;
  870.         l = sqrt(w2[0]*w2[0] + w2[1]*w2[1] + w2[2]*w2[2]);
  871.         w2[0] /= l; w2[1] /= l; w2[2] /= l;
  872.         recorditem(w1, w0, w2, p0, radius, shadeType, avnormal);
  873.     }
  874.     for (i = 0; i < depth-1; i++)
  875.     for (j = 0; i + j < depth-1; j++) {
  876.         k = depth - i - j;
  877.         for (n = 0; n < 3; n++) {
  878.         w0[n] = ((i+1)*v0[n] + (j+1)*v1[n] + (k-2)*v2[n])/depth;
  879.         w1[n] = ((i+1)*v0[n] + j*v1[n] + (k-1)*v2[n])/depth;
  880.         w2[n] = (i*v0[n] + (j+1)*v1[n] + (k-1)*v2[n])/depth;
  881.         }
  882.         l = sqrt(w0[0]*w0[0] + w0[1]*w0[1] + w0[2]*w0[2]);
  883.         w0[0] /= l; w0[1] /= l; w0[2] /= l;
  884.         l = sqrt(w1[0]*w1[0] + w1[1]*w1[1] + w1[2]*w1[2]);
  885.         w1[0] /= l; w1[1] /= l; w1[2] /= l;
  886.         l = sqrt(w2[0]*w2[0] + w2[1]*w2[1] + w2[2]*w2[2]);
  887.         w2[0] /= l; w2[1] /= l; w2[2] /= l;
  888.         recorditem(w0, w1, w2, p0, radius, shadeType, avnormal);
  889.     }
  890. }
  891.  
  892. static void drawtriangle(int i, int geomType, int depth,
  893.     GLdouble p0[3], GLdouble radius, GLenum shadeType, int avnormal)
  894. {
  895.     GLdouble *x0, *x1, *x2;
  896.  
  897.     switch (geomType) {
  898.     case 0:    /* icosahedron */
  899.         x0 = &idata[index[i][0]][0];
  900.         x1 = &idata[index[i][1]][0];
  901.         x2 = &idata[index[i][2]][0];
  902.         break;
  903.     case 1: /* octahedron */
  904.         x0 = &odata[ondex[i][0]][0];
  905.         x1 = &odata[ondex[i][1]][0];
  906.         x2 = &odata[ondex[i][2]][0];
  907.         break;
  908.     case 2: /* tetrahedron */
  909.         x0 = &tdata[tndex[i][0]][0];
  910.         x1 = &tdata[tndex[i][1]][0];
  911.         x2 = &tdata[tndex[i][2]][0];
  912.         break;
  913.     }
  914.     subdivide(depth, x0, x1, x2, p0, radius, shadeType, avnormal);
  915. }
  916.  
  917. static void recorditem(GLdouble *n1, GLdouble *n2, GLdouble *n3,
  918.     GLdouble center[3], GLdouble radius, GLenum shadeType, int avnormal)
  919. {
  920.     GLdouble p1[3], p2[3], p3[3], q0[3], q1[3], n11[3], n22[3], n33[3];
  921.     int    i;
  922.  
  923.     for (i = 0; i < 3; i++) {
  924.     p1[i] = n1[i]*radius + center[i];
  925.     p2[i] = n2[i]*radius + center[i];
  926.     p3[i] = n3[i]*radius + center[i];
  927.     }
  928.     if (avnormal == 0) {
  929.     diff3(p1, p2, q0);
  930.     diff3(p2, p3, q1);
  931.     crossprod(q0, q1, q1);
  932.     normalize(q1);
  933.     m_xformpt(p1, p1, q1, n11);
  934.     m_xformptonly(p2, p2);
  935.     m_xformptonly(p3, p3);
  936.  
  937.     glBegin (shadeType);
  938.     glNormal3dv(n11);
  939.     glVertex3dv(p1);
  940.     glVertex3dv(p2);
  941.     glVertex3dv(p3);
  942.     glEnd();
  943.     return;
  944.     }
  945.     m_xformpt(p1, p1, n1, n11);
  946.     m_xformpt(p2, p2, n2, n22);
  947.     m_xformpt(p3, p3, n3, n33);
  948.  
  949.     glBegin (shadeType);
  950.     glNormal3dv(n11);
  951.     glVertex3dv(p1);
  952.     glNormal3dv(n22);
  953.     glVertex3dv(p2);
  954.     glNormal3dv(n33);
  955.     glVertex3dv(p3);
  956.     glEnd();
  957. }
  958.  
  959. static GLdouble dodec[20][3];
  960.  
  961. static void initdodec()
  962. {
  963.     GLdouble alpha, beta;
  964.  
  965.     alpha = sqrt(2.0/(3.0 + sqrt(5.0)));
  966.     beta = 1.0 + sqrt(6.0/(3.0 + sqrt(5.0)) - 2.0 + 2.0*sqrt(2.0/(3.0 +
  967.                                 sqrt(5.0))));
  968.     dodec[0][0] = -alpha; dodec[0][1] = 0; dodec[0][2] = beta;
  969.     dodec[1][0] = alpha; dodec[1][1] = 0; dodec[1][2] = beta;
  970.     dodec[2][0] = -1; dodec[2][1] = -1; dodec[2][2] = -1;
  971.     dodec[3][0] = -1; dodec[3][1] = -1; dodec[3][2] = 1;
  972.     dodec[4][0] = -1; dodec[4][1] = 1; dodec[4][2] = -1;
  973.     dodec[5][0] = -1; dodec[5][1] = 1; dodec[5][2] = 1;
  974.     dodec[6][0] = 1; dodec[6][1] = -1; dodec[6][2] = -1;
  975.     dodec[7][0] = 1; dodec[7][1] = -1; dodec[7][2] = 1;
  976.     dodec[8][0] = 1; dodec[8][1] = 1; dodec[8][2] = -1;
  977.     dodec[9][0] = 1; dodec[9][1] = 1; dodec[9][2] = 1;
  978.     dodec[10][0] = beta; dodec[10][1] = alpha; dodec[10][2] = 0;
  979.     dodec[11][0] = beta; dodec[11][1] = -alpha; dodec[11][2] = 0;
  980.     dodec[12][0] = -beta; dodec[12][1] = alpha; dodec[12][2] = 0;
  981.     dodec[13][0] = -beta; dodec[13][1] = -alpha; dodec[13][2] = 0;
  982.     dodec[14][0] = -alpha; dodec[14][1] = 0; dodec[14][2] = -beta;
  983.     dodec[15][0] = alpha; dodec[15][1] = 0; dodec[15][2] = -beta;
  984.     dodec[16][0] = 0; dodec[16][1] = beta; dodec[16][2] = alpha;
  985.     dodec[17][0] = 0; dodec[17][1] = beta; dodec[17][2] = -alpha;
  986.     dodec[18][0] = 0; dodec[18][1] = -beta; dodec[18][2] = alpha;
  987.     dodec[19][0] = 0; dodec[19][1] = -beta; dodec[19][2] = -alpha;
  988. }
  989.  
  990. /* dodecahedron:
  991.  *
  992.  * Draws an dodecahedron with center at 0.0. The radius
  993.  * is sqrt(3).
  994.  */
  995. static void dodecahedron(GLdouble center[3], GLdouble sc, GLenum type)
  996. {
  997.     static int inited = 0;
  998.  
  999.     if ( inited == 0) {
  1000.     inited = 1;
  1001.     initdodec();
  1002.     }
  1003.     m_pushmatrix();
  1004.     m_translate(center[0], center[1], center[2]);
  1005.     m_scale(sc, sc, sc);
  1006.     pentagon(0, 1, 9, 16, 5, type);
  1007.     pentagon(1, 0, 3, 18, 7, type);
  1008.     pentagon(1, 7, 11, 10, 9, type);
  1009.     pentagon(11, 7, 18, 19, 6, type);
  1010.     pentagon(8, 17, 16, 9, 10, type);
  1011.     pentagon(2, 14, 15, 6, 19, type);
  1012.     pentagon(2, 13, 12, 4, 14, type);
  1013.     pentagon(2, 19, 18, 3, 13, type);
  1014.     pentagon(3, 0, 5, 12, 13, type);
  1015.     pentagon(6, 15, 8, 10, 11, type);
  1016.     pentagon(4, 17, 8, 15, 14, type);
  1017.     pentagon(4, 12, 5, 16, 17, type);
  1018.     m_popmatrix();
  1019. }
  1020.  
  1021. static void pentagon(int a, int b, int c, int d, int e, GLenum shadeType)
  1022. {
  1023.     GLdouble n0[3], d1[3], d2[3], d3[3], d4[3], d5[3], nout[3];
  1024.  
  1025.     diff3(&dodec[a][0], &dodec[b][0], d1);
  1026.     diff3(&dodec[b][0], &dodec[c][0], d2);
  1027.     crossprod(d1, d2, n0);
  1028.     normalize(n0);
  1029.     m_xformpt(&dodec[a][0], d1, n0, nout);
  1030.     m_xformptonly(&dodec[b][0], d2);
  1031.     m_xformptonly(&dodec[c][0], d3);
  1032.     m_xformptonly(&dodec[d][0], d4);
  1033.     m_xformptonly(&dodec[e][0], d5);
  1034.  
  1035.     glBegin (shadeType);
  1036.     glNormal3dv(nout);
  1037.     glVertex3dv(d1);
  1038.     glVertex3dv(d2);
  1039.     glVertex3dv(d3);
  1040.     glVertex3dv(d4);
  1041.     glVertex3dv(d5);
  1042.     glEnd();
  1043. }
  1044.  
  1045. /*    linked lists--display lists for each different 
  1046.  *    type of geometric objects.  The linked list is 
  1047.  *    searched, until an object of the requested
  1048.  *    size is found.  If no geometric object of that size
  1049.  *    has been previously made, a new one is created.
  1050.  */
  1051. GLuint findList (int index, GLdouble *paramArray, int size) 
  1052. {
  1053.     MODELPTR endList;
  1054.     int found = 0;
  1055.     
  1056.     endList = lists[index];
  1057.     while (endList != NULL) {
  1058.     if (compareParams (endList->params, paramArray, size))
  1059.         return (endList->list);
  1060.     endList = endList->ptr;
  1061.     }
  1062. /*  if not found, return 0 and calling routine should
  1063.  *  make a new list    
  1064.  */
  1065.     return (0);
  1066. }
  1067.  
  1068. int compareParams (GLdouble *oneArray, GLdouble *twoArray, int size) 
  1069. {
  1070.     int i;
  1071.     int matches = 1;
  1072.  
  1073.     for (i = 0; (i < size) && matches; i++) {
  1074.     if (*oneArray++ != *twoArray++)
  1075.         matches = 0;
  1076.     }
  1077.     return (matches);
  1078. }
  1079.  
  1080. GLuint makeModelPtr (int index, GLdouble *sizeArray, int count)
  1081. {
  1082.     MODELPTR newModel;
  1083.  
  1084.     newModel = (MODELPTR) malloc (sizeof (MODEL));
  1085.     newModel->list = glGenLists (1);
  1086.     newModel->numParam = count;
  1087.     newModel->params = sizeArray;
  1088.     newModel->ptr = lists[index];
  1089.     lists[index] = newModel;
  1090.  
  1091.     return (newModel->list);
  1092. }
  1093.