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