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