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