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