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