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