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