blob: 047d571c70583a4c2fc09419c8cec09ca300a6d8 [file] [log] [blame]
jtgafb833d1999-08-19 00:55:39 +00001
2/*-
3 * morph3d.c - Shows 3D morphing objects
4 *
5 * Converted to GLUT by brianp on 1/1/98
6 *
7 * This program was inspired on a WindowsNT(R)'s screen saver. It was written
8 * from scratch and it was not based on any other source code.
9 *
10 * Porting it to xlock (the final objective of this code since the moment I
11 * decided to create it) was possible by comparing the original Mesa's gear
12 * demo with it's ported version, so thanks for Danny Sung for his indirect
13 * help (look at gear.c in xlock source tree). NOTE: At the moment this code
14 * was sent to Brian Paul for package inclusion, the XLock Version was not
15 * available. In fact, I'll wait it to appear on the next Mesa release (If you
16 * are reading this, it means THIS release) to send it for xlock package
17 * inclusion). It will probably there be a GLUT version too.
18 *
19 * Thanks goes also to Brian Paul for making it possible and inexpensive
20 * to use OpenGL at home.
21 *
22 * Since I'm not a native english speaker, my apologies for any gramatical
23 * mistake.
24 *
25 * My e-mail addresses are
26 *
27 * vianna@cat.cbpf.br
28 * and
29 * marcelo@venus.rdc.puc-rio.br
30 *
31 * Marcelo F. Vianna (Feb-13-1997)
32 */
33
34/*
35This document is VERY incomplete, but tries to describe the mathematics used
36in the program. At this moment it just describes how the polyhedra are
37generated. On futhurer versions, this document will be probabbly improved.
38
39Since I'm not a native english speaker, my apologies for any gramatical
40mistake.
41
42Marcelo Fernandes Vianna
43- Undergraduate in Computer Engeneering at Catholic Pontifical University
44- of Rio de Janeiro (PUC-Rio) Brasil.
45- e-mail: vianna@cat.cbpf.br or marcelo@venus.rdc.puc-rio.br
46- Feb-13-1997
47
48POLYHEDRA GENERATION
49
50For the purpose of this program it's not sufficient to know the polyhedra
51vertexes coordinates. Since the morphing algorithm applies a nonlinear
52transformation over the surfaces (faces) of the polyhedron, each face has
53to be divided into smaller ones. The morphing algorithm needs to transform
54each vertex of these smaller faces individually. It's a very time consoming
55task.
56
57In order to reduce calculation overload, and since all the macro faces of
58the polyhedron are transformed by the same way, the generation is made by
59creating only one face of the polyhedron, morphing it and then rotating it
60around the polyhedron center.
61
62What we need to know is the face radius of the polyhedron (the radius of
63the inscribed sphere) and the angle between the center of two adjacent
64faces using the center of the sphere as the angle's vertex.
65
66The face radius of the regular polyhedra are known values which I decided
67to not waste my time calculating. Following is a table of face radius for
68the regular polyhedra with edge length = 1:
69
70 TETRAHEDRON : 1/(2*sqrt(2))/sqrt(3)
71 CUBE : 1/2
72 OCTAHEDRON : 1/sqrt(6)
73 DODECAHEDRON : T^2 * sqrt((T+2)/5) / 2 -> where T=(sqrt(5)+1)/2
74 ICOSAHEDRON : (3*sqrt(3)+sqrt(15))/12
75
76I've not found any reference about the mentioned angles, so I needed to
77calculate them, not a trivial task until I figured out how :)
78Curiously these angles are the same for the tetrahedron and octahedron.
79A way to obtain this value is inscribing the tetrahedron inside the cube
80by matching their vertexes. So you'll notice that the remaining unmatched
81vertexes are in the same straight line starting in the cube/tetrahedron
82center and crossing the center of each tetrahedron's face. At this point
83it's easy to obtain the bigger angle of the isosceles triangle formed by
84the center of the cube and two opposite vertexes on the same cube face.
85The edges of this triangle have the following lenghts: sqrt(2) for the base
86and sqrt(3)/2 for the other two other edges. So the angle we want is:
87 +-----------------------------------------------------------+
88 | 2*ARCSIN(sqrt(2)/sqrt(3)) = 109.47122063449069174 degrees |
89 +-----------------------------------------------------------+
90For the cube this angle is obvious, but just for formality it can be
91easily obtained because we also know it's isosceles edge lenghts:
92sqrt(2)/2 for the base and 1/2 for the other two edges. So the angle we
93want is:
94 +-----------------------------------------------------------+
95 | 2*ARCSIN((sqrt(2)/2)/1) = 90.000000000000000000 degrees |
96 +-----------------------------------------------------------+
97For the octahedron we use the same idea used for the tetrahedron, but now
98we inscribe the cube inside the octahedron so that all cubes's vertexes
99matches excatly the center of each octahedron's face. It's now clear that
100this angle is the same of the thetrahedron one:
101 +-----------------------------------------------------------+
102 | 2*ARCSIN(sqrt(2)/sqrt(3)) = 109.47122063449069174 degrees |
103 +-----------------------------------------------------------+
104For the dodecahedron it's a little bit harder because it's only relationship
105with the cube is useless to us. So we need to solve the problem by another
106way. The concept of Face radius also exists on 2D polygons with the name
107Edge radius:
108 Edge Radius For Pentagon (ERp)
109 ERp = (1/2)/TAN(36 degrees) * VRp = 0.6881909602355867905
110 (VRp is the pentagon's vertex radio).
111 Face Radius For Dodecahedron
112 FRd = T^2 * sqrt((T+2)/5) / 2 = 1.1135163644116068404
113Why we need ERp? Well, ERp and FRd segments forms a 90 degrees angle,
114completing this triangle, the lesser angle is a half of the angle we are
115looking for, so this angle is:
116 +-----------------------------------------------------------+
117 | 2*ARCTAN(ERp/FRd) = 63.434948822922009981 degrees |
118 +-----------------------------------------------------------+
119For the icosahedron we can use the same method used for dodecahedron (well
120the method used for dodecahedron may be used for all regular polyhedra)
121 Edge Radius For Triangle (this one is well known: 1/3 of the triangle height)
122 ERt = sin(60)/3 = sqrt(3)/6 = 0.2886751345948128655
123 Face Radius For Icosahedron
124 FRi= (3*sqrt(3)+sqrt(15))/12 = 0.7557613140761707538
125So the angle is:
126 +-----------------------------------------------------------+
127 | 2*ARCTAN(ERt/FRi) = 41.810314895778596167 degrees |
128 +-----------------------------------------------------------+
129
130*/
131
132
133#include <stdio.h>
134#include <stdlib.h>
135#ifndef _WIN32
136#include <unistd.h>
137#endif
138#include <GL/glut.h>
139#include <math.h>
140#include <string.h>
141
142#define Scale 0.3
143
144#define VectMul(X1,Y1,Z1,X2,Y2,Z2) (Y1)*(Z2)-(Z1)*(Y2),(Z1)*(X2)-(X1)*(Z2),(X1)*(Y2)-(Y1)*(X2)
145#define sqr(A) ((A)*(A))
146
147/* Increasing this values produces better image quality, the price is speed. */
148/* Very low values produces erroneous/incorrect plotting */
149#define tetradivisions 23
150#define cubedivisions 20
151#define octadivisions 21
152#define dodecadivisions 10
153#define icodivisions 15
154
155#define tetraangle 109.47122063449069174
156#define cubeangle 90.000000000000000000
157#define octaangle 109.47122063449069174
158#define dodecaangle 63.434948822922009981
159#define icoangle 41.810314895778596167
160
161#ifndef Pi
162#define Pi 3.1415926535897932385
163#endif
164#define SQRT2 1.4142135623730951455
165#define SQRT3 1.7320508075688771932
166#define SQRT5 2.2360679774997898051
167#define SQRT6 2.4494897427831778813
168#define SQRT15 3.8729833462074170214
169#define cossec36_2 0.8506508083520399322
170#define cos72 0.3090169943749474241
171#define sin72 0.9510565162951535721
172#define cos36 0.8090169943749474241
173#define sin36 0.5877852522924731292
174
175/*************************************************************************/
176
177static int mono=0;
178static int smooth=1;
179static GLint WindH, WindW;
180static GLfloat step=0;
181static GLfloat seno;
182static int object;
183static int edgedivisions;
184static void (*draw_object)( void );
185static float Magnitude;
186static float *MaterialColor[20];
187
188static float front_shininess[] = {60.0};
189static float front_specular[] = { 0.7, 0.7, 0.7, 1.0 };
190static float ambient[] = { 0.0, 0.0, 0.0, 1.0 };
191static float diffuse[] = { 1.0, 1.0, 1.0, 1.0 };
192static float position0[] = { 1.0, 1.0, 1.0, 0.0 };
193static float position1[] = {-1.0,-1.0, 1.0, 0.0 };
194static float lmodel_ambient[] = { 0.5, 0.5, 0.5, 1.0 };
195static float lmodel_twoside[] = {GL_TRUE};
196
197static float MaterialRed[] = { 0.7, 0.0, 0.0, 1.0 };
198static float MaterialGreen[] = { 0.1, 0.5, 0.2, 1.0 };
199static float MaterialBlue[] = { 0.0, 0.0, 0.7, 1.0 };
200static float MaterialCyan[] = { 0.2, 0.5, 0.7, 1.0 };
201static float MaterialYellow[] = { 0.7, 0.7, 0.0, 1.0 };
202static float MaterialMagenta[] = { 0.6, 0.2, 0.5, 1.0 };
203static float MaterialWhite[] = { 0.7, 0.7, 0.7, 1.0 };
204static float MaterialGray[] = { 0.2, 0.2, 0.2, 1.0 };
205
206#define TRIANGLE(Edge, Amp, Divisions, Z) \
207{ \
208 GLfloat Xf,Yf,Xa,Yb,Xf2,Yf2; \
209 GLfloat Factor,Factor1,Factor2; \
210 GLfloat VertX,VertY,VertZ,NeiAX,NeiAY,NeiAZ,NeiBX,NeiBY,NeiBZ; \
211 GLfloat Ax,Ay,Bx; \
212 int Ri,Ti; \
213 GLfloat Vr=(Edge)*SQRT3/3; \
214 GLfloat AmpVr2=(Amp)/sqr(Vr); \
215 GLfloat Zf=(Edge)*(Z); \
216 \
217 Ax=(Edge)*(+0.5/(Divisions)), Ay=(Edge)*(-SQRT3/(2*Divisions)); \
218 Bx=(Edge)*(-0.5/(Divisions)); \
219 \
220 for (Ri=1; Ri<=(Divisions); Ri++) { \
221 glBegin(GL_TRIANGLE_STRIP); \
222 for (Ti=0; Ti<Ri; Ti++) { \
223 Xf=(float)(Ri-Ti)*Ax + (float)Ti*Bx; \
224 Yf=Vr+(float)(Ri-Ti)*Ay + (float)Ti*Ay; \
225 Xa=Xf+0.001; Yb=Yf+0.001; \
226 Factor=1-(((Xf2=sqr(Xf))+(Yf2=sqr(Yf)))*AmpVr2); \
227 Factor1=1-((sqr(Xa)+Yf2)*AmpVr2); \
228 Factor2=1-((Xf2+sqr(Yb))*AmpVr2); \
229 VertX=Factor*Xf; VertY=Factor*Yf; VertZ=Factor*Zf; \
230 NeiAX=Factor1*Xa-VertX; NeiAY=Factor1*Yf-VertY; NeiAZ=Factor1*Zf-VertZ; \
231 NeiBX=Factor2*Xf-VertX; NeiBY=Factor2*Yb-VertY; NeiBZ=Factor2*Zf-VertZ; \
232 glNormal3f(VectMul(NeiAX, NeiAY, NeiAZ, NeiBX, NeiBY, NeiBZ)); \
233 glVertex3f(VertX, VertY, VertZ); \
234 \
235 Xf=(float)(Ri-Ti-1)*Ax + (float)Ti*Bx; \
236 Yf=Vr+(float)(Ri-Ti-1)*Ay + (float)Ti*Ay; \
237 Xa=Xf+0.001; Yb=Yf+0.001; \
238 Factor=1-(((Xf2=sqr(Xf))+(Yf2=sqr(Yf)))*AmpVr2); \
239 Factor1=1-((sqr(Xa)+Yf2)*AmpVr2); \
240 Factor2=1-((Xf2+sqr(Yb))*AmpVr2); \
241 VertX=Factor*Xf; VertY=Factor*Yf; VertZ=Factor*Zf; \
242 NeiAX=Factor1*Xa-VertX; NeiAY=Factor1*Yf-VertY; NeiAZ=Factor1*Zf-VertZ; \
243 NeiBX=Factor2*Xf-VertX; NeiBY=Factor2*Yb-VertY; NeiBZ=Factor2*Zf-VertZ; \
244 glNormal3f(VectMul(NeiAX, NeiAY, NeiAZ, NeiBX, NeiBY, NeiBZ)); \
245 glVertex3f(VertX, VertY, VertZ); \
246 \
247 } \
248 Xf=(float)Ri*Bx; \
249 Yf=Vr+(float)Ri*Ay; \
250 Xa=Xf+0.001; Yb=Yf+0.001; \
251 Factor=1-(((Xf2=sqr(Xf))+(Yf2=sqr(Yf)))*AmpVr2); \
252 Factor1=1-((sqr(Xa)+Yf2)*AmpVr2); \
253 Factor2=1-((Xf2+sqr(Yb))*AmpVr2); \
254 VertX=Factor*Xf; VertY=Factor*Yf; VertZ=Factor*Zf; \
255 NeiAX=Factor1*Xa-VertX; NeiAY=Factor1*Yf-VertY; NeiAZ=Factor1*Zf-VertZ; \
256 NeiBX=Factor2*Xf-VertX; NeiBY=Factor2*Yb-VertY; NeiBZ=Factor2*Zf-VertZ; \
257 glNormal3f(VectMul(NeiAX, NeiAY, NeiAZ, NeiBX, NeiBY, NeiBZ)); \
258 glVertex3f(VertX, VertY, VertZ); \
259 glEnd(); \
260 } \
261}
262
263#define SQUARE(Edge, Amp, Divisions, Z) \
264{ \
265 int Xi,Yi; \
266 GLfloat Xf,Yf,Y,Xf2,Yf2,Y2,Xa,Yb; \
267 GLfloat Factor,Factor1,Factor2; \
268 GLfloat VertX,VertY,VertZ,NeiAX,NeiAY,NeiAZ,NeiBX,NeiBY,NeiBZ; \
269 GLfloat Zf=(Edge)*(Z); \
270 GLfloat AmpVr2=(Amp)/sqr((Edge)*SQRT2/2); \
271 \
272 for (Yi=0; Yi<(Divisions); Yi++) { \
273 Yf=-((Edge)/2.0) + ((float)Yi)/(Divisions)*(Edge); \
274 Yf2=sqr(Yf); \
275 Y=Yf+1.0/(Divisions)*(Edge); \
276 Y2=sqr(Y); \
277 glBegin(GL_QUAD_STRIP); \
278 for (Xi=0; Xi<=(Divisions); Xi++) { \
279 Xf=-((Edge)/2.0) + ((float)Xi)/(Divisions)*(Edge); \
280 Xf2=sqr(Xf); \
281 \
282 Xa=Xf+0.001; Yb=Y+0.001; \
283 Factor=1-((Xf2+Y2)*AmpVr2); \
284 Factor1=1-((sqr(Xa)+Y2)*AmpVr2); \
285 Factor2=1-((Xf2+sqr(Yb))*AmpVr2); \
286 VertX=Factor*Xf; VertY=Factor*Y; VertZ=Factor*Zf; \
287 NeiAX=Factor1*Xa-VertX; NeiAY=Factor1*Y-VertY; NeiAZ=Factor1*Zf-VertZ; \
288 NeiBX=Factor2*Xf-VertX; NeiBY=Factor2*Yb-VertY; NeiBZ=Factor2*Zf-VertZ; \
289 glNormal3f(VectMul(NeiAX, NeiAY, NeiAZ, NeiBX, NeiBY, NeiBZ)); \
290 glVertex3f(VertX, VertY, VertZ); \
291 \
292 Xa=Xf+0.001; Yb=Yf+0.001; \
293 Factor=1-((Xf2+Yf2)*AmpVr2); \
294 Factor1=1-((sqr(Xa)+Yf2)*AmpVr2); \
295 Factor2=1-((Xf2+sqr(Yb))*AmpVr2); \
296 VertX=Factor*Xf; VertY=Factor*Yf; VertZ=Factor*Zf; \
297 NeiAX=Factor1*Xa-VertX; NeiAY=Factor1*Yf-VertY; NeiAZ=Factor1*Zf-VertZ; \
298 NeiBX=Factor2*Xf-VertX; NeiBY=Factor2*Yb-VertY; NeiBZ=Factor2*Zf-VertZ; \
299 glNormal3f(VectMul(NeiAX, NeiAY, NeiAZ, NeiBX, NeiBY, NeiBZ)); \
300 glVertex3f(VertX, VertY, VertZ); \
301 } \
302 glEnd(); \
303 } \
304}
305
306#define PENTAGON(Edge, Amp, Divisions, Z) \
307{ \
308 int Ri,Ti,Fi; \
309 GLfloat Xf,Yf,Xa,Yb,Xf2,Yf2; \
310 GLfloat x[6],y[6]; \
311 GLfloat Factor,Factor1,Factor2; \
312 GLfloat VertX,VertY,VertZ,NeiAX,NeiAY,NeiAZ,NeiBX,NeiBY,NeiBZ; \
313 GLfloat Zf=(Edge)*(Z); \
314 GLfloat AmpVr2=(Amp)/sqr((Edge)*cossec36_2); \
315 \
316 for(Fi=0;Fi<6;Fi++) { \
317 x[Fi]=-cos( Fi*2*Pi/5 + Pi/10 )/(Divisions)*cossec36_2*(Edge); \
318 y[Fi]=sin( Fi*2*Pi/5 + Pi/10 )/(Divisions)*cossec36_2*(Edge); \
319 } \
320 \
321 for (Ri=1; Ri<=(Divisions); Ri++) { \
322 for (Fi=0; Fi<5; Fi++) { \
323 glBegin(GL_TRIANGLE_STRIP); \
324 for (Ti=0; Ti<Ri; Ti++) { \
325 Xf=(float)(Ri-Ti)*x[Fi] + (float)Ti*x[Fi+1]; \
326 Yf=(float)(Ri-Ti)*y[Fi] + (float)Ti*y[Fi+1]; \
327 Xa=Xf+0.001; Yb=Yf+0.001; \
328 Factor=1-(((Xf2=sqr(Xf))+(Yf2=sqr(Yf)))*AmpVr2); \
329 Factor1=1-((sqr(Xa)+Yf2)*AmpVr2); \
330 Factor2=1-((Xf2+sqr(Yb))*AmpVr2); \
331 VertX=Factor*Xf; VertY=Factor*Yf; VertZ=Factor*Zf; \
332 NeiAX=Factor1*Xa-VertX; NeiAY=Factor1*Yf-VertY; NeiAZ=Factor1*Zf-VertZ; \
333 NeiBX=Factor2*Xf-VertX; NeiBY=Factor2*Yb-VertY; NeiBZ=Factor2*Zf-VertZ; \
334 glNormal3f(VectMul(NeiAX, NeiAY, NeiAZ, NeiBX, NeiBY, NeiBZ)); \
335 glVertex3f(VertX, VertY, VertZ); \
336 \
337 Xf=(float)(Ri-Ti-1)*x[Fi] + (float)Ti*x[Fi+1]; \
338 Yf=(float)(Ri-Ti-1)*y[Fi] + (float)Ti*y[Fi+1]; \
339 Xa=Xf+0.001; Yb=Yf+0.001; \
340 Factor=1-(((Xf2=sqr(Xf))+(Yf2=sqr(Yf)))*AmpVr2); \
341 Factor1=1-((sqr(Xa)+Yf2)*AmpVr2); \
342 Factor2=1-((Xf2+sqr(Yb))*AmpVr2); \
343 VertX=Factor*Xf; VertY=Factor*Yf; VertZ=Factor*Zf; \
344 NeiAX=Factor1*Xa-VertX; NeiAY=Factor1*Yf-VertY; NeiAZ=Factor1*Zf-VertZ; \
345 NeiBX=Factor2*Xf-VertX; NeiBY=Factor2*Yb-VertY; NeiBZ=Factor2*Zf-VertZ; \
346 glNormal3f(VectMul(NeiAX, NeiAY, NeiAZ, NeiBX, NeiBY, NeiBZ)); \
347 glVertex3f(VertX, VertY, VertZ); \
348 \
349 } \
350 Xf=(float)Ri*x[Fi+1]; \
351 Yf=(float)Ri*y[Fi+1]; \
352 Xa=Xf+0.001; Yb=Yf+0.001; \
353 Factor=1-(((Xf2=sqr(Xf))+(Yf2=sqr(Yf)))*AmpVr2); \
354 Factor1=1-((sqr(Xa)+Yf2)*AmpVr2); \
355 Factor2=1-((Xf2+sqr(Yb))*AmpVr2); \
356 VertX=Factor*Xf; VertY=Factor*Yf; VertZ=Factor*Zf; \
357 NeiAX=Factor1*Xa-VertX; NeiAY=Factor1*Yf-VertY; NeiAZ=Factor1*Zf-VertZ; \
358 NeiBX=Factor2*Xf-VertX; NeiBY=Factor2*Yb-VertY; NeiBZ=Factor2*Zf-VertZ; \
359 glNormal3f(VectMul(NeiAX, NeiAY, NeiAZ, NeiBX, NeiBY, NeiBZ)); \
360 glVertex3f(VertX, VertY, VertZ); \
361 glEnd(); \
362 } \
363 } \
364}
365
366static void draw_tetra( void )
367{
368 GLuint list;
369
370 list = glGenLists( 1 );
371 glNewList( list, GL_COMPILE );
372 TRIANGLE(2,seno,edgedivisions,0.5/SQRT6);
373 glEndList();
374
375 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialColor[0]);
376 glCallList(list);
377 glPushMatrix();
378 glRotatef(180,0,0,1);
379 glRotatef(-tetraangle,1,0,0);
380 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialColor[1]);
381 glCallList(list);
382 glPopMatrix();
383 glPushMatrix();
384 glRotatef(180,0,1,0);
385 glRotatef(-180+tetraangle,0.5,SQRT3/2,0);
386 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialColor[2]);
387 glCallList(list);
388 glPopMatrix();
389 glRotatef(180,0,1,0);
390 glRotatef(-180+tetraangle,0.5,-SQRT3/2,0);
391 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialColor[3]);
392 glCallList(list);
393
394 glDeleteLists(list,1);
395}
396
397static void draw_cube( void )
398{
399 GLuint list;
400
401 list = glGenLists( 1 );
402 glNewList( list, GL_COMPILE );
403 SQUARE(2, seno, edgedivisions, 0.5)
404 glEndList();
405
406 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialColor[0]);
407 glCallList(list);
408 glRotatef(cubeangle,1,0,0);
409 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialColor[1]);
410 glCallList(list);
411 glRotatef(cubeangle,1,0,0);
412 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialColor[2]);
413 glCallList(list);
414 glRotatef(cubeangle,1,0,0);
415 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialColor[3]);
416 glCallList(list);
417 glRotatef(cubeangle,0,1,0);
418 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialColor[4]);
419 glCallList(list);
420 glRotatef(2*cubeangle,0,1,0);
421 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialColor[5]);
422 glCallList(list);
423
424 glDeleteLists(list,1);
425}
426
427static void draw_octa( void )
428{
429 GLuint list;
430
431 list = glGenLists( 1 );
432 glNewList( list, GL_COMPILE );
433 TRIANGLE(2,seno,edgedivisions,1/SQRT6);
434 glEndList();
435
436 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialColor[0]);
437 glCallList(list);
438 glPushMatrix();
439 glRotatef(180,0,0,1);
440 glRotatef(-180+octaangle,1,0,0);
441 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialColor[1]);
442 glCallList(list);
443 glPopMatrix();
444 glPushMatrix();
445 glRotatef(180,0,1,0);
446 glRotatef(-octaangle,0.5,SQRT3/2,0);
447 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialColor[2]);
448 glCallList(list);
449 glPopMatrix();
450 glPushMatrix();
451 glRotatef(180,0,1,0);
452 glRotatef(-octaangle,0.5,-SQRT3/2,0);
453 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialColor[3]);
454 glCallList(list);
455 glPopMatrix();
456 glRotatef(180,1,0,0);
457 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialColor[4]);
458 glCallList(list);
459 glPushMatrix();
460 glRotatef(180,0,0,1);
461 glRotatef(-180+octaangle,1,0,0);
462 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialColor[5]);
463 glCallList(list);
464 glPopMatrix();
465 glPushMatrix();
466 glRotatef(180,0,1,0);
467 glRotatef(-octaangle,0.5,SQRT3/2,0);
468 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialColor[6]);
469 glCallList(list);
470 glPopMatrix();
471 glRotatef(180,0,1,0);
472 glRotatef(-octaangle,0.5,-SQRT3/2,0);
473 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialColor[7]);
474 glCallList(list);
475
476 glDeleteLists(list,1);
477}
478
479static void draw_dodeca( void )
480{
481 GLuint list;
482
Brian Paul7e401c11999-12-15 13:00:45 +0000483#define TAU ((SQRT5+1)/2)
jtgafb833d1999-08-19 00:55:39 +0000484
485 list = glGenLists( 1 );
486 glNewList( list, GL_COMPILE );
487 PENTAGON(1,seno,edgedivisions,sqr(TAU) * sqrt((TAU+2)/5) / 2);
488 glEndList();
489
490 glPushMatrix();
491 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialColor[0]);
492 glCallList(list);
493 glRotatef(180,0,0,1);
494 glPushMatrix();
495 glRotatef(-dodecaangle,1,0,0);
496 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialColor[1]);
497 glCallList(list);
498 glPopMatrix();
499 glPushMatrix();
500 glRotatef(-dodecaangle,cos72,sin72,0);
501 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialColor[2]);
502 glCallList(list);
503 glPopMatrix();
504 glPushMatrix();
505 glRotatef(-dodecaangle,cos72,-sin72,0);
506 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialColor[3]);
507 glCallList(list);
508 glPopMatrix();
509 glPushMatrix();
510 glRotatef(dodecaangle,cos36,-sin36,0);
511 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialColor[4]);
512 glCallList(list);
513 glPopMatrix();
514 glRotatef(dodecaangle,cos36,sin36,0);
515 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialColor[5]);
516 glCallList(list);
517 glPopMatrix();
518 glRotatef(180,1,0,0);
519 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialColor[6]);
520 glCallList(list);
521 glRotatef(180,0,0,1);
522 glPushMatrix();
523 glRotatef(-dodecaangle,1,0,0);
524 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialColor[7]);
525 glCallList(list);
526 glPopMatrix();
527 glPushMatrix();
528 glRotatef(-dodecaangle,cos72,sin72,0);
529 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialColor[8]);
530 glCallList(list);
531 glPopMatrix();
532 glPushMatrix();
533 glRotatef(-dodecaangle,cos72,-sin72,0);
534 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialColor[9]);
535 glCallList(list);
536 glPopMatrix();
537 glPushMatrix();
538 glRotatef(dodecaangle,cos36,-sin36,0);
539 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialColor[10]);
540 glCallList(list);
541 glPopMatrix();
542 glRotatef(dodecaangle,cos36,sin36,0);
543 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialColor[11]);
544 glCallList(list);
545
546 glDeleteLists(list,1);
547}
548
549static void draw_ico( void )
550{
551 GLuint list;
552
553 list = glGenLists( 1 );
554 glNewList( list, GL_COMPILE );
555 TRIANGLE(1.5,seno,edgedivisions,(3*SQRT3+SQRT15)/12);
556 glEndList();
557
558 glPushMatrix();
559
560 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialColor[0]);
561 glCallList(list);
562 glPushMatrix();
563 glRotatef(180,0,0,1);
564 glRotatef(-icoangle,1,0,0);
565 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialColor[1]);
566 glCallList(list);
567 glPushMatrix();
568 glRotatef(180,0,1,0);
569 glRotatef(-180+icoangle,0.5,SQRT3/2,0);
570 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialColor[2]);
571 glCallList(list);
572 glPopMatrix();
573 glRotatef(180,0,1,0);
574 glRotatef(-180+icoangle,0.5,-SQRT3/2,0);
575 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialColor[3]);
576 glCallList(list);
577 glPopMatrix();
578 glPushMatrix();
579 glRotatef(180,0,1,0);
580 glRotatef(-180+icoangle,0.5,SQRT3/2,0);
581 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialColor[4]);
582 glCallList(list);
583 glPushMatrix();
584 glRotatef(180,0,1,0);
585 glRotatef(-180+icoangle,0.5,SQRT3/2,0);
586 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialColor[5]);
587 glCallList(list);
588 glPopMatrix();
589 glRotatef(180,0,0,1);
590 glRotatef(-icoangle,1,0,0);
591 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialColor[6]);
592 glCallList(list);
593 glPopMatrix();
594 glRotatef(180,0,1,0);
595 glRotatef(-180+icoangle,0.5,-SQRT3/2,0);
596 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialColor[7]);
597 glCallList(list);
598 glPushMatrix();
599 glRotatef(180,0,1,0);
600 glRotatef(-180+icoangle,0.5,-SQRT3/2,0);
601 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialColor[8]);
602 glCallList(list);
603 glPopMatrix();
604 glRotatef(180,0,0,1);
605 glRotatef(-icoangle,1,0,0);
606 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialColor[9]);
607 glCallList(list);
608 glPopMatrix();
609 glRotatef(180,1,0,0);
610 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialColor[10]);
611 glCallList(list);
612 glPushMatrix();
613 glRotatef(180,0,0,1);
614 glRotatef(-icoangle,1,0,0);
615 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialColor[11]);
616 glCallList(list);
617 glPushMatrix();
618 glRotatef(180,0,1,0);
619 glRotatef(-180+icoangle,0.5,SQRT3/2,0);
620 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialColor[12]);
621 glCallList(list);
622 glPopMatrix();
623 glRotatef(180,0,1,0);
624 glRotatef(-180+icoangle,0.5,-SQRT3/2,0);
625 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialColor[13]);
626 glCallList(list);
627 glPopMatrix();
628 glPushMatrix();
629 glRotatef(180,0,1,0);
630 glRotatef(-180+icoangle,0.5,SQRT3/2,0);
631 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialColor[14]);
632 glCallList(list);
633 glPushMatrix();
634 glRotatef(180,0,1,0);
635 glRotatef(-180+icoangle,0.5,SQRT3/2,0);
636 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialColor[15]);
637 glCallList(list);
638 glPopMatrix();
639 glRotatef(180,0,0,1);
640 glRotatef(-icoangle,1,0,0);
641 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialColor[16]);
642 glCallList(list);
643 glPopMatrix();
644 glRotatef(180,0,1,0);
645 glRotatef(-180+icoangle,0.5,-SQRT3/2,0);
646 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialColor[17]);
647 glCallList(list);
648 glPushMatrix();
649 glRotatef(180,0,1,0);
650 glRotatef(-180+icoangle,0.5,-SQRT3/2,0);
651 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialColor[18]);
652 glCallList(list);
653 glPopMatrix();
654 glRotatef(180,0,0,1);
655 glRotatef(-icoangle,1,0,0);
656 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialColor[19]);
657 glCallList(list);
658
659 glDeleteLists(list,1);
660}
661
662static void draw ( void ) {
Brian Paul92eddb02005-01-09 17:37:50 +0000663 static double t0 = -1.;
664 double dt, t = glutGet(GLUT_ELAPSED_TIME) / 1000.0;
665 if (t0 < 0.0)
666 t0 = t;
667 dt = t - t0;
668 t0 = t;
669
jtgafb833d1999-08-19 00:55:39 +0000670 glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
671
672 glPushMatrix();
673
674 glTranslatef( 0.0, 0.0, -10.0 );
675 glScalef( Scale*WindH/WindW, Scale, Scale );
676 glTranslatef(2.5*WindW/WindH*sin(step*1.11),2.5*cos(step*1.25*1.11),0);
677 glRotatef(step*100,1,0,0);
678 glRotatef(step*95,0,1,0);
679 glRotatef(step*90,0,0,1);
680
681 seno=(sin(step)+1.0/3.0)*(4.0/5.0)*Magnitude;
682
683 draw_object();
684
685 glPopMatrix();
686
687 glFlush();
688
689 glutSwapBuffers();
690
Brian Paul92eddb02005-01-09 17:37:50 +0000691 step += dt;
jtgafb833d1999-08-19 00:55:39 +0000692}
693
694static void idle_( void )
695{
696 glutPostRedisplay();
697}
698
699static void reshape( int width, int height )
700{
701 glViewport(0, 0, WindW=(GLint)width, WindH=(GLint)height);
702 glMatrixMode(GL_PROJECTION);
703 glLoadIdentity();
704 glFrustum( -1.0, 1.0, -1.0, 1.0, 5.0, 15.0 );
705 glMatrixMode(GL_MODELVIEW);
706}
707
708static void pinit(void);
709
710static void key( unsigned char k, int x, int y )
711{
Brian Paulecaf1a01999-09-17 12:27:01 +0000712 (void) x;
713 (void) y;
jtgafb833d1999-08-19 00:55:39 +0000714 switch (k) {
715 case '1': object=1; break;
716 case '2': object=2; break;
717 case '3': object=3; break;
718 case '4': object=4; break;
719 case '5': object=5; break;
720 case ' ': mono^=1; break;
721 case 13: smooth^=1; break;
722 case 27:
723 exit(0);
724 }
725 pinit();
726}
727
728static void pinit(void)
729{
730 switch(object) {
731 case 1:
732 draw_object=draw_tetra;
733 MaterialColor[0]=MaterialRed;
734 MaterialColor[1]=MaterialGreen;
735 MaterialColor[2]=MaterialBlue;
736 MaterialColor[3]=MaterialWhite;
737 edgedivisions=tetradivisions;
738 Magnitude=2.5;
739 break;
740 case 2:
741 draw_object=draw_cube;
742 MaterialColor[0]=MaterialRed;
743 MaterialColor[1]=MaterialGreen;
744 MaterialColor[2]=MaterialCyan;
745 MaterialColor[3]=MaterialMagenta;
746 MaterialColor[4]=MaterialYellow;
747 MaterialColor[5]=MaterialBlue;
748 edgedivisions=cubedivisions;
749 Magnitude=2.0;
750 break;
751 case 3:
752 draw_object=draw_octa;
753 MaterialColor[0]=MaterialRed;
754 MaterialColor[1]=MaterialGreen;
755 MaterialColor[2]=MaterialBlue;
756 MaterialColor[3]=MaterialWhite;
757 MaterialColor[4]=MaterialCyan;
758 MaterialColor[5]=MaterialMagenta;
759 MaterialColor[6]=MaterialGray;
760 MaterialColor[7]=MaterialYellow;
761 edgedivisions=octadivisions;
762 Magnitude=2.5;
763 break;
764 case 4:
765 draw_object=draw_dodeca;
766 MaterialColor[ 0]=MaterialRed;
767 MaterialColor[ 1]=MaterialGreen;
768 MaterialColor[ 2]=MaterialCyan;
769 MaterialColor[ 3]=MaterialBlue;
770 MaterialColor[ 4]=MaterialMagenta;
771 MaterialColor[ 5]=MaterialYellow;
772 MaterialColor[ 6]=MaterialGreen;
773 MaterialColor[ 7]=MaterialCyan;
774 MaterialColor[ 8]=MaterialRed;
775 MaterialColor[ 9]=MaterialMagenta;
776 MaterialColor[10]=MaterialBlue;
777 MaterialColor[11]=MaterialYellow;
778 edgedivisions=dodecadivisions;
779 Magnitude=2.0;
780 break;
781 case 5:
782 draw_object=draw_ico;
783 MaterialColor[ 0]=MaterialRed;
784 MaterialColor[ 1]=MaterialGreen;
785 MaterialColor[ 2]=MaterialBlue;
786 MaterialColor[ 3]=MaterialCyan;
787 MaterialColor[ 4]=MaterialYellow;
788 MaterialColor[ 5]=MaterialMagenta;
789 MaterialColor[ 6]=MaterialRed;
790 MaterialColor[ 7]=MaterialGreen;
791 MaterialColor[ 8]=MaterialBlue;
792 MaterialColor[ 9]=MaterialWhite;
793 MaterialColor[10]=MaterialCyan;
794 MaterialColor[11]=MaterialYellow;
795 MaterialColor[12]=MaterialMagenta;
796 MaterialColor[13]=MaterialRed;
797 MaterialColor[14]=MaterialGreen;
798 MaterialColor[15]=MaterialBlue;
799 MaterialColor[16]=MaterialCyan;
800 MaterialColor[17]=MaterialYellow;
801 MaterialColor[18]=MaterialMagenta;
802 MaterialColor[19]=MaterialGray;
803 edgedivisions=icodivisions;
804 Magnitude=2.5;
805 break;
806 }
807 if (mono) {
808 int loop;
809 for (loop=0; loop<20; loop++) MaterialColor[loop]=MaterialGray;
810 }
811 if (smooth) {
812 glShadeModel( GL_SMOOTH );
813 } else {
814 glShadeModel( GL_FLAT );
815 }
816
817}
818
Brian Paul02e8a032000-06-27 17:04:43 +0000819static void INIT(void)
jtgafb833d1999-08-19 00:55:39 +0000820{
821 printf("Morph 3D - Shows morphing platonic polyhedra\n");
822 printf("Author: Marcelo Fernandes Vianna (vianna@cat.cbpf.br)\n\n");
823 printf(" [1] - Tetrahedron\n");
824 printf(" [2] - Hexahedron (Cube)\n");
825 printf(" [3] - Octahedron\n");
826 printf(" [4] - Dodecahedron\n");
827 printf(" [5] - Icosahedron\n");
828 printf("[SPACE] - Toggle colored faces\n");
829 printf("[RETURN] - Toggle smooth/flat shading\n");
830 printf(" [ESC] - Quit\n");
831
832 object=1;
833
834 glutInitWindowPosition(0,0);
835 glutInitWindowSize(640,480);
836
837 glutInitDisplayMode( GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGB );
838
839 if (glutCreateWindow("Morph 3D - Shows morphing platonic polyhedra") <= 0) {
840 exit(0);
841 }
842
843 glClearDepth(1.0);
844 glClearColor( 0.0, 0.0, 0.0, 1.0 );
845 glColor3f( 1.0, 1.0, 1.0 );
846
847 glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
848 glFlush();
849 glutSwapBuffers();
850
851 glLightfv(GL_LIGHT0, GL_AMBIENT, ambient);
852 glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse);
853 glLightfv(GL_LIGHT0, GL_POSITION, position0);
854 glLightfv(GL_LIGHT1, GL_AMBIENT, ambient);
855 glLightfv(GL_LIGHT1, GL_DIFFUSE, diffuse);
856 glLightfv(GL_LIGHT1, GL_POSITION, position1);
857 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient);
858 glLightModelfv(GL_LIGHT_MODEL_TWO_SIDE, lmodel_twoside);
859 glEnable(GL_LIGHTING);
860 glEnable(GL_LIGHT0);
861 glEnable(GL_LIGHT1);
862 glEnable(GL_DEPTH_TEST);
863 glEnable(GL_NORMALIZE);
864
865 glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, front_shininess);
866 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, front_specular);
867
868 glHint(GL_FOG_HINT, GL_FASTEST);
869 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
870 glHint(GL_POLYGON_SMOOTH_HINT, GL_FASTEST);
871
872 pinit();
873
874 glutReshapeFunc( reshape );
875 glutKeyboardFunc( key );
876 glutIdleFunc( idle_ );
877 glutDisplayFunc( draw );
878 glutMainLoop();
879
880}
881
882int main(int argc, char **argv)
883{
884 INIT();
885 return(0);
886}