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