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