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