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 );