2 (c) Copyright 2001 convergence integrated media GmbH.
5 Written by Denis Oliver Kropp <dok@convergence.de> and
6 Andreas Hundt <andi@convergence.de>.
8 This library is free software; you can redistribute it and/or
9 modify it under the terms of the GNU Lesser General Public
10 License as published by the Free Software Foundation; either
11 version 2 of the License, or (at your option) any later version.
13 This library is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public
19 License along with this library; if not, write to the
20 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21 Boston, MA 02111-1307, USA.
25 * morph3d.c - Shows 3D morphing objects
27 * Converted to GLUT by brianp on 1/1/98
29 * This program was inspired on a WindowsNT(R)'s screen saver. It was written
30 * from scratch and it was not based on any other source code.
32 * Porting it to xlock (the final objective of this code since the moment I
33 * decided to create it) was possible by comparing the original Mesa's gear
34 * demo with it's ported version, so thanks for Danny Sung for his indirect
35 * help (look at gear.c in xlock source tree). NOTE: At the moment this code
36 * was sent to Brian Paul for package inclusion, the XLock Version was not
37 * available. In fact, I'll wait it to appear on the next Mesa release (If you
38 * are reading this, it means THIS release) to send it for xlock package
39 * inclusion). It will probably there be a GLUT version too.
41 * Thanks goes also to Brian Paul for making it possible and inexpensive
42 * to use OpenGL at home.
44 * Since I'm not a native english speaker, my apologies for any gramatical
47 * My e-mail addresses are
51 * marcelo@venus.rdc.puc-rio.br
53 * Marcelo F. Vianna (Feb-13-1997)
57 This document is VERY incomplete, but tries to describe the mathematics used
58 in the program. At this moment it just describes how the polyhedra are
59 generated. On futhurer versions, this document will be probabbly improved.
61 Since I'm not a native english speaker, my apologies for any gramatical
64 Marcelo Fernandes Vianna
65 - Undergraduate in Computer Engeneering at Catholic Pontifical University
66 - of Rio de Janeiro (PUC-Rio) Brasil.
67 - e-mail: vianna@cat.cbpf.br or marcelo@venus.rdc.puc-rio.br
72 For the purpose of this program it's not sufficient to know the polyhedra
73 vertexes coordinates. Since the morphing algorithm applies a nonlinear
74 transformation over the surfaces (faces) of the polyhedron, each face has
75 to be divided into smaller ones. The morphing algorithm needs to transform
76 each vertex of these smaller faces individually. It's a very time consoming
79 In order to reduce calculation overload, and since all the macro faces of
80 the polyhedron are transformed by the same way, the generation is made by
81 creating only one face of the polyhedron, morphing it and then rotating it
82 around the polyhedron center.
84 What we need to know is the face radius of the polyhedron (the radius of
85 the inscribed sphere) and the angle between the center of two adjacent
86 faces using the center of the sphere as the angle's vertex.
88 The face radius of the regular polyhedra are known values which I decided
89 to not waste my time calculating. Following is a table of face radius for
90 the regular polyhedra with edge length = 1:
92 TETRAHEDRON : 1/(2*sqrt(2))/sqrt(3)
94 OCTAHEDRON : 1/sqrt(6)
95 DODECAHEDRON : T^2 * sqrt((T+2)/5) / 2 -> where T=(sqrt(5)+1)/2
96 ICOSAHEDRON : (3*sqrt(3)+sqrt(15))/12
98 I've not found any reference about the mentioned angles, so I needed to
99 calculate them, not a trivial task until I figured out how :)
100 Curiously these angles are the same for the tetrahedron and octahedron.
101 A way to obtain this value is inscribing the tetrahedron inside the cube
102 by matching their vertexes. So you'll notice that the remaining unmatched
103 vertexes are in the same straight line starting in the cube/tetrahedron
104 center and crossing the center of each tetrahedron's face. At this point
105 it's easy to obtain the bigger angle of the isosceles triangle formed by
106 the center of the cube and two opposite vertexes on the same cube face.
107 The edges of this triangle have the following lenghts: sqrt(2) for the base
108 and sqrt(3)/2 for the other two other edges. So the angle we want is:
109 +-----------------------------------------------------------+
110 | 2*ARCSIN(sqrt(2)/sqrt(3)) = 109.47122063449069174 degrees |
111 +-----------------------------------------------------------+
112 For the cube this angle is obvious, but just for formality it can be
113 easily obtained because we also know it's isosceles edge lenghts:
114 sqrt(2)/2 for the base and 1/2 for the other two edges. So the angle we
116 +-----------------------------------------------------------+
117 | 2*ARCSIN((sqrt(2)/2)/1) = 90.000000000000000000 degrees |
118 +-----------------------------------------------------------+
119 For the octahedron we use the same idea used for the tetrahedron, but now
120 we inscribe the cube inside the octahedron so that all cubes's vertexes
121 matches excatly the center of each octahedron's face. It's now clear that
122 this angle is the same of the thetrahedron one:
123 +-----------------------------------------------------------+
124 | 2*ARCSIN(sqrt(2)/sqrt(3)) = 109.47122063449069174 degrees |
125 +-----------------------------------------------------------+
126 For the dodecahedron it's a little bit harder because it's only relationship
127 with the cube is useless to us. So we need to solve the problem by another
128 way. The concept of Face radius also exists on 2D polygons with the name
130 Edge Radius For Pentagon (ERp)
131 ERp = (1/2)/TAN(36 degrees) * VRp = 0.6881909602355867905
132 (VRp is the pentagon's vertex radio).
133 Face Radius For Dodecahedron
134 FRd = T^2 * sqrt((T+2)/5) / 2 = 1.1135163644116068404
135 Why we need ERp? Well, ERp and FRd segments forms a 90 degrees angle,
136 completing this triangle, the lesser angle is a half of the angle we are
137 looking for, so this angle is:
138 +-----------------------------------------------------------+
139 | 2*ARCTAN(ERp/FRd) = 63.434948822922009981 degrees |
140 +-----------------------------------------------------------+
141 For the icosahedron we can use the same method used for dodecahedron (well
142 the method used for dodecahedron may be used for all regular polyhedra)
143 Edge Radius For Triangle (this one is well known: 1/3 of the triangle height)
144 ERt = sin(60)/3 = sqrt(3)/6 = 0.2886751345948128655
145 Face Radius For Icosahedron
146 FRi= (3*sqrt(3)+sqrt(15))/12 = 0.7557613140761707538
148 +-----------------------------------------------------------+
149 | 2*ARCTAN(ERt/FRi) = 41.810314895778596167 degrees |
150 +-----------------------------------------------------------+
161 #include <directfb.h>
162 #include <directfbgl.h>
167 /* the super interface */
170 /* the primary surface (surface of primary layer) */
171 IDirectFBSurface
*primary
;
174 IDirectFBGL
*primary_gl
;
180 IDirectFBEventBuffer
*events
;
182 /* macro for a safe call to DirectFB functions */
183 #define DFBCHECK(x...) \
186 if (err != DFB_OK) { \
187 fprintf( stderr, "%s <%d>:\n\t", __FILE__, __LINE__ ); \
188 DirectFBErrorFatal( #x, err ); \
192 static int screen_width
, screen_height
;
194 static unsigned long T0
= 0;
195 static GLint Frames
= 0;
196 static GLfloat fps
= 0;
198 static inline unsigned long get_millis()
202 gettimeofday (&tv
, NULL
);
203 return (tv
.tv_sec
* 1000 + tv
.tv_usec
/ 1000);
210 #define VectMul(X1,Y1,Z1,X2,Y2,Z2) (Y1)*(Z2)-(Z1)*(Y2),(Z1)*(X2)-(X1)*(Z2),(X1)*(Y2)-(Y1)*(X2)
211 #define sqr(A) ((A)*(A))
213 /* Increasing this values produces better image quality, the price is speed. */
214 /* Very low values produces erroneous/incorrect plotting */
215 #define tetradivisions 23
216 #define cubedivisions 20
217 #define octadivisions 21
218 #define dodecadivisions 10
219 #define icodivisions 15
221 #define tetraangle 109.47122063449069174
222 #define cubeangle 90.000000000000000000
223 #define octaangle 109.47122063449069174
224 #define dodecaangle 63.434948822922009981
225 #define icoangle 41.810314895778596167
228 #define Pi 3.1415926535897932385
230 #define SQRT2 1.4142135623730951455
231 #define SQRT3 1.7320508075688771932
232 #define SQRT5 2.2360679774997898051
233 #define SQRT6 2.4494897427831778813
234 #define SQRT15 3.8729833462074170214
235 #define cossec36_2 0.8506508083520399322
236 #define cos72 0.3090169943749474241
237 #define sin72 0.9510565162951535721
238 #define cos36 0.8090169943749474241
239 #define sin36 0.5877852522924731292
241 /*************************************************************************/
245 static GLint WindH
, WindW
;
246 static GLfloat step
=0;
249 static int edgedivisions
;
250 static void (*draw_object
)( void );
251 static float Magnitude
;
252 static float *MaterialColor
[20];
254 static float front_shininess
[] = {60.0};
255 static float front_specular
[] = { 0.7, 0.7, 0.7, 1.0 };
256 static float ambient
[] = { 0.0, 0.0, 0.0, 1.0 };
257 static float diffuse
[] = { 1.0, 1.0, 1.0, 1.0 };
258 static float position0
[] = { 1.0, 1.0, 1.0, 0.0 };
259 static float position1
[] = {-1.0,-1.0, 1.0, 0.0 };
260 static float lmodel_ambient
[] = { 0.5, 0.5, 0.5, 1.0 };
261 static float lmodel_twoside
[] = {GL_TRUE
};
263 static float MaterialRed
[] = { 0.7, 0.0, 0.0, 1.0 };
264 static float MaterialGreen
[] = { 0.1, 0.5, 0.2, 1.0 };
265 static float MaterialBlue
[] = { 0.0, 0.0, 0.7, 1.0 };
266 static float MaterialCyan
[] = { 0.2, 0.5, 0.7, 1.0 };
267 static float MaterialYellow
[] = { 0.7, 0.7, 0.0, 1.0 };
268 static float MaterialMagenta
[] = { 0.6, 0.2, 0.5, 1.0 };
269 static float MaterialWhite
[] = { 0.7, 0.7, 0.7, 1.0 };
270 static float MaterialGray
[] = { 0.2, 0.2, 0.2, 1.0 };
272 #define TRIANGLE(Edge, Amp, Divisions, Z) \
274 GLfloat Xf,Yf,Xa,Yb,Xf2,Yf2; \
275 GLfloat Factor,Factor1,Factor2; \
276 GLfloat VertX,VertY,VertZ,NeiAX,NeiAY,NeiAZ,NeiBX,NeiBY,NeiBZ; \
279 GLfloat Vr=(Edge)*SQRT3/3; \
280 GLfloat AmpVr2=(Amp)/sqr(Vr); \
281 GLfloat Zf=(Edge)*(Z); \
283 Ax=(Edge)*(+0.5/(Divisions)), Ay=(Edge)*(-SQRT3/(2*Divisions)); \
284 Bx=(Edge)*(-0.5/(Divisions)); \
286 for (Ri=1; Ri<=(Divisions); Ri++) { \
287 glBegin(GL_TRIANGLE_STRIP); \
288 for (Ti=0; Ti<Ri; Ti++) { \
289 Xf=(float)(Ri-Ti)*Ax + (float)Ti*Bx; \
290 Yf=Vr+(float)(Ri-Ti)*Ay + (float)Ti*Ay; \
291 Xa=Xf+0.001; Yb=Yf+0.001; \
292 Factor=1-(((Xf2=sqr(Xf))+(Yf2=sqr(Yf)))*AmpVr2); \
293 Factor1=1-((sqr(Xa)+Yf2)*AmpVr2); \
294 Factor2=1-((Xf2+sqr(Yb))*AmpVr2); \
295 VertX=Factor*Xf; VertY=Factor*Yf; VertZ=Factor*Zf; \
296 NeiAX=Factor1*Xa-VertX; NeiAY=Factor1*Yf-VertY; NeiAZ=Factor1*Zf-VertZ; \
297 NeiBX=Factor2*Xf-VertX; NeiBY=Factor2*Yb-VertY; NeiBZ=Factor2*Zf-VertZ; \
298 glNormal3f(VectMul(NeiAX, NeiAY, NeiAZ, NeiBX, NeiBY, NeiBZ)); \
299 glVertex3f(VertX, VertY, VertZ); \
301 Xf=(float)(Ri-Ti-1)*Ax + (float)Ti*Bx; \
302 Yf=Vr+(float)(Ri-Ti-1)*Ay + (float)Ti*Ay; \
303 Xa=Xf+0.001; Yb=Yf+0.001; \
304 Factor=1-(((Xf2=sqr(Xf))+(Yf2=sqr(Yf)))*AmpVr2); \
305 Factor1=1-((sqr(Xa)+Yf2)*AmpVr2); \
306 Factor2=1-((Xf2+sqr(Yb))*AmpVr2); \
307 VertX=Factor*Xf; VertY=Factor*Yf; VertZ=Factor*Zf; \
308 NeiAX=Factor1*Xa-VertX; NeiAY=Factor1*Yf-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); \
315 Yf=Vr+(float)Ri*Ay; \
316 Xa=Xf+0.001; Yb=Yf+0.001; \
317 Factor=1-(((Xf2=sqr(Xf))+(Yf2=sqr(Yf)))*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); \
329 #define SQUARE(Edge, Amp, Divisions, Z) \
332 GLfloat Xf,Yf,Y,Xf2,Yf2,Y2,Xa,Yb; \
333 GLfloat Factor,Factor1,Factor2; \
334 GLfloat VertX,VertY,VertZ,NeiAX,NeiAY,NeiAZ,NeiBX,NeiBY,NeiBZ; \
335 GLfloat Zf=(Edge)*(Z); \
336 GLfloat AmpVr2=(Amp)/sqr((Edge)*SQRT2/2); \
338 for (Yi=0; Yi<(Divisions); Yi++) { \
339 Yf=-((Edge)/2.0) + ((float)Yi)/(Divisions)*(Edge); \
341 Y=Yf+1.0/(Divisions)*(Edge); \
343 glBegin(GL_QUAD_STRIP); \
344 for (Xi=0; Xi<=(Divisions); Xi++) { \
345 Xf=-((Edge)/2.0) + ((float)Xi)/(Divisions)*(Edge); \
348 Xa=Xf+0.001; Yb=Y+0.001; \
349 Factor=1-((Xf2+Y2)*AmpVr2); \
350 Factor1=1-((sqr(Xa)+Y2)*AmpVr2); \
351 Factor2=1-((Xf2+sqr(Yb))*AmpVr2); \
352 VertX=Factor*Xf; VertY=Factor*Y; VertZ=Factor*Zf; \
353 NeiAX=Factor1*Xa-VertX; NeiAY=Factor1*Y-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); \
358 Xa=Xf+0.001; Yb=Yf+0.001; \
359 Factor=1-((Xf2+Yf2)*AmpVr2); \
360 Factor1=1-((sqr(Xa)+Yf2)*AmpVr2); \
361 Factor2=1-((Xf2+sqr(Yb))*AmpVr2); \
362 VertX=Factor*Xf; VertY=Factor*Yf; VertZ=Factor*Zf; \
363 NeiAX=Factor1*Xa-VertX; NeiAY=Factor1*Yf-VertY; NeiAZ=Factor1*Zf-VertZ; \
364 NeiBX=Factor2*Xf-VertX; NeiBY=Factor2*Yb-VertY; NeiBZ=Factor2*Zf-VertZ; \
365 glNormal3f(VectMul(NeiAX, NeiAY, NeiAZ, NeiBX, NeiBY, NeiBZ)); \
366 glVertex3f(VertX, VertY, VertZ); \
372 #define PENTAGON(Edge, Amp, Divisions, Z) \
375 GLfloat Xf,Yf,Xa,Yb,Xf2,Yf2; \
377 GLfloat Factor,Factor1,Factor2; \
378 GLfloat VertX,VertY,VertZ,NeiAX,NeiAY,NeiAZ,NeiBX,NeiBY,NeiBZ; \
379 GLfloat Zf=(Edge)*(Z); \
380 GLfloat AmpVr2=(Amp)/sqr((Edge)*cossec36_2); \
382 for(Fi=0;Fi<6;Fi++) { \
383 x[Fi]=-cos( Fi*2*Pi/5 + Pi/10 )/(Divisions)*cossec36_2*(Edge); \
384 y[Fi]=sin( Fi*2*Pi/5 + Pi/10 )/(Divisions)*cossec36_2*(Edge); \
387 for (Ri=1; Ri<=(Divisions); Ri++) { \
388 for (Fi=0; Fi<5; Fi++) { \
389 glBegin(GL_TRIANGLE_STRIP); \
390 for (Ti=0; Ti<Ri; Ti++) { \
391 Xf=(float)(Ri-Ti)*x[Fi] + (float)Ti*x[Fi+1]; \
392 Yf=(float)(Ri-Ti)*y[Fi] + (float)Ti*y[Fi+1]; \
393 Xa=Xf+0.001; Yb=Yf+0.001; \
394 Factor=1-(((Xf2=sqr(Xf))+(Yf2=sqr(Yf)))*AmpVr2); \
395 Factor1=1-((sqr(Xa)+Yf2)*AmpVr2); \
396 Factor2=1-((Xf2+sqr(Yb))*AmpVr2); \
397 VertX=Factor*Xf; VertY=Factor*Yf; VertZ=Factor*Zf; \
398 NeiAX=Factor1*Xa-VertX; NeiAY=Factor1*Yf-VertY; NeiAZ=Factor1*Zf-VertZ; \
399 NeiBX=Factor2*Xf-VertX; NeiBY=Factor2*Yb-VertY; NeiBZ=Factor2*Zf-VertZ; \
400 glNormal3f(VectMul(NeiAX, NeiAY, NeiAZ, NeiBX, NeiBY, NeiBZ)); \
401 glVertex3f(VertX, VertY, VertZ); \
403 Xf=(float)(Ri-Ti-1)*x[Fi] + (float)Ti*x[Fi+1]; \
404 Yf=(float)(Ri-Ti-1)*y[Fi] + (float)Ti*y[Fi+1]; \
405 Xa=Xf+0.001; Yb=Yf+0.001; \
406 Factor=1-(((Xf2=sqr(Xf))+(Yf2=sqr(Yf)))*AmpVr2); \
407 Factor1=1-((sqr(Xa)+Yf2)*AmpVr2); \
408 Factor2=1-((Xf2+sqr(Yb))*AmpVr2); \
409 VertX=Factor*Xf; VertY=Factor*Yf; VertZ=Factor*Zf; \
410 NeiAX=Factor1*Xa-VertX; NeiAY=Factor1*Yf-VertY; NeiAZ=Factor1*Zf-VertZ; \
411 NeiBX=Factor2*Xf-VertX; NeiBY=Factor2*Yb-VertY; NeiBZ=Factor2*Zf-VertZ; \
412 glNormal3f(VectMul(NeiAX, NeiAY, NeiAZ, NeiBX, NeiBY, NeiBZ)); \
413 glVertex3f(VertX, VertY, VertZ); \
416 Xf=(float)Ri*x[Fi+1]; \
417 Yf=(float)Ri*y[Fi+1]; \
418 Xa=Xf+0.001; Yb=Yf+0.001; \
419 Factor=1-(((Xf2=sqr(Xf))+(Yf2=sqr(Yf)))*AmpVr2); \
420 Factor1=1-((sqr(Xa)+Yf2)*AmpVr2); \
421 Factor2=1-((Xf2+sqr(Yb))*AmpVr2); \
422 VertX=Factor*Xf; VertY=Factor*Yf; VertZ=Factor*Zf; \
423 NeiAX=Factor1*Xa-VertX; NeiAY=Factor1*Yf-VertY; NeiAZ=Factor1*Zf-VertZ; \
424 NeiBX=Factor2*Xf-VertX; NeiBY=Factor2*Yb-VertY; NeiBZ=Factor2*Zf-VertZ; \
425 glNormal3f(VectMul(NeiAX, NeiAY, NeiAZ, NeiBX, NeiBY, NeiBZ)); \
426 glVertex3f(VertX, VertY, VertZ); \
432 static void draw_tetra( void )
436 list
= glGenLists( 1 );
437 glNewList( list
, GL_COMPILE
);
438 TRIANGLE(2,seno
,edgedivisions
,0.5/SQRT6
);
441 glMaterialfv(GL_FRONT_AND_BACK
, GL_DIFFUSE
, MaterialColor
[0]);
444 glRotatef(180,0,0,1);
445 glRotatef(-tetraangle
,1,0,0);
446 glMaterialfv(GL_FRONT_AND_BACK
, GL_DIFFUSE
, MaterialColor
[1]);
450 glRotatef(180,0,1,0);
451 glRotatef(-180+tetraangle
,0.5,SQRT3
/2,0);
452 glMaterialfv(GL_FRONT_AND_BACK
, GL_DIFFUSE
, MaterialColor
[2]);
455 glRotatef(180,0,1,0);
456 glRotatef(-180+tetraangle
,0.5,-SQRT3
/2,0);
457 glMaterialfv(GL_FRONT_AND_BACK
, GL_DIFFUSE
, MaterialColor
[3]);
460 glDeleteLists(list
,1);
463 static void draw_cube( void )
467 list
= glGenLists( 1 );
468 glNewList( list
, GL_COMPILE
);
469 SQUARE(2, seno
, edgedivisions
, 0.5)
472 glMaterialfv(GL_FRONT_AND_BACK
, GL_DIFFUSE
, MaterialColor
[0]);
474 glRotatef(cubeangle
,1,0,0);
475 glMaterialfv(GL_FRONT_AND_BACK
, GL_DIFFUSE
, MaterialColor
[1]);
477 glRotatef(cubeangle
,1,0,0);
478 glMaterialfv(GL_FRONT_AND_BACK
, GL_DIFFUSE
, MaterialColor
[2]);
480 glRotatef(cubeangle
,1,0,0);
481 glMaterialfv(GL_FRONT_AND_BACK
, GL_DIFFUSE
, MaterialColor
[3]);
483 glRotatef(cubeangle
,0,1,0);
484 glMaterialfv(GL_FRONT_AND_BACK
, GL_DIFFUSE
, MaterialColor
[4]);
486 glRotatef(2*cubeangle
,0,1,0);
487 glMaterialfv(GL_FRONT_AND_BACK
, GL_DIFFUSE
, MaterialColor
[5]);
490 glDeleteLists(list
,1);
493 static void draw_octa( void )
497 list
= glGenLists( 1 );
498 glNewList( list
, GL_COMPILE
);
499 TRIANGLE(2,seno
,edgedivisions
,1/SQRT6
);
502 glMaterialfv(GL_FRONT_AND_BACK
, GL_DIFFUSE
, MaterialColor
[0]);
505 glRotatef(180,0,0,1);
506 glRotatef(-180+octaangle
,1,0,0);
507 glMaterialfv(GL_FRONT_AND_BACK
, GL_DIFFUSE
, MaterialColor
[1]);
511 glRotatef(180,0,1,0);
512 glRotatef(-octaangle
,0.5,SQRT3
/2,0);
513 glMaterialfv(GL_FRONT_AND_BACK
, GL_DIFFUSE
, MaterialColor
[2]);
517 glRotatef(180,0,1,0);
518 glRotatef(-octaangle
,0.5,-SQRT3
/2,0);
519 glMaterialfv(GL_FRONT_AND_BACK
, GL_DIFFUSE
, MaterialColor
[3]);
522 glRotatef(180,1,0,0);
523 glMaterialfv(GL_FRONT_AND_BACK
, GL_DIFFUSE
, MaterialColor
[4]);
526 glRotatef(180,0,0,1);
527 glRotatef(-180+octaangle
,1,0,0);
528 glMaterialfv(GL_FRONT_AND_BACK
, GL_DIFFUSE
, MaterialColor
[5]);
532 glRotatef(180,0,1,0);
533 glRotatef(-octaangle
,0.5,SQRT3
/2,0);
534 glMaterialfv(GL_FRONT_AND_BACK
, GL_DIFFUSE
, MaterialColor
[6]);
537 glRotatef(180,0,1,0);
538 glRotatef(-octaangle
,0.5,-SQRT3
/2,0);
539 glMaterialfv(GL_FRONT_AND_BACK
, GL_DIFFUSE
, MaterialColor
[7]);
542 glDeleteLists(list
,1);
545 static void draw_dodeca( void )
549 #define TAU ((SQRT5+1)/2)
551 list
= glGenLists( 1 );
552 glNewList( list
, GL_COMPILE
);
553 PENTAGON(1,seno
,edgedivisions
,sqr(TAU
) * sqrt((TAU
+2)/5) / 2);
557 glMaterialfv(GL_FRONT_AND_BACK
, GL_DIFFUSE
, MaterialColor
[0]);
559 glRotatef(180,0,0,1);
561 glRotatef(-dodecaangle
,1,0,0);
562 glMaterialfv(GL_FRONT_AND_BACK
, GL_DIFFUSE
, MaterialColor
[1]);
566 glRotatef(-dodecaangle
,cos72
,sin72
,0);
567 glMaterialfv(GL_FRONT_AND_BACK
, GL_DIFFUSE
, MaterialColor
[2]);
571 glRotatef(-dodecaangle
,cos72
,-sin72
,0);
572 glMaterialfv(GL_FRONT_AND_BACK
, GL_DIFFUSE
, MaterialColor
[3]);
576 glRotatef(dodecaangle
,cos36
,-sin36
,0);
577 glMaterialfv(GL_FRONT_AND_BACK
, GL_DIFFUSE
, MaterialColor
[4]);
580 glRotatef(dodecaangle
,cos36
,sin36
,0);
581 glMaterialfv(GL_FRONT_AND_BACK
, GL_DIFFUSE
, MaterialColor
[5]);
584 glRotatef(180,1,0,0);
585 glMaterialfv(GL_FRONT_AND_BACK
, GL_DIFFUSE
, MaterialColor
[6]);
587 glRotatef(180,0,0,1);
589 glRotatef(-dodecaangle
,1,0,0);
590 glMaterialfv(GL_FRONT_AND_BACK
, GL_DIFFUSE
, MaterialColor
[7]);
594 glRotatef(-dodecaangle
,cos72
,sin72
,0);
595 glMaterialfv(GL_FRONT_AND_BACK
, GL_DIFFUSE
, MaterialColor
[8]);
599 glRotatef(-dodecaangle
,cos72
,-sin72
,0);
600 glMaterialfv(GL_FRONT_AND_BACK
, GL_DIFFUSE
, MaterialColor
[9]);
604 glRotatef(dodecaangle
,cos36
,-sin36
,0);
605 glMaterialfv(GL_FRONT_AND_BACK
, GL_DIFFUSE
, MaterialColor
[10]);
608 glRotatef(dodecaangle
,cos36
,sin36
,0);
609 glMaterialfv(GL_FRONT_AND_BACK
, GL_DIFFUSE
, MaterialColor
[11]);
612 glDeleteLists(list
,1);
615 static void draw_ico( void )
619 list
= glGenLists( 1 );
620 glNewList( list
, GL_COMPILE
);
621 TRIANGLE(1.5,seno
,edgedivisions
,(3*SQRT3
+SQRT15
)/12);
626 glMaterialfv(GL_FRONT_AND_BACK
, GL_DIFFUSE
, MaterialColor
[0]);
629 glRotatef(180,0,0,1);
630 glRotatef(-icoangle
,1,0,0);
631 glMaterialfv(GL_FRONT_AND_BACK
, GL_DIFFUSE
, MaterialColor
[1]);
634 glRotatef(180,0,1,0);
635 glRotatef(-180+icoangle
,0.5,SQRT3
/2,0);
636 glMaterialfv(GL_FRONT_AND_BACK
, GL_DIFFUSE
, MaterialColor
[2]);
639 glRotatef(180,0,1,0);
640 glRotatef(-180+icoangle
,0.5,-SQRT3
/2,0);
641 glMaterialfv(GL_FRONT_AND_BACK
, GL_DIFFUSE
, MaterialColor
[3]);
645 glRotatef(180,0,1,0);
646 glRotatef(-180+icoangle
,0.5,SQRT3
/2,0);
647 glMaterialfv(GL_FRONT_AND_BACK
, GL_DIFFUSE
, MaterialColor
[4]);
650 glRotatef(180,0,1,0);
651 glRotatef(-180+icoangle
,0.5,SQRT3
/2,0);
652 glMaterialfv(GL_FRONT_AND_BACK
, GL_DIFFUSE
, MaterialColor
[5]);
655 glRotatef(180,0,0,1);
656 glRotatef(-icoangle
,1,0,0);
657 glMaterialfv(GL_FRONT_AND_BACK
, GL_DIFFUSE
, MaterialColor
[6]);
660 glRotatef(180,0,1,0);
661 glRotatef(-180+icoangle
,0.5,-SQRT3
/2,0);
662 glMaterialfv(GL_FRONT_AND_BACK
, GL_DIFFUSE
, MaterialColor
[7]);
665 glRotatef(180,0,1,0);
666 glRotatef(-180+icoangle
,0.5,-SQRT3
/2,0);
667 glMaterialfv(GL_FRONT_AND_BACK
, GL_DIFFUSE
, MaterialColor
[8]);
670 glRotatef(180,0,0,1);
671 glRotatef(-icoangle
,1,0,0);
672 glMaterialfv(GL_FRONT_AND_BACK
, GL_DIFFUSE
, MaterialColor
[9]);
675 glRotatef(180,1,0,0);
676 glMaterialfv(GL_FRONT_AND_BACK
, GL_DIFFUSE
, MaterialColor
[10]);
679 glRotatef(180,0,0,1);
680 glRotatef(-icoangle
,1,0,0);
681 glMaterialfv(GL_FRONT_AND_BACK
, GL_DIFFUSE
, MaterialColor
[11]);
684 glRotatef(180,0,1,0);
685 glRotatef(-180+icoangle
,0.5,SQRT3
/2,0);
686 glMaterialfv(GL_FRONT_AND_BACK
, GL_DIFFUSE
, MaterialColor
[12]);
689 glRotatef(180,0,1,0);
690 glRotatef(-180+icoangle
,0.5,-SQRT3
/2,0);
691 glMaterialfv(GL_FRONT_AND_BACK
, GL_DIFFUSE
, MaterialColor
[13]);
695 glRotatef(180,0,1,0);
696 glRotatef(-180+icoangle
,0.5,SQRT3
/2,0);
697 glMaterialfv(GL_FRONT_AND_BACK
, GL_DIFFUSE
, MaterialColor
[14]);
700 glRotatef(180,0,1,0);
701 glRotatef(-180+icoangle
,0.5,SQRT3
/2,0);
702 glMaterialfv(GL_FRONT_AND_BACK
, GL_DIFFUSE
, MaterialColor
[15]);
705 glRotatef(180,0,0,1);
706 glRotatef(-icoangle
,1,0,0);
707 glMaterialfv(GL_FRONT_AND_BACK
, GL_DIFFUSE
, MaterialColor
[16]);
710 glRotatef(180,0,1,0);
711 glRotatef(-180+icoangle
,0.5,-SQRT3
/2,0);
712 glMaterialfv(GL_FRONT_AND_BACK
, GL_DIFFUSE
, MaterialColor
[17]);
715 glRotatef(180,0,1,0);
716 glRotatef(-180+icoangle
,0.5,-SQRT3
/2,0);
717 glMaterialfv(GL_FRONT_AND_BACK
, GL_DIFFUSE
, MaterialColor
[18]);
720 glRotatef(180,0,0,1);
721 glRotatef(-icoangle
,1,0,0);
722 glMaterialfv(GL_FRONT_AND_BACK
, GL_DIFFUSE
, MaterialColor
[19]);
725 glDeleteLists(list
,1);
728 static void draw ( void ) {
729 glClear( /*GL_COLOR_BUFFER_BIT |*/ GL_DEPTH_BUFFER_BIT
);
733 glTranslatef( 0.0, 0.0, -10.0 );
734 glScalef( Scale
*WindH
/WindW
, Scale
, Scale
);
735 glTranslatef(2.5*WindW
/WindH
*sin(step
*1.11),2.5*cos(step
*1.25*1.11),0);
736 glRotatef(step
*100,1,0,0);
737 glRotatef(step
*95,0,1,0);
738 glRotatef(step
*90,0,0,1);
740 seno
=(sin(step
)+1.0/3.0)*(4.0/5.0)*Magnitude
;
751 static void reshape( int width
, int height
)
753 glViewport(0, 0, WindW
=(GLint
)width
, WindH
=(GLint
)height
);
754 glMatrixMode(GL_PROJECTION
);
756 glFrustum( -1.0, 1.0, -1.0, 1.0, 5.0, 15.0 );
757 glMatrixMode(GL_MODELVIEW
);
760 static void pinit(void)
764 draw_object
=draw_tetra
;
765 MaterialColor
[0]=MaterialRed
;
766 MaterialColor
[1]=MaterialGreen
;
767 MaterialColor
[2]=MaterialBlue
;
768 MaterialColor
[3]=MaterialWhite
;
769 edgedivisions
=tetradivisions
;
773 draw_object
=draw_cube
;
774 MaterialColor
[0]=MaterialRed
;
775 MaterialColor
[1]=MaterialGreen
;
776 MaterialColor
[2]=MaterialCyan
;
777 MaterialColor
[3]=MaterialMagenta
;
778 MaterialColor
[4]=MaterialYellow
;
779 MaterialColor
[5]=MaterialBlue
;
780 edgedivisions
=cubedivisions
;
784 draw_object
=draw_octa
;
785 MaterialColor
[0]=MaterialRed
;
786 MaterialColor
[1]=MaterialGreen
;
787 MaterialColor
[2]=MaterialBlue
;
788 MaterialColor
[3]=MaterialWhite
;
789 MaterialColor
[4]=MaterialCyan
;
790 MaterialColor
[5]=MaterialMagenta
;
791 MaterialColor
[6]=MaterialGray
;
792 MaterialColor
[7]=MaterialYellow
;
793 edgedivisions
=octadivisions
;
797 draw_object
=draw_dodeca
;
798 MaterialColor
[ 0]=MaterialRed
;
799 MaterialColor
[ 1]=MaterialGreen
;
800 MaterialColor
[ 2]=MaterialCyan
;
801 MaterialColor
[ 3]=MaterialBlue
;
802 MaterialColor
[ 4]=MaterialMagenta
;
803 MaterialColor
[ 5]=MaterialYellow
;
804 MaterialColor
[ 6]=MaterialGreen
;
805 MaterialColor
[ 7]=MaterialCyan
;
806 MaterialColor
[ 8]=MaterialRed
;
807 MaterialColor
[ 9]=MaterialMagenta
;
808 MaterialColor
[10]=MaterialBlue
;
809 MaterialColor
[11]=MaterialYellow
;
810 edgedivisions
=dodecadivisions
;
814 draw_object
=draw_ico
;
815 MaterialColor
[ 0]=MaterialRed
;
816 MaterialColor
[ 1]=MaterialGreen
;
817 MaterialColor
[ 2]=MaterialBlue
;
818 MaterialColor
[ 3]=MaterialCyan
;
819 MaterialColor
[ 4]=MaterialYellow
;
820 MaterialColor
[ 5]=MaterialMagenta
;
821 MaterialColor
[ 6]=MaterialRed
;
822 MaterialColor
[ 7]=MaterialGreen
;
823 MaterialColor
[ 8]=MaterialBlue
;
824 MaterialColor
[ 9]=MaterialWhite
;
825 MaterialColor
[10]=MaterialCyan
;
826 MaterialColor
[11]=MaterialYellow
;
827 MaterialColor
[12]=MaterialMagenta
;
828 MaterialColor
[13]=MaterialRed
;
829 MaterialColor
[14]=MaterialGreen
;
830 MaterialColor
[15]=MaterialBlue
;
831 MaterialColor
[16]=MaterialCyan
;
832 MaterialColor
[17]=MaterialYellow
;
833 MaterialColor
[18]=MaterialMagenta
;
834 MaterialColor
[19]=MaterialGray
;
835 edgedivisions
=icodivisions
;
841 for (loop
=0; loop
<20; loop
++) MaterialColor
[loop
]=MaterialGray
;
844 glShadeModel( GL_SMOOTH
);
846 glShadeModel( GL_FLAT
);
851 static void init(void)
853 printf("Morph 3D - Shows morphing platonic polyhedra\n");
854 printf("Author: Marcelo Fernandes Vianna (vianna@cat.cbpf.br)\n\n");
855 printf(" [1] - Tetrahedron\n");
856 printf(" [2] - Hexahedron (Cube)\n");
857 printf(" [3] - Octahedron\n");
858 printf(" [4] - Dodecahedron\n");
859 printf(" [5] - Icosahedron\n");
860 printf("[SPACE] - Toggle colored faces\n");
861 printf("[RETURN] - Toggle smooth/flat shading\n");
862 printf(" [ESC] - Quit\n");
867 glClearColor( 0.0, 0.0, 0.0, 0.0 );
868 glColor3f( 1.0, 1.0, 1.0 );
870 glClear( GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
);
872 primary
->Flip( primary
, NULL
, 0 );
874 glLightfv(GL_LIGHT0
, GL_AMBIENT
, ambient
);
875 glLightfv(GL_LIGHT0
, GL_DIFFUSE
, diffuse
);
876 glLightfv(GL_LIGHT0
, GL_POSITION
, position0
);
877 glLightfv(GL_LIGHT1
, GL_AMBIENT
, ambient
);
878 glLightfv(GL_LIGHT1
, GL_DIFFUSE
, diffuse
);
879 glLightfv(GL_LIGHT1
, GL_POSITION
, position1
);
880 glLightModelfv(GL_LIGHT_MODEL_AMBIENT
, lmodel_ambient
);
881 glLightModelfv(GL_LIGHT_MODEL_TWO_SIDE
, lmodel_twoside
);
882 glEnable(GL_LIGHTING
);
885 glEnable(GL_DEPTH_TEST
);
886 glEnable(GL_NORMALIZE
);
888 glMaterialfv(GL_FRONT_AND_BACK
, GL_SHININESS
, front_shininess
);
889 glMaterialfv(GL_FRONT_AND_BACK
, GL_SPECULAR
, front_specular
);
891 glHint(GL_FOG_HINT
, GL_FASTEST
);
892 glHint(GL_PERSPECTIVE_CORRECTION_HINT
, GL_FASTEST
);
893 glHint(GL_POLYGON_SMOOTH_HINT
, GL_FASTEST
);
898 int main( int argc
, char *argv
[] )
902 DFBSurfaceDescription dsc
;
904 DFBCHECK(DirectFBInit( &argc
, &argv
));
906 /* create the super interface */
907 DFBCHECK(DirectFBCreate( &dfb
));
909 /* create an event buffer for all devices with these caps */
910 DFBCHECK(dfb
->CreateInputEventBuffer( dfb
, DICAPS_KEYS
, DFB_FALSE
, &events
));
912 /* set our cooperative level to DFSCL_FULLSCREEN
913 for exclusive access to the primary layer */
914 dfb
->SetCooperativeLevel( dfb
, DFSCL_FULLSCREEN
);
916 /* get the primary surface, i.e. the surface of the
917 primary layer we have exclusive access to */
918 dsc
.flags
= DSDESC_CAPS
;
919 dsc
.caps
= DSCAPS_PRIMARY
| DSCAPS_DOUBLE
;
921 DFBCHECK(dfb
->CreateSurface( dfb
, &dsc
, &primary
));
923 /* get the size of the surface and fill it */
924 DFBCHECK(primary
->GetSize( primary
, &screen_width
, &screen_height
));
925 DFBCHECK(primary
->FillRectangle( primary
, 0, 0,
926 screen_width
, screen_height
));
928 /* create the default font and set it */
929 DFBCHECK(dfb
->CreateFont( dfb
, NULL
, NULL
, &font
));
930 DFBCHECK(primary
->SetFont( primary
, font
));
932 /* get the GL context */
933 DFBCHECK(primary
->GetGL( primary
, &primary_gl
));
935 DFBCHECK(primary_gl
->Lock( primary_gl
));
938 reshape(screen_width
, screen_height
);
940 DFBCHECK(primary_gl
->Unlock( primary_gl
));
948 primary
->Clear( primary
, 0, 0, 0, 0 );
950 DFBCHECK(primary_gl
->Lock( primary_gl
));
954 DFBCHECK(primary_gl
->Unlock( primary_gl
));
959 sprintf(buf
, "%4.1f FPS\n", fps
);
960 primary
->SetColor( primary
, 0xff, 0, 0, 0xff );
961 primary
->DrawString( primary
, buf
, -1, screen_width
- 5, 5, DSTF_TOPRIGHT
);
964 primary
->Flip( primary
, NULL
, 0 );
969 if (t
- T0
>= 1000) {
970 GLfloat seconds
= (t
- T0
) / 1000.0;
972 fps
= Frames
/ seconds
;
979 while (events
->GetEvent( events
, DFB_EVENT(&evt
) ) == DFB_OK
) {
982 switch (evt
.key_symbol
) {
986 case DIKS_1
: object
=1; break;
987 case DIKS_2
: object
=2; break;
988 case DIKS_3
: object
=3; break;
989 case DIKS_4
: object
=4; break;
990 case DIKS_5
: object
=5; break;
991 case DIKS_SPACE
: mono
^=1; break;
992 case DIKS_ENTER
: smooth
^=1; break;
1004 /* release our interfaces to shutdown DirectFB */
1005 primary_gl
->Release( primary_gl
);
1006 primary
->Release( primary
);
1007 font
->Release( font
);
1008 events
->Release( events
);
1009 dfb
->Release( dfb
);