1 /* -*- Mode: C; tab-width: 4 -*- */
2 /* morph3d --- Shows 3D morphing objects */
5 static const char sccsid[] = "@(#)morph3d.c 5.01 2001/03/01 xlockmore";
11 * Permission to use, copy, modify, and distribute this software and its
12 * documentation for any purpose and without fee is hereby granted,
13 * provided that the above copyright notice appear in all copies and that
14 * both that copyright notice and this permission notice appear in
15 * supporting documentation.
17 * This file is provided AS IS with no warranties of any kind. The author
18 * shall have no liability with respect to the infringement of copyrights,
19 * trade secrets or any patents by this file or any part thereof. In no
20 * event will the author be liable for any lost revenue or profits or
21 * other special, indirect and consequential damages.
23 * The original code for this mode was written by Marcelo Fernandes Vianna
24 * (me...) and was inspired on a WindowsNT(R)'s screen saver (Flower Box).
25 * It was written from scratch and it was not based on any other source code.
27 * Porting it to xlock (the final objective of this code since the moment I
28 * decided to create it) was possible by comparing the original Mesa's gear
29 * demo with it's ported version to xlock, so thanks for Danny Sung (look at
30 * gear.c) for his indirect help.
32 * Thanks goes also to Brian Paul for making it possible and inexpensive
33 * to use OpenGL at home.
35 * If you are interested in the original version of this program (not a xlock
36 * mode, please refer to the Mesa package (ftp iris.ssec.wisc.edu on /pub/Mesa)
38 * Since I'm not a native English speaker, my apologies for any grammatical
41 * My e-mail address is
42 * mfvianna@centroin.com.br
44 * Marcelo F. Vianna (Feb-13-1997)
47 * 05-Apr-2002: Removed all gllist uses (fix some bug with nvidia driver)
48 * 01-Mar-2001: Added FPS stuff E.Lassauge <lassauge@mail.dotcom.fr>
49 * 27-Jul-1997: Speed ups by Marcelo F. Vianna.
50 * 08-May-1997: Speed ups by Marcelo F. Vianna.
56 * due to a Bug/feature in VMS X11/Intrinsic.h has to be placed before xlock.
57 * otherwise caddr_t is not defined correctly
60 #include <X11/Intrinsic.h>
65 # define PROGCLASS "Morph3d"
66 # define HACK_INIT init_morph3d
67 # define HACK_DRAW draw_morph3d
68 # define HACK_RESHAPE reshape
69 # define morph3d_opts xlockmore_opts
70 # define DEFAULTS "*delay: 40000 \n" \
71 "*showFPS: False \n" \
73 # include "xlockmore.h" /* from the xscreensaver distribution */
74 #else /* !STANDALONE */
75 # include "xlock.h" /* from the xlockmore distribution */
76 #endif /* !STANDALONE */
80 ModeSpecOpt morph3d_opts =
81 {0, (XrmOptionDescRec *) NULL, 0, (argtype *) NULL, (OptionStruct *) NULL};
84 ModStruct morph3d_description =
85 {"morph3d", "init_morph3d", "draw_morph3d", "release_morph3d",
86 "draw_morph3d", "change_morph3d", (char *) NULL, &morph3d_opts,
87 1000, 0, 1, 1, 4, 1.0, "",
88 "Shows GL morphing polyhedra", 0, NULL};
92 #define Scale4Window 0.3
93 #define Scale4Iconic 1.0
95 #define VectMul(X1,Y1,Z1,X2,Y2,Z2) (Y1)*(Z2)-(Z1)*(Y2),(Z1)*(X2)-(X1)*(Z2),(X1)*(Y2)-(Y1)*(X2)
96 #define sqr(A) ((A)*(A))
98 /* Increasing this values produces better image quality, the price is speed. */
99 #define tetradivisions 23
100 #define cubedivisions 20
101 #define octadivisions 21
102 #define dodecadivisions 10
103 #define icodivisions 15
105 #define tetraangle 109.47122063449069174
106 #define cubeangle 90.000000000000000000
107 #define octaangle 109.47122063449069174
108 #define dodecaangle 63.434948822922009981
109 #define icoangle 41.810314895778596167
114 #define SQRT2 1.4142135623730951455
115 #define SQRT3 1.7320508075688771932
116 #define SQRT5 2.2360679774997898051
117 #define SQRT6 2.4494897427831778813
118 #define SQRT15 3.8729833462074170214
119 #define cossec36_2 0.8506508083520399322
120 #define cos72 0.3090169943749474241
121 #define sin72 0.9510565162951535721
122 #define cos36 0.8090169943749474241
123 #define sin36 0.5877852522924731292
125 /*************************************************************************/
134 void (*draw_object) (ModeInfo * mi);
136 float *MaterialColor[20];
137 GLXContext *glx_context;
140 static float front_shininess[] =
142 static float front_specular[] =
143 {0.7, 0.7, 0.7, 1.0};
144 static float ambient[] =
145 {0.0, 0.0, 0.0, 1.0};
146 static float diffuse[] =
147 {1.0, 1.0, 1.0, 1.0};
148 static float position0[] =
149 {1.0, 1.0, 1.0, 0.0};
150 static float position1[] =
151 {-1.0, -1.0, 1.0, 0.0};
152 static float lmodel_ambient[] =
153 {0.5, 0.5, 0.5, 1.0};
154 static float lmodel_twoside[] =
157 static float MaterialRed[] =
158 {0.7, 0.0, 0.0, 1.0};
159 static float MaterialGreen[] =
160 {0.1, 0.5, 0.2, 1.0};
161 static float MaterialBlue[] =
162 {0.0, 0.0, 0.7, 1.0};
163 static float MaterialCyan[] =
164 {0.2, 0.5, 0.7, 1.0};
165 static float MaterialYellow[] =
166 {0.7, 0.7, 0.0, 1.0};
167 static float MaterialMagenta[] =
168 {0.6, 0.2, 0.5, 1.0};
169 static float MaterialWhite[] =
170 {0.7, 0.7, 0.7, 1.0};
171 static float MaterialGray[] =
172 {0.5, 0.5, 0.5, 1.0};
174 static morph3dstruct *morph3d = (morph3dstruct *) NULL;
176 #define TRIANGLE(Edge, Amp, Divisions, Z, VS) \
178 GLfloat Xf,Yf,Xa,Yb=0.0,Xf2=0.0,Yf2=0.0,Yf_2=0.0,Yb2,Yb_2; \
179 GLfloat Factor=0.0,Factor1,Factor2; \
180 GLfloat VertX,VertY,VertZ,NeiAX,NeiAY,NeiAZ,NeiBX,NeiBY,NeiBZ; \
183 GLfloat Vr=(Edge)*SQRT3/3; \
184 GLfloat AmpVr2=(Amp)/sqr(Vr); \
185 GLfloat Zf=(Edge)*(Z); \
187 Ax=(Edge)*(+0.5/(Divisions)), Ay=(Edge)*(-SQRT3/(2*Divisions)); \
189 Yf=Vr+Ay; Yb=Yf+0.001; \
190 for (Ri=1; Ri<=(Divisions); Ri++) { \
191 glBegin(GL_TRIANGLE_STRIP); \
192 Xf=(float)Ri*Ax; Xa=Xf+0.001; \
193 Yf2=sqr(Yf); Yf_2=sqr(Yf-Ay); \
194 Yb2=sqr(Yb); Yb_2=sqr(Yb-Ay); \
195 for (Ti=0; Ti<Ri; Ti++) { \
196 Factor=1-(((Xf2=sqr(Xf))+Yf2)*AmpVr2); \
197 Factor1=1-((sqr(Xa)+Yf2)*AmpVr2); \
198 Factor2=1-((Xf2+Yb2)*AmpVr2); \
199 VertX=Factor*Xf; VertY=Factor*Yf; VertZ=Factor*Zf; \
200 NeiAX=Factor1*Xa-VertX; NeiAY=Factor1*Yf-VertY; NeiAZ=Factor1*Zf-VertZ; \
201 NeiBX=Factor2*Xf-VertX; NeiBY=Factor2*Yb-VertY; NeiBZ=Factor2*Zf-VertZ; \
202 glNormal3f(VectMul(NeiAX, NeiAY, NeiAZ, NeiBX, NeiBY, NeiBZ)); \
203 glVertex3f(VertX, VertY, VertZ); \
205 Xf-=Ax; Yf-=Ay; Xa-=Ax; Yb-=Ay; \
207 Factor=1-(((Xf2=sqr(Xf))+Yf_2)*AmpVr2); \
208 Factor1=1-((sqr(Xa)+Yf_2)*AmpVr2); \
209 Factor2=1-((Xf2+Yb_2)*AmpVr2); \
210 VertX=Factor*Xf; VertY=Factor*Yf; VertZ=Factor*Zf; \
211 NeiAX=Factor1*Xa-VertX; NeiAY=Factor1*Yf-VertY; NeiAZ=Factor1*Zf-VertZ; \
212 NeiBX=Factor2*Xf-VertX; NeiBY=Factor2*Yb-VertY; NeiBZ=Factor2*Zf-VertZ; \
213 glNormal3f(VectMul(NeiAX, NeiAY, NeiAZ, NeiBX, NeiBY, NeiBZ)); \
214 glVertex3f(VertX, VertY, VertZ); \
216 Xf-=Ax; Yf+=Ay; Xa-=Ax; Yb+=Ay; \
218 Factor=1-(((Xf2=sqr(Xf))+(Yf2=sqr(Yf)))*AmpVr2); \
219 Factor1=1-((sqr(Xa)+Yf2)*AmpVr2); \
220 Factor2=1-((Xf2+sqr(Yb))*AmpVr2); \
221 VertX=Factor*Xf; VertY=Factor*Yf; VertZ=Factor*Zf; \
222 NeiAX=Factor1*Xa-VertX; NeiAY=Factor1*Yf-VertY; NeiAZ=Factor1*Zf-VertZ; \
223 NeiBX=Factor2*Xf-VertX; NeiBY=Factor2*Yb-VertY; NeiBZ=Factor2*Zf-VertZ; \
224 glNormal3f(VectMul(NeiAX, NeiAY, NeiAZ, NeiBX, NeiBY, NeiBZ)); \
225 glVertex3f(VertX, VertY, VertZ); \
232 #define SQUARE(Edge, Amp, Divisions, Z, VS) \
235 GLfloat Xf,Yf,Y,Xf2,Yf2,Y2,Xa,Xa2,Yb; \
236 GLfloat Factor=0.0,Factor1,Factor2; \
237 GLfloat VertX,VertY,VertZ,NeiAX,NeiAY,NeiAZ,NeiBX,NeiBY,NeiBZ; \
238 GLfloat Zf=(Edge)*(Z); \
239 GLfloat AmpVr2=(Amp)/sqr((Edge)*SQRT2/2); \
241 for (Yi=0; Yi<(Divisions); Yi++) { \
242 Yf=-((Edge)/2.0) + ((float)Yi)/(Divisions)*(Edge); \
244 Y=Yf+1.0/(Divisions)*(Edge); \
246 glBegin(GL_QUAD_STRIP); \
247 for (Xi=0; Xi<=(Divisions); Xi++) { \
248 Xf=-((Edge)/2.0) + ((float)Xi)/(Divisions)*(Edge); \
251 Xa=Xf+0.001; Yb=Y+0.001; \
252 Factor=1-((Xf2+Y2)*AmpVr2); \
253 Factor1=1-(((Xa2=sqr(Xa))+Y2)*AmpVr2); \
254 Factor2=1-((Xf2+sqr(Yb))*AmpVr2); \
255 VertX=Factor*Xf; VertY=Factor*Y; VertZ=Factor*Zf; \
256 NeiAX=Factor1*Xa-VertX; NeiAY=Factor1*Y-VertY; NeiAZ=Factor1*Zf-VertZ; \
257 NeiBX=Factor2*Xf-VertX; NeiBY=Factor2*Yb-VertY; NeiBZ=Factor2*Zf-VertZ; \
258 glNormal3f(VectMul(NeiAX, NeiAY, NeiAZ, NeiBX, NeiBY, NeiBZ)); \
259 glVertex3f(VertX, VertY, VertZ); \
262 Factor=1-((Xf2+Yf2)*AmpVr2); \
263 Factor1=1-((Xa2+Yf2)*AmpVr2); \
264 Factor2=1-((Xf2+sqr(Yb))*AmpVr2); \
265 VertX=Factor*Xf; VertY=Factor*Yf; VertZ=Factor*Zf; \
266 NeiAX=Factor1*Xa-VertX; NeiAY=Factor1*Yf-VertY; NeiAZ=Factor1*Zf-VertZ; \
267 NeiBX=Factor2*Xf-VertX; NeiBY=Factor2*Yb-VertY; NeiBZ=Factor2*Zf-VertZ; \
268 glNormal3f(VectMul(NeiAX, NeiAY, NeiAZ, NeiBX, NeiBY, NeiBZ)); \
269 glVertex3f(VertX, VertY, VertZ); \
276 #define PENTAGON(Edge, Amp, Divisions, Z, VS) \
279 GLfloat Xf,Yf,Xa,Yb,Xf2,Yf2; \
280 GLfloat Factor=0.0,Factor1,Factor2; \
281 GLfloat VertX,VertY,VertZ,NeiAX,NeiAY,NeiAZ,NeiBX,NeiBY,NeiBZ; \
282 GLfloat Zf=(Edge)*(Z); \
283 GLfloat AmpVr2=(Amp)/sqr((Edge)*cossec36_2); \
285 static GLfloat x[6],y[6]; \
286 static int arrayninit=1; \
289 for(Fi=0;Fi<6;Fi++) { \
290 x[Fi]=-cos( Fi*2*Pi/5 + Pi/10 )/(Divisions)*cossec36_2*(Edge); \
291 y[Fi]=sin( Fi*2*Pi/5 + Pi/10 )/(Divisions)*cossec36_2*(Edge); \
296 for (Ri=1; Ri<=(Divisions); Ri++) { \
297 for (Fi=0; Fi<5; Fi++) { \
298 glBegin(GL_TRIANGLE_STRIP); \
299 for (Ti=0; Ti<Ri; Ti++) { \
300 Xf=(float)(Ri-Ti)*x[Fi] + (float)Ti*x[Fi+1]; \
301 Yf=(float)(Ri-Ti)*y[Fi] + (float)Ti*y[Fi+1]; \
302 Xa=Xf+0.001; Yb=Yf+0.001; \
303 Factor=1-(((Xf2=sqr(Xf))+(Yf2=sqr(Yf)))*AmpVr2); \
304 Factor1=1-((sqr(Xa)+Yf2)*AmpVr2); \
305 Factor2=1-((Xf2+sqr(Yb))*AmpVr2); \
306 VertX=Factor*Xf; VertY=Factor*Yf; VertZ=Factor*Zf; \
307 NeiAX=Factor1*Xa-VertX; NeiAY=Factor1*Yf-VertY; NeiAZ=Factor1*Zf-VertZ; \
308 NeiBX=Factor2*Xf-VertX; NeiBY=Factor2*Yb-VertY; NeiBZ=Factor2*Zf-VertZ; \
309 glNormal3f(VectMul(NeiAX, NeiAY, NeiAZ, NeiBX, NeiBY, NeiBZ)); \
310 glVertex3f(VertX, VertY, VertZ); \
312 Xf-=x[Fi]; Yf-=y[Fi]; Xa-=x[Fi]; Yb-=y[Fi]; \
314 Factor=1-(((Xf2=sqr(Xf))+(Yf2=sqr(Yf)))*AmpVr2); \
315 Factor1=1-((sqr(Xa)+Yf2)*AmpVr2); \
316 Factor2=1-((Xf2+sqr(Yb))*AmpVr2); \
317 VertX=Factor*Xf; VertY=Factor*Yf; VertZ=Factor*Zf; \
318 NeiAX=Factor1*Xa-VertX; NeiAY=Factor1*Yf-VertY; NeiAZ=Factor1*Zf-VertZ; \
319 NeiBX=Factor2*Xf-VertX; NeiBY=Factor2*Yb-VertY; NeiBZ=Factor2*Zf-VertZ; \
320 glNormal3f(VectMul(NeiAX, NeiAY, NeiAZ, NeiBX, NeiBY, NeiBZ)); \
321 glVertex3f(VertX, VertY, VertZ); \
324 Xf=(float)Ri*x[Fi+1]; \
325 Yf=(float)Ri*y[Fi+1]; \
326 Xa=Xf+0.001; Yb=Yf+0.001; \
327 Factor=1-(((Xf2=sqr(Xf))+(Yf2=sqr(Yf)))*AmpVr2); \
328 Factor1=1-((sqr(Xa)+Yf2)*AmpVr2); \
329 Factor2=1-((Xf2+sqr(Yb))*AmpVr2); \
330 VertX=Factor*Xf; VertY=Factor*Yf; VertZ=Factor*Zf; \
331 NeiAX=Factor1*Xa-VertX; NeiAY=Factor1*Yf-VertY; NeiAZ=Factor1*Zf-VertZ; \
332 NeiBX=Factor2*Xf-VertX; NeiBY=Factor2*Yb-VertY; NeiBZ=Factor2*Zf-VertZ; \
333 glNormal3f(VectMul(NeiAX, NeiAY, NeiAZ, NeiBX, NeiBY, NeiBZ)); \
334 glVertex3f(VertX, VertY, VertZ); \
342 draw_tetra(ModeInfo * mi)
344 morph3dstruct *mp = &morph3d[MI_SCREEN(mi)];
346 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[0]);
348 TRIANGLE(2, mp->seno, mp->edgedivisions, 0.5 / SQRT6, mp->VisibleSpikes);
351 glRotatef(180, 0, 0, 1);
352 glRotatef(-tetraangle, 1, 0, 0);
353 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[1]);
354 TRIANGLE(2, mp->seno, mp->edgedivisions, 0.5 / SQRT6, mp->VisibleSpikes);
357 glRotatef(180, 0, 1, 0);
358 glRotatef(-180 + tetraangle, 0.5, SQRT3 / 2, 0);
359 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[2]);
360 TRIANGLE(2, mp->seno, mp->edgedivisions, 0.5 / SQRT6, mp->VisibleSpikes);
362 glRotatef(180, 0, 1, 0);
363 glRotatef(-180 + tetraangle, 0.5, -SQRT3 / 2, 0);
364 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[3]);
365 TRIANGLE(2, mp->seno, mp->edgedivisions, 0.5 / SQRT6, mp->VisibleSpikes);
369 draw_cube(ModeInfo * mi)
371 morph3dstruct *mp = &morph3d[MI_SCREEN(mi)];
373 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[0]);
375 SQUARE(2, mp->seno, mp->edgedivisions, 0.5, mp->VisibleSpikes)
377 glRotatef(cubeangle, 1, 0, 0);
378 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[1]);
379 SQUARE(2, mp->seno, mp->edgedivisions, 0.5, mp->VisibleSpikes)
380 glRotatef(cubeangle, 1, 0, 0);
381 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[2]);
382 SQUARE(2, mp->seno, mp->edgedivisions, 0.5, mp->VisibleSpikes)
383 glRotatef(cubeangle, 1, 0, 0);
384 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[3]);
385 SQUARE(2, mp->seno, mp->edgedivisions, 0.5, mp->VisibleSpikes)
386 glRotatef(cubeangle, 0, 1, 0);
387 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[4]);
388 SQUARE(2, mp->seno, mp->edgedivisions, 0.5, mp->VisibleSpikes)
389 glRotatef(2 * cubeangle, 0, 1, 0);
390 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[5]);
391 SQUARE(2, mp->seno, mp->edgedivisions, 0.5, mp->VisibleSpikes)
395 draw_octa(ModeInfo * mi)
397 morph3dstruct *mp = &morph3d[MI_SCREEN(mi)];
399 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[0]);
400 TRIANGLE(2, mp->seno, mp->edgedivisions, 1 / SQRT6, mp->VisibleSpikes);
403 glRotatef(180, 0, 0, 1);
404 glRotatef(-180 + octaangle, 1, 0, 0);
405 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[1]);
406 TRIANGLE(2, mp->seno, mp->edgedivisions, 1 / SQRT6, mp->VisibleSpikes);
409 glRotatef(180, 0, 1, 0);
410 glRotatef(-octaangle, 0.5, SQRT3 / 2, 0);
411 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[2]);
412 TRIANGLE(2, mp->seno, mp->edgedivisions, 1 / SQRT6, mp->VisibleSpikes);
415 glRotatef(180, 0, 1, 0);
416 glRotatef(-octaangle, 0.5, -SQRT3 / 2, 0);
417 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[3]);
418 TRIANGLE(2, mp->seno, mp->edgedivisions, 1 / SQRT6, mp->VisibleSpikes);
420 glRotatef(180, 1, 0, 0);
421 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[4]);
422 TRIANGLE(2, mp->seno, mp->edgedivisions, 1 / SQRT6, mp->VisibleSpikes);
424 glRotatef(180, 0, 0, 1);
425 glRotatef(-180 + octaangle, 1, 0, 0);
426 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[5]);
427 TRIANGLE(2, mp->seno, mp->edgedivisions, 1 / SQRT6, mp->VisibleSpikes);
430 glRotatef(180, 0, 1, 0);
431 glRotatef(-octaangle, 0.5, SQRT3 / 2, 0);
432 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[6]);
433 TRIANGLE(2, mp->seno, mp->edgedivisions, 1 / SQRT6, mp->VisibleSpikes);
435 glRotatef(180, 0, 1, 0);
436 glRotatef(-octaangle, 0.5, -SQRT3 / 2, 0);
437 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[7]);
438 TRIANGLE(2, mp->seno, mp->edgedivisions, 1 / SQRT6, mp->VisibleSpikes);
442 draw_dodeca(ModeInfo * mi)
444 morph3dstruct *mp = &morph3d[MI_SCREEN(mi)];
446 #define TAU ((SQRT5+1)/2)
448 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[0]);
450 PENTAGON(1, mp->seno, mp->edgedivisions, sqr(TAU) * sqrt((TAU + 2) / 5) / 2, mp->VisibleSpikes);
453 glRotatef(180, 0, 0, 1);
455 glRotatef(-dodecaangle, 1, 0, 0);
456 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[1]);
457 PENTAGON(1, mp->seno, mp->edgedivisions, sqr(TAU) * sqrt((TAU + 2) / 5) / 2, mp->VisibleSpikes);
460 glRotatef(-dodecaangle, cos72, sin72, 0);
461 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[2]);
462 PENTAGON(1, mp->seno, mp->edgedivisions, sqr(TAU) * sqrt((TAU + 2) / 5) / 2, mp->VisibleSpikes);
465 glRotatef(-dodecaangle, cos72, -sin72, 0);
466 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[3]);
467 PENTAGON(1, mp->seno, mp->edgedivisions, sqr(TAU) * sqrt((TAU + 2) / 5) / 2, mp->VisibleSpikes);
470 glRotatef(dodecaangle, cos36, -sin36, 0);
471 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[4]);
472 PENTAGON(1, mp->seno, mp->edgedivisions, sqr(TAU) * sqrt((TAU + 2) / 5) / 2, mp->VisibleSpikes);
474 glRotatef(dodecaangle, cos36, sin36, 0);
475 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[5]);
476 PENTAGON(1, mp->seno, mp->edgedivisions, sqr(TAU) * sqrt((TAU + 2) / 5) / 2, mp->VisibleSpikes);
478 glRotatef(180, 1, 0, 0);
479 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[6]);
480 PENTAGON(1, mp->seno, mp->edgedivisions, sqr(TAU) * sqrt((TAU + 2) / 5) / 2, mp->VisibleSpikes);
481 glRotatef(180, 0, 0, 1);
483 glRotatef(-dodecaangle, 1, 0, 0);
484 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[7]);
485 PENTAGON(1, mp->seno, mp->edgedivisions, sqr(TAU) * sqrt((TAU + 2) / 5) / 2, mp->VisibleSpikes);
488 glRotatef(-dodecaangle, cos72, sin72, 0);
489 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[8]);
490 PENTAGON(1, mp->seno, mp->edgedivisions, sqr(TAU) * sqrt((TAU + 2) / 5) / 2, mp->VisibleSpikes);
493 glRotatef(-dodecaangle, cos72, -sin72, 0);
494 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[9]);
495 PENTAGON(1, mp->seno, mp->edgedivisions, sqr(TAU) * sqrt((TAU + 2) / 5) / 2, mp->VisibleSpikes);
498 glRotatef(dodecaangle, cos36, -sin36, 0);
499 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[10]);
500 PENTAGON(1, mp->seno, mp->edgedivisions, sqr(TAU) * sqrt((TAU + 2) / 5) / 2, mp->VisibleSpikes);
502 glRotatef(dodecaangle, cos36, sin36, 0);
503 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[11]);
504 PENTAGON(1, mp->seno, mp->edgedivisions, sqr(TAU) * sqrt((TAU + 2) / 5) / 2, mp->VisibleSpikes);
508 draw_icosa(ModeInfo * mi)
510 morph3dstruct *mp = &morph3d[MI_SCREEN(mi)];
512 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[0]);
514 TRIANGLE(1.5, mp->seno, mp->edgedivisions, (3 * SQRT3 + SQRT15) / 12, mp->VisibleSpikes);
519 glRotatef(180, 0, 0, 1);
520 glRotatef(-icoangle, 1, 0, 0);
521 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[1]);
522 TRIANGLE(1.5, mp->seno, mp->edgedivisions, (3 * SQRT3 + SQRT15) / 12, mp->VisibleSpikes);
524 glRotatef(180, 0, 1, 0);
525 glRotatef(-180 + icoangle, 0.5, SQRT3 / 2, 0);
526 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[2]);
527 TRIANGLE(1.5, mp->seno, mp->edgedivisions, (3 * SQRT3 + SQRT15) / 12, mp->VisibleSpikes);
529 glRotatef(180, 0, 1, 0);
530 glRotatef(-180 + icoangle, 0.5, -SQRT3 / 2, 0);
531 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[3]);
532 TRIANGLE(1.5, mp->seno, mp->edgedivisions, (3 * SQRT3 + SQRT15) / 12, mp->VisibleSpikes);
535 glRotatef(180, 0, 1, 0);
536 glRotatef(-180 + icoangle, 0.5, SQRT3 / 2, 0);
537 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[4]);
538 TRIANGLE(1.5, mp->seno, mp->edgedivisions, (3 * SQRT3 + SQRT15) / 12, mp->VisibleSpikes);
540 glRotatef(180, 0, 1, 0);
541 glRotatef(-180 + icoangle, 0.5, SQRT3 / 2, 0);
542 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[5]);
543 TRIANGLE(1.5, mp->seno, mp->edgedivisions, (3 * SQRT3 + SQRT15) / 12, mp->VisibleSpikes);
545 glRotatef(180, 0, 0, 1);
546 glRotatef(-icoangle, 1, 0, 0);
547 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[6]);
548 TRIANGLE(1.5, mp->seno, mp->edgedivisions, (3 * SQRT3 + SQRT15) / 12, mp->VisibleSpikes);
550 glRotatef(180, 0, 1, 0);
551 glRotatef(-180 + icoangle, 0.5, -SQRT3 / 2, 0);
552 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[7]);
553 TRIANGLE(1.5, mp->seno, mp->edgedivisions, (3 * SQRT3 + SQRT15) / 12, mp->VisibleSpikes);
555 glRotatef(180, 0, 1, 0);
556 glRotatef(-180 + icoangle, 0.5, -SQRT3 / 2, 0);
557 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[8]);
558 TRIANGLE(1.5, mp->seno, mp->edgedivisions, (3 * SQRT3 + SQRT15) / 12, mp->VisibleSpikes);
560 glRotatef(180, 0, 0, 1);
561 glRotatef(-icoangle, 1, 0, 0);
562 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[9]);
563 TRIANGLE(1.5, mp->seno, mp->edgedivisions, (3 * SQRT3 + SQRT15) / 12, mp->VisibleSpikes);
565 glRotatef(180, 1, 0, 0);
566 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[10]);
567 TRIANGLE(1.5, mp->seno, mp->edgedivisions, (3 * SQRT3 + SQRT15) / 12, mp->VisibleSpikes);
569 glRotatef(180, 0, 0, 1);
570 glRotatef(-icoangle, 1, 0, 0);
571 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[11]);
572 TRIANGLE(1.5, mp->seno, mp->edgedivisions, (3 * SQRT3 + SQRT15) / 12, mp->VisibleSpikes);
574 glRotatef(180, 0, 1, 0);
575 glRotatef(-180 + icoangle, 0.5, SQRT3 / 2, 0);
576 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[12]);
577 TRIANGLE(1.5, mp->seno, mp->edgedivisions, (3 * SQRT3 + SQRT15) / 12, mp->VisibleSpikes);
579 glRotatef(180, 0, 1, 0);
580 glRotatef(-180 + icoangle, 0.5, -SQRT3 / 2, 0);
581 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[13]);
582 TRIANGLE(1.5, mp->seno, mp->edgedivisions, (3 * SQRT3 + SQRT15) / 12, mp->VisibleSpikes);
585 glRotatef(180, 0, 1, 0);
586 glRotatef(-180 + icoangle, 0.5, SQRT3 / 2, 0);
587 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[14]);
588 TRIANGLE(1.5, mp->seno, mp->edgedivisions, (3 * SQRT3 + SQRT15) / 12, mp->VisibleSpikes);
590 glRotatef(180, 0, 1, 0);
591 glRotatef(-180 + icoangle, 0.5, SQRT3 / 2, 0);
592 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[15]);
593 TRIANGLE(1.5, mp->seno, mp->edgedivisions, (3 * SQRT3 + SQRT15) / 12, mp->VisibleSpikes);
595 glRotatef(180, 0, 0, 1);
596 glRotatef(-icoangle, 1, 0, 0);
597 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[16]);
598 TRIANGLE(1.5, mp->seno, mp->edgedivisions, (3 * SQRT3 + SQRT15) / 12, mp->VisibleSpikes);
600 glRotatef(180, 0, 1, 0);
601 glRotatef(-180 + icoangle, 0.5, -SQRT3 / 2, 0);
602 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[17]);
603 TRIANGLE(1.5, mp->seno, mp->edgedivisions, (3 * SQRT3 + SQRT15) / 12, mp->VisibleSpikes);
605 glRotatef(180, 0, 1, 0);
606 glRotatef(-180 + icoangle, 0.5, -SQRT3 / 2, 0);
607 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[18]);
608 TRIANGLE(1.5, mp->seno, mp->edgedivisions, (3 * SQRT3 + SQRT15) / 12, mp->VisibleSpikes);
610 glRotatef(180, 0, 0, 1);
611 glRotatef(-icoangle, 1, 0, 0);
612 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[19]);
613 TRIANGLE(1.5, mp->seno, mp->edgedivisions, (3 * SQRT3 + SQRT15) / 12, mp->VisibleSpikes);
617 reshape(ModeInfo * mi, int width, int height)
619 morph3dstruct *mp = &morph3d[MI_SCREEN(mi)];
621 glViewport(0, 0, mp->WindW = (GLint) width, mp->WindH = (GLint) height);
622 glMatrixMode(GL_PROJECTION);
624 glFrustum(-1.0, 1.0, -1.0, 1.0, 5.0, 15.0);
625 glMatrixMode(GL_MODELVIEW);
631 morph3dstruct *mp = &morph3d[MI_SCREEN(mi)];
634 glClearColor(0.0, 0.0, 0.0, 1.0);
635 glColor3f(1.0, 1.0, 1.0);
637 glLightfv(GL_LIGHT0, GL_AMBIENT, ambient);
638 glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse);
639 glLightfv(GL_LIGHT0, GL_POSITION, position0);
640 glLightfv(GL_LIGHT1, GL_AMBIENT, ambient);
641 glLightfv(GL_LIGHT1, GL_DIFFUSE, diffuse);
642 glLightfv(GL_LIGHT1, GL_POSITION, position1);
643 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient);
644 glLightModelfv(GL_LIGHT_MODEL_TWO_SIDE, lmodel_twoside);
645 glEnable(GL_LIGHTING);
648 glEnable(GL_DEPTH_TEST);
649 glEnable(GL_NORMALIZE);
651 glShadeModel(GL_SMOOTH);
652 glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, front_shininess);
653 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, front_specular);
655 switch (mp->object) {
657 mp->draw_object = draw_cube;
658 mp->MaterialColor[0] = MaterialRed;
659 mp->MaterialColor[1] = MaterialGreen;
660 mp->MaterialColor[2] = MaterialCyan;
661 mp->MaterialColor[3] = MaterialMagenta;
662 mp->MaterialColor[4] = MaterialYellow;
663 mp->MaterialColor[5] = MaterialBlue;
664 mp->edgedivisions = cubedivisions;
668 mp->draw_object = draw_octa;
669 mp->MaterialColor[0] = MaterialRed;
670 mp->MaterialColor[1] = MaterialGreen;
671 mp->MaterialColor[2] = MaterialBlue;
672 mp->MaterialColor[3] = MaterialWhite;
673 mp->MaterialColor[4] = MaterialCyan;
674 mp->MaterialColor[5] = MaterialMagenta;
675 mp->MaterialColor[6] = MaterialGray;
676 mp->MaterialColor[7] = MaterialYellow;
677 mp->edgedivisions = octadivisions;
681 mp->draw_object = draw_dodeca;
682 mp->MaterialColor[0] = MaterialRed;
683 mp->MaterialColor[1] = MaterialGreen;
684 mp->MaterialColor[2] = MaterialCyan;
685 mp->MaterialColor[3] = MaterialBlue;
686 mp->MaterialColor[4] = MaterialMagenta;
687 mp->MaterialColor[5] = MaterialYellow;
688 mp->MaterialColor[6] = MaterialGreen;
689 mp->MaterialColor[7] = MaterialCyan;
690 mp->MaterialColor[8] = MaterialRed;
691 mp->MaterialColor[9] = MaterialMagenta;
692 mp->MaterialColor[10] = MaterialBlue;
693 mp->MaterialColor[11] = MaterialYellow;
694 mp->edgedivisions = dodecadivisions;
698 mp->draw_object = draw_icosa;
699 mp->MaterialColor[0] = MaterialRed;
700 mp->MaterialColor[1] = MaterialGreen;
701 mp->MaterialColor[2] = MaterialBlue;
702 mp->MaterialColor[3] = MaterialCyan;
703 mp->MaterialColor[4] = MaterialYellow;
704 mp->MaterialColor[5] = MaterialMagenta;
705 mp->MaterialColor[6] = MaterialRed;
706 mp->MaterialColor[7] = MaterialGreen;
707 mp->MaterialColor[8] = MaterialBlue;
708 mp->MaterialColor[9] = MaterialWhite;
709 mp->MaterialColor[10] = MaterialCyan;
710 mp->MaterialColor[11] = MaterialYellow;
711 mp->MaterialColor[12] = MaterialMagenta;
712 mp->MaterialColor[13] = MaterialRed;
713 mp->MaterialColor[14] = MaterialGreen;
714 mp->MaterialColor[15] = MaterialBlue;
715 mp->MaterialColor[16] = MaterialCyan;
716 mp->MaterialColor[17] = MaterialYellow;
717 mp->MaterialColor[18] = MaterialMagenta;
718 mp->MaterialColor[19] = MaterialGray;
719 mp->edgedivisions = icodivisions;
723 mp->draw_object = draw_tetra;
724 mp->MaterialColor[0] = MaterialRed;
725 mp->MaterialColor[1] = MaterialGreen;
726 mp->MaterialColor[2] = MaterialBlue;
727 mp->MaterialColor[3] = MaterialWhite;
728 mp->edgedivisions = tetradivisions;
732 if (MI_IS_MONO(mi)) {
735 for (loop = 0; loop < 20; loop++)
736 mp->MaterialColor[loop] = MaterialGray;
741 init_morph3d(ModeInfo * mi)
745 if (morph3d == NULL) {
746 if ((morph3d = (morph3dstruct *) calloc(MI_NUM_SCREENS(mi),
747 sizeof (morph3dstruct))) == NULL)
750 mp = &morph3d[MI_SCREEN(mi)];
751 mp->step = NRAND(90);
752 mp->VisibleSpikes = 1;
754 if ((mp->glx_context = init_GL(mi)) != NULL) {
756 reshape(mi, MI_WIDTH(mi), MI_HEIGHT(mi));
757 glDrawBuffer(GL_BACK);
758 mp->object = MI_COUNT(mi);
759 if (mp->object <= 0 || mp->object > 5)
760 mp->object = NRAND(5) + 1;
768 draw_morph3d(ModeInfo * mi)
770 Display *display = MI_DISPLAY(mi);
771 Window window = MI_WINDOW(mi);
776 mp = &morph3d[MI_SCREEN(mi)];
778 MI_IS_DRAWN(mi) = True;
780 if (!mp->glx_context)
783 glXMakeCurrent(display, window, *(mp->glx_context));
785 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
789 glTranslatef(0.0, 0.0, -10.0);
791 if (!MI_IS_ICONIC(mi)) {
792 glScalef(Scale4Window * mp->WindH / mp->WindW, Scale4Window, Scale4Window);
793 glTranslatef(2.5 * mp->WindW / mp->WindH * sin(mp->step * 1.11), 2.5 * cos(mp->step * 1.25 * 1.11), 0);
795 glScalef(Scale4Iconic * mp->WindH / mp->WindW, Scale4Iconic, Scale4Iconic);
798 glRotatef(mp->step * 100, 1, 0, 0);
799 glRotatef(mp->step * 95, 0, 1, 0);
800 glRotatef(mp->step * 90, 0, 0, 1);
802 mp->seno = (sin(mp->step) + 1.0 / 3.0) * (4.0 / 5.0) * mp->Magnitude;
804 if (mp->VisibleSpikes) {
805 #ifdef DEBUG_CULL_FACE
808 for (loop = 0; loop < 20; loop++)
809 mp->MaterialColor[loop] = MaterialGray;
811 glDisable(GL_CULL_FACE);
813 #ifdef DEBUG_CULL_FACE
816 for (loop = 0; loop < 20; loop++)
817 mp->MaterialColor[loop] = MaterialWhite;
819 glEnable(GL_CULL_FACE);
826 if (MI_IS_FPS(mi)) do_fps (mi);
827 glXSwapBuffers(display, window);
833 change_morph3d(ModeInfo * mi)
835 morph3dstruct *mp = &morph3d[MI_SCREEN(mi)];
837 if (!mp->glx_context)
840 mp->object = (mp->object) % 5 + 1;
845 release_morph3d(ModeInfo * mi)
847 if (morph3d != NULL) {
848 (void) free((void *) morph3d);
849 morph3d = (morph3dstruct *) NULL;