1 /* -*- Mode: C; tab-width: 4 -*- */
2 /* morph3d --- Shows 3D morphing objects */
4 #if !defined( lint ) && !defined( SABER )
5 static const char sccsid[] = "@(#)morph3d.c 5.01 2001/03/01 xlockmore";
12 * Permission to use, copy, modify, and distribute this software and its
13 * documentation for any purpose and without fee is hereby granted,
14 * provided that the above copyright notice appear in all copies and that
15 * both that copyright notice and this permission notice appear in
16 * supporting documentation.
18 * This file is provided AS IS with no warranties of any kind. The author
19 * shall have no liability with respect to the infringement of copyrights,
20 * trade secrets or any patents by this file or any part thereof. In no
21 * event will the author be liable for any lost revenue or profits or
22 * other special, indirect and consequential damages.
24 * The original code for this mode was written by Marcelo Fernandes Vianna
25 * (me...) and was inspired on a WindowsNT(R)'s screen saver (Flower Box).
26 * It was written from scratch and it was not based on any other source code.
28 * Porting it to xlock (the final objective of this code since the moment I
29 * decided to create it) was possible by comparing the original Mesa's gear
30 * demo with it's ported version to xlock, so thanks for Danny Sung (look at
31 * gear.c) for his indirect help.
33 * Thanks goes also to Brian Paul for making it possible and inexpensive
34 * to use OpenGL at home.
36 * If you are interested in the original version of this program (not a xlock
37 * mode, please refer to the Mesa package (ftp iris.ssec.wisc.edu on /pub/Mesa)
39 * Since I'm not a native English speaker, my apologies for any grammatical
42 * My e-mail address is
43 * mfvianna@centroin.com.br
45 * Marcelo F. Vianna (Feb-13-1997)
48 * 05-Apr-2002: Removed all gllist uses (fix some bug with nvidia driver)
49 * 01-Mar-2001: Added FPS stuff E.Lassauge <lassauge@mail.dotcom.fr>
50 * 27-Jul-1997: Speed ups by Marcelo F. Vianna.
51 * 08-May-1997: Speed ups by Marcelo F. Vianna.
57 * due to a Bug/feature in VMS X11/Intrinsic.h has to be placed before xlock.
58 * otherwise caddr_t is not defined correctly
61 #include <X11/Intrinsic.h>
66 # define PROGCLASS "Morph3d"
67 # define HACK_INIT init_morph3d
68 # define HACK_DRAW draw_morph3d
69 # define HACK_RESHAPE reshape
70 # define morph3d_opts xlockmore_opts
71 # define DEFAULTS "*delay: 40000 \n" \
72 "*showFPS: False \n" \
74 # include "xlockmore.h" /* from the xscreensaver distribution */
75 #else /* !STANDALONE */
76 # include "xlock.h" /* from the xlockmore distribution */
77 #endif /* !STANDALONE */
81 ModeSpecOpt morph3d_opts =
82 {0, (XrmOptionDescRec *) NULL, 0, (argtype *) NULL, (OptionStruct *) NULL};
85 ModStruct morph3d_description =
86 {"morph3d", "init_morph3d", "draw_morph3d", "release_morph3d",
87 "draw_morph3d", "change_morph3d", (char *) NULL, &morph3d_opts,
88 1000, 0, 1, 1, 4, 1.0, "",
89 "Shows GL morphing polyhedra", 0, NULL};
93 #define Scale4Window 0.3
94 #define Scale4Iconic 1.0
96 #define VectMul(X1,Y1,Z1,X2,Y2,Z2) (Y1)*(Z2)-(Z1)*(Y2),(Z1)*(X2)-(X1)*(Z2),(X1)*(Y2)-(Y1)*(X2)
97 #define sqr(A) ((A)*(A))
99 /* Increasing this values produces better image quality, the price is speed. */
100 #define tetradivisions 23
101 #define cubedivisions 20
102 #define octadivisions 21
103 #define dodecadivisions 10
104 #define icodivisions 15
106 #define tetraangle 109.47122063449069174
107 #define cubeangle 90.000000000000000000
108 #define octaangle 109.47122063449069174
109 #define dodecaangle 63.434948822922009981
110 #define icoangle 41.810314895778596167
115 #define SQRT2 1.4142135623730951455
116 #define SQRT3 1.7320508075688771932
117 #define SQRT5 2.2360679774997898051
118 #define SQRT6 2.4494897427831778813
119 #define SQRT15 3.8729833462074170214
120 #define cossec36_2 0.8506508083520399322
121 #define cos72 0.3090169943749474241
122 #define sin72 0.9510565162951535721
123 #define cos36 0.8090169943749474241
124 #define sin36 0.5877852522924731292
126 /*************************************************************************/
135 void (*draw_object) (ModeInfo * mi);
137 float *MaterialColor[20];
138 GLXContext *glx_context;
141 static float front_shininess[] =
143 static float front_specular[] =
144 {0.7, 0.7, 0.7, 1.0};
145 static float ambient[] =
146 {0.0, 0.0, 0.0, 1.0};
147 static float diffuse[] =
148 {1.0, 1.0, 1.0, 1.0};
149 static float position0[] =
150 {1.0, 1.0, 1.0, 0.0};
151 static float position1[] =
152 {-1.0, -1.0, 1.0, 0.0};
153 static float lmodel_ambient[] =
154 {0.5, 0.5, 0.5, 1.0};
155 static float lmodel_twoside[] =
158 static float MaterialRed[] =
159 {0.7, 0.0, 0.0, 1.0};
160 static float MaterialGreen[] =
161 {0.1, 0.5, 0.2, 1.0};
162 static float MaterialBlue[] =
163 {0.0, 0.0, 0.7, 1.0};
164 static float MaterialCyan[] =
165 {0.2, 0.5, 0.7, 1.0};
166 static float MaterialYellow[] =
167 {0.7, 0.7, 0.0, 1.0};
168 static float MaterialMagenta[] =
169 {0.6, 0.2, 0.5, 1.0};
170 static float MaterialWhite[] =
171 {0.7, 0.7, 0.7, 1.0};
172 static float MaterialGray[] =
173 {0.5, 0.5, 0.5, 1.0};
175 static morph3dstruct *morph3d = (morph3dstruct *) NULL;
177 #define TRIANGLE(Edge, Amp, Divisions, Z, VS) \
179 GLfloat Xf,Yf,Xa,Yb=0.0,Xf2=0.0,Yf2=0.0,Yf_2=0.0,Yb2,Yb_2; \
180 GLfloat Factor=0.0,Factor1,Factor2; \
181 GLfloat VertX,VertY,VertZ,NeiAX,NeiAY,NeiAZ,NeiBX,NeiBY,NeiBZ; \
184 GLfloat Vr=(Edge)*SQRT3/3; \
185 GLfloat AmpVr2=(Amp)/sqr(Vr); \
186 GLfloat Zf=(Edge)*(Z); \
188 Ax=(Edge)*(+0.5/(Divisions)), Ay=(Edge)*(-SQRT3/(2*Divisions)); \
190 Yf=Vr+Ay; Yb=Yf+0.001; \
191 for (Ri=1; Ri<=(Divisions); Ri++) { \
192 glBegin(GL_TRIANGLE_STRIP); \
193 Xf=(float)Ri*Ax; Xa=Xf+0.001; \
194 Yf2=sqr(Yf); Yf_2=sqr(Yf-Ay); \
195 Yb2=sqr(Yb); Yb_2=sqr(Yb-Ay); \
196 for (Ti=0; Ti<Ri; Ti++) { \
197 Factor=1-(((Xf2=sqr(Xf))+Yf2)*AmpVr2); \
198 Factor1=1-((sqr(Xa)+Yf2)*AmpVr2); \
199 Factor2=1-((Xf2+Yb2)*AmpVr2); \
200 VertX=Factor*Xf; VertY=Factor*Yf; VertZ=Factor*Zf; \
201 NeiAX=Factor1*Xa-VertX; NeiAY=Factor1*Yf-VertY; NeiAZ=Factor1*Zf-VertZ; \
202 NeiBX=Factor2*Xf-VertX; NeiBY=Factor2*Yb-VertY; NeiBZ=Factor2*Zf-VertZ; \
203 glNormal3f(VectMul(NeiAX, NeiAY, NeiAZ, NeiBX, NeiBY, NeiBZ)); \
204 glVertex3f(VertX, VertY, VertZ); \
206 Xf-=Ax; Yf-=Ay; Xa-=Ax; Yb-=Ay; \
208 Factor=1-(((Xf2=sqr(Xf))+Yf_2)*AmpVr2); \
209 Factor1=1-((sqr(Xa)+Yf_2)*AmpVr2); \
210 Factor2=1-((Xf2+Yb_2)*AmpVr2); \
211 VertX=Factor*Xf; VertY=Factor*Yf; VertZ=Factor*Zf; \
212 NeiAX=Factor1*Xa-VertX; NeiAY=Factor1*Yf-VertY; NeiAZ=Factor1*Zf-VertZ; \
213 NeiBX=Factor2*Xf-VertX; NeiBY=Factor2*Yb-VertY; NeiBZ=Factor2*Zf-VertZ; \
214 glNormal3f(VectMul(NeiAX, NeiAY, NeiAZ, NeiBX, NeiBY, NeiBZ)); \
215 glVertex3f(VertX, VertY, VertZ); \
217 Xf-=Ax; Yf+=Ay; Xa-=Ax; Yb+=Ay; \
219 Factor=1-(((Xf2=sqr(Xf))+(Yf2=sqr(Yf)))*AmpVr2); \
220 Factor1=1-((sqr(Xa)+Yf2)*AmpVr2); \
221 Factor2=1-((Xf2+sqr(Yb))*AmpVr2); \
222 VertX=Factor*Xf; VertY=Factor*Yf; VertZ=Factor*Zf; \
223 NeiAX=Factor1*Xa-VertX; NeiAY=Factor1*Yf-VertY; NeiAZ=Factor1*Zf-VertZ; \
224 NeiBX=Factor2*Xf-VertX; NeiBY=Factor2*Yb-VertY; NeiBZ=Factor2*Zf-VertZ; \
225 glNormal3f(VectMul(NeiAX, NeiAY, NeiAZ, NeiBX, NeiBY, NeiBZ)); \
226 glVertex3f(VertX, VertY, VertZ); \
233 #define SQUARE(Edge, Amp, Divisions, Z, VS) \
236 GLfloat Xf,Yf,Y,Xf2,Yf2,Y2,Xa,Xa2,Yb; \
237 GLfloat Factor=0.0,Factor1,Factor2; \
238 GLfloat VertX,VertY,VertZ,NeiAX,NeiAY,NeiAZ,NeiBX,NeiBY,NeiBZ; \
239 GLfloat Zf=(Edge)*(Z); \
240 GLfloat AmpVr2=(Amp)/sqr((Edge)*SQRT2/2); \
242 for (Yi=0; Yi<(Divisions); Yi++) { \
243 Yf=-((Edge)/2.0) + ((float)Yi)/(Divisions)*(Edge); \
245 Y=Yf+1.0/(Divisions)*(Edge); \
247 glBegin(GL_QUAD_STRIP); \
248 for (Xi=0; Xi<=(Divisions); Xi++) { \
249 Xf=-((Edge)/2.0) + ((float)Xi)/(Divisions)*(Edge); \
252 Xa=Xf+0.001; Yb=Y+0.001; \
253 Factor=1-((Xf2+Y2)*AmpVr2); \
254 Factor1=1-(((Xa2=sqr(Xa))+Y2)*AmpVr2); \
255 Factor2=1-((Xf2+sqr(Yb))*AmpVr2); \
256 VertX=Factor*Xf; VertY=Factor*Y; VertZ=Factor*Zf; \
257 NeiAX=Factor1*Xa-VertX; NeiAY=Factor1*Y-VertY; NeiAZ=Factor1*Zf-VertZ; \
258 NeiBX=Factor2*Xf-VertX; NeiBY=Factor2*Yb-VertY; NeiBZ=Factor2*Zf-VertZ; \
259 glNormal3f(VectMul(NeiAX, NeiAY, NeiAZ, NeiBX, NeiBY, NeiBZ)); \
260 glVertex3f(VertX, VertY, VertZ); \
263 Factor=1-((Xf2+Yf2)*AmpVr2); \
264 Factor1=1-((Xa2+Yf2)*AmpVr2); \
265 Factor2=1-((Xf2+sqr(Yb))*AmpVr2); \
266 VertX=Factor*Xf; VertY=Factor*Yf; VertZ=Factor*Zf; \
267 NeiAX=Factor1*Xa-VertX; NeiAY=Factor1*Yf-VertY; NeiAZ=Factor1*Zf-VertZ; \
268 NeiBX=Factor2*Xf-VertX; NeiBY=Factor2*Yb-VertY; NeiBZ=Factor2*Zf-VertZ; \
269 glNormal3f(VectMul(NeiAX, NeiAY, NeiAZ, NeiBX, NeiBY, NeiBZ)); \
270 glVertex3f(VertX, VertY, VertZ); \
277 #define PENTAGON(Edge, Amp, Divisions, Z, VS) \
280 GLfloat Xf,Yf,Xa,Yb,Xf2,Yf2; \
281 GLfloat Factor=0.0,Factor1,Factor2; \
282 GLfloat VertX,VertY,VertZ,NeiAX,NeiAY,NeiAZ,NeiBX,NeiBY,NeiBZ; \
283 GLfloat Zf=(Edge)*(Z); \
284 GLfloat AmpVr2=(Amp)/sqr((Edge)*cossec36_2); \
286 static GLfloat x[6],y[6]; \
287 static int arrayninit=1; \
290 for(Fi=0;Fi<6;Fi++) { \
291 x[Fi]=-cos( Fi*2*Pi/5 + Pi/10 )/(Divisions)*cossec36_2*(Edge); \
292 y[Fi]=sin( Fi*2*Pi/5 + Pi/10 )/(Divisions)*cossec36_2*(Edge); \
297 for (Ri=1; Ri<=(Divisions); Ri++) { \
298 for (Fi=0; Fi<5; Fi++) { \
299 glBegin(GL_TRIANGLE_STRIP); \
300 for (Ti=0; Ti<Ri; Ti++) { \
301 Xf=(float)(Ri-Ti)*x[Fi] + (float)Ti*x[Fi+1]; \
302 Yf=(float)(Ri-Ti)*y[Fi] + (float)Ti*y[Fi+1]; \
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); \
313 Xf-=x[Fi]; Yf-=y[Fi]; Xa-=x[Fi]; Yb-=y[Fi]; \
315 Factor=1-(((Xf2=sqr(Xf))+(Yf2=sqr(Yf)))*AmpVr2); \
316 Factor1=1-((sqr(Xa)+Yf2)*AmpVr2); \
317 Factor2=1-((Xf2+sqr(Yb))*AmpVr2); \
318 VertX=Factor*Xf; VertY=Factor*Yf; VertZ=Factor*Zf; \
319 NeiAX=Factor1*Xa-VertX; NeiAY=Factor1*Yf-VertY; NeiAZ=Factor1*Zf-VertZ; \
320 NeiBX=Factor2*Xf-VertX; NeiBY=Factor2*Yb-VertY; NeiBZ=Factor2*Zf-VertZ; \
321 glNormal3f(VectMul(NeiAX, NeiAY, NeiAZ, NeiBX, NeiBY, NeiBZ)); \
322 glVertex3f(VertX, VertY, VertZ); \
325 Xf=(float)Ri*x[Fi+1]; \
326 Yf=(float)Ri*y[Fi+1]; \
327 Xa=Xf+0.001; Yb=Yf+0.001; \
328 Factor=1-(((Xf2=sqr(Xf))+(Yf2=sqr(Yf)))*AmpVr2); \
329 Factor1=1-((sqr(Xa)+Yf2)*AmpVr2); \
330 Factor2=1-((Xf2+sqr(Yb))*AmpVr2); \
331 VertX=Factor*Xf; VertY=Factor*Yf; VertZ=Factor*Zf; \
332 NeiAX=Factor1*Xa-VertX; NeiAY=Factor1*Yf-VertY; NeiAZ=Factor1*Zf-VertZ; \
333 NeiBX=Factor2*Xf-VertX; NeiBY=Factor2*Yb-VertY; NeiBZ=Factor2*Zf-VertZ; \
334 glNormal3f(VectMul(NeiAX, NeiAY, NeiAZ, NeiBX, NeiBY, NeiBZ)); \
335 glVertex3f(VertX, VertY, VertZ); \
343 draw_tetra(ModeInfo * mi)
345 morph3dstruct *mp = &morph3d[MI_SCREEN(mi)];
347 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[0]);
349 TRIANGLE(2, mp->seno, mp->edgedivisions, 0.5 / SQRT6, mp->VisibleSpikes);
352 glRotatef(180, 0, 0, 1);
353 glRotatef(-tetraangle, 1, 0, 0);
354 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[1]);
355 TRIANGLE(2, mp->seno, mp->edgedivisions, 0.5 / SQRT6, mp->VisibleSpikes);
358 glRotatef(180, 0, 1, 0);
359 glRotatef(-180 + tetraangle, 0.5, SQRT3 / 2, 0);
360 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[2]);
361 TRIANGLE(2, mp->seno, mp->edgedivisions, 0.5 / SQRT6, mp->VisibleSpikes);
363 glRotatef(180, 0, 1, 0);
364 glRotatef(-180 + tetraangle, 0.5, -SQRT3 / 2, 0);
365 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[3]);
366 TRIANGLE(2, mp->seno, mp->edgedivisions, 0.5 / SQRT6, mp->VisibleSpikes);
370 draw_cube(ModeInfo * mi)
372 morph3dstruct *mp = &morph3d[MI_SCREEN(mi)];
374 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[0]);
376 SQUARE(2, mp->seno, mp->edgedivisions, 0.5, mp->VisibleSpikes)
378 glRotatef(cubeangle, 1, 0, 0);
379 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[1]);
380 SQUARE(2, mp->seno, mp->edgedivisions, 0.5, mp->VisibleSpikes)
381 glRotatef(cubeangle, 1, 0, 0);
382 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[2]);
383 SQUARE(2, mp->seno, mp->edgedivisions, 0.5, mp->VisibleSpikes)
384 glRotatef(cubeangle, 1, 0, 0);
385 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[3]);
386 SQUARE(2, mp->seno, mp->edgedivisions, 0.5, mp->VisibleSpikes)
387 glRotatef(cubeangle, 0, 1, 0);
388 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[4]);
389 SQUARE(2, mp->seno, mp->edgedivisions, 0.5, mp->VisibleSpikes)
390 glRotatef(2 * cubeangle, 0, 1, 0);
391 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[5]);
392 SQUARE(2, mp->seno, mp->edgedivisions, 0.5, mp->VisibleSpikes)
396 draw_octa(ModeInfo * mi)
398 morph3dstruct *mp = &morph3d[MI_SCREEN(mi)];
400 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[0]);
401 TRIANGLE(2, mp->seno, mp->edgedivisions, 1 / SQRT6, mp->VisibleSpikes);
404 glRotatef(180, 0, 0, 1);
405 glRotatef(-180 + octaangle, 1, 0, 0);
406 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[1]);
407 TRIANGLE(2, mp->seno, mp->edgedivisions, 1 / SQRT6, mp->VisibleSpikes);
410 glRotatef(180, 0, 1, 0);
411 glRotatef(-octaangle, 0.5, SQRT3 / 2, 0);
412 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[2]);
413 TRIANGLE(2, mp->seno, mp->edgedivisions, 1 / SQRT6, mp->VisibleSpikes);
416 glRotatef(180, 0, 1, 0);
417 glRotatef(-octaangle, 0.5, -SQRT3 / 2, 0);
418 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[3]);
419 TRIANGLE(2, mp->seno, mp->edgedivisions, 1 / SQRT6, mp->VisibleSpikes);
421 glRotatef(180, 1, 0, 0);
422 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[4]);
423 TRIANGLE(2, mp->seno, mp->edgedivisions, 1 / SQRT6, mp->VisibleSpikes);
425 glRotatef(180, 0, 0, 1);
426 glRotatef(-180 + octaangle, 1, 0, 0);
427 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[5]);
428 TRIANGLE(2, mp->seno, mp->edgedivisions, 1 / SQRT6, mp->VisibleSpikes);
431 glRotatef(180, 0, 1, 0);
432 glRotatef(-octaangle, 0.5, SQRT3 / 2, 0);
433 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[6]);
434 TRIANGLE(2, mp->seno, mp->edgedivisions, 1 / SQRT6, mp->VisibleSpikes);
436 glRotatef(180, 0, 1, 0);
437 glRotatef(-octaangle, 0.5, -SQRT3 / 2, 0);
438 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[7]);
439 TRIANGLE(2, mp->seno, mp->edgedivisions, 1 / SQRT6, mp->VisibleSpikes);
443 draw_dodeca(ModeInfo * mi)
445 morph3dstruct *mp = &morph3d[MI_SCREEN(mi)];
447 #define TAU ((SQRT5+1)/2)
449 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[0]);
451 PENTAGON(1, mp->seno, mp->edgedivisions, sqr(TAU) * sqrt((TAU + 2) / 5) / 2, mp->VisibleSpikes);
454 glRotatef(180, 0, 0, 1);
456 glRotatef(-dodecaangle, 1, 0, 0);
457 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[1]);
458 PENTAGON(1, mp->seno, mp->edgedivisions, sqr(TAU) * sqrt((TAU + 2) / 5) / 2, mp->VisibleSpikes);
461 glRotatef(-dodecaangle, cos72, sin72, 0);
462 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[2]);
463 PENTAGON(1, mp->seno, mp->edgedivisions, sqr(TAU) * sqrt((TAU + 2) / 5) / 2, mp->VisibleSpikes);
466 glRotatef(-dodecaangle, cos72, -sin72, 0);
467 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[3]);
468 PENTAGON(1, mp->seno, mp->edgedivisions, sqr(TAU) * sqrt((TAU + 2) / 5) / 2, mp->VisibleSpikes);
471 glRotatef(dodecaangle, cos36, -sin36, 0);
472 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[4]);
473 PENTAGON(1, mp->seno, mp->edgedivisions, sqr(TAU) * sqrt((TAU + 2) / 5) / 2, mp->VisibleSpikes);
475 glRotatef(dodecaangle, cos36, sin36, 0);
476 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[5]);
477 PENTAGON(1, mp->seno, mp->edgedivisions, sqr(TAU) * sqrt((TAU + 2) / 5) / 2, mp->VisibleSpikes);
479 glRotatef(180, 1, 0, 0);
480 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[6]);
481 PENTAGON(1, mp->seno, mp->edgedivisions, sqr(TAU) * sqrt((TAU + 2) / 5) / 2, mp->VisibleSpikes);
482 glRotatef(180, 0, 0, 1);
484 glRotatef(-dodecaangle, 1, 0, 0);
485 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[7]);
486 PENTAGON(1, mp->seno, mp->edgedivisions, sqr(TAU) * sqrt((TAU + 2) / 5) / 2, mp->VisibleSpikes);
489 glRotatef(-dodecaangle, cos72, sin72, 0);
490 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[8]);
491 PENTAGON(1, mp->seno, mp->edgedivisions, sqr(TAU) * sqrt((TAU + 2) / 5) / 2, mp->VisibleSpikes);
494 glRotatef(-dodecaangle, cos72, -sin72, 0);
495 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[9]);
496 PENTAGON(1, mp->seno, mp->edgedivisions, sqr(TAU) * sqrt((TAU + 2) / 5) / 2, mp->VisibleSpikes);
499 glRotatef(dodecaangle, cos36, -sin36, 0);
500 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[10]);
501 PENTAGON(1, mp->seno, mp->edgedivisions, sqr(TAU) * sqrt((TAU + 2) / 5) / 2, mp->VisibleSpikes);
503 glRotatef(dodecaangle, cos36, sin36, 0);
504 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[11]);
505 PENTAGON(1, mp->seno, mp->edgedivisions, sqr(TAU) * sqrt((TAU + 2) / 5) / 2, mp->VisibleSpikes);
509 draw_icosa(ModeInfo * mi)
511 morph3dstruct *mp = &morph3d[MI_SCREEN(mi)];
513 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[0]);
515 TRIANGLE(1.5, mp->seno, mp->edgedivisions, (3 * SQRT3 + SQRT15) / 12, mp->VisibleSpikes);
520 glRotatef(180, 0, 0, 1);
521 glRotatef(-icoangle, 1, 0, 0);
522 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[1]);
523 TRIANGLE(1.5, mp->seno, mp->edgedivisions, (3 * SQRT3 + SQRT15) / 12, mp->VisibleSpikes);
525 glRotatef(180, 0, 1, 0);
526 glRotatef(-180 + icoangle, 0.5, SQRT3 / 2, 0);
527 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[2]);
528 TRIANGLE(1.5, mp->seno, mp->edgedivisions, (3 * SQRT3 + SQRT15) / 12, mp->VisibleSpikes);
530 glRotatef(180, 0, 1, 0);
531 glRotatef(-180 + icoangle, 0.5, -SQRT3 / 2, 0);
532 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[3]);
533 TRIANGLE(1.5, mp->seno, mp->edgedivisions, (3 * SQRT3 + SQRT15) / 12, mp->VisibleSpikes);
536 glRotatef(180, 0, 1, 0);
537 glRotatef(-180 + icoangle, 0.5, SQRT3 / 2, 0);
538 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[4]);
539 TRIANGLE(1.5, mp->seno, mp->edgedivisions, (3 * SQRT3 + SQRT15) / 12, mp->VisibleSpikes);
541 glRotatef(180, 0, 1, 0);
542 glRotatef(-180 + icoangle, 0.5, SQRT3 / 2, 0);
543 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[5]);
544 TRIANGLE(1.5, mp->seno, mp->edgedivisions, (3 * SQRT3 + SQRT15) / 12, mp->VisibleSpikes);
546 glRotatef(180, 0, 0, 1);
547 glRotatef(-icoangle, 1, 0, 0);
548 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[6]);
549 TRIANGLE(1.5, mp->seno, mp->edgedivisions, (3 * SQRT3 + SQRT15) / 12, mp->VisibleSpikes);
551 glRotatef(180, 0, 1, 0);
552 glRotatef(-180 + icoangle, 0.5, -SQRT3 / 2, 0);
553 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[7]);
554 TRIANGLE(1.5, mp->seno, mp->edgedivisions, (3 * SQRT3 + SQRT15) / 12, mp->VisibleSpikes);
556 glRotatef(180, 0, 1, 0);
557 glRotatef(-180 + icoangle, 0.5, -SQRT3 / 2, 0);
558 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[8]);
559 TRIANGLE(1.5, mp->seno, mp->edgedivisions, (3 * SQRT3 + SQRT15) / 12, mp->VisibleSpikes);
561 glRotatef(180, 0, 0, 1);
562 glRotatef(-icoangle, 1, 0, 0);
563 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[9]);
564 TRIANGLE(1.5, mp->seno, mp->edgedivisions, (3 * SQRT3 + SQRT15) / 12, mp->VisibleSpikes);
566 glRotatef(180, 1, 0, 0);
567 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[10]);
568 TRIANGLE(1.5, mp->seno, mp->edgedivisions, (3 * SQRT3 + SQRT15) / 12, mp->VisibleSpikes);
570 glRotatef(180, 0, 0, 1);
571 glRotatef(-icoangle, 1, 0, 0);
572 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[11]);
573 TRIANGLE(1.5, mp->seno, mp->edgedivisions, (3 * SQRT3 + SQRT15) / 12, mp->VisibleSpikes);
575 glRotatef(180, 0, 1, 0);
576 glRotatef(-180 + icoangle, 0.5, SQRT3 / 2, 0);
577 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[12]);
578 TRIANGLE(1.5, mp->seno, mp->edgedivisions, (3 * SQRT3 + SQRT15) / 12, mp->VisibleSpikes);
580 glRotatef(180, 0, 1, 0);
581 glRotatef(-180 + icoangle, 0.5, -SQRT3 / 2, 0);
582 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[13]);
583 TRIANGLE(1.5, mp->seno, mp->edgedivisions, (3 * SQRT3 + SQRT15) / 12, mp->VisibleSpikes);
586 glRotatef(180, 0, 1, 0);
587 glRotatef(-180 + icoangle, 0.5, SQRT3 / 2, 0);
588 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[14]);
589 TRIANGLE(1.5, mp->seno, mp->edgedivisions, (3 * SQRT3 + SQRT15) / 12, mp->VisibleSpikes);
591 glRotatef(180, 0, 1, 0);
592 glRotatef(-180 + icoangle, 0.5, SQRT3 / 2, 0);
593 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[15]);
594 TRIANGLE(1.5, mp->seno, mp->edgedivisions, (3 * SQRT3 + SQRT15) / 12, mp->VisibleSpikes);
596 glRotatef(180, 0, 0, 1);
597 glRotatef(-icoangle, 1, 0, 0);
598 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[16]);
599 TRIANGLE(1.5, mp->seno, mp->edgedivisions, (3 * SQRT3 + SQRT15) / 12, mp->VisibleSpikes);
601 glRotatef(180, 0, 1, 0);
602 glRotatef(-180 + icoangle, 0.5, -SQRT3 / 2, 0);
603 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[17]);
604 TRIANGLE(1.5, mp->seno, mp->edgedivisions, (3 * SQRT3 + SQRT15) / 12, mp->VisibleSpikes);
606 glRotatef(180, 0, 1, 0);
607 glRotatef(-180 + icoangle, 0.5, -SQRT3 / 2, 0);
608 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[18]);
609 TRIANGLE(1.5, mp->seno, mp->edgedivisions, (3 * SQRT3 + SQRT15) / 12, mp->VisibleSpikes);
611 glRotatef(180, 0, 0, 1);
612 glRotatef(-icoangle, 1, 0, 0);
613 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[19]);
614 TRIANGLE(1.5, mp->seno, mp->edgedivisions, (3 * SQRT3 + SQRT15) / 12, mp->VisibleSpikes);
618 reshape(ModeInfo * mi, int width, int height)
620 morph3dstruct *mp = &morph3d[MI_SCREEN(mi)];
622 glViewport(0, 0, mp->WindW = (GLint) width, mp->WindH = (GLint) height);
623 glMatrixMode(GL_PROJECTION);
625 glFrustum(-1.0, 1.0, -1.0, 1.0, 5.0, 15.0);
626 glMatrixMode(GL_MODELVIEW);
632 morph3dstruct *mp = &morph3d[MI_SCREEN(mi)];
635 glClearColor(0.0, 0.0, 0.0, 1.0);
636 glColor3f(1.0, 1.0, 1.0);
638 glLightfv(GL_LIGHT0, GL_AMBIENT, ambient);
639 glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse);
640 glLightfv(GL_LIGHT0, GL_POSITION, position0);
641 glLightfv(GL_LIGHT1, GL_AMBIENT, ambient);
642 glLightfv(GL_LIGHT1, GL_DIFFUSE, diffuse);
643 glLightfv(GL_LIGHT1, GL_POSITION, position1);
644 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient);
645 glLightModelfv(GL_LIGHT_MODEL_TWO_SIDE, lmodel_twoside);
646 glEnable(GL_LIGHTING);
649 glEnable(GL_DEPTH_TEST);
650 glEnable(GL_NORMALIZE);
652 glShadeModel(GL_SMOOTH);
653 glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, front_shininess);
654 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, front_specular);
656 switch (mp->object) {
658 mp->draw_object = draw_cube;
659 mp->MaterialColor[0] = MaterialRed;
660 mp->MaterialColor[1] = MaterialGreen;
661 mp->MaterialColor[2] = MaterialCyan;
662 mp->MaterialColor[3] = MaterialMagenta;
663 mp->MaterialColor[4] = MaterialYellow;
664 mp->MaterialColor[5] = MaterialBlue;
665 mp->edgedivisions = cubedivisions;
669 mp->draw_object = draw_octa;
670 mp->MaterialColor[0] = MaterialRed;
671 mp->MaterialColor[1] = MaterialGreen;
672 mp->MaterialColor[2] = MaterialBlue;
673 mp->MaterialColor[3] = MaterialWhite;
674 mp->MaterialColor[4] = MaterialCyan;
675 mp->MaterialColor[5] = MaterialMagenta;
676 mp->MaterialColor[6] = MaterialGray;
677 mp->MaterialColor[7] = MaterialYellow;
678 mp->edgedivisions = octadivisions;
682 mp->draw_object = draw_dodeca;
683 mp->MaterialColor[0] = MaterialRed;
684 mp->MaterialColor[1] = MaterialGreen;
685 mp->MaterialColor[2] = MaterialCyan;
686 mp->MaterialColor[3] = MaterialBlue;
687 mp->MaterialColor[4] = MaterialMagenta;
688 mp->MaterialColor[5] = MaterialYellow;
689 mp->MaterialColor[6] = MaterialGreen;
690 mp->MaterialColor[7] = MaterialCyan;
691 mp->MaterialColor[8] = MaterialRed;
692 mp->MaterialColor[9] = MaterialMagenta;
693 mp->MaterialColor[10] = MaterialBlue;
694 mp->MaterialColor[11] = MaterialYellow;
695 mp->edgedivisions = dodecadivisions;
699 mp->draw_object = draw_icosa;
700 mp->MaterialColor[0] = MaterialRed;
701 mp->MaterialColor[1] = MaterialGreen;
702 mp->MaterialColor[2] = MaterialBlue;
703 mp->MaterialColor[3] = MaterialCyan;
704 mp->MaterialColor[4] = MaterialYellow;
705 mp->MaterialColor[5] = MaterialMagenta;
706 mp->MaterialColor[6] = MaterialRed;
707 mp->MaterialColor[7] = MaterialGreen;
708 mp->MaterialColor[8] = MaterialBlue;
709 mp->MaterialColor[9] = MaterialWhite;
710 mp->MaterialColor[10] = MaterialCyan;
711 mp->MaterialColor[11] = MaterialYellow;
712 mp->MaterialColor[12] = MaterialMagenta;
713 mp->MaterialColor[13] = MaterialRed;
714 mp->MaterialColor[14] = MaterialGreen;
715 mp->MaterialColor[15] = MaterialBlue;
716 mp->MaterialColor[16] = MaterialCyan;
717 mp->MaterialColor[17] = MaterialYellow;
718 mp->MaterialColor[18] = MaterialMagenta;
719 mp->MaterialColor[19] = MaterialGray;
720 mp->edgedivisions = icodivisions;
724 mp->draw_object = draw_tetra;
725 mp->MaterialColor[0] = MaterialRed;
726 mp->MaterialColor[1] = MaterialGreen;
727 mp->MaterialColor[2] = MaterialBlue;
728 mp->MaterialColor[3] = MaterialWhite;
729 mp->edgedivisions = tetradivisions;
733 if (MI_IS_MONO(mi)) {
736 for (loop = 0; loop < 20; loop++)
737 mp->MaterialColor[loop] = MaterialGray;
742 init_morph3d(ModeInfo * mi)
746 if (morph3d == NULL) {
747 if ((morph3d = (morph3dstruct *) calloc(MI_NUM_SCREENS(mi),
748 sizeof (morph3dstruct))) == NULL)
751 mp = &morph3d[MI_SCREEN(mi)];
752 mp->step = NRAND(90);
753 mp->VisibleSpikes = 1;
755 if ((mp->glx_context = init_GL(mi)) != NULL) {
757 reshape(mi, MI_WIDTH(mi), MI_HEIGHT(mi));
758 glDrawBuffer(GL_BACK);
759 mp->object = MI_COUNT(mi);
760 if (mp->object <= 0 || mp->object > 5)
761 mp->object = NRAND(5) + 1;
769 draw_morph3d(ModeInfo * mi)
771 Display *display = MI_DISPLAY(mi);
772 Window window = MI_WINDOW(mi);
777 mp = &morph3d[MI_SCREEN(mi)];
779 MI_IS_DRAWN(mi) = True;
781 if (!mp->glx_context)
784 glXMakeCurrent(display, window, *(mp->glx_context));
786 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
790 glTranslatef(0.0, 0.0, -10.0);
792 if (!MI_IS_ICONIC(mi)) {
793 glScalef(Scale4Window * mp->WindH / mp->WindW, Scale4Window, Scale4Window);
794 glTranslatef(2.5 * mp->WindW / mp->WindH * sin(mp->step * 1.11), 2.5 * cos(mp->step * 1.25 * 1.11), 0);
796 glScalef(Scale4Iconic * mp->WindH / mp->WindW, Scale4Iconic, Scale4Iconic);
799 glRotatef(mp->step * 100, 1, 0, 0);
800 glRotatef(mp->step * 95, 0, 1, 0);
801 glRotatef(mp->step * 90, 0, 0, 1);
803 mp->seno = (sin(mp->step) + 1.0 / 3.0) * (4.0 / 5.0) * mp->Magnitude;
805 if (mp->VisibleSpikes) {
806 #ifdef DEBUG_CULL_FACE
809 for (loop = 0; loop < 20; loop++)
810 mp->MaterialColor[loop] = MaterialGray;
812 glDisable(GL_CULL_FACE);
814 #ifdef DEBUG_CULL_FACE
817 for (loop = 0; loop < 20; loop++)
818 mp->MaterialColor[loop] = MaterialWhite;
820 glEnable(GL_CULL_FACE);
827 if (MI_IS_FPS(mi)) do_fps (mi);
828 glXSwapBuffers(display, window);
834 change_morph3d(ModeInfo * mi)
836 morph3dstruct *mp = &morph3d[MI_SCREEN(mi)];
838 if (!mp->glx_context)
841 mp->object = (mp->object) % 5 + 1;
846 release_morph3d(ModeInfo * mi)
848 if (morph3d != NULL) {
849 (void) free((void *) morph3d);
850 morph3d = (morph3dstruct *) NULL;