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