Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1134 lines
33 KiB

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