1 
2 /* Copyright (c) Mark J. Kilgard, 1994. */
3 
4 /**
5 (c) Copyright 1993, Silicon Graphics, Inc.
6 
7 ALL RIGHTS RESERVED
8 
9 Permission to use, copy, modify, and distribute this software
10 for any purpose and without fee is hereby granted, provided
11 that the above copyright notice appear in all copies and that
12 both the copyright notice and this permission notice appear in
13 supporting documentation, and that the name of Silicon
14 Graphics, Inc. not be used in advertising or publicity
15 pertaining to distribution of the software without specific,
16 written prior permission.
17 
18 THE MATERIAL EMBODIED ON THIS SOFTWARE IS PROVIDED TO YOU
19 "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, EXPRESS, IMPLIED OR
20 OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF
21 MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  IN NO
22 EVENT SHALL SILICON GRAPHICS, INC.  BE LIABLE TO YOU OR ANYONE
23 ELSE FOR ANY DIRECT, SPECIAL, INCIDENTAL, INDIRECT OR
24 CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER,
25 INCLUDING WITHOUT LIMITATION, LOSS OF PROFIT, LOSS OF USE,
26 SAVINGS OR REVENUE, OR THE CLAIMS OF THIRD PARTIES, WHETHER OR
27 NOT SILICON GRAPHICS, INC.  HAS BEEN ADVISED OF THE POSSIBILITY
28 OF SUCH LOSS, HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29 ARISING OUT OF OR IN CONNECTION WITH THE POSSESSION, USE OR
30 PERFORMANCE OF THIS SOFTWARE.
31 
32 US Government Users Restricted Rights
33 
34 Use, duplication, or disclosure by the Government is subject to
35 restrictions set forth in FAR 52.227.19(c)(2) or subparagraph
36 (c)(1)(ii) of the Rights in Technical Data and Computer
37 Software clause at DFARS 252.227-7013 and/or in similar or
38 successor clauses in the FAR or the DOD or NASA FAR
39 Supplement.  Unpublished-- rights reserved under the copyright
40 laws of the United States.  Contractor/manufacturer is Silicon
41 Graphics, Inc., 2011 N.  Shoreline Blvd., Mountain View, CA
42 94039-7311.
43 
44 OpenGL(TM) is a trademark of Silicon Graphics, Inc.
45 */
46 
47 #include <math.h>
48 #include <GL/glut_cgx.h>
49 #include "glutint.h"
50 
51 /* Some <math.h> files do not define M_PI... */
52 #ifndef M_PI
53 #define M_PI 3.14159265
54 #endif
55 
56 static GLUquadricObj *quadObj;
57 
58 #define QUAD_OBJ_INIT() { if(!quadObj) initQuadObj(); }
59 
60 static void
initQuadObj(void)61 initQuadObj(void)
62 {
63   quadObj = gluNewQuadric();
64   if (!quadObj)
65     __glutFatalError("out of memory.");
66 }
67 
68 /* CENTRY */
69 void APIENTRY
glutWireSphere(GLdouble radius,GLint slices,GLint stacks)70 glutWireSphere(GLdouble radius, GLint slices, GLint stacks)
71 {
72   QUAD_OBJ_INIT();
73   gluQuadricDrawStyle(quadObj, GLU_LINE);
74   gluQuadricNormals(quadObj, GLU_SMOOTH);
75   /* If we ever changed/used the texture or orientation state
76      of quadObj, we'd need to change it to the defaults here
77      with gluQuadricTexture and/or gluQuadricOrientation. */
78   gluSphere(quadObj, radius, slices, stacks);
79 }
80 
81 void APIENTRY
glutSolidSphere(GLdouble radius,GLint slices,GLint stacks)82 glutSolidSphere(GLdouble radius, GLint slices, GLint stacks)
83 {
84   QUAD_OBJ_INIT();
85   gluQuadricDrawStyle(quadObj, GLU_FILL);
86   gluQuadricNormals(quadObj, GLU_SMOOTH);
87   /* If we ever changed/used the texture or orientation state
88      of quadObj, we'd need to change it to the defaults here
89      with gluQuadricTexture and/or gluQuadricOrientation. */
90   gluSphere(quadObj, radius, slices, stacks);
91 }
92 
93 void APIENTRY
glutWireCone(GLdouble base,GLdouble height,GLint slices,GLint stacks)94 glutWireCone(GLdouble base, GLdouble height,
95   GLint slices, GLint stacks)
96 {
97   QUAD_OBJ_INIT();
98   gluQuadricDrawStyle(quadObj, GLU_LINE);
99   gluQuadricNormals(quadObj, GLU_SMOOTH);
100   /* If we ever changed/used the texture or orientation state
101      of quadObj, we'd need to change it to the defaults here
102      with gluQuadricTexture and/or gluQuadricOrientation. */
103   gluCylinder(quadObj, base, 0.0, height, slices, stacks);
104 }
105 
106 void APIENTRY
glutSolidCone(GLdouble base,GLdouble height,GLint slices,GLint stacks)107 glutSolidCone(GLdouble base, GLdouble height,
108   GLint slices, GLint stacks)
109 {
110   QUAD_OBJ_INIT();
111   gluQuadricDrawStyle(quadObj, GLU_FILL);
112   gluQuadricNormals(quadObj, GLU_SMOOTH);
113   /* If we ever changed/used the texture or orientation state
114      of quadObj, we'd need to change it to the defaults here
115      with gluQuadricTexture and/or gluQuadricOrientation. */
116   gluCylinder(quadObj, base, 0.0, height, slices, stacks);
117 }
118 
119 /* ENDCENTRY */
120 
121 static void
drawBox(GLfloat size,GLenum type)122 drawBox(GLfloat size, GLenum type)
123 {
124   static GLfloat n[6][3] =
125   {
126     {-1.0, 0.0, 0.0},
127     {0.0, 1.0, 0.0},
128     {1.0, 0.0, 0.0},
129     {0.0, -1.0, 0.0},
130     {0.0, 0.0, 1.0},
131     {0.0, 0.0, -1.0}
132   };
133   static GLint faces[6][4] =
134   {
135     {0, 1, 2, 3},
136     {3, 2, 6, 7},
137     {7, 6, 5, 4},
138     {4, 5, 1, 0},
139     {5, 6, 2, 1},
140     {7, 4, 0, 3}
141   };
142   GLfloat v[8][3];
143   GLint i;
144 
145   v[0][0] = v[1][0] = v[2][0] = v[3][0] = -size / 2;
146   v[4][0] = v[5][0] = v[6][0] = v[7][0] = size / 2;
147   v[0][1] = v[1][1] = v[4][1] = v[5][1] = -size / 2;
148   v[2][1] = v[3][1] = v[6][1] = v[7][1] = size / 2;
149   v[0][2] = v[3][2] = v[4][2] = v[7][2] = -size / 2;
150   v[1][2] = v[2][2] = v[5][2] = v[6][2] = size / 2;
151 
152   for (i = 0; i < 6; i++) {
153     glBegin(type);
154     glNormal3fv(&n[i][0]);
155     glVertex3fv(&v[faces[i][0]][0]);
156     glVertex3fv(&v[faces[i][1]][0]);
157     glVertex3fv(&v[faces[i][2]][0]);
158     glVertex3fv(&v[faces[i][3]][0]);
159     glEnd();
160   }
161 }
162 
163 /* CENTRY */
164 void APIENTRY
glutWireCube(GLdouble size)165 glutWireCube(GLdouble size)
166 {
167   drawBox(size, GL_LINE_LOOP);
168 }
169 
170 void APIENTRY
glutSolidCube(GLdouble size)171 glutSolidCube(GLdouble size)
172 {
173   drawBox(size, GL_QUADS);
174 }
175 
176 /* ENDCENTRY */
177 
178 static void
doughnut(GLfloat r,GLfloat R,GLint nsides,GLint rings,GLenum type)179 doughnut(GLfloat r, GLfloat R, GLint nsides,
180   GLint rings, GLenum type)
181 {
182   int i, j;
183   GLfloat theta, phi, theta1, phi1;
184   GLfloat p0[03], p1[3], p2[3], p3[3];
185   GLfloat n0[3], n1[3], n2[3], n3[3];
186 
187   for (i = 0; i < rings; i++) {
188     theta = (GLfloat) i *2.0 * M_PI / rings;
189     theta1 = (GLfloat) (i + 1) * 2.0 * M_PI / rings;
190     for (j = 0; j < nsides; j++) {
191       phi = (GLfloat) j *2.0 * M_PI / nsides;
192       phi1 = (GLfloat) (j + 1) * 2.0 * M_PI / nsides;
193 
194       p0[0] = cos(theta) * (R + r * cos(phi));
195       p0[1] = -sin(theta) * (R + r * cos(phi));
196       p0[2] = r * sin(phi);
197 
198       p1[0] = cos(theta1) * (R + r * cos(phi));
199       p1[1] = -sin(theta1) * (R + r * cos(phi));
200       p1[2] = r * sin(phi);
201 
202       p2[0] = cos(theta1) * (R + r * cos(phi1));
203       p2[1] = -sin(theta1) * (R + r * cos(phi1));
204       p2[2] = r * sin(phi1);
205 
206       p3[0] = cos(theta) * (R + r * cos(phi1));
207       p3[1] = -sin(theta) * (R + r * cos(phi1));
208       p3[2] = r * sin(phi1);
209 
210       n0[0] = cos(theta) * (cos(phi));
211       n0[1] = -sin(theta) * (cos(phi));
212       n0[2] = sin(phi);
213 
214       n1[0] = cos(theta1) * (cos(phi));
215       n1[1] = -sin(theta1) * (cos(phi));
216       n1[2] = sin(phi);
217 
218       n2[0] = cos(theta1) * (cos(phi1));
219       n2[1] = -sin(theta1) * (cos(phi1));
220       n2[2] = sin(phi1);
221 
222       n3[0] = cos(theta) * (cos(phi1));
223       n3[1] = -sin(theta) * (cos(phi1));
224       n3[2] = sin(phi1);
225 
226       glBegin(type);
227       glNormal3fv(n3);
228       glVertex3fv(p3);
229       glNormal3fv(n2);
230       glVertex3fv(p2);
231       glNormal3fv(n1);
232       glVertex3fv(p1);
233       glNormal3fv(n0);
234       glVertex3fv(p0);
235       glEnd();
236     }
237   }
238 }
239 
240 /* CENTRY */
241 void APIENTRY
glutWireTorus(GLdouble innerRadius,GLdouble outerRadius,GLint nsides,GLint rings)242 glutWireTorus(GLdouble innerRadius, GLdouble outerRadius,
243   GLint nsides, GLint rings)
244 {
245   doughnut(innerRadius, outerRadius,
246     nsides, rings, GL_LINE_LOOP);
247 }
248 
249 void APIENTRY
glutSolidTorus(GLdouble innerRadius,GLdouble outerRadius,GLint nsides,GLint rings)250 glutSolidTorus(GLdouble innerRadius, GLdouble outerRadius,
251   GLint nsides, GLint rings)
252 {
253   doughnut(innerRadius, outerRadius, nsides, rings, GL_QUADS);
254 }
255 
256 /* ENDCENTRY */
257 
258 static GLfloat dodec[20][3];
259 
260 static void
initDodecahedron(void)261 initDodecahedron(void)
262 {
263   GLfloat alpha, beta;
264 
265   alpha = sqrt(2.0 / (3.0 + sqrt(5.0)));
266   beta = 1.0 + sqrt(6.0 / (3.0 + sqrt(5.0)) -
267     2.0 + 2.0 * sqrt(2.0 / (3.0 + sqrt(5.0))));
268   /* *INDENT-OFF* */
269   dodec[0][0] = -alpha; dodec[0][1] = 0; dodec[0][2] = beta;
270   dodec[1][0] = alpha; dodec[1][1] = 0; dodec[1][2] = beta;
271   dodec[2][0] = -1; dodec[2][1] = -1; dodec[2][2] = -1;
272   dodec[3][0] = -1; dodec[3][1] = -1; dodec[3][2] = 1;
273   dodec[4][0] = -1; dodec[4][1] = 1; dodec[4][2] = -1;
274   dodec[5][0] = -1; dodec[5][1] = 1; dodec[5][2] = 1;
275   dodec[6][0] = 1; dodec[6][1] = -1; dodec[6][2] = -1;
276   dodec[7][0] = 1; dodec[7][1] = -1; dodec[7][2] = 1;
277   dodec[8][0] = 1; dodec[8][1] = 1; dodec[8][2] = -1;
278   dodec[9][0] = 1; dodec[9][1] = 1; dodec[9][2] = 1;
279   dodec[10][0] = beta; dodec[10][1] = alpha; dodec[10][2] = 0;
280   dodec[11][0] = beta; dodec[11][1] = -alpha; dodec[11][2] = 0;
281   dodec[12][0] = -beta; dodec[12][1] = alpha; dodec[12][2] = 0;
282   dodec[13][0] = -beta; dodec[13][1] = -alpha; dodec[13][2] = 0;
283   dodec[14][0] = -alpha; dodec[14][1] = 0; dodec[14][2] = -beta;
284   dodec[15][0] = alpha; dodec[15][1] = 0; dodec[15][2] = -beta;
285   dodec[16][0] = 0; dodec[16][1] = beta; dodec[16][2] = alpha;
286   dodec[17][0] = 0; dodec[17][1] = beta; dodec[17][2] = -alpha;
287   dodec[18][0] = 0; dodec[18][1] = -beta; dodec[18][2] = alpha;
288   dodec[19][0] = 0; dodec[19][1] = -beta; dodec[19][2] = -alpha;
289   /* *INDENT-ON* */
290 
291 }
292 
293 #define DIFF3(_a,_b,_c) { \
294     (_c)[0] = (_a)[0] - (_b)[0]; \
295     (_c)[1] = (_a)[1] - (_b)[1]; \
296     (_c)[2] = (_a)[2] - (_b)[2]; \
297 }
298 
299 static void
crossprod(GLfloat v1[3],GLfloat v2[3],GLfloat prod[3])300 crossprod(GLfloat v1[3], GLfloat v2[3], GLfloat prod[3])
301 {
302   GLfloat p[3];         /* in case prod == v1 or v2 */
303 
304   p[0] = v1[1] * v2[2] - v2[1] * v1[2];
305   p[1] = v1[2] * v2[0] - v2[2] * v1[0];
306   p[2] = v1[0] * v2[1] - v2[0] * v1[1];
307   prod[0] = p[0];
308   prod[1] = p[1];
309   prod[2] = p[2];
310 }
311 
312 static void
normalize(GLfloat v[3])313 normalize(GLfloat v[3])
314 {
315   GLfloat d;
316 
317   d = sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
318   if (d == 0.0) {
319     __glutWarning("normalize: zero length vector");
320     v[0] = d = 1.0;
321   }
322   d = 1 / d;
323   v[0] *= d;
324   v[1] *= d;
325   v[2] *= d;
326 }
327 
328 static void
pentagon(int a,int b,int c,int d,int e,GLenum shadeType)329 pentagon(int a, int b, int c, int d, int e, GLenum shadeType)
330 {
331   GLfloat n0[3], d1[3], d2[3];
332 
333   DIFF3(dodec[a], dodec[b], d1);
334   DIFF3(dodec[b], dodec[c], d2);
335   crossprod(d1, d2, n0);
336   normalize(n0);
337 
338   glBegin(shadeType);
339   glNormal3fv(n0);
340   glVertex3fv(&dodec[a][0]);
341   glVertex3fv(&dodec[b][0]);
342   glVertex3fv(&dodec[c][0]);
343   glVertex3fv(&dodec[d][0]);
344   glVertex3fv(&dodec[e][0]);
345   glEnd();
346 }
347 
348 static void
dodecahedron(GLenum type)349 dodecahedron(GLenum type)
350 {
351   static int inited = 0;
352 
353   if (inited == 0) {
354     inited = 1;
355     initDodecahedron();
356   }
357   pentagon(0, 1, 9, 16, 5, type);
358   pentagon(1, 0, 3, 18, 7, type);
359   pentagon(1, 7, 11, 10, 9, type);
360   pentagon(11, 7, 18, 19, 6, type);
361   pentagon(8, 17, 16, 9, 10, type);
362   pentagon(2, 14, 15, 6, 19, type);
363   pentagon(2, 13, 12, 4, 14, type);
364   pentagon(2, 19, 18, 3, 13, type);
365   pentagon(3, 0, 5, 12, 13, type);
366   pentagon(6, 15, 8, 10, 11, type);
367   pentagon(4, 17, 8, 15, 14, type);
368   pentagon(4, 12, 5, 16, 17, type);
369 }
370 
371 /* CENTRY */
372 void APIENTRY
glutWireDodecahedron(void)373 glutWireDodecahedron(void)
374 {
375   dodecahedron(GL_LINE_LOOP);
376 }
377 
378 void APIENTRY
glutSolidDodecahedron(void)379 glutSolidDodecahedron(void)
380 {
381   dodecahedron(GL_TRIANGLE_FAN);
382 }
383 
384 /* ENDCENTRY */
385 
386 static void
recorditem(GLfloat * n1,GLfloat * n2,GLfloat * n3,GLenum shadeType)387 recorditem(GLfloat * n1, GLfloat * n2, GLfloat * n3,
388   GLenum shadeType)
389 {
390   GLfloat q0[3], q1[3];
391 
392   DIFF3(n1, n2, q0);
393   DIFF3(n2, n3, q1);
394   crossprod(q0, q1, q1);
395   normalize(q1);
396 
397   glBegin(shadeType);
398   glNormal3fv(q1);
399   glVertex3fv(n1);
400   glVertex3fv(n2);
401   glVertex3fv(n3);
402   glEnd();
403 }
404 
405 static void
subdivide(GLfloat * v0,GLfloat * v1,GLfloat * v2,GLenum shadeType)406 subdivide(GLfloat * v0, GLfloat * v1, GLfloat * v2,
407   GLenum shadeType)
408 {
409   int depth;
410   GLfloat w0[3], w1[3], w2[3];
411   GLfloat l;
412   int i, j, k, n;
413 
414   depth = 1;
415   for (i = 0; i < depth; i++) {
416     for (j = 0; i + j < depth; j++) {
417       k = depth - i - j;
418       for (n = 0; n < 3; n++) {
419         w0[n] = (i * v0[n] + j * v1[n] + k * v2[n]) / depth;
420         w1[n] = ((i + 1) * v0[n] + j * v1[n] + (k - 1) * v2[n])
421           / depth;
422         w2[n] = (i * v0[n] + (j + 1) * v1[n] + (k - 1) * v2[n])
423           / depth;
424       }
425       l = sqrt(w0[0] * w0[0] + w0[1] * w0[1] + w0[2] * w0[2]);
426       w0[0] /= l;
427       w0[1] /= l;
428       w0[2] /= l;
429       l = sqrt(w1[0] * w1[0] + w1[1] * w1[1] + w1[2] * w1[2]);
430       w1[0] /= l;
431       w1[1] /= l;
432       w1[2] /= l;
433       l = sqrt(w2[0] * w2[0] + w2[1] * w2[1] + w2[2] * w2[2]);
434       w2[0] /= l;
435       w2[1] /= l;
436       w2[2] /= l;
437       recorditem(w1, w0, w2, shadeType);
438     }
439   }
440 }
441 
442 static void
drawtriangle(int i,GLfloat data[][3],int ndx[][3],GLenum shadeType)443 drawtriangle(int i, GLfloat data[][3], int ndx[][3],
444   GLenum shadeType)
445 {
446   GLfloat *x0, *x1, *x2;
447 
448   x0 = data[ndx[i][0]];
449   x1 = data[ndx[i][1]];
450   x2 = data[ndx[i][2]];
451   subdivide(x0, x1, x2, shadeType);
452 }
453 
454 /* octahedron data: The octahedron produced is centered at the
455    origin and has radius 1.0 */
456 static GLfloat odata[6][3] =
457 {
458   {1.0, 0.0, 0.0},
459   {-1.0, 0.0, 0.0},
460   {0.0, 1.0, 0.0},
461   {0.0, -1.0, 0.0},
462   {0.0, 0.0, 1.0},
463   {0.0, 0.0, -1.0}
464 };
465 
466 static int ondex[8][3] =
467 {
468   {0, 4, 2},
469   {1, 2, 4},
470   {0, 3, 4},
471   {1, 4, 3},
472   {0, 2, 5},
473   {1, 5, 2},
474   {0, 5, 3},
475   {1, 3, 5}
476 };
477 
478 static void
octahedron(GLenum shadeType)479 octahedron(GLenum shadeType)
480 {
481   int i;
482 
483   for (i = 0; i < 8; i++) {
484     drawtriangle(i, odata, ondex, shadeType);
485   }
486 }
487 
488 /* CENTRY */
489 void APIENTRY
glutWireOctahedron(void)490 glutWireOctahedron(void)
491 {
492   octahedron(GL_LINE_LOOP);
493 }
494 
495 void APIENTRY
glutSolidOctahedron(void)496 glutSolidOctahedron(void)
497 {
498   octahedron(GL_TRIANGLES);
499 }
500 
501 /* ENDCENTRY */
502 
503 /* icosahedron data: These numbers are rigged to make an
504    icosahedron of radius 1.0 */
505 
506 #define X .525731112119133606
507 #define Z .850650808352039932
508 
509 static GLfloat idata[12][3] =
510 {
511   {-X, 0, Z},
512   {X, 0, Z},
513   {-X, 0, -Z},
514   {X, 0, -Z},
515   {0, Z, X},
516   {0, Z, -X},
517   {0, -Z, X},
518   {0, -Z, -X},
519   {Z, X, 0},
520   {-Z, X, 0},
521   {Z, -X, 0},
522   {-Z, -X, 0}
523 };
524 
525 static int index[20][3] =
526 {
527   {0, 4, 1},
528   {0, 9, 4},
529   {9, 5, 4},
530   {4, 5, 8},
531   {4, 8, 1},
532   {8, 10, 1},
533   {8, 3, 10},
534   {5, 3, 8},
535   {5, 2, 3},
536   {2, 7, 3},
537   {7, 10, 3},
538   {7, 6, 10},
539   {7, 11, 6},
540   {11, 0, 6},
541   {0, 1, 6},
542   {6, 1, 10},
543   {9, 0, 11},
544   {9, 11, 2},
545   {9, 2, 5},
546   {7, 2, 11},
547 };
548 
549 static void
icosahedron(GLenum shadeType)550 icosahedron(GLenum shadeType)
551 {
552   int i;
553 
554   for (i = 0; i < 20; i++) {
555     drawtriangle(i, idata, index, shadeType);
556   }
557 }
558 
559 /* CENTRY */
560 void APIENTRY
glutWireIcosahedron(void)561 glutWireIcosahedron(void)
562 {
563   icosahedron(GL_LINE_LOOP);
564 }
565 
566 void APIENTRY
glutSolidIcosahedron(void)567 glutSolidIcosahedron(void)
568 {
569   icosahedron(GL_TRIANGLES);
570 }
571 
572 /* ENDCENTRY */
573 
574 /* tetrahedron data: */
575 
576 #define T       1.73205080756887729
577 
578 static GLfloat tdata[4][3] =
579 {
580   {T, T, T},
581   {T, -T, -T},
582   {-T, T, -T},
583   {-T, -T, T}
584 };
585 
586 static int tndex[4][3] =
587 {
588   {0, 1, 3},
589   {2, 1, 0},
590   {3, 2, 0},
591   {1, 2, 3}
592 };
593 
594 static void
tetrahedron(GLenum shadeType)595 tetrahedron(GLenum shadeType)
596 {
597   int i;
598 
599   for (i = 0; i < 4; i++)
600     drawtriangle(i, tdata, tndex, shadeType);
601 }
602 
603 /* CENTRY */
604 void APIENTRY
glutWireTetrahedron(void)605 glutWireTetrahedron(void)
606 {
607   tetrahedron(GL_LINE_LOOP);
608 }
609 
610 void APIENTRY
glutSolidTetrahedron(void)611 glutSolidTetrahedron(void)
612 {
613   tetrahedron(GL_TRIANGLES);
614 }
615 
616 /* ENDCENTRY */
617