From http://www.jwz.org/xscreensaver/xscreensaver-5.35.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 morph3d_handle_event 0
63 # include "xlockmore.h"         /* from the xscreensaver distribution */
64 #else /* !STANDALONE */
65 # include "xlock.h"             /* from the xlockmore distribution */
66 #endif /* !STANDALONE */
67
68 #ifdef MODE_moebius
69
70 ENTRYPOINT ModeSpecOpt morph3d_opts =
71 {0, (XrmOptionDescRec *) NULL, 0, (argtype *) NULL, (OptionStruct *) NULL};
72
73 #ifdef USE_MODULES
74 ModStruct   morph3d_description =
75 {"morph3d", "init_morph3d", "draw_morph3d", "release_morph3d",
76  "draw_morph3d", "change_morph3d", (char *) NULL, &morph3d_opts,
77  1000, 0, 1, 1, 4, 1.0, "",
78  "Shows GL morphing polyhedra", 0, NULL};
79
80 #endif
81
82 #define Scale4Window               0.3
83 #define Scale4Iconic               1.0
84
85 #define VectMul(X1,Y1,Z1,X2,Y2,Z2) (Y1)*(Z2)-(Z1)*(Y2),(Z1)*(X2)-(X1)*(Z2),(X1)*(Y2)-(Y1)*(X2)
86 #define sqr(A)                     ((A)*(A))
87
88 /* Increasing this values produces better image quality, the price is speed. */
89 #define tetradivisions             23
90 #define cubedivisions              20
91 #define octadivisions              21
92 #define dodecadivisions            10
93 #define icodivisions               15
94
95 #define tetraangle                 109.47122063449069174
96 #define cubeangle                  90.000000000000000000
97 #define octaangle                  109.47122063449069174
98 #define dodecaangle                63.434948822922009981
99 #define icoangle                   41.810314895778596167
100
101 #ifndef Pi
102 #define Pi                         M_PI
103 #endif
104 #define SQRT2                      1.4142135623730951455
105 #define SQRT3                      1.7320508075688771932
106 #define SQRT5                      2.2360679774997898051
107 #define SQRT6                      2.4494897427831778813
108 #define SQRT15                     3.8729833462074170214
109 #define cossec36_2                 0.8506508083520399322
110 #define cos72                      0.3090169943749474241
111 #define sin72                      0.9510565162951535721
112 #define cos36                      0.8090169943749474241
113 #define sin36                      0.5877852522924731292
114
115 /*************************************************************************/
116
117 typedef struct {
118         GLint       WindH, WindW;
119         GLfloat     step;
120         GLfloat     seno;
121         int         object;
122         int         edgedivisions;
123         int         VisibleSpikes;
124         void        (*draw_object) (ModeInfo * mi);
125         float       Magnitude;
126         const float *MaterialColor[20];
127         GLXContext *glx_context;
128     int         arrayninit;
129
130 } morph3dstruct;
131
132 static const GLfloat front_shininess[] = {60.0};
133 static const GLfloat front_specular[]  = {0.7, 0.7, 0.7, 1.0};
134 static const GLfloat ambient[]         = {0.0, 0.0, 0.0, 1.0};
135 static const GLfloat diffuse[]         = {1.0, 1.0, 1.0, 1.0};
136 static const GLfloat position0[]       = {1.0, 1.0, 1.0, 0.0};
137 static const GLfloat position1[]       = {-1.0, -1.0, 1.0, 0.0};
138 static const GLfloat lmodel_ambient[]  = {0.5, 0.5, 0.5, 1.0};
139 static const GLfloat lmodel_twoside[]  = {GL_TRUE};
140
141 static const GLfloat MaterialRed[]     = {0.7, 0.0, 0.0, 1.0};
142 static const GLfloat MaterialGreen[]   = {0.1, 0.5, 0.2, 1.0};
143 static const GLfloat MaterialBlue[]    = {0.0, 0.0, 0.7, 1.0};
144 static const GLfloat MaterialCyan[]    = {0.2, 0.5, 0.7, 1.0};
145 static const GLfloat MaterialYellow[]  = {0.7, 0.7, 0.0, 1.0};
146 static const GLfloat MaterialMagenta[] = {0.6, 0.2, 0.5, 1.0};
147 static const GLfloat MaterialWhite[]   = {0.7, 0.7, 0.7, 1.0};
148 static const GLfloat MaterialGray[]    = {0.5, 0.5, 0.5, 1.0};
149
150 static morph3dstruct *morph3d = (morph3dstruct *) NULL;
151
152 #define TRIANGLE(Edge, Amp, Divisions, Z, VS)                                                                    \
153 {                                                                                                                \
154   GLfloat   Xf,Yf,Xa,Yb=0.0,Xf2=0.0,Yf2=0.0,Yf_2=0.0,Yb2,Yb_2;                                                   \
155   GLfloat   Factor=0.0,Factor1,Factor2;                                                                          \
156   GLfloat   VertX,VertY,VertZ,NeiAX,NeiAY,NeiAZ,NeiBX,NeiBY,NeiBZ;                                               \
157   GLfloat   Ax,Ay;                                                                                               \
158   int       Ri,Ti;                                                                                               \
159   GLfloat   Vr=(Edge)*SQRT3/3;                                                                                   \
160   GLfloat   AmpVr2=(Amp)/sqr(Vr);                                                                                \
161   GLfloat   Zf=(Edge)*(Z);                                                                                       \
162                                                                                                                  \
163   Ax=(Edge)*(+0.5/(Divisions)), Ay=(Edge)*(-SQRT3/(2*Divisions));                                                \
164                                                                                                                  \
165   Yf=Vr+Ay; Yb=Yf+0.001;                                                                                         \
166   for (Ri=1; Ri<=(Divisions); Ri++) {                                                                            \
167     glBegin(GL_TRIANGLE_STRIP);                                                                                  \
168     Xf=(float)Ri*Ax; Xa=Xf+0.001;                                                                                \
169     Yf2=sqr(Yf); Yf_2=sqr(Yf-Ay);                                                                                \
170     Yb2=sqr(Yb); Yb_2=sqr(Yb-Ay);                                                                                \
171     for (Ti=0; Ti<Ri; Ti++) {                                                                                    \
172       Factor=1-(((Xf2=sqr(Xf))+Yf2)*AmpVr2);                                                                     \
173       Factor1=1-((sqr(Xa)+Yf2)*AmpVr2);                                                                          \
174       Factor2=1-((Xf2+Yb2)*AmpVr2);                                                                              \
175       VertX=Factor*Xf;        VertY=Factor*Yf;        VertZ=Factor*Zf;                                           \
176       NeiAX=Factor1*Xa-VertX; NeiAY=Factor1*Yf-VertY; NeiAZ=Factor1*Zf-VertZ;                                    \
177       NeiBX=Factor2*Xf-VertX; NeiBY=Factor2*Yb-VertY; NeiBZ=Factor2*Zf-VertZ;                                    \
178       glNormal3f(VectMul(NeiAX, NeiAY, NeiAZ, NeiBX, NeiBY, NeiBZ));                                             \
179       glVertex3f(VertX, VertY, VertZ);                                                                           \
180       mi->polygon_count++;                                                                                       \
181                                                                                                                  \
182       Xf-=Ax; Yf-=Ay; Xa-=Ax; Yb-=Ay;                                                                            \
183                                                                                                                  \
184       Factor=1-(((Xf2=sqr(Xf))+Yf_2)*AmpVr2);                                                                    \
185       Factor1=1-((sqr(Xa)+Yf_2)*AmpVr2);                                                                         \
186       Factor2=1-((Xf2+Yb_2)*AmpVr2);                                                                             \
187       VertX=Factor*Xf;        VertY=Factor*Yf;        VertZ=Factor*Zf;                                           \
188       NeiAX=Factor1*Xa-VertX; NeiAY=Factor1*Yf-VertY; NeiAZ=Factor1*Zf-VertZ;                                    \
189       NeiBX=Factor2*Xf-VertX; NeiBY=Factor2*Yb-VertY; NeiBZ=Factor2*Zf-VertZ;                                    \
190       glNormal3f(VectMul(NeiAX, NeiAY, NeiAZ, NeiBX, NeiBY, NeiBZ));                                             \
191       glVertex3f(VertX, VertY, VertZ);                                                                           \
192       mi->polygon_count++;                                                                                       \
193                                                                                                                  \
194       Xf-=Ax; Yf+=Ay; Xa-=Ax; Yb+=Ay;                                                                            \
195     }                                                                                                            \
196     Factor=1-(((Xf2=sqr(Xf))+(Yf2=sqr(Yf)))*AmpVr2);                                                             \
197     Factor1=1-((sqr(Xa)+Yf2)*AmpVr2);                                                                            \
198     Factor2=1-((Xf2+sqr(Yb))*AmpVr2);                                                                            \
199     VertX=Factor*Xf;        VertY=Factor*Yf;        VertZ=Factor*Zf;                                             \
200     NeiAX=Factor1*Xa-VertX; NeiAY=Factor1*Yf-VertY; NeiAZ=Factor1*Zf-VertZ;                                      \
201     NeiBX=Factor2*Xf-VertX; NeiBY=Factor2*Yb-VertY; NeiBZ=Factor2*Zf-VertZ;                                      \
202     glNormal3f(VectMul(NeiAX, NeiAY, NeiAZ, NeiBX, NeiBY, NeiBZ));                                               \
203     glVertex3f(VertX, VertY, VertZ);                                                                             \
204     Yf+=Ay; Yb+=Ay;                                                                                              \
205     glEnd();                                                                                                     \
206   }                                                                                                              \
207   VS=(Factor<0);                                                                                                 \
208 }
209
210 #define SQUARE(Edge, Amp, Divisions, Z, VS)                                                                      \
211 {                                                                                                                \
212   int       Xi,Yi;                                                                                               \
213   GLfloat   Xf,Yf,Y,Xf2,Yf2,Y2,Xa,Xa2,Yb;                                                                        \
214   GLfloat   Factor=0.0,Factor1,Factor2;                                                                          \
215   GLfloat   VertX,VertY,VertZ,NeiAX,NeiAY,NeiAZ,NeiBX,NeiBY,NeiBZ;                                               \
216   GLfloat   Zf=(Edge)*(Z);                                                                                       \
217   GLfloat   AmpVr2=(Amp)/sqr((Edge)*SQRT2/2);                                                                    \
218                                                                                                                  \
219   for (Yi=0; Yi<(Divisions); Yi++) {                                                                             \
220     Yf=-((Edge)/2.0) + ((float)Yi)/(Divisions)*(Edge);                                                           \
221     Yf2=sqr(Yf);                                                                                                 \
222     Y=Yf+1.0/(Divisions)*(Edge);                                                                                 \
223     Y2=sqr(Y);                                                                                                   \
224     glBegin(GL_QUAD_STRIP);                                                                                      \
225     for (Xi=0; Xi<=(Divisions); Xi++) {                                                                          \
226       Xf=-((Edge)/2.0) + ((float)Xi)/(Divisions)*(Edge);                                                         \
227       Xf2=sqr(Xf);                                                                                               \
228                                                                                                                  \
229       Xa=Xf+0.001; Yb=Y+0.001;                                                                                   \
230       Factor=1-((Xf2+Y2)*AmpVr2);                                                                                \
231       Factor1=1-(((Xa2=sqr(Xa))+Y2)*AmpVr2);                                                                     \
232       Factor2=1-((Xf2+sqr(Yb))*AmpVr2);                                                                          \
233       VertX=Factor*Xf;        VertY=Factor*Y;         VertZ=Factor*Zf;                                           \
234       NeiAX=Factor1*Xa-VertX; NeiAY=Factor1*Y-VertY;  NeiAZ=Factor1*Zf-VertZ;                                    \
235       NeiBX=Factor2*Xf-VertX; NeiBY=Factor2*Yb-VertY; NeiBZ=Factor2*Zf-VertZ;                                    \
236       glNormal3f(VectMul(NeiAX, NeiAY, NeiAZ, NeiBX, NeiBY, NeiBZ));                                             \
237       glVertex3f(VertX, VertY, VertZ);                                                                           \
238                                                                                                                  \
239       Yb=Yf+0.001;                                                                                               \
240       Factor=1-((Xf2+Yf2)*AmpVr2);                                                                               \
241       Factor1=1-((Xa2+Yf2)*AmpVr2);                                                                              \
242       Factor2=1-((Xf2+sqr(Yb))*AmpVr2);                                                                          \
243       VertX=Factor*Xf;        VertY=Factor*Yf;        VertZ=Factor*Zf;                                           \
244       NeiAX=Factor1*Xa-VertX; NeiAY=Factor1*Yf-VertY; NeiAZ=Factor1*Zf-VertZ;                                    \
245       NeiBX=Factor2*Xf-VertX; NeiBY=Factor2*Yb-VertY; NeiBZ=Factor2*Zf-VertZ;                                    \
246       glNormal3f(VectMul(NeiAX, NeiAY, NeiAZ, NeiBX, NeiBY, NeiBZ));                                             \
247       glVertex3f(VertX, VertY, VertZ);                                                                           \
248       mi->polygon_count++;                                                                                       \
249     }                                                                                                            \
250     glEnd();                                                                                                     \
251   }                                                                                                              \
252   VS=(Factor<0);                                                                                                 \
253 }
254
255 #define PENTAGON(Edge, Amp, Divisions, Z, VS)                                                                    \
256 {                                                                                                                \
257   int       Ri,Ti,Fi;                                                                                            \
258   GLfloat   Xf,Yf,Xa,Yb,Xf2,Yf2;                                                                                 \
259   GLfloat   Factor=0.0,Factor1,Factor2;                                                                          \
260   GLfloat   VertX,VertY,VertZ,NeiAX,NeiAY,NeiAZ,NeiBX,NeiBY,NeiBZ;                                               \
261   GLfloat   Zf=(Edge)*(Z);                                                                                       \
262   GLfloat   AmpVr2=(Amp)/sqr((Edge)*cossec36_2);                                                                 \
263                                                                                                                  \
264   GLfloat x[6],y[6];                                                                                             \
265                                                                                                                  \
266   for(Fi=0;Fi<6;Fi++) {                                                                                          \
267     x[Fi]=-cos( Fi*2*Pi/5 + Pi/10 )/(Divisions)*cossec36_2*(Edge);                                               \
268     y[Fi]=sin( Fi*2*Pi/5 + Pi/10 )/(Divisions)*cossec36_2*(Edge);                                                \
269   }                                                                                                              \
270                                                                                                                  \
271   for (Ri=1; Ri<=(Divisions); Ri++) {                                                                            \
272     for (Fi=0; Fi<5; Fi++) {                                                                                     \
273       glBegin(GL_TRIANGLE_STRIP);                                                                                \
274       for (Ti=0; Ti<Ri; Ti++) {                                                                                  \
275         Xf=(float)(Ri-Ti)*x[Fi] + (float)Ti*x[Fi+1];                                                             \
276         Yf=(float)(Ri-Ti)*y[Fi] + (float)Ti*y[Fi+1];                                                             \
277         Xa=Xf+0.001; Yb=Yf+0.001;                                                                                \
278         Factor=1-(((Xf2=sqr(Xf))+(Yf2=sqr(Yf)))*AmpVr2);                                                             \
279         Factor1=1-((sqr(Xa)+Yf2)*AmpVr2);                                                                            \
280         Factor2=1-((Xf2+sqr(Yb))*AmpVr2);                                                                            \
281         VertX=Factor*Xf;        VertY=Factor*Yf;        VertZ=Factor*Zf;                                         \
282         NeiAX=Factor1*Xa-VertX; NeiAY=Factor1*Yf-VertY; NeiAZ=Factor1*Zf-VertZ;                                  \
283         NeiBX=Factor2*Xf-VertX; NeiBY=Factor2*Yb-VertY; NeiBZ=Factor2*Zf-VertZ;                                  \
284         glNormal3f(VectMul(NeiAX, NeiAY, NeiAZ, NeiBX, NeiBY, NeiBZ));                                           \
285                 glVertex3f(VertX, VertY, VertZ);                                                                         \
286             mi->polygon_count++;                                                                                     \
287                                                                                                                  \
288         Xf-=x[Fi]; Yf-=y[Fi]; Xa-=x[Fi]; Yb-=y[Fi];                                                              \
289                                                                                                                  \
290                 Factor=1-(((Xf2=sqr(Xf))+(Yf2=sqr(Yf)))*AmpVr2);                                                         \
291                 Factor1=1-((sqr(Xa)+Yf2)*AmpVr2);                                                                        \
292                 Factor2=1-((Xf2+sqr(Yb))*AmpVr2);                                                                        \
293         VertX=Factor*Xf;        VertY=Factor*Yf;        VertZ=Factor*Zf;                                         \
294         NeiAX=Factor1*Xa-VertX; NeiAY=Factor1*Yf-VertY; NeiAZ=Factor1*Zf-VertZ;                                  \
295         NeiBX=Factor2*Xf-VertX; NeiBY=Factor2*Yb-VertY; NeiBZ=Factor2*Zf-VertZ;                                  \
296         glNormal3f(VectMul(NeiAX, NeiAY, NeiAZ, NeiBX, NeiBY, NeiBZ));                                           \
297                 glVertex3f(VertX, VertY, VertZ);                                                                         \
298             mi->polygon_count++;                                                                                     \
299                                                                                                                  \
300       }                                                                                                          \
301       Xf=(float)Ri*x[Fi+1];                                                                                      \
302       Yf=(float)Ri*y[Fi+1];                                                                                      \
303       Xa=Xf+0.001; Yb=Yf+0.001;                                                                                  \
304       Factor=1-(((Xf2=sqr(Xf))+(Yf2=sqr(Yf)))*AmpVr2);                                                           \
305       Factor1=1-((sqr(Xa)+Yf2)*AmpVr2);                                                                          \
306       Factor2=1-((Xf2+sqr(Yb))*AmpVr2);                                                                          \
307       VertX=Factor*Xf;        VertY=Factor*Yf;        VertZ=Factor*Zf;                                           \
308       NeiAX=Factor1*Xa-VertX; NeiAY=Factor1*Yf-VertY; NeiAZ=Factor1*Zf-VertZ;                                    \
309       NeiBX=Factor2*Xf-VertX; NeiBY=Factor2*Yb-VertY; NeiBZ=Factor2*Zf-VertZ;                                    \
310       glNormal3f(VectMul(NeiAX, NeiAY, NeiAZ, NeiBX, NeiBY, NeiBZ));                                             \
311       glVertex3f(VertX, VertY, VertZ);                                                                           \
312       glEnd();                                                                                                   \
313     }                                                                                                            \
314   }                                                                                                              \
315   VS=(Factor<0);                                                                                                     \
316 }
317
318 static void
319 draw_tetra(ModeInfo * mi)
320 {
321         morph3dstruct *mp = &morph3d[MI_SCREEN(mi)];
322
323         glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[0]);
324
325         TRIANGLE(2, mp->seno, mp->edgedivisions, 0.5 / SQRT6, mp->VisibleSpikes);
326
327         glPushMatrix();
328         glRotatef(180, 0, 0, 1);
329         glRotatef(-tetraangle, 1, 0, 0);
330         glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[1]);
331         TRIANGLE(2, mp->seno, mp->edgedivisions, 0.5 / SQRT6, mp->VisibleSpikes);
332         glPopMatrix();
333         glPushMatrix();
334         glRotatef(180, 0, 1, 0);
335         glRotatef(-180 + tetraangle, 0.5, SQRT3 / 2, 0);
336         glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[2]);
337         TRIANGLE(2, mp->seno, mp->edgedivisions, 0.5 / SQRT6, mp->VisibleSpikes);
338         glPopMatrix();
339         glRotatef(180, 0, 1, 0);
340         glRotatef(-180 + tetraangle, 0.5, -SQRT3 / 2, 0);
341         glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[3]);
342         TRIANGLE(2, mp->seno, mp->edgedivisions, 0.5 / SQRT6, mp->VisibleSpikes);
343 }
344
345 static void
346 draw_cube(ModeInfo * mi)
347 {
348         morph3dstruct *mp = &morph3d[MI_SCREEN(mi)];
349
350         glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[0]);
351
352         SQUARE(2, mp->seno, mp->edgedivisions, 0.5, mp->VisibleSpikes)
353
354         glRotatef(cubeangle, 1, 0, 0);
355         glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[1]);
356         SQUARE(2, mp->seno, mp->edgedivisions, 0.5, mp->VisibleSpikes)
357         glRotatef(cubeangle, 1, 0, 0);
358         glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[2]);
359         SQUARE(2, mp->seno, mp->edgedivisions, 0.5, mp->VisibleSpikes)
360         glRotatef(cubeangle, 1, 0, 0);
361         glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[3]);
362         SQUARE(2, mp->seno, mp->edgedivisions, 0.5, mp->VisibleSpikes)
363         glRotatef(cubeangle, 0, 1, 0);
364         glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[4]);
365         SQUARE(2, mp->seno, mp->edgedivisions, 0.5, mp->VisibleSpikes)
366         glRotatef(2 * cubeangle, 0, 1, 0);
367         glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[5]);
368         SQUARE(2, mp->seno, mp->edgedivisions, 0.5, mp->VisibleSpikes)
369 }
370
371 static void
372 draw_octa(ModeInfo * mi)
373 {
374         morph3dstruct *mp = &morph3d[MI_SCREEN(mi)];
375
376         glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[0]);
377         TRIANGLE(2, mp->seno, mp->edgedivisions, 1 / SQRT6, mp->VisibleSpikes);
378
379         glPushMatrix();
380         glRotatef(180, 0, 0, 1);
381         glRotatef(-180 + octaangle, 1, 0, 0);
382         glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[1]);
383         TRIANGLE(2, mp->seno, mp->edgedivisions, 1 / SQRT6, mp->VisibleSpikes);
384         glPopMatrix();
385         glPushMatrix();
386         glRotatef(180, 0, 1, 0);
387         glRotatef(-octaangle, 0.5, SQRT3 / 2, 0);
388         glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[2]);
389         TRIANGLE(2, mp->seno, mp->edgedivisions, 1 / SQRT6, mp->VisibleSpikes);
390         glPopMatrix();
391         glPushMatrix();
392         glRotatef(180, 0, 1, 0);
393         glRotatef(-octaangle, 0.5, -SQRT3 / 2, 0);
394         glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[3]);
395         TRIANGLE(2, mp->seno, mp->edgedivisions, 1 / SQRT6, mp->VisibleSpikes);
396         glPopMatrix();
397         glRotatef(180, 1, 0, 0);
398         glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[4]);
399         TRIANGLE(2, mp->seno, mp->edgedivisions, 1 / SQRT6, mp->VisibleSpikes);
400         glPushMatrix();
401         glRotatef(180, 0, 0, 1);
402         glRotatef(-180 + octaangle, 1, 0, 0);
403         glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[5]);
404         TRIANGLE(2, mp->seno, mp->edgedivisions, 1 / SQRT6, mp->VisibleSpikes);
405         glPopMatrix();
406         glPushMatrix();
407         glRotatef(180, 0, 1, 0);
408         glRotatef(-octaangle, 0.5, SQRT3 / 2, 0);
409         glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[6]);
410         TRIANGLE(2, mp->seno, mp->edgedivisions, 1 / SQRT6, mp->VisibleSpikes);
411         glPopMatrix();
412         glRotatef(180, 0, 1, 0);
413         glRotatef(-octaangle, 0.5, -SQRT3 / 2, 0);
414         glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[7]);
415         TRIANGLE(2, mp->seno, mp->edgedivisions, 1 / SQRT6, mp->VisibleSpikes);
416 }
417
418 static void
419 draw_dodeca(ModeInfo * mi)
420 {
421         morph3dstruct *mp = &morph3d[MI_SCREEN(mi)];
422
423 #define TAU ((SQRT5+1)/2)
424
425         glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[0]);
426
427         PENTAGON(1, mp->seno, mp->edgedivisions, sqr(TAU) * sqrt((TAU + 2) / 5) / 2, mp->VisibleSpikes);
428
429         glPushMatrix();
430         glRotatef(180, 0, 0, 1);
431         glPushMatrix();
432         glRotatef(-dodecaangle, 1, 0, 0);
433         glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[1]);
434         PENTAGON(1, mp->seno, mp->edgedivisions, sqr(TAU) * sqrt((TAU + 2) / 5) / 2, mp->VisibleSpikes);
435         glPopMatrix();
436         glPushMatrix();
437         glRotatef(-dodecaangle, cos72, sin72, 0);
438         glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[2]);
439         PENTAGON(1, mp->seno, mp->edgedivisions, sqr(TAU) * sqrt((TAU + 2) / 5) / 2, mp->VisibleSpikes);
440         glPopMatrix();
441         glPushMatrix();
442         glRotatef(-dodecaangle, cos72, -sin72, 0);
443         glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[3]);
444         PENTAGON(1, mp->seno, mp->edgedivisions, sqr(TAU) * sqrt((TAU + 2) / 5) / 2, mp->VisibleSpikes);
445         glPopMatrix();
446         glPushMatrix();
447         glRotatef(dodecaangle, cos36, -sin36, 0);
448         glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[4]);
449         PENTAGON(1, mp->seno, mp->edgedivisions, sqr(TAU) * sqrt((TAU + 2) / 5) / 2, mp->VisibleSpikes);
450         glPopMatrix();
451         glRotatef(dodecaangle, cos36, sin36, 0);
452         glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[5]);
453         PENTAGON(1, mp->seno, mp->edgedivisions, sqr(TAU) * sqrt((TAU + 2) / 5) / 2, mp->VisibleSpikes);
454         glPopMatrix();
455         glRotatef(180, 1, 0, 0);
456         glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[6]);
457         PENTAGON(1, mp->seno, mp->edgedivisions, sqr(TAU) * sqrt((TAU + 2) / 5) / 2, mp->VisibleSpikes);
458         glRotatef(180, 0, 0, 1);
459         glPushMatrix();
460         glRotatef(-dodecaangle, 1, 0, 0);
461         glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[7]);
462         PENTAGON(1, mp->seno, mp->edgedivisions, sqr(TAU) * sqrt((TAU + 2) / 5) / 2, mp->VisibleSpikes);
463         glPopMatrix();
464         glPushMatrix();
465         glRotatef(-dodecaangle, cos72, sin72, 0);
466         glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[8]);
467         PENTAGON(1, mp->seno, mp->edgedivisions, sqr(TAU) * sqrt((TAU + 2) / 5) / 2, mp->VisibleSpikes);
468         glPopMatrix();
469         glPushMatrix();
470         glRotatef(-dodecaangle, cos72, -sin72, 0);
471         glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[9]);
472         PENTAGON(1, mp->seno, mp->edgedivisions, sqr(TAU) * sqrt((TAU + 2) / 5) / 2, mp->VisibleSpikes);
473         glPopMatrix();
474         glPushMatrix();
475         glRotatef(dodecaangle, cos36, -sin36, 0);
476         glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[10]);
477         PENTAGON(1, mp->seno, mp->edgedivisions, sqr(TAU) * sqrt((TAU + 2) / 5) / 2, mp->VisibleSpikes);
478         glPopMatrix();
479         glRotatef(dodecaangle, cos36, sin36, 0);
480         glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[11]);
481         PENTAGON(1, mp->seno, mp->edgedivisions, sqr(TAU) * sqrt((TAU + 2) / 5) / 2, mp->VisibleSpikes);
482 }
483
484 static void
485 draw_icosa(ModeInfo * mi)
486 {
487         morph3dstruct *mp = &morph3d[MI_SCREEN(mi)];
488
489         glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[0]);
490
491         TRIANGLE(1.5, mp->seno, mp->edgedivisions, (3 * SQRT3 + SQRT15) / 12, mp->VisibleSpikes);
492
493         glPushMatrix();
494
495         glPushMatrix();
496         glRotatef(180, 0, 0, 1);
497         glRotatef(-icoangle, 1, 0, 0);
498         glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[1]);
499         TRIANGLE(1.5, mp->seno, mp->edgedivisions, (3 * SQRT3 + SQRT15) / 12, mp->VisibleSpikes);
500         glPushMatrix();
501         glRotatef(180, 0, 1, 0);
502         glRotatef(-180 + icoangle, 0.5, SQRT3 / 2, 0);
503         glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[2]);
504         TRIANGLE(1.5, mp->seno, mp->edgedivisions, (3 * SQRT3 + SQRT15) / 12, mp->VisibleSpikes);
505         glPopMatrix();
506         glRotatef(180, 0, 1, 0);
507         glRotatef(-180 + icoangle, 0.5, -SQRT3 / 2, 0);
508         glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[3]);
509         TRIANGLE(1.5, mp->seno, mp->edgedivisions, (3 * SQRT3 + SQRT15) / 12, mp->VisibleSpikes);
510         glPopMatrix();
511         glPushMatrix();
512         glRotatef(180, 0, 1, 0);
513         glRotatef(-180 + icoangle, 0.5, SQRT3 / 2, 0);
514         glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[4]);
515         TRIANGLE(1.5, mp->seno, mp->edgedivisions, (3 * SQRT3 + SQRT15) / 12, mp->VisibleSpikes);
516         glPushMatrix();
517         glRotatef(180, 0, 1, 0);
518         glRotatef(-180 + icoangle, 0.5, SQRT3 / 2, 0);
519         glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[5]);
520         TRIANGLE(1.5, mp->seno, mp->edgedivisions, (3 * SQRT3 + SQRT15) / 12, mp->VisibleSpikes);
521         glPopMatrix();
522         glRotatef(180, 0, 0, 1);
523         glRotatef(-icoangle, 1, 0, 0);
524         glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[6]);
525         TRIANGLE(1.5, mp->seno, mp->edgedivisions, (3 * SQRT3 + SQRT15) / 12, mp->VisibleSpikes);
526         glPopMatrix();
527         glRotatef(180, 0, 1, 0);
528         glRotatef(-180 + icoangle, 0.5, -SQRT3 / 2, 0);
529         glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[7]);
530         TRIANGLE(1.5, mp->seno, mp->edgedivisions, (3 * SQRT3 + SQRT15) / 12, mp->VisibleSpikes);
531         glPushMatrix();
532         glRotatef(180, 0, 1, 0);
533         glRotatef(-180 + icoangle, 0.5, -SQRT3 / 2, 0);
534         glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[8]);
535         TRIANGLE(1.5, mp->seno, mp->edgedivisions, (3 * SQRT3 + SQRT15) / 12, mp->VisibleSpikes);
536         glPopMatrix();
537         glRotatef(180, 0, 0, 1);
538         glRotatef(-icoangle, 1, 0, 0);
539         glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[9]);
540         TRIANGLE(1.5, mp->seno, mp->edgedivisions, (3 * SQRT3 + SQRT15) / 12, mp->VisibleSpikes);
541         glPopMatrix();
542         glRotatef(180, 1, 0, 0);
543         glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[10]);
544         TRIANGLE(1.5, mp->seno, mp->edgedivisions, (3 * SQRT3 + SQRT15) / 12, mp->VisibleSpikes);
545         glPushMatrix();
546         glRotatef(180, 0, 0, 1);
547         glRotatef(-icoangle, 1, 0, 0);
548         glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[11]);
549         TRIANGLE(1.5, mp->seno, mp->edgedivisions, (3 * SQRT3 + SQRT15) / 12, mp->VisibleSpikes);
550         glPushMatrix();
551         glRotatef(180, 0, 1, 0);
552         glRotatef(-180 + icoangle, 0.5, SQRT3 / 2, 0);
553         glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[12]);
554         TRIANGLE(1.5, mp->seno, mp->edgedivisions, (3 * SQRT3 + SQRT15) / 12, mp->VisibleSpikes);
555         glPopMatrix();
556         glRotatef(180, 0, 1, 0);
557         glRotatef(-180 + icoangle, 0.5, -SQRT3 / 2, 0);
558         glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[13]);
559         TRIANGLE(1.5, mp->seno, mp->edgedivisions, (3 * SQRT3 + SQRT15) / 12, mp->VisibleSpikes);
560         glPopMatrix();
561         glPushMatrix();
562         glRotatef(180, 0, 1, 0);
563         glRotatef(-180 + icoangle, 0.5, SQRT3 / 2, 0);
564         glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[14]);
565         TRIANGLE(1.5, mp->seno, mp->edgedivisions, (3 * SQRT3 + SQRT15) / 12, mp->VisibleSpikes);
566         glPushMatrix();
567         glRotatef(180, 0, 1, 0);
568         glRotatef(-180 + icoangle, 0.5, SQRT3 / 2, 0);
569         glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[15]);
570         TRIANGLE(1.5, mp->seno, mp->edgedivisions, (3 * SQRT3 + SQRT15) / 12, mp->VisibleSpikes);
571         glPopMatrix();
572         glRotatef(180, 0, 0, 1);
573         glRotatef(-icoangle, 1, 0, 0);
574         glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[16]);
575         TRIANGLE(1.5, mp->seno, mp->edgedivisions, (3 * SQRT3 + SQRT15) / 12, mp->VisibleSpikes);
576         glPopMatrix();
577         glRotatef(180, 0, 1, 0);
578         glRotatef(-180 + icoangle, 0.5, -SQRT3 / 2, 0);
579         glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[17]);
580         TRIANGLE(1.5, mp->seno, mp->edgedivisions, (3 * SQRT3 + SQRT15) / 12, mp->VisibleSpikes);
581         glPushMatrix();
582         glRotatef(180, 0, 1, 0);
583         glRotatef(-180 + icoangle, 0.5, -SQRT3 / 2, 0);
584         glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[18]);
585         TRIANGLE(1.5, mp->seno, mp->edgedivisions, (3 * SQRT3 + SQRT15) / 12, mp->VisibleSpikes);
586         glPopMatrix();
587         glRotatef(180, 0, 0, 1);
588         glRotatef(-icoangle, 1, 0, 0);
589         glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->MaterialColor[19]);
590         TRIANGLE(1.5, mp->seno, mp->edgedivisions, (3 * SQRT3 + SQRT15) / 12, mp->VisibleSpikes);
591 }
592
593 ENTRYPOINT void
594 reshape_morph3d(ModeInfo * mi, int width, int height)
595 {
596         morph3dstruct *mp = &morph3d[MI_SCREEN(mi)];
597
598         glViewport(0, 0, mp->WindW = (GLint) width, mp->WindH = (GLint) height);
599         glMatrixMode(GL_PROJECTION);
600         glLoadIdentity();
601         glFrustum(-1.0, 1.0, -1.0, 1.0, 5.0, 15.0);
602         glMatrixMode(GL_MODELVIEW);
603 }
604
605 static void
606 pinit(ModeInfo * mi)
607 {
608         morph3dstruct *mp = &morph3d[MI_SCREEN(mi)];
609
610         glClearDepth(1.0);
611         glColor3f(1.0, 1.0, 1.0);
612
613         glLightfv(GL_LIGHT0, GL_AMBIENT, ambient);
614         glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse);
615         glLightfv(GL_LIGHT0, GL_POSITION, position0);
616         glLightfv(GL_LIGHT1, GL_AMBIENT, ambient);
617         glLightfv(GL_LIGHT1, GL_DIFFUSE, diffuse);
618         glLightfv(GL_LIGHT1, GL_POSITION, position1);
619         glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient);
620         glLightModelfv(GL_LIGHT_MODEL_TWO_SIDE, lmodel_twoside);
621         glEnable(GL_LIGHTING);
622         glEnable(GL_LIGHT0);
623         glEnable(GL_LIGHT1);
624         glEnable(GL_DEPTH_TEST);
625         glEnable(GL_NORMALIZE);
626
627         glShadeModel(GL_SMOOTH);
628         glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, front_shininess);
629         glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, front_specular);
630
631         switch (mp->object) {
632                 case 2:
633                         mp->draw_object = draw_cube;
634                         mp->MaterialColor[0] = MaterialRed;
635                         mp->MaterialColor[1] = MaterialGreen;
636                         mp->MaterialColor[2] = MaterialCyan;
637                         mp->MaterialColor[3] = MaterialMagenta;
638                         mp->MaterialColor[4] = MaterialYellow;
639                         mp->MaterialColor[5] = MaterialBlue;
640                         mp->edgedivisions = cubedivisions;
641                         mp->Magnitude = 2.0;
642                         break;
643                 case 3:
644                         mp->draw_object = draw_octa;
645                         mp->MaterialColor[0] = MaterialRed;
646                         mp->MaterialColor[1] = MaterialGreen;
647                         mp->MaterialColor[2] = MaterialBlue;
648                         mp->MaterialColor[3] = MaterialWhite;
649                         mp->MaterialColor[4] = MaterialCyan;
650                         mp->MaterialColor[5] = MaterialMagenta;
651                         mp->MaterialColor[6] = MaterialGray;
652                         mp->MaterialColor[7] = MaterialYellow;
653                         mp->edgedivisions = octadivisions;
654                         mp->Magnitude = 2.5;
655                         break;
656                 case 4:
657                         mp->draw_object = draw_dodeca;
658                         mp->MaterialColor[0] = MaterialRed;
659                         mp->MaterialColor[1] = MaterialGreen;
660                         mp->MaterialColor[2] = MaterialCyan;
661                         mp->MaterialColor[3] = MaterialBlue;
662                         mp->MaterialColor[4] = MaterialMagenta;
663                         mp->MaterialColor[5] = MaterialYellow;
664                         mp->MaterialColor[6] = MaterialGreen;
665                         mp->MaterialColor[7] = MaterialCyan;
666                         mp->MaterialColor[8] = MaterialRed;
667                         mp->MaterialColor[9] = MaterialMagenta;
668                         mp->MaterialColor[10] = MaterialBlue;
669                         mp->MaterialColor[11] = MaterialYellow;
670                         mp->edgedivisions = dodecadivisions;
671                         mp->Magnitude = 2.0;
672                         break;
673                 case 5:
674                         mp->draw_object = draw_icosa;
675                         mp->MaterialColor[0] = MaterialRed;
676                         mp->MaterialColor[1] = MaterialGreen;
677                         mp->MaterialColor[2] = MaterialBlue;
678                         mp->MaterialColor[3] = MaterialCyan;
679                         mp->MaterialColor[4] = MaterialYellow;
680                         mp->MaterialColor[5] = MaterialMagenta;
681                         mp->MaterialColor[6] = MaterialRed;
682                         mp->MaterialColor[7] = MaterialGreen;
683                         mp->MaterialColor[8] = MaterialBlue;
684                         mp->MaterialColor[9] = MaterialWhite;
685                         mp->MaterialColor[10] = MaterialCyan;
686                         mp->MaterialColor[11] = MaterialYellow;
687                         mp->MaterialColor[12] = MaterialMagenta;
688                         mp->MaterialColor[13] = MaterialRed;
689                         mp->MaterialColor[14] = MaterialGreen;
690                         mp->MaterialColor[15] = MaterialBlue;
691                         mp->MaterialColor[16] = MaterialCyan;
692                         mp->MaterialColor[17] = MaterialYellow;
693                         mp->MaterialColor[18] = MaterialMagenta;
694                         mp->MaterialColor[19] = MaterialGray;
695                         mp->edgedivisions = icodivisions;
696                         mp->Magnitude = 2.5;
697                         break;
698                 default:
699                         mp->draw_object = draw_tetra;
700                         mp->MaterialColor[0] = MaterialRed;
701                         mp->MaterialColor[1] = MaterialGreen;
702                         mp->MaterialColor[2] = MaterialBlue;
703                         mp->MaterialColor[3] = MaterialWhite;
704                         mp->edgedivisions = tetradivisions;
705                         mp->Magnitude = 2.5;
706                         break;
707         }
708         if (MI_IS_MONO(mi)) {
709                 int         loop;
710
711                 for (loop = 0; loop < 20; loop++)
712                         mp->MaterialColor[loop] = MaterialGray;
713         }
714 }
715
716 ENTRYPOINT void
717 init_morph3d(ModeInfo * mi)
718 {
719         morph3dstruct *mp;
720
721         if (morph3d == NULL) {
722                 if ((morph3d = (morph3dstruct *) calloc(MI_NUM_SCREENS(mi),
723                                             sizeof (morph3dstruct))) == NULL)
724                         return;
725         }
726         mp = &morph3d[MI_SCREEN(mi)];
727         mp->step = NRAND(90);
728         mp->VisibleSpikes = 1;
729
730         if ((mp->glx_context = init_GL(mi)) != NULL) {
731
732                 reshape_morph3d(mi, MI_WIDTH(mi), MI_HEIGHT(mi));
733                 glDrawBuffer(GL_BACK);
734                 mp->object = MI_COUNT(mi);
735                 if (mp->object <= 0 || mp->object > 5)
736                         mp->object = NRAND(5) + 1;
737                 pinit(mi);
738         } else {
739                 MI_CLEARWINDOW(mi);
740         }
741 }
742
743 ENTRYPOINT void
744 draw_morph3d(ModeInfo * mi)
745 {
746         Display    *display = MI_DISPLAY(mi);
747         Window      window = MI_WINDOW(mi);
748         morph3dstruct *mp;
749
750         if (morph3d == NULL)
751                 return;
752         mp = &morph3d[MI_SCREEN(mi)];
753
754         MI_IS_DRAWN(mi) = True;
755
756         if (!mp->glx_context)
757                 return;
758
759     mi->polygon_count = 0;
760         glXMakeCurrent(display, window, *(mp->glx_context));
761
762         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
763
764         glPushMatrix();
765
766         glTranslatef(0.0, 0.0, -10.0);
767
768         if (!MI_IS_ICONIC(mi)) {
769                 glScalef(Scale4Window * mp->WindH / mp->WindW, Scale4Window, Scale4Window);
770                 glTranslatef(2.5 * mp->WindW / mp->WindH * sin(mp->step * 1.11), 2.5 * cos(mp->step * 1.25 * 1.11), 0);
771         } else {
772                 glScalef(Scale4Iconic * mp->WindH / mp->WindW, Scale4Iconic, Scale4Iconic);
773         }
774
775 # ifdef HAVE_MOBILE     /* Keep it the same relative size when rotated. */
776     {
777       GLfloat h = MI_HEIGHT(mi) / (GLfloat) MI_WIDTH(mi);
778       int o = (int) current_device_rotation();
779       if (o != 0 && o != 180 && o != -180)
780         glScalef (1/h, h, 1);
781     }
782 # endif
783
784         glRotatef(mp->step * 100, 1, 0, 0);
785         glRotatef(mp->step * 95, 0, 1, 0);
786         glRotatef(mp->step * 90, 0, 0, 1);
787
788         mp->seno = (sin(mp->step) + 1.0 / 3.0) * (4.0 / 5.0) * mp->Magnitude;
789
790         if (mp->VisibleSpikes) {
791 #ifdef DEBUG_CULL_FACE
792                 int         loop;
793
794                 for (loop = 0; loop < 20; loop++)
795                         mp->MaterialColor[loop] = MaterialGray;
796 #endif
797                 glDisable(GL_CULL_FACE);
798         } else {
799 #ifdef DEBUG_CULL_FACE
800                 int         loop;
801
802                 for (loop = 0; loop < 20; loop++)
803                         mp->MaterialColor[loop] = MaterialWhite;
804 #endif
805                 glEnable(GL_CULL_FACE);
806         }
807
808         mp->draw_object(mi);
809
810         glPopMatrix();
811
812         if (MI_IS_FPS(mi)) do_fps (mi);
813         glXSwapBuffers(display, window);
814
815         mp->step += 0.05;
816 }
817
818 #ifndef STANDALONE
819 ENTRYPOINT void
820 change_morph3d(ModeInfo * mi)
821 {
822         morph3dstruct *mp = &morph3d[MI_SCREEN(mi)];
823
824         if (!mp->glx_context)
825                 return;
826
827         mp->object = (mp->object) % 5 + 1;
828         pinit(mi);
829 }
830 #endif /* !STANDALONE */
831
832 ENTRYPOINT void
833 release_morph3d(ModeInfo * mi)
834 {
835         if (morph3d != NULL) {
836                 (void) free((void *) morph3d);
837                 morph3d = (morph3dstruct *) NULL;
838         }
839         FreeAllGL(mi);
840 }
841
842 #endif
843
844 XSCREENSAVER_MODULE ("Morph3D", morph3d)