3 * morph3d.c - Shows 3D morphing objects
5 * Converted to GLUT by brianp on 1/1/98
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.
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.
19 * Thanks goes also to Brian Paul for making it possible and inexpensive
20 * to use OpenGL at home.
22 * Since I'm not a native english speaker, my apologies for any gramatical
25 * My e-mail addresses are
29 * marcelo@venus.rdc.puc-rio.br
31 * Marcelo F. Vianna (Feb-13-1997)
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.
39 Since I'm not a native english speaker, my apologies for any gramatical
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
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
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.
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.
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:
70 TETRAHEDRON : 1/(2*sqrt(2))/sqrt(3)
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
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
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
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
126 +-----------------------------------------------------------+
127 | 2*ARCTAN(ERt/FRi) = 41.810314895778596167 degrees |
128 +-----------------------------------------------------------+
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))
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
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
162 #define Pi 3.1415926535897932385
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
175 /*************************************************************************/
179 static GLint WindH
, WindW
;
180 static GLfloat step
=0;
183 static int edgedivisions
;
184 static void (*draw_object
)( void );
185 static float Magnitude
;
186 static float *MaterialColor
[20];
188 static float front_shininess
[] = {60.0};
189 static float front_specular
[] = { 0.7, 0.7, 0.7, 1.0 };
190 static float ambient
[] = { 0.0, 0.0, 0.0, 1.0 };
191 static float diffuse
[] = { 1.0, 1.0, 1.0, 1.0 };
192 static float position0
[] = { 1.0, 1.0, 1.0, 0.0 };
193 static float position1
[] = {-1.0,-1.0, 1.0, 0.0 };
194 static float lmodel_ambient
[] = { 0.5, 0.5, 0.5, 1.0 };
195 static float lmodel_twoside
[] = {GL_TRUE
};
197 static float MaterialRed
[] = { 0.7, 0.0, 0.0, 1.0 };
198 static float MaterialGreen
[] = { 0.1, 0.5, 0.2, 1.0 };
199 static float MaterialBlue
[] = { 0.0, 0.0, 0.7, 1.0 };
200 static float MaterialCyan
[] = { 0.2, 0.5, 0.7, 1.0 };
201 static float MaterialYellow
[] = { 0.7, 0.7, 0.0, 1.0 };
202 static float MaterialMagenta
[] = { 0.6, 0.2, 0.5, 1.0 };
203 static float MaterialWhite
[] = { 0.7, 0.7, 0.7, 1.0 };
204 static float MaterialGray
[] = { 0.2, 0.2, 0.2, 1.0 };
206 #define TRIANGLE(Edge, Amp, Divisions, Z) \
208 GLfloat Xf,Yf,Xa,Yb,Xf2,Yf2; \
209 GLfloat Factor,Factor1,Factor2; \
210 GLfloat VertX,VertY,VertZ,NeiAX,NeiAY,NeiAZ,NeiBX,NeiBY,NeiBZ; \
213 GLfloat Vr=(Edge)*SQRT3/3; \
214 GLfloat AmpVr2=(Amp)/sqr(Vr); \
215 GLfloat Zf=(Edge)*(Z); \
217 Ax=(Edge)*(+0.5/(Divisions)), Ay=(Edge)*(-SQRT3/(2*Divisions)); \
218 Bx=(Edge)*(-0.5/(Divisions)); \
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); \
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); \
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); \
263 #define SQUARE(Edge, Amp, Divisions, Z) \
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); \
272 for (Yi=0; Yi<(Divisions); Yi++) { \
273 Yf=-((Edge)/2.0) + ((float)Yi)/(Divisions)*(Edge); \
275 Y=Yf+1.0/(Divisions)*(Edge); \
277 glBegin(GL_QUAD_STRIP); \
278 for (Xi=0; Xi<=(Divisions); Xi++) { \
279 Xf=-((Edge)/2.0) + ((float)Xi)/(Divisions)*(Edge); \
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); \
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); \
306 #define PENTAGON(Edge, Amp, Divisions, Z) \
309 GLfloat Xf,Yf,Xa,Yb,Xf2,Yf2; \
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); \
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); \
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); \
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); \
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); \
366 static void draw_tetra( void )
370 list
= glGenLists( 1 );
371 glNewList( list
, GL_COMPILE
);
372 TRIANGLE(2,seno
,edgedivisions
,0.5/SQRT6
);
375 glMaterialfv(GL_FRONT_AND_BACK
, GL_DIFFUSE
, MaterialColor
[0]);
378 glRotatef(180,0,0,1);
379 glRotatef(-tetraangle
,1,0,0);
380 glMaterialfv(GL_FRONT_AND_BACK
, GL_DIFFUSE
, MaterialColor
[1]);
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]);
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]);
394 glDeleteLists(list
,1);
397 static void draw_cube( void )
401 list
= glGenLists( 1 );
402 glNewList( list
, GL_COMPILE
);
403 SQUARE(2, seno
, edgedivisions
, 0.5)
406 glMaterialfv(GL_FRONT_AND_BACK
, GL_DIFFUSE
, MaterialColor
[0]);
408 glRotatef(cubeangle
,1,0,0);
409 glMaterialfv(GL_FRONT_AND_BACK
, GL_DIFFUSE
, MaterialColor
[1]);
411 glRotatef(cubeangle
,1,0,0);
412 glMaterialfv(GL_FRONT_AND_BACK
, GL_DIFFUSE
, MaterialColor
[2]);
414 glRotatef(cubeangle
,1,0,0);
415 glMaterialfv(GL_FRONT_AND_BACK
, GL_DIFFUSE
, MaterialColor
[3]);
417 glRotatef(cubeangle
,0,1,0);
418 glMaterialfv(GL_FRONT_AND_BACK
, GL_DIFFUSE
, MaterialColor
[4]);
420 glRotatef(2*cubeangle
,0,1,0);
421 glMaterialfv(GL_FRONT_AND_BACK
, GL_DIFFUSE
, MaterialColor
[5]);
424 glDeleteLists(list
,1);
427 static void draw_octa( void )
431 list
= glGenLists( 1 );
432 glNewList( list
, GL_COMPILE
);
433 TRIANGLE(2,seno
,edgedivisions
,1/SQRT6
);
436 glMaterialfv(GL_FRONT_AND_BACK
, GL_DIFFUSE
, MaterialColor
[0]);
439 glRotatef(180,0,0,1);
440 glRotatef(-180+octaangle
,1,0,0);
441 glMaterialfv(GL_FRONT_AND_BACK
, GL_DIFFUSE
, MaterialColor
[1]);
445 glRotatef(180,0,1,0);
446 glRotatef(-octaangle
,0.5,SQRT3
/2,0);
447 glMaterialfv(GL_FRONT_AND_BACK
, GL_DIFFUSE
, MaterialColor
[2]);
451 glRotatef(180,0,1,0);
452 glRotatef(-octaangle
,0.5,-SQRT3
/2,0);
453 glMaterialfv(GL_FRONT_AND_BACK
, GL_DIFFUSE
, MaterialColor
[3]);
456 glRotatef(180,1,0,0);
457 glMaterialfv(GL_FRONT_AND_BACK
, GL_DIFFUSE
, MaterialColor
[4]);
460 glRotatef(180,0,0,1);
461 glRotatef(-180+octaangle
,1,0,0);
462 glMaterialfv(GL_FRONT_AND_BACK
, GL_DIFFUSE
, MaterialColor
[5]);
466 glRotatef(180,0,1,0);
467 glRotatef(-octaangle
,0.5,SQRT3
/2,0);
468 glMaterialfv(GL_FRONT_AND_BACK
, GL_DIFFUSE
, MaterialColor
[6]);
471 glRotatef(180,0,1,0);
472 glRotatef(-octaangle
,0.5,-SQRT3
/2,0);
473 glMaterialfv(GL_FRONT_AND_BACK
, GL_DIFFUSE
, MaterialColor
[7]);
476 glDeleteLists(list
,1);
479 static void draw_dodeca( void )
483 #define TAU ((SQRT5+1)/2)
485 list
= glGenLists( 1 );
486 glNewList( list
, GL_COMPILE
);
487 PENTAGON(1,seno
,edgedivisions
,sqr(TAU
) * sqrt((TAU
+2)/5) / 2);
491 glMaterialfv(GL_FRONT_AND_BACK
, GL_DIFFUSE
, MaterialColor
[0]);
493 glRotatef(180,0,0,1);
495 glRotatef(-dodecaangle
,1,0,0);
496 glMaterialfv(GL_FRONT_AND_BACK
, GL_DIFFUSE
, MaterialColor
[1]);
500 glRotatef(-dodecaangle
,cos72
,sin72
,0);
501 glMaterialfv(GL_FRONT_AND_BACK
, GL_DIFFUSE
, MaterialColor
[2]);
505 glRotatef(-dodecaangle
,cos72
,-sin72
,0);
506 glMaterialfv(GL_FRONT_AND_BACK
, GL_DIFFUSE
, MaterialColor
[3]);
510 glRotatef(dodecaangle
,cos36
,-sin36
,0);
511 glMaterialfv(GL_FRONT_AND_BACK
, GL_DIFFUSE
, MaterialColor
[4]);
514 glRotatef(dodecaangle
,cos36
,sin36
,0);
515 glMaterialfv(GL_FRONT_AND_BACK
, GL_DIFFUSE
, MaterialColor
[5]);
518 glRotatef(180,1,0,0);
519 glMaterialfv(GL_FRONT_AND_BACK
, GL_DIFFUSE
, MaterialColor
[6]);
521 glRotatef(180,0,0,1);
523 glRotatef(-dodecaangle
,1,0,0);
524 glMaterialfv(GL_FRONT_AND_BACK
, GL_DIFFUSE
, MaterialColor
[7]);
528 glRotatef(-dodecaangle
,cos72
,sin72
,0);
529 glMaterialfv(GL_FRONT_AND_BACK
, GL_DIFFUSE
, MaterialColor
[8]);
533 glRotatef(-dodecaangle
,cos72
,-sin72
,0);
534 glMaterialfv(GL_FRONT_AND_BACK
, GL_DIFFUSE
, MaterialColor
[9]);
538 glRotatef(dodecaangle
,cos36
,-sin36
,0);
539 glMaterialfv(GL_FRONT_AND_BACK
, GL_DIFFUSE
, MaterialColor
[10]);
542 glRotatef(dodecaangle
,cos36
,sin36
,0);
543 glMaterialfv(GL_FRONT_AND_BACK
, GL_DIFFUSE
, MaterialColor
[11]);
546 glDeleteLists(list
,1);
549 static void draw_ico( void )
553 list
= glGenLists( 1 );
554 glNewList( list
, GL_COMPILE
);
555 TRIANGLE(1.5,seno
,edgedivisions
,(3*SQRT3
+SQRT15
)/12);
560 glMaterialfv(GL_FRONT_AND_BACK
, GL_DIFFUSE
, MaterialColor
[0]);
563 glRotatef(180,0,0,1);
564 glRotatef(-icoangle
,1,0,0);
565 glMaterialfv(GL_FRONT_AND_BACK
, GL_DIFFUSE
, MaterialColor
[1]);
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]);
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]);
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]);
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]);
589 glRotatef(180,0,0,1);
590 glRotatef(-icoangle
,1,0,0);
591 glMaterialfv(GL_FRONT_AND_BACK
, GL_DIFFUSE
, MaterialColor
[6]);
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]);
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]);
604 glRotatef(180,0,0,1);
605 glRotatef(-icoangle
,1,0,0);
606 glMaterialfv(GL_FRONT_AND_BACK
, GL_DIFFUSE
, MaterialColor
[9]);
609 glRotatef(180,1,0,0);
610 glMaterialfv(GL_FRONT_AND_BACK
, GL_DIFFUSE
, MaterialColor
[10]);
613 glRotatef(180,0,0,1);
614 glRotatef(-icoangle
,1,0,0);
615 glMaterialfv(GL_FRONT_AND_BACK
, GL_DIFFUSE
, MaterialColor
[11]);
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]);
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]);
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]);
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]);
639 glRotatef(180,0,0,1);
640 glRotatef(-icoangle
,1,0,0);
641 glMaterialfv(GL_FRONT_AND_BACK
, GL_DIFFUSE
, MaterialColor
[16]);
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]);
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]);
654 glRotatef(180,0,0,1);
655 glRotatef(-icoangle
,1,0,0);
656 glMaterialfv(GL_FRONT_AND_BACK
, GL_DIFFUSE
, MaterialColor
[19]);
659 glDeleteLists(list
,1);
662 static void draw ( void ) {
663 glClear( GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
);
667 glTranslatef( 0.0, 0.0, -10.0 );
668 glScalef( Scale
*WindH
/WindW
, Scale
, Scale
);
669 glTranslatef(2.5*WindW
/WindH
*sin(step
*1.11),2.5*cos(step
*1.25*1.11),0);
670 glRotatef(step
*100,1,0,0);
671 glRotatef(step
*95,0,1,0);
672 glRotatef(step
*90,0,0,1);
674 seno
=(sin(step
)+1.0/3.0)*(4.0/5.0)*Magnitude
;
687 static void idle_( void )
692 static void reshape( int width
, int height
)
694 glViewport(0, 0, WindW
=(GLint
)width
, WindH
=(GLint
)height
);
695 glMatrixMode(GL_PROJECTION
);
697 glFrustum( -1.0, 1.0, -1.0, 1.0, 5.0, 15.0 );
698 glMatrixMode(GL_MODELVIEW
);
701 static void pinit(void);
703 static void key( unsigned char k
, int x
, int y
)
708 case '1': object
=1; break;
709 case '2': object
=2; break;
710 case '3': object
=3; break;
711 case '4': object
=4; break;
712 case '5': object
=5; break;
713 case ' ': mono
^=1; break;
714 case 13: smooth
^=1; break;
721 static void pinit(void)
725 draw_object
=draw_tetra
;
726 MaterialColor
[0]=MaterialRed
;
727 MaterialColor
[1]=MaterialGreen
;
728 MaterialColor
[2]=MaterialBlue
;
729 MaterialColor
[3]=MaterialWhite
;
730 edgedivisions
=tetradivisions
;
734 draw_object
=draw_cube
;
735 MaterialColor
[0]=MaterialRed
;
736 MaterialColor
[1]=MaterialGreen
;
737 MaterialColor
[2]=MaterialCyan
;
738 MaterialColor
[3]=MaterialMagenta
;
739 MaterialColor
[4]=MaterialYellow
;
740 MaterialColor
[5]=MaterialBlue
;
741 edgedivisions
=cubedivisions
;
745 draw_object
=draw_octa
;
746 MaterialColor
[0]=MaterialRed
;
747 MaterialColor
[1]=MaterialGreen
;
748 MaterialColor
[2]=MaterialBlue
;
749 MaterialColor
[3]=MaterialWhite
;
750 MaterialColor
[4]=MaterialCyan
;
751 MaterialColor
[5]=MaterialMagenta
;
752 MaterialColor
[6]=MaterialGray
;
753 MaterialColor
[7]=MaterialYellow
;
754 edgedivisions
=octadivisions
;
758 draw_object
=draw_dodeca
;
759 MaterialColor
[ 0]=MaterialRed
;
760 MaterialColor
[ 1]=MaterialGreen
;
761 MaterialColor
[ 2]=MaterialCyan
;
762 MaterialColor
[ 3]=MaterialBlue
;
763 MaterialColor
[ 4]=MaterialMagenta
;
764 MaterialColor
[ 5]=MaterialYellow
;
765 MaterialColor
[ 6]=MaterialGreen
;
766 MaterialColor
[ 7]=MaterialCyan
;
767 MaterialColor
[ 8]=MaterialRed
;
768 MaterialColor
[ 9]=MaterialMagenta
;
769 MaterialColor
[10]=MaterialBlue
;
770 MaterialColor
[11]=MaterialYellow
;
771 edgedivisions
=dodecadivisions
;
775 draw_object
=draw_ico
;
776 MaterialColor
[ 0]=MaterialRed
;
777 MaterialColor
[ 1]=MaterialGreen
;
778 MaterialColor
[ 2]=MaterialBlue
;
779 MaterialColor
[ 3]=MaterialCyan
;
780 MaterialColor
[ 4]=MaterialYellow
;
781 MaterialColor
[ 5]=MaterialMagenta
;
782 MaterialColor
[ 6]=MaterialRed
;
783 MaterialColor
[ 7]=MaterialGreen
;
784 MaterialColor
[ 8]=MaterialBlue
;
785 MaterialColor
[ 9]=MaterialWhite
;
786 MaterialColor
[10]=MaterialCyan
;
787 MaterialColor
[11]=MaterialYellow
;
788 MaterialColor
[12]=MaterialMagenta
;
789 MaterialColor
[13]=MaterialRed
;
790 MaterialColor
[14]=MaterialGreen
;
791 MaterialColor
[15]=MaterialBlue
;
792 MaterialColor
[16]=MaterialCyan
;
793 MaterialColor
[17]=MaterialYellow
;
794 MaterialColor
[18]=MaterialMagenta
;
795 MaterialColor
[19]=MaterialGray
;
796 edgedivisions
=icodivisions
;
802 for (loop
=0; loop
<20; loop
++) MaterialColor
[loop
]=MaterialGray
;
805 glShadeModel( GL_SMOOTH
);
807 glShadeModel( GL_FLAT
);
812 static void INIT(void)
814 printf("Morph 3D - Shows morphing platonic polyhedra\n");
815 printf("Author: Marcelo Fernandes Vianna (vianna@cat.cbpf.br)\n\n");
816 printf(" [1] - Tetrahedron\n");
817 printf(" [2] - Hexahedron (Cube)\n");
818 printf(" [3] - Octahedron\n");
819 printf(" [4] - Dodecahedron\n");
820 printf(" [5] - Icosahedron\n");
821 printf("[SPACE] - Toggle colored faces\n");
822 printf("[RETURN] - Toggle smooth/flat shading\n");
823 printf(" [ESC] - Quit\n");
827 glutInitWindowPosition(0,0);
828 glutInitWindowSize(640,480);
830 glutInitDisplayMode( GLUT_DEPTH
| GLUT_DOUBLE
| GLUT_RGB
);
832 if (glutCreateWindow("Morph 3D - Shows morphing platonic polyhedra") <= 0) {
837 glClearColor( 0.0, 0.0, 0.0, 1.0 );
838 glColor3f( 1.0, 1.0, 1.0 );
840 glClear( GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
);
844 glLightfv(GL_LIGHT0
, GL_AMBIENT
, ambient
);
845 glLightfv(GL_LIGHT0
, GL_DIFFUSE
, diffuse
);
846 glLightfv(GL_LIGHT0
, GL_POSITION
, position0
);
847 glLightfv(GL_LIGHT1
, GL_AMBIENT
, ambient
);
848 glLightfv(GL_LIGHT1
, GL_DIFFUSE
, diffuse
);
849 glLightfv(GL_LIGHT1
, GL_POSITION
, position1
);
850 glLightModelfv(GL_LIGHT_MODEL_AMBIENT
, lmodel_ambient
);
851 glLightModelfv(GL_LIGHT_MODEL_TWO_SIDE
, lmodel_twoside
);
852 glEnable(GL_LIGHTING
);
855 glEnable(GL_DEPTH_TEST
);
856 glEnable(GL_NORMALIZE
);
858 glMaterialfv(GL_FRONT_AND_BACK
, GL_SHININESS
, front_shininess
);
859 glMaterialfv(GL_FRONT_AND_BACK
, GL_SPECULAR
, front_specular
);
861 glHint(GL_FOG_HINT
, GL_FASTEST
);
862 glHint(GL_PERSPECTIVE_CORRECTION_HINT
, GL_FASTEST
);
863 glHint(GL_POLYGON_SMOOTH_HINT
, GL_FASTEST
);
867 glutReshapeFunc( reshape
);
868 glutKeyboardFunc( key
);
869 glutIdleFunc( idle_
);
870 glutDisplayFunc( draw
);
875 int main(int argc
, char **argv
)