xref: /haiku/src/libs/glut/glut_shapes.c (revision 1026b0a1a76dc88927bb8175c470f638dc5464ee)
1 
2 /* Copyright (c) Mark J. Kilgard, 1994, 1997. */
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 "glutint.h"
49 
50 /* Some <math.h> files do not define M_PI... */
51 #ifndef M_PI
52 #define M_PI 3.14159265358979323846
53 #endif
54 
55 static GLUquadricObj *quadObj;
56 
57 #define QUAD_OBJ_INIT() { if(!quadObj) initQuadObj(); }
58 
59 static void
60 initQuadObj(void)
61 {
62   quadObj = gluNewQuadric();
63   if (!quadObj)
64     __glutFatalError("out of memory.");
65 }
66 
67 /* CENTRY */
68 void APIENTRY
69 glutWireSphere(GLdouble radius, GLint slices, GLint stacks)
70 {
71   QUAD_OBJ_INIT();
72   gluQuadricDrawStyle(quadObj, GLU_LINE);
73   gluQuadricNormals(quadObj, GLU_SMOOTH);
74   /* If we ever changed/used the texture or orientation state
75      of quadObj, we'd need to change it to the defaults here
76      with gluQuadricTexture and/or gluQuadricOrientation. */
77   gluSphere(quadObj, radius, slices, stacks);
78 }
79 
80 void APIENTRY
81 glutSolidSphere(GLdouble radius, GLint slices, GLint stacks)
82 {
83   QUAD_OBJ_INIT();
84   gluQuadricDrawStyle(quadObj, GLU_FILL);
85   gluQuadricNormals(quadObj, GLU_SMOOTH);
86   /* If we ever changed/used the texture or orientation state
87      of quadObj, we'd need to change it to the defaults here
88      with gluQuadricTexture and/or gluQuadricOrientation. */
89   gluSphere(quadObj, radius, slices, stacks);
90 }
91 
92 void APIENTRY
93 glutWireCone(GLdouble base, GLdouble height,
94   GLint slices, GLint stacks)
95 {
96   QUAD_OBJ_INIT();
97   gluQuadricDrawStyle(quadObj, GLU_LINE);
98   gluQuadricNormals(quadObj, GLU_SMOOTH);
99   /* If we ever changed/used the texture or orientation state
100      of quadObj, we'd need to change it to the defaults here
101      with gluQuadricTexture and/or gluQuadricOrientation. */
102   gluCylinder(quadObj, base, 0.0, height, slices, stacks);
103 }
104 
105 void APIENTRY
106 glutSolidCone(GLdouble base, GLdouble height,
107   GLint slices, GLint stacks)
108 {
109   QUAD_OBJ_INIT();
110   gluQuadricDrawStyle(quadObj, GLU_FILL);
111   gluQuadricNormals(quadObj, GLU_SMOOTH);
112   /* If we ever changed/used the texture or orientation state
113      of quadObj, we'd need to change it to the defaults here
114      with gluQuadricTexture and/or gluQuadricOrientation. */
115   gluCylinder(quadObj, base, 0.0, height, slices, stacks);
116 }
117 
118 /* ENDCENTRY */
119 
120 static void
121 drawBox(GLfloat size, GLenum type)
122 {
123   static GLfloat n[6][3] =
124   {
125     {-1.0, 0.0, 0.0},
126     {0.0, 1.0, 0.0},
127     {1.0, 0.0, 0.0},
128     {0.0, -1.0, 0.0},
129     {0.0, 0.0, 1.0},
130     {0.0, 0.0, -1.0}
131   };
132   static GLint faces[6][4] =
133   {
134     {0, 1, 2, 3},
135     {3, 2, 6, 7},
136     {7, 6, 5, 4},
137     {4, 5, 1, 0},
138     {5, 6, 2, 1},
139     {7, 4, 0, 3}
140   };
141   GLfloat v[8][3];
142   GLint i;
143 
144   v[0][0] = v[1][0] = v[2][0] = v[3][0] = -size / 2;
145   v[4][0] = v[5][0] = v[6][0] = v[7][0] = size / 2;
146   v[0][1] = v[1][1] = v[4][1] = v[5][1] = -size / 2;
147   v[2][1] = v[3][1] = v[6][1] = v[7][1] = size / 2;
148   v[0][2] = v[3][2] = v[4][2] = v[7][2] = -size / 2;
149   v[1][2] = v[2][2] = v[5][2] = v[6][2] = size / 2;
150 
151   for (i = 5; i >= 0; i--) {
152     glBegin(type);
153     glNormal3fv(&n[i][0]);
154     glVertex3fv(&v[faces[i][0]][0]);
155     glVertex3fv(&v[faces[i][1]][0]);
156     glVertex3fv(&v[faces[i][2]][0]);
157     glVertex3fv(&v[faces[i][3]][0]);
158     glEnd();
159   }
160 }
161 
162 /* CENTRY */
163 void APIENTRY
164 glutWireCube(GLdouble size)
165 {
166   drawBox(size, GL_LINE_LOOP);
167 }
168 
169 void APIENTRY
170 glutSolidCube(GLdouble size)
171 {
172   drawBox(size, GL_QUADS);
173 }
174 
175 /* ENDCENTRY */
176 
177 static void
178 doughnut(GLfloat r, GLfloat R, GLint nsides, GLint rings)
179 {
180   int i, j;
181   GLfloat theta, phi, theta1;
182   GLfloat cosTheta, sinTheta;
183   GLfloat cosTheta1, sinTheta1;
184   GLfloat ringDelta, sideDelta;
185 
186   ringDelta = 2.0 * M_PI / rings;
187   sideDelta = 2.0 * M_PI / nsides;
188 
189   theta = 0.0;
190   cosTheta = 1.0;
191   sinTheta = 0.0;
192   for (i = rings - 1; i >= 0; i--) {
193     theta1 = theta + ringDelta;
194     cosTheta1 = cos(theta1);
195     sinTheta1 = sin(theta1);
196     glBegin(GL_QUAD_STRIP);
197     phi = 0.0;
198     for (j = nsides; j >= 0; j--) {
199       GLfloat cosPhi, sinPhi, dist;
200 
201       phi += sideDelta;
202       cosPhi = cos(phi);
203       sinPhi = sin(phi);
204       dist = R + r * cosPhi;
205 
206       glNormal3f(cosTheta1 * cosPhi, -sinTheta1 * cosPhi, sinPhi);
207       glVertex3f(cosTheta1 * dist, -sinTheta1 * dist, r * sinPhi);
208       glNormal3f(cosTheta * cosPhi, -sinTheta * cosPhi, sinPhi);
209       glVertex3f(cosTheta * dist, -sinTheta * dist,  r * sinPhi);
210     }
211     glEnd();
212     theta = theta1;
213     cosTheta = cosTheta1;
214     sinTheta = sinTheta1;
215   }
216 }
217 
218 /* CENTRY */
219 void APIENTRY
220 glutWireTorus(GLdouble innerRadius, GLdouble outerRadius,
221   GLint nsides, GLint rings)
222 {
223   glPushAttrib(GL_POLYGON_BIT);
224   glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
225   doughnut(innerRadius, outerRadius, nsides, rings);
226   glPopAttrib();
227 }
228 
229 void APIENTRY
230 glutSolidTorus(GLdouble innerRadius, GLdouble outerRadius,
231   GLint nsides, GLint rings)
232 {
233   doughnut(innerRadius, outerRadius, nsides, rings);
234 }
235 
236 /* ENDCENTRY */
237 
238 static GLfloat dodec[20][3];
239 
240 static void
241 initDodecahedron(void)
242 {
243   GLfloat alpha, beta;
244 
245   alpha = sqrt(2.0 / (3.0 + sqrt(5.0)));
246   beta = 1.0 + sqrt(6.0 / (3.0 + sqrt(5.0)) -
247     2.0 + 2.0 * sqrt(2.0 / (3.0 + sqrt(5.0))));
248   /* *INDENT-OFF* */
249   dodec[0][0] = -alpha; dodec[0][1] = 0; dodec[0][2] = beta;
250   dodec[1][0] = alpha; dodec[1][1] = 0; dodec[1][2] = beta;
251   dodec[2][0] = -1; dodec[2][1] = -1; dodec[2][2] = -1;
252   dodec[3][0] = -1; dodec[3][1] = -1; dodec[3][2] = 1;
253   dodec[4][0] = -1; dodec[4][1] = 1; dodec[4][2] = -1;
254   dodec[5][0] = -1; dodec[5][1] = 1; dodec[5][2] = 1;
255   dodec[6][0] = 1; dodec[6][1] = -1; dodec[6][2] = -1;
256   dodec[7][0] = 1; dodec[7][1] = -1; dodec[7][2] = 1;
257   dodec[8][0] = 1; dodec[8][1] = 1; dodec[8][2] = -1;
258   dodec[9][0] = 1; dodec[9][1] = 1; dodec[9][2] = 1;
259   dodec[10][0] = beta; dodec[10][1] = alpha; dodec[10][2] = 0;
260   dodec[11][0] = beta; dodec[11][1] = -alpha; dodec[11][2] = 0;
261   dodec[12][0] = -beta; dodec[12][1] = alpha; dodec[12][2] = 0;
262   dodec[13][0] = -beta; dodec[13][1] = -alpha; dodec[13][2] = 0;
263   dodec[14][0] = -alpha; dodec[14][1] = 0; dodec[14][2] = -beta;
264   dodec[15][0] = alpha; dodec[15][1] = 0; dodec[15][2] = -beta;
265   dodec[16][0] = 0; dodec[16][1] = beta; dodec[16][2] = alpha;
266   dodec[17][0] = 0; dodec[17][1] = beta; dodec[17][2] = -alpha;
267   dodec[18][0] = 0; dodec[18][1] = -beta; dodec[18][2] = alpha;
268   dodec[19][0] = 0; dodec[19][1] = -beta; dodec[19][2] = -alpha;
269   /* *INDENT-ON* */
270 
271 }
272 
273 #define DIFF3(_a,_b,_c) { \
274     (_c)[0] = (_a)[0] - (_b)[0]; \
275     (_c)[1] = (_a)[1] - (_b)[1]; \
276     (_c)[2] = (_a)[2] - (_b)[2]; \
277 }
278 
279 static void
280 crossprod(GLfloat v1[3], GLfloat v2[3], GLfloat prod[3])
281 {
282   GLfloat p[3];         /* in case prod == v1 or v2 */
283 
284   p[0] = v1[1] * v2[2] - v2[1] * v1[2];
285   p[1] = v1[2] * v2[0] - v2[2] * v1[0];
286   p[2] = v1[0] * v2[1] - v2[0] * v1[1];
287   prod[0] = p[0];
288   prod[1] = p[1];
289   prod[2] = p[2];
290 }
291 
292 static void
293 normalize(GLfloat v[3])
294 {
295   GLfloat d;
296 
297   d = sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
298   if (d == 0.0) {
299     __glutWarning("normalize: zero length vector");
300     v[0] = d = 1.0;
301   }
302   d = 1 / d;
303   v[0] *= d;
304   v[1] *= d;
305   v[2] *= d;
306 }
307 
308 static void
309 pentagon(int a, int b, int c, int d, int e, GLenum shadeType)
310 {
311   GLfloat n0[3], d1[3], d2[3];
312 
313   DIFF3(dodec[a], dodec[b], d1);
314   DIFF3(dodec[b], dodec[c], d2);
315   crossprod(d1, d2, n0);
316   normalize(n0);
317 
318   glBegin(shadeType);
319   glNormal3fv(n0);
320   glVertex3fv(&dodec[a][0]);
321   glVertex3fv(&dodec[b][0]);
322   glVertex3fv(&dodec[c][0]);
323   glVertex3fv(&dodec[d][0]);
324   glVertex3fv(&dodec[e][0]);
325   glEnd();
326 }
327 
328 static void
329 dodecahedron(GLenum type)
330 {
331   static int inited = 0;
332 
333   if (inited == 0) {
334     inited = 1;
335     initDodecahedron();
336   }
337   pentagon(0, 1, 9, 16, 5, type);
338   pentagon(1, 0, 3, 18, 7, type);
339   pentagon(1, 7, 11, 10, 9, type);
340   pentagon(11, 7, 18, 19, 6, type);
341   pentagon(8, 17, 16, 9, 10, type);
342   pentagon(2, 14, 15, 6, 19, type);
343   pentagon(2, 13, 12, 4, 14, type);
344   pentagon(2, 19, 18, 3, 13, type);
345   pentagon(3, 0, 5, 12, 13, type);
346   pentagon(6, 15, 8, 10, 11, type);
347   pentagon(4, 17, 8, 15, 14, type);
348   pentagon(4, 12, 5, 16, 17, type);
349 }
350 
351 /* CENTRY */
352 void APIENTRY
353 glutWireDodecahedron(void)
354 {
355   dodecahedron(GL_LINE_LOOP);
356 }
357 
358 void APIENTRY
359 glutSolidDodecahedron(void)
360 {
361   dodecahedron(GL_TRIANGLE_FAN);
362 }
363 
364 /* ENDCENTRY */
365 
366 static void
367 recorditem(GLfloat * n1, GLfloat * n2, GLfloat * n3,
368   GLenum shadeType)
369 {
370   GLfloat q0[3], q1[3];
371 
372   DIFF3(n1, n2, q0);
373   DIFF3(n2, n3, q1);
374   crossprod(q0, q1, q1);
375   normalize(q1);
376 
377   glBegin(shadeType);
378   glNormal3fv(q1);
379   glVertex3fv(n1);
380   glVertex3fv(n2);
381   glVertex3fv(n3);
382   glEnd();
383 }
384 
385 static void
386 subdivide(GLfloat * v0, GLfloat * v1, GLfloat * v2,
387   GLenum shadeType)
388 {
389   int depth;
390   GLfloat w0[3], w1[3], w2[3];
391   GLfloat l;
392   int i, j, k, n;
393 
394   depth = 1;
395   for (i = 0; i < depth; i++) {
396     for (j = 0; i + j < depth; j++) {
397       k = depth - i - j;
398       for (n = 0; n < 3; n++) {
399         w0[n] = (i * v0[n] + j * v1[n] + k * v2[n]) / depth;
400         w1[n] = ((i + 1) * v0[n] + j * v1[n] + (k - 1) * v2[n])
401           / depth;
402         w2[n] = (i * v0[n] + (j + 1) * v1[n] + (k - 1) * v2[n])
403           / depth;
404       }
405       l = sqrt(w0[0] * w0[0] + w0[1] * w0[1] + w0[2] * w0[2]);
406       w0[0] /= l;
407       w0[1] /= l;
408       w0[2] /= l;
409       l = sqrt(w1[0] * w1[0] + w1[1] * w1[1] + w1[2] * w1[2]);
410       w1[0] /= l;
411       w1[1] /= l;
412       w1[2] /= l;
413       l = sqrt(w2[0] * w2[0] + w2[1] * w2[1] + w2[2] * w2[2]);
414       w2[0] /= l;
415       w2[1] /= l;
416       w2[2] /= l;
417       recorditem(w1, w0, w2, shadeType);
418     }
419   }
420 }
421 
422 static void
423 drawtriangle(int i, GLfloat data[][3], int ndx[][3],
424   GLenum shadeType)
425 {
426   GLfloat *x0, *x1, *x2;
427 
428   x0 = data[ndx[i][0]];
429   x1 = data[ndx[i][1]];
430   x2 = data[ndx[i][2]];
431   subdivide(x0, x1, x2, shadeType);
432 }
433 
434 /* octahedron data: The octahedron produced is centered at the
435    origin and has radius 1.0 */
436 static GLfloat odata[6][3] =
437 {
438   {1.0, 0.0, 0.0},
439   {-1.0, 0.0, 0.0},
440   {0.0, 1.0, 0.0},
441   {0.0, -1.0, 0.0},
442   {0.0, 0.0, 1.0},
443   {0.0, 0.0, -1.0}
444 };
445 
446 static int ondex[8][3] =
447 {
448   {0, 4, 2},
449   {1, 2, 4},
450   {0, 3, 4},
451   {1, 4, 3},
452   {0, 2, 5},
453   {1, 5, 2},
454   {0, 5, 3},
455   {1, 3, 5}
456 };
457 
458 static void
459 octahedron(GLenum shadeType)
460 {
461   int i;
462 
463   for (i = 7; i >= 0; i--) {
464     drawtriangle(i, odata, ondex, shadeType);
465   }
466 }
467 
468 /* CENTRY */
469 void APIENTRY
470 glutWireOctahedron(void)
471 {
472   octahedron(GL_LINE_LOOP);
473 }
474 
475 void APIENTRY
476 glutSolidOctahedron(void)
477 {
478   octahedron(GL_TRIANGLES);
479 }
480 
481 /* ENDCENTRY */
482 
483 /* icosahedron data: These numbers are rigged to make an
484    icosahedron of radius 1.0 */
485 
486 #define X .525731112119133606
487 #define Z .850650808352039932
488 
489 static GLfloat idata[12][3] =
490 {
491   {-X, 0, Z},
492   {X, 0, Z},
493   {-X, 0, -Z},
494   {X, 0, -Z},
495   {0, Z, X},
496   {0, Z, -X},
497   {0, -Z, X},
498   {0, -Z, -X},
499   {Z, X, 0},
500   {-Z, X, 0},
501   {Z, -X, 0},
502   {-Z, -X, 0}
503 };
504 
505 static int index[20][3] =
506 {
507   {0, 4, 1},
508   {0, 9, 4},
509   {9, 5, 4},
510   {4, 5, 8},
511   {4, 8, 1},
512   {8, 10, 1},
513   {8, 3, 10},
514   {5, 3, 8},
515   {5, 2, 3},
516   {2, 7, 3},
517   {7, 10, 3},
518   {7, 6, 10},
519   {7, 11, 6},
520   {11, 0, 6},
521   {0, 1, 6},
522   {6, 1, 10},
523   {9, 0, 11},
524   {9, 11, 2},
525   {9, 2, 5},
526   {7, 2, 11},
527 };
528 
529 static void
530 icosahedron(GLenum shadeType)
531 {
532   int i;
533 
534   for (i = 19; i >= 0; i--) {
535     drawtriangle(i, idata, index, shadeType);
536   }
537 }
538 
539 /* CENTRY */
540 void APIENTRY
541 glutWireIcosahedron(void)
542 {
543   icosahedron(GL_LINE_LOOP);
544 }
545 
546 void APIENTRY
547 glutSolidIcosahedron(void)
548 {
549   icosahedron(GL_TRIANGLES);
550 }
551 
552 /* ENDCENTRY */
553 
554 /* tetrahedron data: */
555 
556 #define T       1.73205080756887729
557 
558 static GLfloat tdata[4][3] =
559 {
560   {T, T, T},
561   {T, -T, -T},
562   {-T, T, -T},
563   {-T, -T, T}
564 };
565 
566 static int tndex[4][3] =
567 {
568   {0, 1, 3},
569   {2, 1, 0},
570   {3, 2, 0},
571   {1, 2, 3}
572 };
573 
574 static void
575 tetrahedron(GLenum shadeType)
576 {
577   int i;
578 
579   for (i = 3; i >= 0; i--)
580     drawtriangle(i, tdata, tndex, shadeType);
581 }
582 
583 /* CENTRY */
584 void APIENTRY
585 glutWireTetrahedron(void)
586 {
587   tetrahedron(GL_LINE_LOOP);
588 }
589 
590 void APIENTRY
591 glutSolidTetrahedron(void)
592 {
593   tetrahedron(GL_TRIANGLES);
594 }
595 
596 /* ENDCENTRY */
597