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