From http://www.jwz.org/xscreensaver/xscreensaver-5.37.tar.gz
[xscreensaver] / hacks / glx / morph3d.c
1 /* -*- Mode: C; tab-width: 4 -*- */
2 /* morph3d --- Shows 3D morphing objects */
3
4 #if 0
5 static const char sccsid[] = "@(#)morph3d.c     5.01 2001/03/01 xlockmore";
6 #endif
7
8 #undef DEBUG_CULL_FACE
9
10 /*-
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.
16  *
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.
22  *
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.
26  *
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.
31  *
32  * Thanks goes also to Brian Paul for making it possible and inexpensive
33  * to use OpenGL at home.
34  *
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)
37  *
38  * Since I'm not a native English speaker, my apologies for any grammatical
39  * mistakes.
40  *
41  * My e-mail address is
42  * mfvianna@centroin.com.br
43  *
44  * Marcelo F. Vianna (Feb-13-1997)
45  *
46  * Revision History:
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.
51  *
52  */
53
54 #ifdef STANDALONE
55 # define MODE_moebius
56 # define DEFAULTS               "*delay:                40000   \n"             \
57                                                 "*showFPS:      False   \n"             \
58                                                 "*count:                0               \n"             \
59                                                 "*suppressRotationAnimation: True\n" \
60
61 # define refresh_morph3d 0
62 # define release_morph3d 0
63 # define morph3d_handle_event 0
64 # include "xlockmore.h"         /* from the xscreensaver distribution */
65 #else /* !STANDALONE */
66 # include "xlock.h"             /* from the xlockmore distribution */
67 #endif /* !STANDALONE */
68
69 #ifdef MODE_moebius
70
71 ENTRYPOINT ModeSpecOpt morph3d_opts =
72 {0, (XrmOptionDescRec *) NULL, 0, (argtype *) NULL, (OptionStruct *) NULL};
73
74 #ifdef USE_MODULES
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};
80
81 #endif
82
83 #define Scale4Window               0.3
84 #define Scale4Iconic               1.0
85
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))
88
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
95
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
101
102 #ifndef Pi
103 #define Pi                         M_PI
104 #endif
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
115
116 /*************************************************************************/
117
118 typedef struct {
119         GLint       WindH, WindW;
120         GLfloat     step;
121         GLfloat     seno;
122         int         object;
123         int         edgedivisions;
124         int         VisibleSpikes;
125         void        (*draw_object) (ModeInfo * mi);
126         float       Magnitude;
127         const float *MaterialColor[20];
128         GLXContext *glx_context;
129     int         arrayninit;
130
131 } morph3dstruct;
132
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};
141
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};
150
151 static morph3dstruct *morph3d = (morph3dstruct *) NULL;
152
153 #define TRIANGLE(Edge, Amp, Divisions, Z, VS)                                                                    \
154 {                                                                                                                \
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;                                               \
158   GLfloat   Ax,Ay;                                                                                               \
159   int       Ri,Ti;                                                                                               \
160   GLfloat   Vr=(Edge)*SQRT3/3;                                                                                   \
161   GLfloat   AmpVr2=(Amp)/sqr(Vr);                                                                                \
162   GLfloat   Zf=(Edge)*(Z);                                                                                       \
163                                                                                                                  \
164   Ax=(Edge)*(+0.5/(Divisions)), Ay=(Edge)*(-SQRT3/(2*Divisions));                                                \
165                                                                                                                  \
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++;                                                                                       \
182                                                                                                                  \
183       Xf-=Ax; Yf-=Ay; Xa-=Ax; Yb-=Ay;                                                                            \
184                                                                                                                  \
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++;                                                                                       \
194                                                                                                                  \
195       Xf-=Ax; Yf+=Ay; Xa-=Ax; Yb+=Ay;                                                                            \
196     }                                                                                                            \
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);                                                                             \
205     Yf+=Ay; Yb+=Ay;                                                                                              \
206     glEnd();                                                                                                     \
207   }                                                                                                              \
208   VS=(Factor<0);                                                                                                 \
209 }
210
211 #define SQUARE(Edge, Amp, Divisions, Z, VS)                                                                      \
212 {                                                                                                                \
213   int       Xi,Yi;                                                                                               \
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);                                                                    \
219                                                                                                                  \
220   for (Yi=0; Yi<(Divisions); Yi++) {                                                                             \
221     Yf=-((Edge)/2.0) + ((float)Yi)/(Divisions)*(Edge);                                                           \
222     Yf2=sqr(Yf);                                                                                                 \
223     Y=Yf+1.0/(Divisions)*(Edge);                                                                                 \
224     Y2=sqr(Y);                                                                                                   \
225     glBegin(GL_QUAD_STRIP);                                                                                      \
226     for (Xi=0; Xi<=(Divisions); Xi++) {                                                                          \
227       Xf=-((Edge)/2.0) + ((float)Xi)/(Divisions)*(Edge);                                                         \
228       Xf2=sqr(Xf);                                                                                               \
229                                                                                                                  \
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);                                                                           \
239                                                                                                                  \
240       Yb=Yf+0.001;                                                                                               \
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++;                                                                                       \
250     }                                                                                                            \
251     glEnd();                                                                                                     \
252   }                                                                                                              \
253   VS=(Factor<0);                                                                                                 \
254 }
255
256 #define PENTAGON(Edge, Amp, Divisions, Z, VS)                                                                    \
257 {                                                                                                                \
258   int       Ri,Ti,Fi;                                                                                            \
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);                                                                 \
264                                                                                                                  \
265   GLfloat x[6],y[6];                                                                                             \
266                                                                                                                  \
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);                                                \
270   }                                                                                                              \
271                                                                                                                  \
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++;                                                                                     \
288                                                                                                                  \
289         Xf-=x[Fi]; Yf-=y[Fi]; Xa-=x[Fi]; Yb-=y[Fi];                                                              \
290                                                                                                                  \
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++;                                                                                     \
300                                                                                                                  \
301       }                                                                                                          \
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);                                                                           \
313       glEnd();                                                                                                   \
314     }                                                                                                            \
315   }                                                                                                              \
316   VS=(Factor<0);                                                                                                     \
317 }
318
319 static void
320 draw_tetra(ModeInfo * mi)
321 {
322         morph3dstruct *mp = &morph3d[MI_SCREEN(mi)];
323
324         glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[0]);
325
326         TRIANGLE(2, mp->seno, mp->edgedivisions, 0.5 / SQRT6, mp->VisibleSpikes);
327
328         glPushMatrix();
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);
333         glPopMatrix();
334         glPushMatrix();
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);
339         glPopMatrix();
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);
344 }
345
346 static void
347 draw_cube(ModeInfo * mi)
348 {
349         morph3dstruct *mp = &morph3d[MI_SCREEN(mi)];
350
351         glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[0]);
352
353         SQUARE(2, mp->seno, mp->edgedivisions, 0.5, mp->VisibleSpikes)
354
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)
370 }
371
372 static void
373 draw_octa(ModeInfo * mi)
374 {
375         morph3dstruct *mp = &morph3d[MI_SCREEN(mi)];
376
377         glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[0]);
378         TRIANGLE(2, mp->seno, mp->edgedivisions, 1 / SQRT6, mp->VisibleSpikes);
379
380         glPushMatrix();
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);
385         glPopMatrix();
386         glPushMatrix();
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);
391         glPopMatrix();
392         glPushMatrix();
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);
397         glPopMatrix();
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);
401         glPushMatrix();
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);
406         glPopMatrix();
407         glPushMatrix();
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);
412         glPopMatrix();
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);
417 }
418
419 static void
420 draw_dodeca(ModeInfo * mi)
421 {
422         morph3dstruct *mp = &morph3d[MI_SCREEN(mi)];
423
424 #define TAU ((SQRT5+1)/2)
425
426         glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[0]);
427
428         PENTAGON(1, mp->seno, mp->edgedivisions, sqr(TAU) * sqrt((TAU + 2) / 5) / 2, mp->VisibleSpikes);
429
430         glPushMatrix();
431         glRotatef(180, 0, 0, 1);
432         glPushMatrix();
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);
436         glPopMatrix();
437         glPushMatrix();
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);
441         glPopMatrix();
442         glPushMatrix();
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);
446         glPopMatrix();
447         glPushMatrix();
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);
451         glPopMatrix();
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);
455         glPopMatrix();
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);
460         glPushMatrix();
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);
464         glPopMatrix();
465         glPushMatrix();
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);
469         glPopMatrix();
470         glPushMatrix();
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);
474         glPopMatrix();
475         glPushMatrix();
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);
479         glPopMatrix();
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);
483 }
484
485 static void
486 draw_icosa(ModeInfo * mi)
487 {
488         morph3dstruct *mp = &morph3d[MI_SCREEN(mi)];
489
490         glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[0]);
491
492         TRIANGLE(1.5, mp->seno, mp->edgedivisions, (3 * SQRT3 + SQRT15) / 12, mp->VisibleSpikes);
493
494         glPushMatrix();
495
496         glPushMatrix();
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);
501         glPushMatrix();
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);
506         glPopMatrix();
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);
511         glPopMatrix();
512         glPushMatrix();
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);
517         glPushMatrix();
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);
522         glPopMatrix();
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);
527         glPopMatrix();
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);
532         glPushMatrix();
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);
537         glPopMatrix();
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);
542         glPopMatrix();
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);
546         glPushMatrix();
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);
551         glPushMatrix();
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);
556         glPopMatrix();
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);
561         glPopMatrix();
562         glPushMatrix();
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);
567         glPushMatrix();
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);
572         glPopMatrix();
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);
577         glPopMatrix();
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);
582         glPushMatrix();
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);
587         glPopMatrix();
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);
592 }
593
594 ENTRYPOINT void
595 reshape_morph3d(ModeInfo * mi, int width, int height)
596 {
597         morph3dstruct *mp = &morph3d[MI_SCREEN(mi)];
598
599         glViewport(0, 0, mp->WindW = (GLint) width, mp->WindH = (GLint) height);
600         glMatrixMode(GL_PROJECTION);
601         glLoadIdentity();
602         glFrustum(-1.0, 1.0, -1.0, 1.0, 5.0, 15.0);
603         glMatrixMode(GL_MODELVIEW);
604 }
605
606 static void
607 pinit(ModeInfo * mi)
608 {
609         morph3dstruct *mp = &morph3d[MI_SCREEN(mi)];
610
611         glClearDepth(1.0);
612         glColor3f(1.0, 1.0, 1.0);
613
614         glLightfv(GL_LIGHT0, GL_AMBIENT, ambient);
615         glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse);
616         glLightfv(GL_LIGHT0, GL_POSITION, position0);
617         glLightfv(GL_LIGHT1, GL_AMBIENT, ambient);
618         glLightfv(GL_LIGHT1, GL_DIFFUSE, diffuse);
619         glLightfv(GL_LIGHT1, GL_POSITION, position1);
620         glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient);
621         glLightModelfv(GL_LIGHT_MODEL_TWO_SIDE, lmodel_twoside);
622         glEnable(GL_LIGHTING);
623         glEnable(GL_LIGHT0);
624         glEnable(GL_LIGHT1);
625         glEnable(GL_DEPTH_TEST);
626         glEnable(GL_NORMALIZE);
627
628         glShadeModel(GL_SMOOTH);
629         glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, front_shininess);
630         glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, front_specular);
631
632         switch (mp->object) {
633                 case 2:
634                         mp->draw_object = draw_cube;
635                         mp->MaterialColor[0] = MaterialRed;
636                         mp->MaterialColor[1] = MaterialGreen;
637                         mp->MaterialColor[2] = MaterialCyan;
638                         mp->MaterialColor[3] = MaterialMagenta;
639                         mp->MaterialColor[4] = MaterialYellow;
640                         mp->MaterialColor[5] = MaterialBlue;
641                         mp->edgedivisions = cubedivisions;
642                         mp->Magnitude = 2.0;
643                         break;
644                 case 3:
645                         mp->draw_object = draw_octa;
646                         mp->MaterialColor[0] = MaterialRed;
647                         mp->MaterialColor[1] = MaterialGreen;
648                         mp->MaterialColor[2] = MaterialBlue;
649                         mp->MaterialColor[3] = MaterialWhite;
650                         mp->MaterialColor[4] = MaterialCyan;
651                         mp->MaterialColor[5] = MaterialMagenta;
652                         mp->MaterialColor[6] = MaterialGray;
653                         mp->MaterialColor[7] = MaterialYellow;
654                         mp->edgedivisions = octadivisions;
655                         mp->Magnitude = 2.5;
656                         break;
657                 case 4:
658                         mp->draw_object = draw_dodeca;
659                         mp->MaterialColor[0] = MaterialRed;
660                         mp->MaterialColor[1] = MaterialGreen;
661                         mp->MaterialColor[2] = MaterialCyan;
662                         mp->MaterialColor[3] = MaterialBlue;
663                         mp->MaterialColor[4] = MaterialMagenta;
664                         mp->MaterialColor[5] = MaterialYellow;
665                         mp->MaterialColor[6] = MaterialGreen;
666                         mp->MaterialColor[7] = MaterialCyan;
667                         mp->MaterialColor[8] = MaterialRed;
668                         mp->MaterialColor[9] = MaterialMagenta;
669                         mp->MaterialColor[10] = MaterialBlue;
670                         mp->MaterialColor[11] = MaterialYellow;
671                         mp->edgedivisions = dodecadivisions;
672                         mp->Magnitude = 2.0;
673                         break;
674                 case 5:
675                         mp->draw_object = draw_icosa;
676                         mp->MaterialColor[0] = MaterialRed;
677                         mp->MaterialColor[1] = MaterialGreen;
678                         mp->MaterialColor[2] = MaterialBlue;
679                         mp->MaterialColor[3] = MaterialCyan;
680                         mp->MaterialColor[4] = MaterialYellow;
681                         mp->MaterialColor[5] = MaterialMagenta;
682                         mp->MaterialColor[6] = MaterialRed;
683                         mp->MaterialColor[7] = MaterialGreen;
684                         mp->MaterialColor[8] = MaterialBlue;
685                         mp->MaterialColor[9] = MaterialWhite;
686                         mp->MaterialColor[10] = MaterialCyan;
687                         mp->MaterialColor[11] = MaterialYellow;
688                         mp->MaterialColor[12] = MaterialMagenta;
689                         mp->MaterialColor[13] = MaterialRed;
690                         mp->MaterialColor[14] = MaterialGreen;
691                         mp->MaterialColor[15] = MaterialBlue;
692                         mp->MaterialColor[16] = MaterialCyan;
693                         mp->MaterialColor[17] = MaterialYellow;
694                         mp->MaterialColor[18] = MaterialMagenta;
695                         mp->MaterialColor[19] = MaterialGray;
696                         mp->edgedivisions = icodivisions;
697                         mp->Magnitude = 2.5;
698                         break;
699                 default:
700                         mp->draw_object = draw_tetra;
701                         mp->MaterialColor[0] = MaterialRed;
702                         mp->MaterialColor[1] = MaterialGreen;
703                         mp->MaterialColor[2] = MaterialBlue;
704                         mp->MaterialColor[3] = MaterialWhite;
705                         mp->edgedivisions = tetradivisions;
706                         mp->Magnitude = 2.5;
707                         break;
708         }
709         if (MI_IS_MONO(mi)) {
710                 int         loop;
711
712                 for (loop = 0; loop < 20; loop++)
713                         mp->MaterialColor[loop] = MaterialGray;
714         }
715 }
716
717 ENTRYPOINT void
718 init_morph3d(ModeInfo * mi)
719 {
720         morph3dstruct *mp;
721
722         MI_INIT (mi, morph3d, NULL);
723         mp = &morph3d[MI_SCREEN(mi)];
724         mp->step = NRAND(90);
725         mp->VisibleSpikes = 1;
726
727         if ((mp->glx_context = init_GL(mi)) != NULL) {
728
729                 reshape_morph3d(mi, MI_WIDTH(mi), MI_HEIGHT(mi));
730                 glDrawBuffer(GL_BACK);
731                 mp->object = MI_COUNT(mi);
732                 if (mp->object <= 0 || mp->object > 5)
733                         mp->object = NRAND(5) + 1;
734                 pinit(mi);
735         } else {
736                 MI_CLEARWINDOW(mi);
737         }
738 }
739
740 ENTRYPOINT void
741 draw_morph3d(ModeInfo * mi)
742 {
743         Display    *display = MI_DISPLAY(mi);
744         Window      window = MI_WINDOW(mi);
745         morph3dstruct *mp;
746
747         if (morph3d == NULL)
748                 return;
749         mp = &morph3d[MI_SCREEN(mi)];
750
751         MI_IS_DRAWN(mi) = True;
752
753         if (!mp->glx_context)
754                 return;
755
756     mi->polygon_count = 0;
757         glXMakeCurrent(display, window, *(mp->glx_context));
758
759         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
760
761         glPushMatrix();
762
763         glTranslatef(0.0, 0.0, -10.0);
764
765         if (!MI_IS_ICONIC(mi)) {
766                 glScalef(Scale4Window * mp->WindH / mp->WindW, Scale4Window, Scale4Window);
767                 glTranslatef(2.5 * mp->WindW / mp->WindH * sin(mp->step * 1.11), 2.5 * cos(mp->step * 1.25 * 1.11), 0);
768         } else {
769                 glScalef(Scale4Iconic * mp->WindH / mp->WindW, Scale4Iconic, Scale4Iconic);
770         }
771
772 # ifdef HAVE_MOBILE     /* Keep it the same relative size when rotated. */
773     {
774       GLfloat h = MI_HEIGHT(mi) / (GLfloat) MI_WIDTH(mi);
775       int o = (int) current_device_rotation();
776       if (o != 0 && o != 180 && o != -180)
777         glScalef (1/h, h, 1);
778     }
779 # endif
780
781         glRotatef(mp->step * 100, 1, 0, 0);
782         glRotatef(mp->step * 95, 0, 1, 0);
783         glRotatef(mp->step * 90, 0, 0, 1);
784
785         mp->seno = (sin(mp->step) + 1.0 / 3.0) * (4.0 / 5.0) * mp->Magnitude;
786
787         if (mp->VisibleSpikes) {
788 #ifdef DEBUG_CULL_FACE
789                 int         loop;
790
791                 for (loop = 0; loop < 20; loop++)
792                         mp->MaterialColor[loop] = MaterialGray;
793 #endif
794                 glDisable(GL_CULL_FACE);
795         } else {
796 #ifdef DEBUG_CULL_FACE
797                 int         loop;
798
799                 for (loop = 0; loop < 20; loop++)
800                         mp->MaterialColor[loop] = MaterialWhite;
801 #endif
802                 glEnable(GL_CULL_FACE);
803         }
804
805         mp->draw_object(mi);
806
807         glPopMatrix();
808
809         if (MI_IS_FPS(mi)) do_fps (mi);
810         glXSwapBuffers(display, window);
811
812         mp->step += 0.05;
813 }
814
815 #ifndef STANDALONE
816 ENTRYPOINT void
817 change_morph3d(ModeInfo * mi)
818 {
819         morph3dstruct *mp = &morph3d[MI_SCREEN(mi)];
820
821         if (!mp->glx_context)
822                 return;
823
824         mp->object = (mp->object) % 5 + 1;
825         pinit(mi);
826 }
827 #endif /* !STANDALONE */
828
829 #endif
830
831 XSCREENSAVER_MODULE ("Morph3D", morph3d)