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 "*suppressRotationAnimation: True\n" \
61 # define free_morph3d 0
62 # define release_morph3d 0
63 # define morph3d_handle_event xlockmore_no_events
64 # include "xlockmore.h" /* from the xscreensaver distribution */
65 #else /* !STANDALONE */
66 # include "xlock.h" /* from the xlockmore distribution */
67 #endif /* !STANDALONE */
71 ENTRYPOINT ModeSpecOpt morph3d_opts =
72 {0, (XrmOptionDescRec *) NULL, 0, (argtype *) NULL, (OptionStruct *) NULL};
75 ModStruct morph3d_description =
76 {"morph3d", "init_morph3d", "draw_morph3d", (char *) NULL,
77 "draw_morph3d", "change_morph3d", (char *) NULL, &morph3d_opts,
78 1000, 0, 1, 1, 4, 1.0, "",
79 "Shows GL morphing polyhedra", 0, NULL};
83 #define Scale4Window 0.3
84 #define Scale4Iconic 1.0
86 #define VectMul(X1,Y1,Z1,X2,Y2,Z2) (Y1)*(Z2)-(Z1)*(Y2),(Z1)*(X2)-(X1)*(Z2),(X1)*(Y2)-(Y1)*(X2)
87 #define sqr(A) ((A)*(A))
89 /* Increasing this values produces better image quality, the price is speed. */
90 #define tetradivisions 23
91 #define cubedivisions 20
92 #define octadivisions 21
93 #define dodecadivisions 10
94 #define icodivisions 15
96 #define tetraangle 109.47122063449069174
97 #define cubeangle 90.000000000000000000
98 #define octaangle 109.47122063449069174
99 #define dodecaangle 63.434948822922009981
100 #define icoangle 41.810314895778596167
105 #define SQRT2 1.4142135623730951455
106 #define SQRT3 1.7320508075688771932
107 #define SQRT5 2.2360679774997898051
108 #define SQRT6 2.4494897427831778813
109 #define SQRT15 3.8729833462074170214
110 #define cossec36_2 0.8506508083520399322
111 #define cos72 0.3090169943749474241
112 #define sin72 0.9510565162951535721
113 #define cos36 0.8090169943749474241
114 #define sin36 0.5877852522924731292
116 /*************************************************************************/
125 void (*draw_object) (ModeInfo * mi);
127 const float *MaterialColor[20];
128 GLXContext *glx_context;
133 static const GLfloat front_shininess[] = {60.0};
134 static const GLfloat front_specular[] = {0.7, 0.7, 0.7, 1.0};
135 static const GLfloat ambient[] = {0.0, 0.0, 0.0, 1.0};
136 static const GLfloat diffuse[] = {1.0, 1.0, 1.0, 1.0};
137 static const GLfloat position0[] = {1.0, 1.0, 1.0, 0.0};
138 static const GLfloat position1[] = {-1.0, -1.0, 1.0, 0.0};
139 static const GLfloat lmodel_ambient[] = {0.5, 0.5, 0.5, 1.0};
140 static const GLfloat lmodel_twoside[] = {GL_TRUE};
142 static const GLfloat MaterialRed[] = {0.7, 0.0, 0.0, 1.0};
143 static const GLfloat MaterialGreen[] = {0.1, 0.5, 0.2, 1.0};
144 static const GLfloat MaterialBlue[] = {0.0, 0.0, 0.7, 1.0};
145 static const GLfloat MaterialCyan[] = {0.2, 0.5, 0.7, 1.0};
146 static const GLfloat MaterialYellow[] = {0.7, 0.7, 0.0, 1.0};
147 static const GLfloat MaterialMagenta[] = {0.6, 0.2, 0.5, 1.0};
148 static const GLfloat MaterialWhite[] = {0.7, 0.7, 0.7, 1.0};
149 static const GLfloat MaterialGray[] = {0.5, 0.5, 0.5, 1.0};
151 static morph3dstruct *morph3d = (morph3dstruct *) NULL;
153 #define TRIANGLE(Edge, Amp, Divisions, Z, VS) \
155 GLfloat Xf,Yf,Xa,Yb=0.0,Xf2=0.0,Yf2=0.0,Yf_2=0.0,Yb2,Yb_2; \
156 GLfloat Factor=0.0,Factor1,Factor2; \
157 GLfloat VertX,VertY,VertZ,NeiAX,NeiAY,NeiAZ,NeiBX,NeiBY,NeiBZ; \
160 GLfloat Vr=(Edge)*SQRT3/3; \
161 GLfloat AmpVr2=(Amp)/sqr(Vr); \
162 GLfloat Zf=(Edge)*(Z); \
164 Ax=(Edge)*(+0.5/(Divisions)), Ay=(Edge)*(-SQRT3/(2*Divisions)); \
166 Yf=Vr+Ay; Yb=Yf+0.001; \
167 for (Ri=1; Ri<=(Divisions); Ri++) { \
168 glBegin(GL_TRIANGLE_STRIP); \
169 Xf=(float)Ri*Ax; Xa=Xf+0.001; \
170 Yf2=sqr(Yf); Yf_2=sqr(Yf-Ay); \
171 Yb2=sqr(Yb); Yb_2=sqr(Yb-Ay); \
172 for (Ti=0; Ti<Ri; Ti++) { \
173 Factor=1-(((Xf2=sqr(Xf))+Yf2)*AmpVr2); \
174 Factor1=1-((sqr(Xa)+Yf2)*AmpVr2); \
175 Factor2=1-((Xf2+Yb2)*AmpVr2); \
176 VertX=Factor*Xf; VertY=Factor*Yf; VertZ=Factor*Zf; \
177 NeiAX=Factor1*Xa-VertX; NeiAY=Factor1*Yf-VertY; NeiAZ=Factor1*Zf-VertZ; \
178 NeiBX=Factor2*Xf-VertX; NeiBY=Factor2*Yb-VertY; NeiBZ=Factor2*Zf-VertZ; \
179 glNormal3f(VectMul(NeiAX, NeiAY, NeiAZ, NeiBX, NeiBY, NeiBZ)); \
180 glVertex3f(VertX, VertY, VertZ); \
181 mi->polygon_count++; \
183 Xf-=Ax; Yf-=Ay; Xa-=Ax; Yb-=Ay; \
185 Factor=1-(((Xf2=sqr(Xf))+Yf_2)*AmpVr2); \
186 Factor1=1-((sqr(Xa)+Yf_2)*AmpVr2); \
187 Factor2=1-((Xf2+Yb_2)*AmpVr2); \
188 VertX=Factor*Xf; VertY=Factor*Yf; VertZ=Factor*Zf; \
189 NeiAX=Factor1*Xa-VertX; NeiAY=Factor1*Yf-VertY; NeiAZ=Factor1*Zf-VertZ; \
190 NeiBX=Factor2*Xf-VertX; NeiBY=Factor2*Yb-VertY; NeiBZ=Factor2*Zf-VertZ; \
191 glNormal3f(VectMul(NeiAX, NeiAY, NeiAZ, NeiBX, NeiBY, NeiBZ)); \
192 glVertex3f(VertX, VertY, VertZ); \
193 mi->polygon_count++; \
195 Xf-=Ax; Yf+=Ay; Xa-=Ax; Yb+=Ay; \
197 Factor=1-(((Xf2=sqr(Xf))+(Yf2=sqr(Yf)))*AmpVr2); \
198 Factor1=1-((sqr(Xa)+Yf2)*AmpVr2); \
199 Factor2=1-((Xf2+sqr(Yb))*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); \
211 #define SQUARE(Edge, Amp, Divisions, Z, VS) \
214 GLfloat Xf,Yf,Y,Xf2,Yf2,Y2,Xa,Xa2,Yb; \
215 GLfloat Factor=0.0,Factor1,Factor2; \
216 GLfloat VertX,VertY,VertZ,NeiAX,NeiAY,NeiAZ,NeiBX,NeiBY,NeiBZ; \
217 GLfloat Zf=(Edge)*(Z); \
218 GLfloat AmpVr2=(Amp)/sqr((Edge)*SQRT2/2); \
220 for (Yi=0; Yi<(Divisions); Yi++) { \
221 Yf=-((Edge)/2.0) + ((float)Yi)/(Divisions)*(Edge); \
223 Y=Yf+1.0/(Divisions)*(Edge); \
225 glBegin(GL_QUAD_STRIP); \
226 for (Xi=0; Xi<=(Divisions); Xi++) { \
227 Xf=-((Edge)/2.0) + ((float)Xi)/(Divisions)*(Edge); \
230 Xa=Xf+0.001; Yb=Y+0.001; \
231 Factor=1-((Xf2+Y2)*AmpVr2); \
232 Factor1=1-(((Xa2=sqr(Xa))+Y2)*AmpVr2); \
233 Factor2=1-((Xf2+sqr(Yb))*AmpVr2); \
234 VertX=Factor*Xf; VertY=Factor*Y; VertZ=Factor*Zf; \
235 NeiAX=Factor1*Xa-VertX; NeiAY=Factor1*Y-VertY; NeiAZ=Factor1*Zf-VertZ; \
236 NeiBX=Factor2*Xf-VertX; NeiBY=Factor2*Yb-VertY; NeiBZ=Factor2*Zf-VertZ; \
237 glNormal3f(VectMul(NeiAX, NeiAY, NeiAZ, NeiBX, NeiBY, NeiBZ)); \
238 glVertex3f(VertX, VertY, VertZ); \
241 Factor=1-((Xf2+Yf2)*AmpVr2); \
242 Factor1=1-((Xa2+Yf2)*AmpVr2); \
243 Factor2=1-((Xf2+sqr(Yb))*AmpVr2); \
244 VertX=Factor*Xf; VertY=Factor*Yf; VertZ=Factor*Zf; \
245 NeiAX=Factor1*Xa-VertX; NeiAY=Factor1*Yf-VertY; NeiAZ=Factor1*Zf-VertZ; \
246 NeiBX=Factor2*Xf-VertX; NeiBY=Factor2*Yb-VertY; NeiBZ=Factor2*Zf-VertZ; \
247 glNormal3f(VectMul(NeiAX, NeiAY, NeiAZ, NeiBX, NeiBY, NeiBZ)); \
248 glVertex3f(VertX, VertY, VertZ); \
249 mi->polygon_count++; \
256 #define PENTAGON(Edge, Amp, Divisions, Z, VS) \
259 GLfloat Xf,Yf,Xa,Yb,Xf2,Yf2; \
260 GLfloat Factor=0.0,Factor1,Factor2; \
261 GLfloat VertX,VertY,VertZ,NeiAX,NeiAY,NeiAZ,NeiBX,NeiBY,NeiBZ; \
262 GLfloat Zf=(Edge)*(Z); \
263 GLfloat AmpVr2=(Amp)/sqr((Edge)*cossec36_2); \
267 for(Fi=0;Fi<6;Fi++) { \
268 x[Fi]=-cos( Fi*2*Pi/5 + Pi/10 )/(Divisions)*cossec36_2*(Edge); \
269 y[Fi]=sin( Fi*2*Pi/5 + Pi/10 )/(Divisions)*cossec36_2*(Edge); \
272 for (Ri=1; Ri<=(Divisions); Ri++) { \
273 for (Fi=0; Fi<5; Fi++) { \
274 glBegin(GL_TRIANGLE_STRIP); \
275 for (Ti=0; Ti<Ri; Ti++) { \
276 Xf=(float)(Ri-Ti)*x[Fi] + (float)Ti*x[Fi+1]; \
277 Yf=(float)(Ri-Ti)*y[Fi] + (float)Ti*y[Fi+1]; \
278 Xa=Xf+0.001; Yb=Yf+0.001; \
279 Factor=1-(((Xf2=sqr(Xf))+(Yf2=sqr(Yf)))*AmpVr2); \
280 Factor1=1-((sqr(Xa)+Yf2)*AmpVr2); \
281 Factor2=1-((Xf2+sqr(Yb))*AmpVr2); \
282 VertX=Factor*Xf; VertY=Factor*Yf; VertZ=Factor*Zf; \
283 NeiAX=Factor1*Xa-VertX; NeiAY=Factor1*Yf-VertY; NeiAZ=Factor1*Zf-VertZ; \
284 NeiBX=Factor2*Xf-VertX; NeiBY=Factor2*Yb-VertY; NeiBZ=Factor2*Zf-VertZ; \
285 glNormal3f(VectMul(NeiAX, NeiAY, NeiAZ, NeiBX, NeiBY, NeiBZ)); \
286 glVertex3f(VertX, VertY, VertZ); \
287 mi->polygon_count++; \
289 Xf-=x[Fi]; Yf-=y[Fi]; Xa-=x[Fi]; Yb-=y[Fi]; \
291 Factor=1-(((Xf2=sqr(Xf))+(Yf2=sqr(Yf)))*AmpVr2); \
292 Factor1=1-((sqr(Xa)+Yf2)*AmpVr2); \
293 Factor2=1-((Xf2+sqr(Yb))*AmpVr2); \
294 VertX=Factor*Xf; VertY=Factor*Yf; VertZ=Factor*Zf; \
295 NeiAX=Factor1*Xa-VertX; NeiAY=Factor1*Yf-VertY; NeiAZ=Factor1*Zf-VertZ; \
296 NeiBX=Factor2*Xf-VertX; NeiBY=Factor2*Yb-VertY; NeiBZ=Factor2*Zf-VertZ; \
297 glNormal3f(VectMul(NeiAX, NeiAY, NeiAZ, NeiBX, NeiBY, NeiBZ)); \
298 glVertex3f(VertX, VertY, VertZ); \
299 mi->polygon_count++; \
302 Xf=(float)Ri*x[Fi+1]; \
303 Yf=(float)Ri*y[Fi+1]; \
304 Xa=Xf+0.001; Yb=Yf+0.001; \
305 Factor=1-(((Xf2=sqr(Xf))+(Yf2=sqr(Yf)))*AmpVr2); \
306 Factor1=1-((sqr(Xa)+Yf2)*AmpVr2); \
307 Factor2=1-((Xf2+sqr(Yb))*AmpVr2); \
308 VertX=Factor*Xf; VertY=Factor*Yf; VertZ=Factor*Zf; \
309 NeiAX=Factor1*Xa-VertX; NeiAY=Factor1*Yf-VertY; NeiAZ=Factor1*Zf-VertZ; \
310 NeiBX=Factor2*Xf-VertX; NeiBY=Factor2*Yb-VertY; NeiBZ=Factor2*Zf-VertZ; \
311 glNormal3f(VectMul(NeiAX, NeiAY, NeiAZ, NeiBX, NeiBY, NeiBZ)); \
312 glVertex3f(VertX, VertY, VertZ); \
320 draw_tetra(ModeInfo * mi)
322 morph3dstruct *mp = &morph3d[MI_SCREEN(mi)];
324 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[0]);
326 TRIANGLE(2, mp->seno, mp->edgedivisions, 0.5 / SQRT6, mp->VisibleSpikes);
329 glRotatef(180, 0, 0, 1);
330 glRotatef(-tetraangle, 1, 0, 0);
331 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[1]);
332 TRIANGLE(2, mp->seno, mp->edgedivisions, 0.5 / SQRT6, mp->VisibleSpikes);
335 glRotatef(180, 0, 1, 0);
336 glRotatef(-180 + tetraangle, 0.5, SQRT3 / 2, 0);
337 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[2]);
338 TRIANGLE(2, mp->seno, mp->edgedivisions, 0.5 / SQRT6, mp->VisibleSpikes);
340 glRotatef(180, 0, 1, 0);
341 glRotatef(-180 + tetraangle, 0.5, -SQRT3 / 2, 0);
342 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[3]);
343 TRIANGLE(2, mp->seno, mp->edgedivisions, 0.5 / SQRT6, mp->VisibleSpikes);
347 draw_cube(ModeInfo * mi)
349 morph3dstruct *mp = &morph3d[MI_SCREEN(mi)];
351 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[0]);
353 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[1]);
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[2]);
360 SQUARE(2, mp->seno, mp->edgedivisions, 0.5, mp->VisibleSpikes)
361 glRotatef(cubeangle, 1, 0, 0);
362 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[3]);
363 SQUARE(2, mp->seno, mp->edgedivisions, 0.5, mp->VisibleSpikes)
364 glRotatef(cubeangle, 0, 1, 0);
365 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[4]);
366 SQUARE(2, mp->seno, mp->edgedivisions, 0.5, mp->VisibleSpikes)
367 glRotatef(2 * cubeangle, 0, 1, 0);
368 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[5]);
369 SQUARE(2, mp->seno, mp->edgedivisions, 0.5, mp->VisibleSpikes)
373 draw_octa(ModeInfo * mi)
375 morph3dstruct *mp = &morph3d[MI_SCREEN(mi)];
377 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[0]);
378 TRIANGLE(2, mp->seno, mp->edgedivisions, 1 / SQRT6, mp->VisibleSpikes);
381 glRotatef(180, 0, 0, 1);
382 glRotatef(-180 + octaangle, 1, 0, 0);
383 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[1]);
384 TRIANGLE(2, mp->seno, mp->edgedivisions, 1 / SQRT6, mp->VisibleSpikes);
387 glRotatef(180, 0, 1, 0);
388 glRotatef(-octaangle, 0.5, SQRT3 / 2, 0);
389 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[2]);
390 TRIANGLE(2, mp->seno, mp->edgedivisions, 1 / SQRT6, mp->VisibleSpikes);
393 glRotatef(180, 0, 1, 0);
394 glRotatef(-octaangle, 0.5, -SQRT3 / 2, 0);
395 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[3]);
396 TRIANGLE(2, mp->seno, mp->edgedivisions, 1 / SQRT6, mp->VisibleSpikes);
398 glRotatef(180, 1, 0, 0);
399 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[4]);
400 TRIANGLE(2, mp->seno, mp->edgedivisions, 1 / SQRT6, mp->VisibleSpikes);
402 glRotatef(180, 0, 0, 1);
403 glRotatef(-180 + octaangle, 1, 0, 0);
404 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[5]);
405 TRIANGLE(2, mp->seno, mp->edgedivisions, 1 / SQRT6, mp->VisibleSpikes);
408 glRotatef(180, 0, 1, 0);
409 glRotatef(-octaangle, 0.5, SQRT3 / 2, 0);
410 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[6]);
411 TRIANGLE(2, mp->seno, mp->edgedivisions, 1 / SQRT6, mp->VisibleSpikes);
413 glRotatef(180, 0, 1, 0);
414 glRotatef(-octaangle, 0.5, -SQRT3 / 2, 0);
415 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[7]);
416 TRIANGLE(2, mp->seno, mp->edgedivisions, 1 / SQRT6, mp->VisibleSpikes);
420 draw_dodeca(ModeInfo * mi)
422 morph3dstruct *mp = &morph3d[MI_SCREEN(mi)];
424 #define TAU ((SQRT5+1)/2)
426 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[0]);
428 PENTAGON(1, mp->seno, mp->edgedivisions, sqr(TAU) * sqrt((TAU + 2) / 5) / 2, mp->VisibleSpikes);
431 glRotatef(180, 0, 0, 1);
433 glRotatef(-dodecaangle, 1, 0, 0);
434 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[1]);
435 PENTAGON(1, mp->seno, mp->edgedivisions, sqr(TAU) * sqrt((TAU + 2) / 5) / 2, mp->VisibleSpikes);
438 glRotatef(-dodecaangle, cos72, sin72, 0);
439 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[2]);
440 PENTAGON(1, mp->seno, mp->edgedivisions, sqr(TAU) * sqrt((TAU + 2) / 5) / 2, mp->VisibleSpikes);
443 glRotatef(-dodecaangle, cos72, -sin72, 0);
444 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[3]);
445 PENTAGON(1, mp->seno, mp->edgedivisions, sqr(TAU) * sqrt((TAU + 2) / 5) / 2, mp->VisibleSpikes);
448 glRotatef(dodecaangle, cos36, -sin36, 0);
449 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[4]);
450 PENTAGON(1, mp->seno, mp->edgedivisions, sqr(TAU) * sqrt((TAU + 2) / 5) / 2, mp->VisibleSpikes);
452 glRotatef(dodecaangle, cos36, sin36, 0);
453 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[5]);
454 PENTAGON(1, mp->seno, mp->edgedivisions, sqr(TAU) * sqrt((TAU + 2) / 5) / 2, mp->VisibleSpikes);
456 glRotatef(180, 1, 0, 0);
457 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[6]);
458 PENTAGON(1, mp->seno, mp->edgedivisions, sqr(TAU) * sqrt((TAU + 2) / 5) / 2, mp->VisibleSpikes);
459 glRotatef(180, 0, 0, 1);
461 glRotatef(-dodecaangle, 1, 0, 0);
462 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[7]);
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[8]);
468 PENTAGON(1, mp->seno, mp->edgedivisions, sqr(TAU) * sqrt((TAU + 2) / 5) / 2, mp->VisibleSpikes);
471 glRotatef(-dodecaangle, cos72, -sin72, 0);
472 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[9]);
473 PENTAGON(1, mp->seno, mp->edgedivisions, sqr(TAU) * sqrt((TAU + 2) / 5) / 2, mp->VisibleSpikes);
476 glRotatef(dodecaangle, cos36, -sin36, 0);
477 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[10]);
478 PENTAGON(1, mp->seno, mp->edgedivisions, sqr(TAU) * sqrt((TAU + 2) / 5) / 2, mp->VisibleSpikes);
480 glRotatef(dodecaangle, cos36, sin36, 0);
481 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[11]);
482 PENTAGON(1, mp->seno, mp->edgedivisions, sqr(TAU) * sqrt((TAU + 2) / 5) / 2, mp->VisibleSpikes);
486 draw_icosa(ModeInfo * mi)
488 morph3dstruct *mp = &morph3d[MI_SCREEN(mi)];
490 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[0]);
492 TRIANGLE(1.5, mp->seno, mp->edgedivisions, (3 * SQRT3 + SQRT15) / 12, mp->VisibleSpikes);
497 glRotatef(180, 0, 0, 1);
498 glRotatef(-icoangle, 1, 0, 0);
499 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[1]);
500 TRIANGLE(1.5, mp->seno, mp->edgedivisions, (3 * SQRT3 + SQRT15) / 12, mp->VisibleSpikes);
502 glRotatef(180, 0, 1, 0);
503 glRotatef(-180 + icoangle, 0.5, SQRT3 / 2, 0);
504 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[2]);
505 TRIANGLE(1.5, mp->seno, mp->edgedivisions, (3 * SQRT3 + SQRT15) / 12, mp->VisibleSpikes);
507 glRotatef(180, 0, 1, 0);
508 glRotatef(-180 + icoangle, 0.5, -SQRT3 / 2, 0);
509 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[3]);
510 TRIANGLE(1.5, mp->seno, mp->edgedivisions, (3 * SQRT3 + SQRT15) / 12, mp->VisibleSpikes);
513 glRotatef(180, 0, 1, 0);
514 glRotatef(-180 + icoangle, 0.5, SQRT3 / 2, 0);
515 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[4]);
516 TRIANGLE(1.5, mp->seno, mp->edgedivisions, (3 * SQRT3 + SQRT15) / 12, mp->VisibleSpikes);
518 glRotatef(180, 0, 1, 0);
519 glRotatef(-180 + icoangle, 0.5, SQRT3 / 2, 0);
520 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[5]);
521 TRIANGLE(1.5, mp->seno, mp->edgedivisions, (3 * SQRT3 + SQRT15) / 12, mp->VisibleSpikes);
523 glRotatef(180, 0, 0, 1);
524 glRotatef(-icoangle, 1, 0, 0);
525 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[6]);
526 TRIANGLE(1.5, mp->seno, mp->edgedivisions, (3 * SQRT3 + SQRT15) / 12, mp->VisibleSpikes);
528 glRotatef(180, 0, 1, 0);
529 glRotatef(-180 + icoangle, 0.5, -SQRT3 / 2, 0);
530 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[7]);
531 TRIANGLE(1.5, mp->seno, mp->edgedivisions, (3 * SQRT3 + SQRT15) / 12, mp->VisibleSpikes);
533 glRotatef(180, 0, 1, 0);
534 glRotatef(-180 + icoangle, 0.5, -SQRT3 / 2, 0);
535 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[8]);
536 TRIANGLE(1.5, mp->seno, mp->edgedivisions, (3 * SQRT3 + SQRT15) / 12, mp->VisibleSpikes);
538 glRotatef(180, 0, 0, 1);
539 glRotatef(-icoangle, 1, 0, 0);
540 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[9]);
541 TRIANGLE(1.5, mp->seno, mp->edgedivisions, (3 * SQRT3 + SQRT15) / 12, mp->VisibleSpikes);
543 glRotatef(180, 1, 0, 0);
544 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[10]);
545 TRIANGLE(1.5, mp->seno, mp->edgedivisions, (3 * SQRT3 + SQRT15) / 12, mp->VisibleSpikes);
547 glRotatef(180, 0, 0, 1);
548 glRotatef(-icoangle, 1, 0, 0);
549 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[11]);
550 TRIANGLE(1.5, mp->seno, mp->edgedivisions, (3 * SQRT3 + SQRT15) / 12, mp->VisibleSpikes);
552 glRotatef(180, 0, 1, 0);
553 glRotatef(-180 + icoangle, 0.5, SQRT3 / 2, 0);
554 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[12]);
555 TRIANGLE(1.5, mp->seno, mp->edgedivisions, (3 * SQRT3 + SQRT15) / 12, mp->VisibleSpikes);
557 glRotatef(180, 0, 1, 0);
558 glRotatef(-180 + icoangle, 0.5, -SQRT3 / 2, 0);
559 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[13]);
560 TRIANGLE(1.5, mp->seno, mp->edgedivisions, (3 * SQRT3 + SQRT15) / 12, mp->VisibleSpikes);
563 glRotatef(180, 0, 1, 0);
564 glRotatef(-180 + icoangle, 0.5, SQRT3 / 2, 0);
565 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[14]);
566 TRIANGLE(1.5, mp->seno, mp->edgedivisions, (3 * SQRT3 + SQRT15) / 12, mp->VisibleSpikes);
568 glRotatef(180, 0, 1, 0);
569 glRotatef(-180 + icoangle, 0.5, SQRT3 / 2, 0);
570 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[15]);
571 TRIANGLE(1.5, mp->seno, mp->edgedivisions, (3 * SQRT3 + SQRT15) / 12, mp->VisibleSpikes);
573 glRotatef(180, 0, 0, 1);
574 glRotatef(-icoangle, 1, 0, 0);
575 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[16]);
576 TRIANGLE(1.5, mp->seno, mp->edgedivisions, (3 * SQRT3 + SQRT15) / 12, mp->VisibleSpikes);
578 glRotatef(180, 0, 1, 0);
579 glRotatef(-180 + icoangle, 0.5, -SQRT3 / 2, 0);
580 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[17]);
581 TRIANGLE(1.5, mp->seno, mp->edgedivisions, (3 * SQRT3 + SQRT15) / 12, mp->VisibleSpikes);
583 glRotatef(180, 0, 1, 0);
584 glRotatef(-180 + icoangle, 0.5, -SQRT3 / 2, 0);
585 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[18]);
586 TRIANGLE(1.5, mp->seno, mp->edgedivisions, (3 * SQRT3 + SQRT15) / 12, mp->VisibleSpikes);
588 glRotatef(180, 0, 0, 1);
589 glRotatef(-icoangle, 1, 0, 0);
590 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[19]);
591 TRIANGLE(1.5, mp->seno, mp->edgedivisions, (3 * SQRT3 + SQRT15) / 12, mp->VisibleSpikes);
595 reshape_morph3d(ModeInfo * mi, int width, int height)
597 morph3dstruct *mp = &morph3d[MI_SCREEN(mi)];
600 if (width > height * 5) { /* tiny window: show middle */
605 glViewport(0, y, mp->WindW = (GLint) width, mp->WindH = (GLint) height);
606 glMatrixMode(GL_PROJECTION);
608 glFrustum(-1.0, 1.0, -1.0, 1.0, 5.0, 15.0);
609 glMatrixMode(GL_MODELVIEW);
615 morph3dstruct *mp = &morph3d[MI_SCREEN(mi)];
618 glColor3f(1.0, 1.0, 1.0);
620 glLightfv(GL_LIGHT0, GL_AMBIENT, ambient);
621 glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse);
622 glLightfv(GL_LIGHT0, GL_POSITION, position0);
623 glLightfv(GL_LIGHT1, GL_AMBIENT, ambient);
624 glLightfv(GL_LIGHT1, GL_DIFFUSE, diffuse);
625 glLightfv(GL_LIGHT1, GL_POSITION, position1);
626 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient);
627 glLightModelfv(GL_LIGHT_MODEL_TWO_SIDE, lmodel_twoside);
628 glEnable(GL_LIGHTING);
631 glEnable(GL_DEPTH_TEST);
632 glEnable(GL_NORMALIZE);
634 glShadeModel(GL_SMOOTH);
635 glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, front_shininess);
636 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, front_specular);
638 switch (mp->object) {
640 mp->draw_object = draw_cube;
641 mp->MaterialColor[0] = MaterialRed;
642 mp->MaterialColor[1] = MaterialGreen;
643 mp->MaterialColor[2] = MaterialCyan;
644 mp->MaterialColor[3] = MaterialMagenta;
645 mp->MaterialColor[4] = MaterialYellow;
646 mp->MaterialColor[5] = MaterialBlue;
647 mp->edgedivisions = cubedivisions;
651 mp->draw_object = draw_octa;
652 mp->MaterialColor[0] = MaterialRed;
653 mp->MaterialColor[1] = MaterialGreen;
654 mp->MaterialColor[2] = MaterialBlue;
655 mp->MaterialColor[3] = MaterialWhite;
656 mp->MaterialColor[4] = MaterialCyan;
657 mp->MaterialColor[5] = MaterialMagenta;
658 mp->MaterialColor[6] = MaterialGray;
659 mp->MaterialColor[7] = MaterialYellow;
660 mp->edgedivisions = octadivisions;
664 mp->draw_object = draw_dodeca;
665 mp->MaterialColor[0] = MaterialRed;
666 mp->MaterialColor[1] = MaterialGreen;
667 mp->MaterialColor[2] = MaterialCyan;
668 mp->MaterialColor[3] = MaterialBlue;
669 mp->MaterialColor[4] = MaterialMagenta;
670 mp->MaterialColor[5] = MaterialYellow;
671 mp->MaterialColor[6] = MaterialGreen;
672 mp->MaterialColor[7] = MaterialCyan;
673 mp->MaterialColor[8] = MaterialRed;
674 mp->MaterialColor[9] = MaterialMagenta;
675 mp->MaterialColor[10] = MaterialBlue;
676 mp->MaterialColor[11] = MaterialYellow;
677 mp->edgedivisions = dodecadivisions;
681 mp->draw_object = draw_icosa;
682 mp->MaterialColor[0] = MaterialRed;
683 mp->MaterialColor[1] = MaterialGreen;
684 mp->MaterialColor[2] = MaterialBlue;
685 mp->MaterialColor[3] = MaterialCyan;
686 mp->MaterialColor[4] = MaterialYellow;
687 mp->MaterialColor[5] = MaterialMagenta;
688 mp->MaterialColor[6] = MaterialRed;
689 mp->MaterialColor[7] = MaterialGreen;
690 mp->MaterialColor[8] = MaterialBlue;
691 mp->MaterialColor[9] = MaterialWhite;
692 mp->MaterialColor[10] = MaterialCyan;
693 mp->MaterialColor[11] = MaterialYellow;
694 mp->MaterialColor[12] = MaterialMagenta;
695 mp->MaterialColor[13] = MaterialRed;
696 mp->MaterialColor[14] = MaterialGreen;
697 mp->MaterialColor[15] = MaterialBlue;
698 mp->MaterialColor[16] = MaterialCyan;
699 mp->MaterialColor[17] = MaterialYellow;
700 mp->MaterialColor[18] = MaterialMagenta;
701 mp->MaterialColor[19] = MaterialGray;
702 mp->edgedivisions = icodivisions;
706 mp->draw_object = draw_tetra;
707 mp->MaterialColor[0] = MaterialRed;
708 mp->MaterialColor[1] = MaterialGreen;
709 mp->MaterialColor[2] = MaterialBlue;
710 mp->MaterialColor[3] = MaterialWhite;
711 mp->edgedivisions = tetradivisions;
715 if (MI_IS_MONO(mi)) {
718 for (loop = 0; loop < 20; loop++)
719 mp->MaterialColor[loop] = MaterialGray;
724 init_morph3d(ModeInfo * mi)
728 MI_INIT (mi, morph3d);
729 mp = &morph3d[MI_SCREEN(mi)];
730 mp->step = NRAND(90);
731 mp->VisibleSpikes = 1;
733 if ((mp->glx_context = init_GL(mi)) != NULL) {
735 reshape_morph3d(mi, MI_WIDTH(mi), MI_HEIGHT(mi));
736 glDrawBuffer(GL_BACK);
737 mp->object = MI_COUNT(mi);
738 if (mp->object <= 0 || mp->object > 5)
739 mp->object = NRAND(5) + 1;
747 draw_morph3d(ModeInfo * mi)
749 Display *display = MI_DISPLAY(mi);
750 Window window = MI_WINDOW(mi);
755 mp = &morph3d[MI_SCREEN(mi)];
757 MI_IS_DRAWN(mi) = True;
759 if (!mp->glx_context)
762 mi->polygon_count = 0;
763 glXMakeCurrent(display, window, *(mp->glx_context));
765 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
769 glTranslatef(0.0, 0.0, -10.0);
771 if (!MI_IS_ICONIC(mi)) {
772 glScalef(Scale4Window * mp->WindH / mp->WindW, Scale4Window, Scale4Window);
773 glTranslatef(2.5 * mp->WindW / mp->WindH * sin(mp->step * 1.11), 2.5 * cos(mp->step * 1.25 * 1.11), 0);
775 glScalef(Scale4Iconic * mp->WindH / mp->WindW, Scale4Iconic, Scale4Iconic);
778 # ifdef HAVE_MOBILE /* Keep it the same relative size when rotated. */
780 GLfloat h = MI_HEIGHT(mi) / (GLfloat) MI_WIDTH(mi);
781 int o = (int) current_device_rotation();
782 if (o != 0 && o != 180 && o != -180)
783 glScalef (1/h, h, 1);
787 glRotatef(mp->step * 100, 1, 0, 0);
788 glRotatef(mp->step * 95, 0, 1, 0);
789 glRotatef(mp->step * 90, 0, 0, 1);
791 mp->seno = (sin(mp->step) + 1.0 / 3.0) * (4.0 / 5.0) * mp->Magnitude;
793 if (mp->VisibleSpikes) {
794 #ifdef DEBUG_CULL_FACE
797 for (loop = 0; loop < 20; loop++)
798 mp->MaterialColor[loop] = MaterialGray;
800 glDisable(GL_CULL_FACE);
802 #ifdef DEBUG_CULL_FACE
805 for (loop = 0; loop < 20; loop++)
806 mp->MaterialColor[loop] = MaterialWhite;
808 glEnable(GL_CULL_FACE);
815 if (MI_IS_FPS(mi)) do_fps (mi);
816 glXSwapBuffers(display, window);
823 change_morph3d(ModeInfo * mi)
825 morph3dstruct *mp = &morph3d[MI_SCREEN(mi)];
827 if (!mp->glx_context)
830 mp->object = (mp->object) % 5 + 1;
833 #endif /* !STANDALONE */
837 XSCREENSAVER_MODULE ("Morph3D", morph3d)