Remove allegro driver
[mesa.git] / progs / directfb / df_morph3d.c
1 /*
2 (c) Copyright 2001 convergence integrated media GmbH.
3 All rights reserved.
4
5 Written by Denis Oliver Kropp <dok@convergence.de> and
6 Andreas Hundt <andi@convergence.de>.
7
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.
12
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.
17
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.
22 */
23
24 /*-
25 * morph3d.c - Shows 3D morphing objects
26 *
27 * Converted to GLUT by brianp on 1/1/98
28 *
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.
31 *
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.
40 *
41 * Thanks goes also to Brian Paul for making it possible and inexpensive
42 * to use OpenGL at home.
43 *
44 * Since I'm not a native english speaker, my apologies for any gramatical
45 * mistake.
46 *
47 * My e-mail addresses are
48 *
49 * vianna@cat.cbpf.br
50 * and
51 * marcelo@venus.rdc.puc-rio.br
52 *
53 * Marcelo F. Vianna (Feb-13-1997)
54 */
55
56 /*
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.
60
61 Since I'm not a native english speaker, my apologies for any gramatical
62 mistake.
63
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
68 - Feb-13-1997
69
70 POLYHEDRA GENERATION
71
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
77 task.
78
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.
83
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.
87
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:
91
92 TETRAHEDRON : 1/(2*sqrt(2))/sqrt(3)
93 CUBE : 1/2
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
97
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
115 want is:
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
129 Edge radius:
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
147 So the angle is:
148 +-----------------------------------------------------------+
149 | 2*ARCTAN(ERt/FRi) = 41.810314895778596167 degrees |
150 +-----------------------------------------------------------+
151
152 */
153
154
155 #include <stdlib.h>
156 #include <stdio.h>
157 #include <string.h>
158 #include <math.h>
159 #include <unistd.h>
160
161 #include <directfb.h>
162 #include <directfbgl.h>
163
164 #include <GL/gl.h>
165
166
167 /* the super interface */
168 IDirectFB *dfb;
169
170 /* the primary surface (surface of primary layer) */
171 IDirectFBSurface *primary;
172
173 /* the GL context */
174 IDirectFBGL *primary_gl;
175
176 /* our font */
177 IDirectFBFont *font;
178
179 /* event buffer */
180 IDirectFBEventBuffer *events;
181
182 /* macro for a safe call to DirectFB functions */
183 #define DFBCHECK(x...) \
184 { \
185 err = x; \
186 if (err != DFB_OK) { \
187 fprintf( stderr, "%s <%d>:\n\t", __FILE__, __LINE__ ); \
188 DirectFBErrorFatal( #x, err ); \
189 } \
190 }
191
192 static int screen_width, screen_height;
193
194 static unsigned long T0 = 0;
195 static GLint Frames = 0;
196 static GLfloat fps = 0;
197
198 static inline unsigned long get_millis()
199 {
200 struct timeval tv;
201
202 gettimeofday (&tv, NULL);
203 return (tv.tv_sec * 1000 + tv.tv_usec / 1000);
204 }
205
206
207
208 #define Scale 0.3
209
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))
212
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
220
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
226
227 #ifndef Pi
228 #define Pi 3.1415926535897932385
229 #endif
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
240
241 /*************************************************************************/
242
243 static int mono=0;
244 static int smooth=1;
245 static GLint WindH, WindW;
246 static GLfloat step=0;
247 static GLfloat seno;
248 static int object;
249 static int edgedivisions;
250 static void (*draw_object)( void );
251 static float Magnitude;
252 static float *MaterialColor[20];
253
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};
262
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 };
271
272 #define TRIANGLE(Edge, Amp, Divisions, Z) \
273 { \
274 GLfloat Xf,Yf,Xa,Yb,Xf2,Yf2; \
275 GLfloat Factor,Factor1,Factor2; \
276 GLfloat VertX,VertY,VertZ,NeiAX,NeiAY,NeiAZ,NeiBX,NeiBY,NeiBZ; \
277 GLfloat Ax,Ay,Bx; \
278 int Ri,Ti; \
279 GLfloat Vr=(Edge)*SQRT3/3; \
280 GLfloat AmpVr2=(Amp)/sqr(Vr); \
281 GLfloat Zf=(Edge)*(Z); \
282 \
283 Ax=(Edge)*(+0.5/(Divisions)), Ay=(Edge)*(-SQRT3/(2*Divisions)); \
284 Bx=(Edge)*(-0.5/(Divisions)); \
285 \
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); \
300 \
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); \
312 \
313 } \
314 Xf=(float)Ri*Bx; \
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); \
325 glEnd(); \
326 } \
327 }
328
329 #define SQUARE(Edge, Amp, Divisions, Z) \
330 { \
331 int Xi,Yi; \
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); \
337 \
338 for (Yi=0; Yi<(Divisions); Yi++) { \
339 Yf=-((Edge)/2.0) + ((float)Yi)/(Divisions)*(Edge); \
340 Yf2=sqr(Yf); \
341 Y=Yf+1.0/(Divisions)*(Edge); \
342 Y2=sqr(Y); \
343 glBegin(GL_QUAD_STRIP); \
344 for (Xi=0; Xi<=(Divisions); Xi++) { \
345 Xf=-((Edge)/2.0) + ((float)Xi)/(Divisions)*(Edge); \
346 Xf2=sqr(Xf); \
347 \
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); \
357 \
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); \
367 } \
368 glEnd(); \
369 } \
370 }
371
372 #define PENTAGON(Edge, Amp, Divisions, Z) \
373 { \
374 int Ri,Ti,Fi; \
375 GLfloat Xf,Yf,Xa,Yb,Xf2,Yf2; \
376 GLfloat x[6],y[6]; \
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); \
381 \
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); \
385 } \
386 \
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); \
402 \
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); \
414 \
415 } \
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); \
427 glEnd(); \
428 } \
429 } \
430 }
431
432 static void draw_tetra( void )
433 {
434 GLuint list;
435
436 list = glGenLists( 1 );
437 glNewList( list, GL_COMPILE );
438 TRIANGLE(2,seno,edgedivisions,0.5/SQRT6);
439 glEndList();
440
441 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialColor[0]);
442 glCallList(list);
443 glPushMatrix();
444 glRotatef(180,0,0,1);
445 glRotatef(-tetraangle,1,0,0);
446 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialColor[1]);
447 glCallList(list);
448 glPopMatrix();
449 glPushMatrix();
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]);
453 glCallList(list);
454 glPopMatrix();
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]);
458 glCallList(list);
459
460 glDeleteLists(list,1);
461 }
462
463 static void draw_cube( void )
464 {
465 GLuint list;
466
467 list = glGenLists( 1 );
468 glNewList( list, GL_COMPILE );
469 SQUARE(2, seno, edgedivisions, 0.5)
470 glEndList();
471
472 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialColor[0]);
473 glCallList(list);
474 glRotatef(cubeangle,1,0,0);
475 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialColor[1]);
476 glCallList(list);
477 glRotatef(cubeangle,1,0,0);
478 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialColor[2]);
479 glCallList(list);
480 glRotatef(cubeangle,1,0,0);
481 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialColor[3]);
482 glCallList(list);
483 glRotatef(cubeangle,0,1,0);
484 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialColor[4]);
485 glCallList(list);
486 glRotatef(2*cubeangle,0,1,0);
487 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialColor[5]);
488 glCallList(list);
489
490 glDeleteLists(list,1);
491 }
492
493 static void draw_octa( void )
494 {
495 GLuint list;
496
497 list = glGenLists( 1 );
498 glNewList( list, GL_COMPILE );
499 TRIANGLE(2,seno,edgedivisions,1/SQRT6);
500 glEndList();
501
502 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialColor[0]);
503 glCallList(list);
504 glPushMatrix();
505 glRotatef(180,0,0,1);
506 glRotatef(-180+octaangle,1,0,0);
507 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialColor[1]);
508 glCallList(list);
509 glPopMatrix();
510 glPushMatrix();
511 glRotatef(180,0,1,0);
512 glRotatef(-octaangle,0.5,SQRT3/2,0);
513 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialColor[2]);
514 glCallList(list);
515 glPopMatrix();
516 glPushMatrix();
517 glRotatef(180,0,1,0);
518 glRotatef(-octaangle,0.5,-SQRT3/2,0);
519 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialColor[3]);
520 glCallList(list);
521 glPopMatrix();
522 glRotatef(180,1,0,0);
523 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialColor[4]);
524 glCallList(list);
525 glPushMatrix();
526 glRotatef(180,0,0,1);
527 glRotatef(-180+octaangle,1,0,0);
528 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialColor[5]);
529 glCallList(list);
530 glPopMatrix();
531 glPushMatrix();
532 glRotatef(180,0,1,0);
533 glRotatef(-octaangle,0.5,SQRT3/2,0);
534 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialColor[6]);
535 glCallList(list);
536 glPopMatrix();
537 glRotatef(180,0,1,0);
538 glRotatef(-octaangle,0.5,-SQRT3/2,0);
539 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialColor[7]);
540 glCallList(list);
541
542 glDeleteLists(list,1);
543 }
544
545 static void draw_dodeca( void )
546 {
547 GLuint list;
548
549 #define TAU ((SQRT5+1)/2)
550
551 list = glGenLists( 1 );
552 glNewList( list, GL_COMPILE );
553 PENTAGON(1,seno,edgedivisions,sqr(TAU) * sqrt((TAU+2)/5) / 2);
554 glEndList();
555
556 glPushMatrix();
557 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialColor[0]);
558 glCallList(list);
559 glRotatef(180,0,0,1);
560 glPushMatrix();
561 glRotatef(-dodecaangle,1,0,0);
562 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialColor[1]);
563 glCallList(list);
564 glPopMatrix();
565 glPushMatrix();
566 glRotatef(-dodecaangle,cos72,sin72,0);
567 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialColor[2]);
568 glCallList(list);
569 glPopMatrix();
570 glPushMatrix();
571 glRotatef(-dodecaangle,cos72,-sin72,0);
572 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialColor[3]);
573 glCallList(list);
574 glPopMatrix();
575 glPushMatrix();
576 glRotatef(dodecaangle,cos36,-sin36,0);
577 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialColor[4]);
578 glCallList(list);
579 glPopMatrix();
580 glRotatef(dodecaangle,cos36,sin36,0);
581 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialColor[5]);
582 glCallList(list);
583 glPopMatrix();
584 glRotatef(180,1,0,0);
585 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialColor[6]);
586 glCallList(list);
587 glRotatef(180,0,0,1);
588 glPushMatrix();
589 glRotatef(-dodecaangle,1,0,0);
590 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialColor[7]);
591 glCallList(list);
592 glPopMatrix();
593 glPushMatrix();
594 glRotatef(-dodecaangle,cos72,sin72,0);
595 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialColor[8]);
596 glCallList(list);
597 glPopMatrix();
598 glPushMatrix();
599 glRotatef(-dodecaangle,cos72,-sin72,0);
600 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialColor[9]);
601 glCallList(list);
602 glPopMatrix();
603 glPushMatrix();
604 glRotatef(dodecaangle,cos36,-sin36,0);
605 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialColor[10]);
606 glCallList(list);
607 glPopMatrix();
608 glRotatef(dodecaangle,cos36,sin36,0);
609 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialColor[11]);
610 glCallList(list);
611
612 glDeleteLists(list,1);
613 }
614
615 static void draw_ico( void )
616 {
617 GLuint list;
618
619 list = glGenLists( 1 );
620 glNewList( list, GL_COMPILE );
621 TRIANGLE(1.5,seno,edgedivisions,(3*SQRT3+SQRT15)/12);
622 glEndList();
623
624 glPushMatrix();
625
626 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialColor[0]);
627 glCallList(list);
628 glPushMatrix();
629 glRotatef(180,0,0,1);
630 glRotatef(-icoangle,1,0,0);
631 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialColor[1]);
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[2]);
637 glCallList(list);
638 glPopMatrix();
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]);
642 glCallList(list);
643 glPopMatrix();
644 glPushMatrix();
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]);
648 glCallList(list);
649 glPushMatrix();
650 glRotatef(180,0,1,0);
651 glRotatef(-180+icoangle,0.5,SQRT3/2,0);
652 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialColor[5]);
653 glCallList(list);
654 glPopMatrix();
655 glRotatef(180,0,0,1);
656 glRotatef(-icoangle,1,0,0);
657 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialColor[6]);
658 glCallList(list);
659 glPopMatrix();
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]);
663 glCallList(list);
664 glPushMatrix();
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]);
668 glCallList(list);
669 glPopMatrix();
670 glRotatef(180,0,0,1);
671 glRotatef(-icoangle,1,0,0);
672 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialColor[9]);
673 glCallList(list);
674 glPopMatrix();
675 glRotatef(180,1,0,0);
676 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialColor[10]);
677 glCallList(list);
678 glPushMatrix();
679 glRotatef(180,0,0,1);
680 glRotatef(-icoangle,1,0,0);
681 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialColor[11]);
682 glCallList(list);
683 glPushMatrix();
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]);
687 glCallList(list);
688 glPopMatrix();
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]);
692 glCallList(list);
693 glPopMatrix();
694 glPushMatrix();
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]);
698 glCallList(list);
699 glPushMatrix();
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]);
703 glCallList(list);
704 glPopMatrix();
705 glRotatef(180,0,0,1);
706 glRotatef(-icoangle,1,0,0);
707 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialColor[16]);
708 glCallList(list);
709 glPopMatrix();
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]);
713 glCallList(list);
714 glPushMatrix();
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]);
718 glCallList(list);
719 glPopMatrix();
720 glRotatef(180,0,0,1);
721 glRotatef(-icoangle,1,0,0);
722 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialColor[19]);
723 glCallList(list);
724
725 glDeleteLists(list,1);
726 }
727
728 static void draw ( void ) {
729 glClear( /*GL_COLOR_BUFFER_BIT |*/ GL_DEPTH_BUFFER_BIT );
730
731 glPushMatrix();
732
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);
739
740 seno=(sin(step)+1.0/3.0)*(4.0/5.0)*Magnitude;
741
742 draw_object();
743
744 glPopMatrix();
745
746 glFlush();
747
748 step+=0.05;
749 }
750
751 static void reshape( int width, int height )
752 {
753 glViewport(0, 0, WindW=(GLint)width, WindH=(GLint)height);
754 glMatrixMode(GL_PROJECTION);
755 glLoadIdentity();
756 glFrustum( -1.0, 1.0, -1.0, 1.0, 5.0, 15.0 );
757 glMatrixMode(GL_MODELVIEW);
758 }
759
760 static void pinit(void)
761 {
762 switch(object) {
763 case 1:
764 draw_object=draw_tetra;
765 MaterialColor[0]=MaterialRed;
766 MaterialColor[1]=MaterialGreen;
767 MaterialColor[2]=MaterialBlue;
768 MaterialColor[3]=MaterialWhite;
769 edgedivisions=tetradivisions;
770 Magnitude=2.5;
771 break;
772 case 2:
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;
781 Magnitude=2.0;
782 break;
783 case 3:
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;
794 Magnitude=2.5;
795 break;
796 case 4:
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;
811 Magnitude=2.0;
812 break;
813 case 5:
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;
836 Magnitude=2.5;
837 break;
838 }
839 if (mono) {
840 int loop;
841 for (loop=0; loop<20; loop++) MaterialColor[loop]=MaterialGray;
842 }
843 if (smooth) {
844 glShadeModel( GL_SMOOTH );
845 } else {
846 glShadeModel( GL_FLAT );
847 }
848
849 }
850
851 static void init(void)
852 {
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");
863
864 object=1;
865
866 glClearDepth(1.0);
867 glClearColor( 0.0, 0.0, 0.0, 0.0 );
868 glColor3f( 1.0, 1.0, 1.0 );
869
870 glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
871 glFlush();
872 primary->Flip( primary, NULL, 0 );
873
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);
883 glEnable(GL_LIGHT0);
884 glEnable(GL_LIGHT1);
885 glEnable(GL_DEPTH_TEST);
886 glEnable(GL_NORMALIZE);
887
888 glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, front_shininess);
889 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, front_specular);
890
891 glHint(GL_FOG_HINT, GL_FASTEST);
892 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
893 glHint(GL_POLYGON_SMOOTH_HINT, GL_FASTEST);
894
895 pinit();
896 }
897
898 int main( int argc, char *argv[] )
899 {
900 int quit = 0;
901 DFBResult err;
902 DFBSurfaceDescription dsc;
903
904 DFBCHECK(DirectFBInit( &argc, &argv ));
905
906 /* create the super interface */
907 DFBCHECK(DirectFBCreate( &dfb ));
908
909 /* create an event buffer for all devices with these caps */
910 DFBCHECK(dfb->CreateInputEventBuffer( dfb, DICAPS_KEYS, DFB_FALSE, &events ));
911
912 /* set our cooperative level to DFSCL_FULLSCREEN
913 for exclusive access to the primary layer */
914 dfb->SetCooperativeLevel( dfb, DFSCL_FULLSCREEN );
915
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;
920
921 DFBCHECK(dfb->CreateSurface( dfb, &dsc, &primary ));
922
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 ));
927
928 /* create the default font and set it */
929 DFBCHECK(dfb->CreateFont( dfb, NULL, NULL, &font ));
930 DFBCHECK(primary->SetFont( primary, font ));
931
932 /* get the GL context */
933 DFBCHECK(primary->GetGL( primary, &primary_gl ));
934
935 DFBCHECK(primary_gl->Lock( primary_gl ));
936
937 init();
938 reshape(screen_width, screen_height);
939
940 DFBCHECK(primary_gl->Unlock( primary_gl ));
941
942 T0 = get_millis();
943
944 while (!quit) {
945 DFBInputEvent evt;
946 unsigned long t;
947
948 primary->Clear( primary, 0, 0, 0, 0 );
949
950 DFBCHECK(primary_gl->Lock( primary_gl ));
951
952 draw();
953
954 DFBCHECK(primary_gl->Unlock( primary_gl ));
955
956 if (fps) {
957 char buf[64];
958
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 );
962 }
963
964 primary->Flip( primary, NULL, 0 );
965 Frames++;
966
967
968 t = get_millis();
969 if (t - T0 >= 1000) {
970 GLfloat seconds = (t - T0) / 1000.0;
971
972 fps = Frames / seconds;
973
974 T0 = t;
975 Frames = 0;
976 }
977
978
979 while (events->GetEvent( events, DFB_EVENT(&evt) ) == DFB_OK) {
980 switch (evt.type) {
981 case DIET_KEYPRESS:
982 switch (evt.key_symbol) {
983 case DIKS_ESCAPE:
984 quit = 1;
985 break;
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;
993 default:
994 ;
995 }
996 pinit();
997 break;
998 default:
999 ;
1000 }
1001 }
1002 }
1003
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 );
1010
1011 return 0;
1012 }
1013