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