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