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 # define DEFAULTS "*delay: 40000 \n" \
57 "*showFPS: False \n" \
59 # define refresh_morph3d 0
60 # define morph3d_handle_event 0
61 # include "xlockmore.h" /* from the xscreensaver distribution */
62 #else /* !STANDALONE */
63 # include "xlock.h" /* from the xlockmore distribution */
64 #endif /* !STANDALONE */
68 ENTRYPOINT ModeSpecOpt morph3d_opts =
69 {0, (XrmOptionDescRec *) NULL, 0, (argtype *) NULL, (OptionStruct *) NULL};
72 ModStruct morph3d_description =
73 {"morph3d", "init_morph3d", "draw_morph3d", "release_morph3d",
74 "draw_morph3d", "change_morph3d", (char *) NULL, &morph3d_opts,
75 1000, 0, 1, 1, 4, 1.0, "",
76 "Shows GL morphing polyhedra", 0, NULL};
80 #define Scale4Window 0.3
81 #define Scale4Iconic 1.0
83 #define VectMul(X1,Y1,Z1,X2,Y2,Z2) (Y1)*(Z2)-(Z1)*(Y2),(Z1)*(X2)-(X1)*(Z2),(X1)*(Y2)-(Y1)*(X2)
84 #define sqr(A) ((A)*(A))
86 /* Increasing this values produces better image quality, the price is speed. */
87 #define tetradivisions 23
88 #define cubedivisions 20
89 #define octadivisions 21
90 #define dodecadivisions 10
91 #define icodivisions 15
93 #define tetraangle 109.47122063449069174
94 #define cubeangle 90.000000000000000000
95 #define octaangle 109.47122063449069174
96 #define dodecaangle 63.434948822922009981
97 #define icoangle 41.810314895778596167
102 #define SQRT2 1.4142135623730951455
103 #define SQRT3 1.7320508075688771932
104 #define SQRT5 2.2360679774997898051
105 #define SQRT6 2.4494897427831778813
106 #define SQRT15 3.8729833462074170214
107 #define cossec36_2 0.8506508083520399322
108 #define cos72 0.3090169943749474241
109 #define sin72 0.9510565162951535721
110 #define cos36 0.8090169943749474241
111 #define sin36 0.5877852522924731292
113 /*************************************************************************/
122 void (*draw_object) (ModeInfo * mi);
124 const float *MaterialColor[20];
125 GLXContext *glx_context;
130 static const GLfloat front_shininess[] = {60.0};
131 static const GLfloat front_specular[] = {0.7, 0.7, 0.7, 1.0};
132 static const GLfloat ambient[] = {0.0, 0.0, 0.0, 1.0};
133 static const GLfloat diffuse[] = {1.0, 1.0, 1.0, 1.0};
134 static const GLfloat position0[] = {1.0, 1.0, 1.0, 0.0};
135 static const GLfloat position1[] = {-1.0, -1.0, 1.0, 0.0};
136 static const GLfloat lmodel_ambient[] = {0.5, 0.5, 0.5, 1.0};
137 static const GLfloat lmodel_twoside[] = {GL_TRUE};
139 static const GLfloat MaterialRed[] = {0.7, 0.0, 0.0, 1.0};
140 static const GLfloat MaterialGreen[] = {0.1, 0.5, 0.2, 1.0};
141 static const GLfloat MaterialBlue[] = {0.0, 0.0, 0.7, 1.0};
142 static const GLfloat MaterialCyan[] = {0.2, 0.5, 0.7, 1.0};
143 static const GLfloat MaterialYellow[] = {0.7, 0.7, 0.0, 1.0};
144 static const GLfloat MaterialMagenta[] = {0.6, 0.2, 0.5, 1.0};
145 static const GLfloat MaterialWhite[] = {0.7, 0.7, 0.7, 1.0};
146 static const GLfloat MaterialGray[] = {0.5, 0.5, 0.5, 1.0};
148 static morph3dstruct *morph3d = (morph3dstruct *) NULL;
150 #define TRIANGLE(Edge, Amp, Divisions, Z, VS) \
152 GLfloat Xf,Yf,Xa,Yb=0.0,Xf2=0.0,Yf2=0.0,Yf_2=0.0,Yb2,Yb_2; \
153 GLfloat Factor=0.0,Factor1,Factor2; \
154 GLfloat VertX,VertY,VertZ,NeiAX,NeiAY,NeiAZ,NeiBX,NeiBY,NeiBZ; \
157 GLfloat Vr=(Edge)*SQRT3/3; \
158 GLfloat AmpVr2=(Amp)/sqr(Vr); \
159 GLfloat Zf=(Edge)*(Z); \
161 Ax=(Edge)*(+0.5/(Divisions)), Ay=(Edge)*(-SQRT3/(2*Divisions)); \
163 Yf=Vr+Ay; Yb=Yf+0.001; \
164 for (Ri=1; Ri<=(Divisions); Ri++) { \
165 glBegin(GL_TRIANGLE_STRIP); \
166 Xf=(float)Ri*Ax; Xa=Xf+0.001; \
167 Yf2=sqr(Yf); Yf_2=sqr(Yf-Ay); \
168 Yb2=sqr(Yb); Yb_2=sqr(Yb-Ay); \
169 for (Ti=0; Ti<Ri; Ti++) { \
170 Factor=1-(((Xf2=sqr(Xf))+Yf2)*AmpVr2); \
171 Factor1=1-((sqr(Xa)+Yf2)*AmpVr2); \
172 Factor2=1-((Xf2+Yb2)*AmpVr2); \
173 VertX=Factor*Xf; VertY=Factor*Yf; VertZ=Factor*Zf; \
174 NeiAX=Factor1*Xa-VertX; NeiAY=Factor1*Yf-VertY; NeiAZ=Factor1*Zf-VertZ; \
175 NeiBX=Factor2*Xf-VertX; NeiBY=Factor2*Yb-VertY; NeiBZ=Factor2*Zf-VertZ; \
176 glNormal3f(VectMul(NeiAX, NeiAY, NeiAZ, NeiBX, NeiBY, NeiBZ)); \
177 glVertex3f(VertX, VertY, VertZ); \
178 mi->polygon_count++; \
180 Xf-=Ax; Yf-=Ay; Xa-=Ax; Yb-=Ay; \
182 Factor=1-(((Xf2=sqr(Xf))+Yf_2)*AmpVr2); \
183 Factor1=1-((sqr(Xa)+Yf_2)*AmpVr2); \
184 Factor2=1-((Xf2+Yb_2)*AmpVr2); \
185 VertX=Factor*Xf; VertY=Factor*Yf; VertZ=Factor*Zf; \
186 NeiAX=Factor1*Xa-VertX; NeiAY=Factor1*Yf-VertY; NeiAZ=Factor1*Zf-VertZ; \
187 NeiBX=Factor2*Xf-VertX; NeiBY=Factor2*Yb-VertY; NeiBZ=Factor2*Zf-VertZ; \
188 glNormal3f(VectMul(NeiAX, NeiAY, NeiAZ, NeiBX, NeiBY, NeiBZ)); \
189 glVertex3f(VertX, VertY, VertZ); \
190 mi->polygon_count++; \
192 Xf-=Ax; Yf+=Ay; Xa-=Ax; Yb+=Ay; \
194 Factor=1-(((Xf2=sqr(Xf))+(Yf2=sqr(Yf)))*AmpVr2); \
195 Factor1=1-((sqr(Xa)+Yf2)*AmpVr2); \
196 Factor2=1-((Xf2+sqr(Yb))*AmpVr2); \
197 VertX=Factor*Xf; VertY=Factor*Yf; VertZ=Factor*Zf; \
198 NeiAX=Factor1*Xa-VertX; NeiAY=Factor1*Yf-VertY; NeiAZ=Factor1*Zf-VertZ; \
199 NeiBX=Factor2*Xf-VertX; NeiBY=Factor2*Yb-VertY; NeiBZ=Factor2*Zf-VertZ; \
200 glNormal3f(VectMul(NeiAX, NeiAY, NeiAZ, NeiBX, NeiBY, NeiBZ)); \
201 glVertex3f(VertX, VertY, VertZ); \
208 #define SQUARE(Edge, Amp, Divisions, Z, VS) \
211 GLfloat Xf,Yf,Y,Xf2,Yf2,Y2,Xa,Xa2,Yb; \
212 GLfloat Factor=0.0,Factor1,Factor2; \
213 GLfloat VertX,VertY,VertZ,NeiAX,NeiAY,NeiAZ,NeiBX,NeiBY,NeiBZ; \
214 GLfloat Zf=(Edge)*(Z); \
215 GLfloat AmpVr2=(Amp)/sqr((Edge)*SQRT2/2); \
217 for (Yi=0; Yi<(Divisions); Yi++) { \
218 Yf=-((Edge)/2.0) + ((float)Yi)/(Divisions)*(Edge); \
220 Y=Yf+1.0/(Divisions)*(Edge); \
222 glBegin(GL_QUAD_STRIP); \
223 for (Xi=0; Xi<=(Divisions); Xi++) { \
224 Xf=-((Edge)/2.0) + ((float)Xi)/(Divisions)*(Edge); \
227 Xa=Xf+0.001; Yb=Y+0.001; \
228 Factor=1-((Xf2+Y2)*AmpVr2); \
229 Factor1=1-(((Xa2=sqr(Xa))+Y2)*AmpVr2); \
230 Factor2=1-((Xf2+sqr(Yb))*AmpVr2); \
231 VertX=Factor*Xf; VertY=Factor*Y; VertZ=Factor*Zf; \
232 NeiAX=Factor1*Xa-VertX; NeiAY=Factor1*Y-VertY; NeiAZ=Factor1*Zf-VertZ; \
233 NeiBX=Factor2*Xf-VertX; NeiBY=Factor2*Yb-VertY; NeiBZ=Factor2*Zf-VertZ; \
234 glNormal3f(VectMul(NeiAX, NeiAY, NeiAZ, NeiBX, NeiBY, NeiBZ)); \
235 glVertex3f(VertX, VertY, VertZ); \
238 Factor=1-((Xf2+Yf2)*AmpVr2); \
239 Factor1=1-((Xa2+Yf2)*AmpVr2); \
240 Factor2=1-((Xf2+sqr(Yb))*AmpVr2); \
241 VertX=Factor*Xf; VertY=Factor*Yf; VertZ=Factor*Zf; \
242 NeiAX=Factor1*Xa-VertX; NeiAY=Factor1*Yf-VertY; NeiAZ=Factor1*Zf-VertZ; \
243 NeiBX=Factor2*Xf-VertX; NeiBY=Factor2*Yb-VertY; NeiBZ=Factor2*Zf-VertZ; \
244 glNormal3f(VectMul(NeiAX, NeiAY, NeiAZ, NeiBX, NeiBY, NeiBZ)); \
245 glVertex3f(VertX, VertY, VertZ); \
246 mi->polygon_count++; \
253 #define PENTAGON(Edge, Amp, Divisions, Z, VS) \
256 GLfloat Xf,Yf,Xa,Yb,Xf2,Yf2; \
257 GLfloat Factor=0.0,Factor1,Factor2; \
258 GLfloat VertX,VertY,VertZ,NeiAX,NeiAY,NeiAZ,NeiBX,NeiBY,NeiBZ; \
259 GLfloat Zf=(Edge)*(Z); \
260 GLfloat AmpVr2=(Amp)/sqr((Edge)*cossec36_2); \
264 for(Fi=0;Fi<6;Fi++) { \
265 x[Fi]=-cos( Fi*2*Pi/5 + Pi/10 )/(Divisions)*cossec36_2*(Edge); \
266 y[Fi]=sin( Fi*2*Pi/5 + Pi/10 )/(Divisions)*cossec36_2*(Edge); \
269 for (Ri=1; Ri<=(Divisions); Ri++) { \
270 for (Fi=0; Fi<5; Fi++) { \
271 glBegin(GL_TRIANGLE_STRIP); \
272 for (Ti=0; Ti<Ri; Ti++) { \
273 Xf=(float)(Ri-Ti)*x[Fi] + (float)Ti*x[Fi+1]; \
274 Yf=(float)(Ri-Ti)*y[Fi] + (float)Ti*y[Fi+1]; \
275 Xa=Xf+0.001; Yb=Yf+0.001; \
276 Factor=1-(((Xf2=sqr(Xf))+(Yf2=sqr(Yf)))*AmpVr2); \
277 Factor1=1-((sqr(Xa)+Yf2)*AmpVr2); \
278 Factor2=1-((Xf2+sqr(Yb))*AmpVr2); \
279 VertX=Factor*Xf; VertY=Factor*Yf; VertZ=Factor*Zf; \
280 NeiAX=Factor1*Xa-VertX; NeiAY=Factor1*Yf-VertY; NeiAZ=Factor1*Zf-VertZ; \
281 NeiBX=Factor2*Xf-VertX; NeiBY=Factor2*Yb-VertY; NeiBZ=Factor2*Zf-VertZ; \
282 glNormal3f(VectMul(NeiAX, NeiAY, NeiAZ, NeiBX, NeiBY, NeiBZ)); \
283 glVertex3f(VertX, VertY, VertZ); \
284 mi->polygon_count++; \
286 Xf-=x[Fi]; Yf-=y[Fi]; Xa-=x[Fi]; Yb-=y[Fi]; \
288 Factor=1-(((Xf2=sqr(Xf))+(Yf2=sqr(Yf)))*AmpVr2); \
289 Factor1=1-((sqr(Xa)+Yf2)*AmpVr2); \
290 Factor2=1-((Xf2+sqr(Yb))*AmpVr2); \
291 VertX=Factor*Xf; VertY=Factor*Yf; VertZ=Factor*Zf; \
292 NeiAX=Factor1*Xa-VertX; NeiAY=Factor1*Yf-VertY; NeiAZ=Factor1*Zf-VertZ; \
293 NeiBX=Factor2*Xf-VertX; NeiBY=Factor2*Yb-VertY; NeiBZ=Factor2*Zf-VertZ; \
294 glNormal3f(VectMul(NeiAX, NeiAY, NeiAZ, NeiBX, NeiBY, NeiBZ)); \
295 glVertex3f(VertX, VertY, VertZ); \
296 mi->polygon_count++; \
299 Xf=(float)Ri*x[Fi+1]; \
300 Yf=(float)Ri*y[Fi+1]; \
301 Xa=Xf+0.001; Yb=Yf+0.001; \
302 Factor=1-(((Xf2=sqr(Xf))+(Yf2=sqr(Yf)))*AmpVr2); \
303 Factor1=1-((sqr(Xa)+Yf2)*AmpVr2); \
304 Factor2=1-((Xf2+sqr(Yb))*AmpVr2); \
305 VertX=Factor*Xf; VertY=Factor*Yf; VertZ=Factor*Zf; \
306 NeiAX=Factor1*Xa-VertX; NeiAY=Factor1*Yf-VertY; NeiAZ=Factor1*Zf-VertZ; \
307 NeiBX=Factor2*Xf-VertX; NeiBY=Factor2*Yb-VertY; NeiBZ=Factor2*Zf-VertZ; \
308 glNormal3f(VectMul(NeiAX, NeiAY, NeiAZ, NeiBX, NeiBY, NeiBZ)); \
309 glVertex3f(VertX, VertY, VertZ); \
317 draw_tetra(ModeInfo * mi)
319 morph3dstruct *mp = &morph3d[MI_SCREEN(mi)];
321 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[0]);
323 TRIANGLE(2, mp->seno, mp->edgedivisions, 0.5 / SQRT6, mp->VisibleSpikes);
326 glRotatef(180, 0, 0, 1);
327 glRotatef(-tetraangle, 1, 0, 0);
328 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[1]);
329 TRIANGLE(2, mp->seno, mp->edgedivisions, 0.5 / SQRT6, mp->VisibleSpikes);
332 glRotatef(180, 0, 1, 0);
333 glRotatef(-180 + tetraangle, 0.5, SQRT3 / 2, 0);
334 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[2]);
335 TRIANGLE(2, mp->seno, mp->edgedivisions, 0.5 / SQRT6, mp->VisibleSpikes);
337 glRotatef(180, 0, 1, 0);
338 glRotatef(-180 + tetraangle, 0.5, -SQRT3 / 2, 0);
339 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[3]);
340 TRIANGLE(2, mp->seno, mp->edgedivisions, 0.5 / SQRT6, mp->VisibleSpikes);
344 draw_cube(ModeInfo * mi)
346 morph3dstruct *mp = &morph3d[MI_SCREEN(mi)];
348 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[0]);
350 SQUARE(2, mp->seno, mp->edgedivisions, 0.5, mp->VisibleSpikes)
352 glRotatef(cubeangle, 1, 0, 0);
353 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[1]);
354 SQUARE(2, mp->seno, mp->edgedivisions, 0.5, mp->VisibleSpikes)
355 glRotatef(cubeangle, 1, 0, 0);
356 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[2]);
357 SQUARE(2, mp->seno, mp->edgedivisions, 0.5, mp->VisibleSpikes)
358 glRotatef(cubeangle, 1, 0, 0);
359 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[3]);
360 SQUARE(2, mp->seno, mp->edgedivisions, 0.5, mp->VisibleSpikes)
361 glRotatef(cubeangle, 0, 1, 0);
362 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[4]);
363 SQUARE(2, mp->seno, mp->edgedivisions, 0.5, mp->VisibleSpikes)
364 glRotatef(2 * cubeangle, 0, 1, 0);
365 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[5]);
366 SQUARE(2, mp->seno, mp->edgedivisions, 0.5, mp->VisibleSpikes)
370 draw_octa(ModeInfo * mi)
372 morph3dstruct *mp = &morph3d[MI_SCREEN(mi)];
374 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[0]);
375 TRIANGLE(2, mp->seno, mp->edgedivisions, 1 / SQRT6, mp->VisibleSpikes);
378 glRotatef(180, 0, 0, 1);
379 glRotatef(-180 + octaangle, 1, 0, 0);
380 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[1]);
381 TRIANGLE(2, mp->seno, mp->edgedivisions, 1 / SQRT6, mp->VisibleSpikes);
384 glRotatef(180, 0, 1, 0);
385 glRotatef(-octaangle, 0.5, SQRT3 / 2, 0);
386 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[2]);
387 TRIANGLE(2, mp->seno, mp->edgedivisions, 1 / SQRT6, mp->VisibleSpikes);
390 glRotatef(180, 0, 1, 0);
391 glRotatef(-octaangle, 0.5, -SQRT3 / 2, 0);
392 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[3]);
393 TRIANGLE(2, mp->seno, mp->edgedivisions, 1 / SQRT6, mp->VisibleSpikes);
395 glRotatef(180, 1, 0, 0);
396 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[4]);
397 TRIANGLE(2, mp->seno, mp->edgedivisions, 1 / SQRT6, mp->VisibleSpikes);
399 glRotatef(180, 0, 0, 1);
400 glRotatef(-180 + octaangle, 1, 0, 0);
401 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[5]);
402 TRIANGLE(2, mp->seno, mp->edgedivisions, 1 / SQRT6, mp->VisibleSpikes);
405 glRotatef(180, 0, 1, 0);
406 glRotatef(-octaangle, 0.5, SQRT3 / 2, 0);
407 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[6]);
408 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[7]);
413 TRIANGLE(2, mp->seno, mp->edgedivisions, 1 / SQRT6, mp->VisibleSpikes);
417 draw_dodeca(ModeInfo * mi)
419 morph3dstruct *mp = &morph3d[MI_SCREEN(mi)];
421 #define TAU ((SQRT5+1)/2)
423 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[0]);
425 PENTAGON(1, mp->seno, mp->edgedivisions, sqr(TAU) * sqrt((TAU + 2) / 5) / 2, mp->VisibleSpikes);
428 glRotatef(180, 0, 0, 1);
430 glRotatef(-dodecaangle, 1, 0, 0);
431 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[1]);
432 PENTAGON(1, mp->seno, mp->edgedivisions, sqr(TAU) * sqrt((TAU + 2) / 5) / 2, mp->VisibleSpikes);
435 glRotatef(-dodecaangle, cos72, sin72, 0);
436 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[2]);
437 PENTAGON(1, mp->seno, mp->edgedivisions, sqr(TAU) * sqrt((TAU + 2) / 5) / 2, mp->VisibleSpikes);
440 glRotatef(-dodecaangle, cos72, -sin72, 0);
441 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[3]);
442 PENTAGON(1, mp->seno, mp->edgedivisions, sqr(TAU) * sqrt((TAU + 2) / 5) / 2, mp->VisibleSpikes);
445 glRotatef(dodecaangle, cos36, -sin36, 0);
446 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[4]);
447 PENTAGON(1, mp->seno, mp->edgedivisions, sqr(TAU) * sqrt((TAU + 2) / 5) / 2, mp->VisibleSpikes);
449 glRotatef(dodecaangle, cos36, sin36, 0);
450 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[5]);
451 PENTAGON(1, mp->seno, mp->edgedivisions, sqr(TAU) * sqrt((TAU + 2) / 5) / 2, mp->VisibleSpikes);
453 glRotatef(180, 1, 0, 0);
454 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[6]);
455 PENTAGON(1, mp->seno, mp->edgedivisions, sqr(TAU) * sqrt((TAU + 2) / 5) / 2, mp->VisibleSpikes);
456 glRotatef(180, 0, 0, 1);
458 glRotatef(-dodecaangle, 1, 0, 0);
459 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[7]);
460 PENTAGON(1, mp->seno, mp->edgedivisions, sqr(TAU) * sqrt((TAU + 2) / 5) / 2, mp->VisibleSpikes);
463 glRotatef(-dodecaangle, cos72, sin72, 0);
464 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[8]);
465 PENTAGON(1, mp->seno, mp->edgedivisions, sqr(TAU) * sqrt((TAU + 2) / 5) / 2, mp->VisibleSpikes);
468 glRotatef(-dodecaangle, cos72, -sin72, 0);
469 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[9]);
470 PENTAGON(1, mp->seno, mp->edgedivisions, sqr(TAU) * sqrt((TAU + 2) / 5) / 2, mp->VisibleSpikes);
473 glRotatef(dodecaangle, cos36, -sin36, 0);
474 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[10]);
475 PENTAGON(1, mp->seno, mp->edgedivisions, sqr(TAU) * sqrt((TAU + 2) / 5) / 2, mp->VisibleSpikes);
477 glRotatef(dodecaangle, cos36, sin36, 0);
478 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[11]);
479 PENTAGON(1, mp->seno, mp->edgedivisions, sqr(TAU) * sqrt((TAU + 2) / 5) / 2, mp->VisibleSpikes);
483 draw_icosa(ModeInfo * mi)
485 morph3dstruct *mp = &morph3d[MI_SCREEN(mi)];
487 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[0]);
489 TRIANGLE(1.5, mp->seno, mp->edgedivisions, (3 * SQRT3 + SQRT15) / 12, mp->VisibleSpikes);
494 glRotatef(180, 0, 0, 1);
495 glRotatef(-icoangle, 1, 0, 0);
496 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[1]);
497 TRIANGLE(1.5, mp->seno, mp->edgedivisions, (3 * SQRT3 + SQRT15) / 12, mp->VisibleSpikes);
499 glRotatef(180, 0, 1, 0);
500 glRotatef(-180 + icoangle, 0.5, SQRT3 / 2, 0);
501 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[2]);
502 TRIANGLE(1.5, mp->seno, mp->edgedivisions, (3 * SQRT3 + SQRT15) / 12, mp->VisibleSpikes);
504 glRotatef(180, 0, 1, 0);
505 glRotatef(-180 + icoangle, 0.5, -SQRT3 / 2, 0);
506 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[3]);
507 TRIANGLE(1.5, mp->seno, mp->edgedivisions, (3 * SQRT3 + SQRT15) / 12, mp->VisibleSpikes);
510 glRotatef(180, 0, 1, 0);
511 glRotatef(-180 + icoangle, 0.5, SQRT3 / 2, 0);
512 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[4]);
513 TRIANGLE(1.5, mp->seno, mp->edgedivisions, (3 * SQRT3 + SQRT15) / 12, mp->VisibleSpikes);
515 glRotatef(180, 0, 1, 0);
516 glRotatef(-180 + icoangle, 0.5, SQRT3 / 2, 0);
517 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[5]);
518 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[6]);
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[7]);
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[8]);
533 TRIANGLE(1.5, mp->seno, mp->edgedivisions, (3 * SQRT3 + SQRT15) / 12, mp->VisibleSpikes);
535 glRotatef(180, 0, 0, 1);
536 glRotatef(-icoangle, 1, 0, 0);
537 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[9]);
538 TRIANGLE(1.5, mp->seno, mp->edgedivisions, (3 * SQRT3 + SQRT15) / 12, mp->VisibleSpikes);
540 glRotatef(180, 1, 0, 0);
541 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[10]);
542 TRIANGLE(1.5, mp->seno, mp->edgedivisions, (3 * SQRT3 + SQRT15) / 12, mp->VisibleSpikes);
544 glRotatef(180, 0, 0, 1);
545 glRotatef(-icoangle, 1, 0, 0);
546 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[11]);
547 TRIANGLE(1.5, mp->seno, mp->edgedivisions, (3 * SQRT3 + SQRT15) / 12, mp->VisibleSpikes);
549 glRotatef(180, 0, 1, 0);
550 glRotatef(-180 + icoangle, 0.5, SQRT3 / 2, 0);
551 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[12]);
552 TRIANGLE(1.5, mp->seno, mp->edgedivisions, (3 * SQRT3 + SQRT15) / 12, mp->VisibleSpikes);
554 glRotatef(180, 0, 1, 0);
555 glRotatef(-180 + icoangle, 0.5, -SQRT3 / 2, 0);
556 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[13]);
557 TRIANGLE(1.5, mp->seno, mp->edgedivisions, (3 * SQRT3 + SQRT15) / 12, mp->VisibleSpikes);
560 glRotatef(180, 0, 1, 0);
561 glRotatef(-180 + icoangle, 0.5, SQRT3 / 2, 0);
562 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[14]);
563 TRIANGLE(1.5, mp->seno, mp->edgedivisions, (3 * SQRT3 + SQRT15) / 12, mp->VisibleSpikes);
565 glRotatef(180, 0, 1, 0);
566 glRotatef(-180 + icoangle, 0.5, SQRT3 / 2, 0);
567 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[15]);
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[16]);
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[17]);
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[18]);
583 TRIANGLE(1.5, mp->seno, mp->edgedivisions, (3 * SQRT3 + SQRT15) / 12, mp->VisibleSpikes);
585 glRotatef(180, 0, 0, 1);
586 glRotatef(-icoangle, 1, 0, 0);
587 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[19]);
588 TRIANGLE(1.5, mp->seno, mp->edgedivisions, (3 * SQRT3 + SQRT15) / 12, mp->VisibleSpikes);
592 reshape_morph3d(ModeInfo * mi, int width, int height)
594 morph3dstruct *mp = &morph3d[MI_SCREEN(mi)];
596 glViewport(0, 0, mp->WindW = (GLint) width, mp->WindH = (GLint) height);
597 glMatrixMode(GL_PROJECTION);
599 glFrustum(-1.0, 1.0, -1.0, 1.0, 5.0, 15.0);
600 glMatrixMode(GL_MODELVIEW);
606 morph3dstruct *mp = &morph3d[MI_SCREEN(mi)];
609 glClearColor(0.0, 0.0, 0.0, 1.0);
610 glColor3f(1.0, 1.0, 1.0);
612 glLightfv(GL_LIGHT0, GL_AMBIENT, ambient);
613 glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse);
614 glLightfv(GL_LIGHT0, GL_POSITION, position0);
615 glLightfv(GL_LIGHT1, GL_AMBIENT, ambient);
616 glLightfv(GL_LIGHT1, GL_DIFFUSE, diffuse);
617 glLightfv(GL_LIGHT1, GL_POSITION, position1);
618 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient);
619 glLightModelfv(GL_LIGHT_MODEL_TWO_SIDE, lmodel_twoside);
620 glEnable(GL_LIGHTING);
623 glEnable(GL_DEPTH_TEST);
624 glEnable(GL_NORMALIZE);
626 glShadeModel(GL_SMOOTH);
627 glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, front_shininess);
628 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, front_specular);
630 switch (mp->object) {
632 mp->draw_object = draw_cube;
633 mp->MaterialColor[0] = MaterialRed;
634 mp->MaterialColor[1] = MaterialGreen;
635 mp->MaterialColor[2] = MaterialCyan;
636 mp->MaterialColor[3] = MaterialMagenta;
637 mp->MaterialColor[4] = MaterialYellow;
638 mp->MaterialColor[5] = MaterialBlue;
639 mp->edgedivisions = cubedivisions;
643 mp->draw_object = draw_octa;
644 mp->MaterialColor[0] = MaterialRed;
645 mp->MaterialColor[1] = MaterialGreen;
646 mp->MaterialColor[2] = MaterialBlue;
647 mp->MaterialColor[3] = MaterialWhite;
648 mp->MaterialColor[4] = MaterialCyan;
649 mp->MaterialColor[5] = MaterialMagenta;
650 mp->MaterialColor[6] = MaterialGray;
651 mp->MaterialColor[7] = MaterialYellow;
652 mp->edgedivisions = octadivisions;
656 mp->draw_object = draw_dodeca;
657 mp->MaterialColor[0] = MaterialRed;
658 mp->MaterialColor[1] = MaterialGreen;
659 mp->MaterialColor[2] = MaterialCyan;
660 mp->MaterialColor[3] = MaterialBlue;
661 mp->MaterialColor[4] = MaterialMagenta;
662 mp->MaterialColor[5] = MaterialYellow;
663 mp->MaterialColor[6] = MaterialGreen;
664 mp->MaterialColor[7] = MaterialCyan;
665 mp->MaterialColor[8] = MaterialRed;
666 mp->MaterialColor[9] = MaterialMagenta;
667 mp->MaterialColor[10] = MaterialBlue;
668 mp->MaterialColor[11] = MaterialYellow;
669 mp->edgedivisions = dodecadivisions;
673 mp->draw_object = draw_icosa;
674 mp->MaterialColor[0] = MaterialRed;
675 mp->MaterialColor[1] = MaterialGreen;
676 mp->MaterialColor[2] = MaterialBlue;
677 mp->MaterialColor[3] = MaterialCyan;
678 mp->MaterialColor[4] = MaterialYellow;
679 mp->MaterialColor[5] = MaterialMagenta;
680 mp->MaterialColor[6] = MaterialRed;
681 mp->MaterialColor[7] = MaterialGreen;
682 mp->MaterialColor[8] = MaterialBlue;
683 mp->MaterialColor[9] = MaterialWhite;
684 mp->MaterialColor[10] = MaterialCyan;
685 mp->MaterialColor[11] = MaterialYellow;
686 mp->MaterialColor[12] = MaterialMagenta;
687 mp->MaterialColor[13] = MaterialRed;
688 mp->MaterialColor[14] = MaterialGreen;
689 mp->MaterialColor[15] = MaterialBlue;
690 mp->MaterialColor[16] = MaterialCyan;
691 mp->MaterialColor[17] = MaterialYellow;
692 mp->MaterialColor[18] = MaterialMagenta;
693 mp->MaterialColor[19] = MaterialGray;
694 mp->edgedivisions = icodivisions;
698 mp->draw_object = draw_tetra;
699 mp->MaterialColor[0] = MaterialRed;
700 mp->MaterialColor[1] = MaterialGreen;
701 mp->MaterialColor[2] = MaterialBlue;
702 mp->MaterialColor[3] = MaterialWhite;
703 mp->edgedivisions = tetradivisions;
707 if (MI_IS_MONO(mi)) {
710 for (loop = 0; loop < 20; loop++)
711 mp->MaterialColor[loop] = MaterialGray;
716 init_morph3d(ModeInfo * mi)
720 if (morph3d == NULL) {
721 if ((morph3d = (morph3dstruct *) calloc(MI_NUM_SCREENS(mi),
722 sizeof (morph3dstruct))) == NULL)
725 mp = &morph3d[MI_SCREEN(mi)];
726 mp->step = NRAND(90);
727 mp->VisibleSpikes = 1;
729 if ((mp->glx_context = init_GL(mi)) != NULL) {
731 reshape_morph3d(mi, MI_WIDTH(mi), MI_HEIGHT(mi));
732 glDrawBuffer(GL_BACK);
733 mp->object = MI_COUNT(mi);
734 if (mp->object <= 0 || mp->object > 5)
735 mp->object = NRAND(5) + 1;
743 draw_morph3d(ModeInfo * mi)
745 Display *display = MI_DISPLAY(mi);
746 Window window = MI_WINDOW(mi);
751 mp = &morph3d[MI_SCREEN(mi)];
753 MI_IS_DRAWN(mi) = True;
755 if (!mp->glx_context)
758 mi->polygon_count = 0;
759 glXMakeCurrent(display, window, *(mp->glx_context));
761 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
765 glTranslatef(0.0, 0.0, -10.0);
767 if (!MI_IS_ICONIC(mi)) {
768 glScalef(Scale4Window * mp->WindH / mp->WindW, Scale4Window, Scale4Window);
769 glTranslatef(2.5 * mp->WindW / mp->WindH * sin(mp->step * 1.11), 2.5 * cos(mp->step * 1.25 * 1.11), 0);
771 glScalef(Scale4Iconic * mp->WindH / mp->WindW, Scale4Iconic, Scale4Iconic);
774 glRotatef(mp->step * 100, 1, 0, 0);
775 glRotatef(mp->step * 95, 0, 1, 0);
776 glRotatef(mp->step * 90, 0, 0, 1);
778 mp->seno = (sin(mp->step) + 1.0 / 3.0) * (4.0 / 5.0) * mp->Magnitude;
780 if (mp->VisibleSpikes) {
781 #ifdef DEBUG_CULL_FACE
784 for (loop = 0; loop < 20; loop++)
785 mp->MaterialColor[loop] = MaterialGray;
787 glDisable(GL_CULL_FACE);
789 #ifdef DEBUG_CULL_FACE
792 for (loop = 0; loop < 20; loop++)
793 mp->MaterialColor[loop] = MaterialWhite;
795 glEnable(GL_CULL_FACE);
802 if (MI_IS_FPS(mi)) do_fps (mi);
803 glXSwapBuffers(display, window);
810 change_morph3d(ModeInfo * mi)
812 morph3dstruct *mp = &morph3d[MI_SCREEN(mi)];
814 if (!mp->glx_context)
817 mp->object = (mp->object) % 5 + 1;
820 #endif /* !STANDALONE */
823 release_morph3d(ModeInfo * mi)
825 if (morph3d != NULL) {
826 (void) free((void *) morph3d);
827 morph3d = (morph3dstruct *) NULL;
834 XSCREENSAVER_MODULE ("Morph3D", morph3d)