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