1 /* -*- Mode: C; tab-width: 4 -*-
2 * escher.c - Shows some Escher like scenes
4 #if !defined( lint ) && !defined( SABER )
5 static const char sccsid[] = "@(#)escher.c 4.04 97/07/28 xlockmore";
10 /* Permission to use, copy, modify, and distribute this software and its
11 * documentation for any purpose and without fee is hereby granted,
12 * provided that the above copyright notice appear in all copies and that
13 * both that copyright notice and this permission notice appear in
14 * supporting documentation.
16 * This file is provided AS IS with no warranties of any kind. The author
17 * shall have no liability with respect to the infringement of copyrights,
18 * trade secrets or any patents by this file or any part thereof. In no
19 * event will the author be liable for any lost revenue or profits or
20 * other special, indirect and consequential damages.
22 * The RotateAroundU() routine was adapted from the book
23 * "Computer Graphics Principles and Practice
24 * Foley - vanDam - Feiner - Hughes
25 * Second Edition" Pag. 227, exercise 5.15.
27 * This mode shows some interesting scenes that are impossible OR very
28 * wierd to build in the real universe. Much of the scenes are inspirated
29 * on Mauritz Cornelis Escher's works which derivated the mode's name.
30 * M.C. Escher (1898-1972) was a dutch artist and many people prefer to
31 * say he was a mathematician.
33 * Thanks goes to Brian Paul for making it possible and inexpensive to use
36 * Since I'm not a native english speaker, my apologies for any gramatical
39 * My e-mail addresses are
42 * marcelo@venus.rdc.puc-rio.br
44 * Marcelo F. Vianna (Jun-01-1997)
47 * 08-Jun-97: New scene implemented: "Impossible Cage" based in a M.C. Escher's
48 * painting with the same name (quite similar). The first GL mode
49 * to use texture mapping.
50 * The "Impossible Cage" scene doesn't use DEPTH BUFFER, the
51 * wood planks are drawn consistently using GL_CULL_FACE, and
52 * the painter's algorithm is used to sort the planks.
54 * 07-Jun-97: Speed ups in Moebius Strip using GL_CULL_FACE.
56 * 03-Jun-97: Initial Release (Only one scene: "Moebius Strip")
57 * The Moebious Strip scene was inspirated in a M.C. Escher's
58 * painting named Moebius Strip II in wich ants walk across a
59 * Moebius Strip path, sometimes meeting each other and sometimes
60 * being in "opposite faces" (note that the moebius strip has
61 * only one face and one edge).
67 * Texture mapping is only available on RGBA contexts, Mono and color index
68 * visuals DO NOT support texture mapping in OpenGL.
70 * BUT Mesa do implements RGBA contexts in pseudo color visuals, so texture
71 * mapping shuld work on PseudoColor, DirectColor, TrueColor using Mesa. Mono
72 * is not officially supported for both OpenGL and Mesa, but seems to not crash
75 * In real OpenGL, PseudoColor DO NOT support texture map (as far as I know).
78 #include <X11/Intrinsic.h>
81 # define PROGCLASS "Escher"
82 # define HACK_INIT init_escher
83 # define HACK_DRAW draw_escher
84 # define escher_opts xlockmore_opts
85 # define DEFAULTS "*count: 0 \n" \
88 "*wireframe: False \n"
89 # include "xlockmore.h" /* from the xscreensaver distribution */
90 #else /* !STANDALONE */
91 # include "xlock.h" /* from the xlockmore distribution */
92 #endif /* !STANDALONE */
99 #include "e_textures.h"
101 #define DEF_SOLIDMOEBIUS "False"
102 #define DEF_NOANTS "False"
104 static int solidmoebius;
107 static XrmOptionDescRec opts[] =
109 {"-solidmoebius", ".escher.solidmoebius", XrmoptionNoArg, (caddr_t) "on"},
110 {"+solidmoebius", ".escher.solidmoebius", XrmoptionNoArg, (caddr_t) "off"},
111 {"-noants", ".escher.noants", XrmoptionNoArg, (caddr_t) "on"},
112 {"+noants", ".escher.noants", XrmoptionNoArg, (caddr_t) "off"}
114 static argtype vars[] =
116 {(caddr_t *) & solidmoebius, "solidmoebius", "Solidmoebius", DEF_SOLIDMOEBIUS, t_Bool},
117 {(caddr_t *) & noants, "noants", "Noants", DEF_NOANTS, t_Bool}
119 static OptionStruct desc[] =
121 {"-/+solidmoebius", "select between a SOLID or a NET Moebius Strip"},
122 {"-/+noants", "turn on/off walking ants"}
125 ModeSpecOpt escher_opts =
126 {4, opts, 2, vars, desc};
128 #define Scale4Window 0.3
129 #define Scale4Iconic 0.4
131 #define sqr(A) ((A)*(A))
137 /*************************************************************************/
142 GLfloat ant_position;
144 int AreObjectsDefined[3];
145 GLXContext glx_context;
148 static float front_shininess[] =
150 static float front_specular[] =
151 {0.7, 0.7, 0.7, 1.0};
152 static float ambient[] =
153 {0.0, 0.0, 0.0, 1.0};
154 static float diffuse[] =
155 {1.0, 1.0, 1.0, 1.0};
156 static float position0[] =
157 {1.0, 1.0, 1.0, 0.0};
158 static float position1[] =
159 {-1.0, -1.0, 1.0, 0.0};
160 static float lmodel_ambient[] =
161 {0.5, 0.5, 0.5, 1.0};
162 static float lmodel_twoside[] =
165 static float MaterialRed[] =
166 {0.7, 0.0, 0.0, 1.0};
167 static float MaterialGreen[] =
168 {0.1, 0.5, 0.2, 1.0};
169 static float MaterialBlue[] =
170 {0.0, 0.0, 0.7, 1.0};
171 static float MaterialCyan[] =
172 {0.2, 0.5, 0.7, 1.0};
173 static float MaterialYellow[] =
174 {0.7, 0.7, 0.0, 1.0};
175 static float MaterialMagenta[] =
176 {0.6, 0.2, 0.5, 1.0};
177 static float MaterialWhite[] =
178 {0.7, 0.7, 0.7, 1.0};
179 static float MaterialGray[] =
180 {0.2, 0.2, 0.2, 1.0};
182 static escherstruct *escher = NULL;
183 static GLuint objects;
187 #define ObjMoebiusStrip 0
189 #define ObjWoodPlank 2
191 #define PlankWidth 3.0
192 #define PlankHeight 0.35
193 #define PlankThickness 0.15
196 mySphere(float radius)
198 GLUquadricObj *quadObj;
200 quadObj = gluNewQuadric();
201 gluQuadricDrawStyle(quadObj, (GLenum) GLU_FILL);
202 gluSphere(quadObj, radius, 16, 16);
203 gluDeleteQuadric(quadObj);
209 GLUquadricObj *quadObj;
211 quadObj = gluNewQuadric();
212 gluQuadricDrawStyle(quadObj, (GLenum) GLU_FILL);
213 gluCylinder(quadObj, radius, 0, radius * 3, 8, 1);
214 gluDeleteQuadric(quadObj);
218 draw_escher_ant(escherstruct * ep, float *Material)
220 static float ant_step = 0;
221 float cos1 = cos(ant_step);
222 float cos2 = cos(ant_step + 2 * Pi / 3);
223 float cos3 = cos(ant_step + 4 * Pi / 3);
224 float sin1 = sin(ant_step);
225 float sin2 = sin(ant_step + 2 * Pi / 3);
226 float sin3 = sin(ant_step + 4 * Pi / 3);
228 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, Material);
229 if (!ep->AreObjectsDefined[ObjAntBody]) {
230 glNewList(objects + ObjAntBody, GL_COMPILE_AND_EXECUTE);
231 glEnable(GL_CULL_FACE);
235 glScalef(1, 1 / 1.3, 1);
236 glTranslatef(0.00, 0.30, 0.00);
239 glTranslatef(-0.05, 0.17, 0.05);
240 glRotatef(-90, 1, 0, 0);
241 glRotatef(-25, 0, 1, 0);
243 glTranslatef(0.00, 0.10, 0.00);
245 glRotatef(25, 0, 1, 0);
246 glRotatef(90, 1, 0, 0);
249 glTranslatef(0.15, -0.65, 0.05);
251 glScalef(1, 1 / 1.3, 1);
253 glDisable(GL_CULL_FACE);
255 ep->AreObjectsDefined[ObjAntBody] = 1;
257 (void) printf("Ant drawn SLOWLY\n");
260 glCallList(objects + ObjAntBody);
262 (void) printf("Ant drawn quickly\n");
266 glDisable(GL_LIGHTING);
269 glColor3fv(Material);
270 glVertex3f(0.00, 0.30, 0.00);
271 glColor3fv(MaterialGray);
272 glVertex3f(0.40, 0.70, 0.40);
273 glColor3fv(Material);
274 glVertex3f(0.00, 0.30, 0.00);
275 glColor3fv(MaterialGray);
276 glVertex3f(0.40, 0.70, -0.40);
279 glColor3fv(MaterialRed);
280 glVertex3f(0.40, 0.70, 0.40);
281 glVertex3f(0.40, 0.70, -0.40);
285 glBegin(GL_LINE_STRIP);
286 glColor3fv(Material);
287 glVertex3f(0.00, 0.05, 0.18);
288 glVertex3f(0.35 + 0.05 * cos1, 0.15, 0.25);
289 glColor3fv(MaterialGray);
290 glVertex3f(-0.20 + 0.05 * cos1, 0.25 + 0.1 * sin1, 0.45);
293 /* LEFT-CENTER ARM */
294 glBegin(GL_LINE_STRIP);
295 glColor3fv(Material);
296 glVertex3f(0.00, 0.00, 0.18);
297 glVertex3f(0.35 + 0.05 * cos2, 0.00, 0.25);
298 glColor3fv(MaterialGray);
299 glVertex3f(-0.20 + 0.05 * cos2, 0.00 + 0.1 * sin2, 0.45);
303 glBegin(GL_LINE_STRIP);
304 glColor3fv(Material);
305 glVertex3f(0.00, -0.05, 0.18);
306 glVertex3f(0.35 + 0.05 * cos3, -0.15, 0.25);
307 glColor3fv(MaterialGray);
308 glVertex3f(-0.20 + 0.05 * cos3, -0.25 + 0.1 * sin3, 0.45);
311 /* RIGHT-FRONT ARM */
312 glBegin(GL_LINE_STRIP);
313 glColor3fv(Material);
314 glVertex3f(0.00, 0.05, -0.18);
315 glVertex3f(0.35 - 0.05 * sin1, 0.15, -0.25);
316 glColor3fv(MaterialGray);
317 glVertex3f(-0.20 - 0.05 * sin1, 0.25 + 0.1 * cos1, -0.45);
320 /* RIGHT-CENTER ARM */
321 glBegin(GL_LINE_STRIP);
322 glColor3fv(Material);
323 glVertex3f(0.00, 0.00, -0.18);
324 glVertex3f(0.35 - 0.05 * sin2, 0.00, -0.25);
325 glColor3fv(MaterialGray);
326 glVertex3f(-0.20 - 0.05 * sin2, 0.00 + 0.1 * cos2, -0.45);
330 glBegin(GL_LINE_STRIP);
331 glColor3fv(Material);
332 glVertex3f(0.00, -0.05, -0.18);
333 glVertex3f(0.35 - 0.05 * sin3, -0.15, -0.25);
334 glColor3fv(MaterialGray);
335 glVertex3f(-0.20 - 0.05 * sin3, -0.25 + 0.1 * cos3, -0.45);
339 glColor3fv(MaterialMagenta);
340 glVertex3f(-0.20 + 0.05 * cos1, 0.25 + 0.1 * sin1, 0.45);
341 glVertex3f(-0.20 + 0.05 * cos2, 0.00 + 0.1 * sin2, 0.45);
342 glVertex3f(-0.20 + 0.05 * cos3, -0.25 + 0.1 * sin3, 0.45);
343 glVertex3f(-0.20 - 0.05 * sin1, 0.25 + 0.1 * cos1, -0.45);
344 glVertex3f(-0.20 - 0.05 * sin2, 0.00 + 0.1 * cos2, -0.45);
345 glVertex3f(-0.20 - 0.05 * sin3, -0.25 + 0.1 * cos3, -0.45);
348 glEnable(GL_LIGHTING);
354 RotateAaroundU(float Ax, float Ay, float Az,
355 float Ux, float Uy, float Uz,
356 float *Cx, float *Cy, float *Cz,
359 float cosO = cos(Theta);
360 float sinO = sin(Theta);
361 float one_cosO = 1 - cosO;
365 float UxUy = Ux * Uy;
366 float UxUz = Ux * Uz;
367 float UyUz = Uy * Uz;
369 *Cx = (Ux2 + cosO * (1 - Ux2)) * Ax + (UxUy * one_cosO - Uz * sinO) * Ay + (UxUz * one_cosO + Uy * sinO) * Az;
370 *Cy = (UxUy * one_cosO + Uz * sinO) * Ax + (Uy2 + cosO * (1 - Uy2)) * Ay + (UyUz * one_cosO - Ux * sinO) * Az;
371 *Cz = (UxUz * one_cosO - Uy * sinO) * Ax + (UyUz * one_cosO + Ux * sinO) * Ay + (Uz2 + cosO * (1 - Uz2)) * Az;
374 #define MoebiusDivisions 40
375 #define MoebiusTransversals 4
377 draw_moebius(ModeInfo * mi)
381 escherstruct *ep = &escher[MI_SCREEN(mi)];
386 if (!ep->AreObjectsDefined[ObjMoebiusStrip]) {
387 glNewList(objects + ObjMoebiusStrip, GL_COMPILE_AND_EXECUTE);
390 glBegin(GL_QUAD_STRIP);
393 while (i < (MoebiusDivisions * 2 + 1)) {
400 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialRed);
402 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialGray);
404 RotateAaroundU(cPhi, sPhi, 0, -sPhi, cPhi, 0, &Cx, &Cy, &Cz, Theta);
405 glNormal3f(Cx, Cy, Cz);
406 RotateAaroundU(0, 0, 1, -sPhi, cPhi, 0, &Cx, &Cy, &Cz, Theta);
407 glVertex3f(cPhi * 3 + Cx, sPhi * 3 + Cy, +Cz);
408 glVertex3f(cPhi * 3 - Cx, sPhi * 3 - Cy, -Cz);
410 Phi += Pi / MoebiusDivisions;
414 for (j = -MoebiusTransversals; j < MoebiusTransversals; j++) {
415 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
416 glBegin(GL_QUAD_STRIP);
419 while (i < (MoebiusDivisions * 2 + 1)) {
424 RotateAaroundU(cPhi, sPhi, 0, -sPhi, cPhi, 0, &Cx, &Cy, &Cz, Theta);
425 glNormal3f(Cx, Cy, Cz);
426 RotateAaroundU(0, 0, 1, -sPhi, cPhi, 0, &Cx, &Cy, &Cz, Theta);
428 if (j == MoebiusTransversals)
429 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialWhite);
431 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialRed);
433 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialGray);
434 glVertex3f(cPhi * 3 + Cx / MoebiusTransversals * j, sPhi * 3 + Cy / MoebiusTransversals * j, +Cz / MoebiusTransversals * j);
436 if (j == -MoebiusTransversals)
437 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialWhite);
439 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialRed);
441 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialGray);
442 glVertex3f(cPhi * 3 + Cx / MoebiusTransversals * j, sPhi * 3 + Cy / MoebiusTransversals * j, +Cz / MoebiusTransversals * j);
444 Phi += Pi / MoebiusDivisions;
449 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
453 ep->AreObjectsDefined[ObjMoebiusStrip] = 1;
455 (void) printf("Strip drawn SLOWLY\n");
458 glCallList(objects + ObjMoebiusStrip);
460 (void) printf("Strip drawn quickly\n");
467 glRotatef(ep->ant_position + 180, 0, 0, 1);
468 glTranslatef(3, 0, 0);
469 glRotatef(ep->ant_position / 2 + 90, 0, 1, 0);
470 glTranslatef(0.28, 0, -0.45);
471 draw_escher_ant(ep, MaterialYellow);
474 /* DRAW YELLOW ANT */
476 glRotatef(ep->ant_position, 0, 0, 1);
477 glTranslatef(3, 0, 0);
478 glRotatef(ep->ant_position / 2, 0, 1, 0);
479 glTranslatef(0.28, 0, -0.45);
480 draw_escher_ant(ep, MaterialBlue);
485 glRotatef(-ep->ant_position, 0, 0, 1);
486 glTranslatef(3, 0, 0);
487 glRotatef(-ep->ant_position / 2, 0, 1, 0);
488 glTranslatef(0.28, 0, 0.45);
489 glRotatef(180, 1, 0, 0);
490 draw_escher_ant(ep, MaterialGreen);
495 glRotatef(-ep->ant_position + 180, 0, 0, 1);
496 glTranslatef(3, 0, 0);
497 glRotatef(-ep->ant_position / 2 + 90, 0, 1, 0);
498 glTranslatef(0.28, 0, 0.45);
499 glRotatef(180, 1, 0, 0);
500 draw_escher_ant(ep, MaterialCyan);
503 ep->ant_position += 1;
505 #undef MoebiusDivisions
506 #undef MoebiusTransversals
509 draw_woodplank(escherstruct * ep)
511 if (!ep->AreObjectsDefined[ObjWoodPlank]) {
512 glNewList(objects + ObjWoodPlank, GL_COMPILE_AND_EXECUTE);
516 glVertex3f(-PlankWidth, -PlankHeight, PlankThickness);
518 glVertex3f(PlankWidth, -PlankHeight, PlankThickness);
520 glVertex3f(PlankWidth, PlankHeight, PlankThickness);
522 glVertex3f(-PlankWidth, PlankHeight, PlankThickness);
523 glNormal3f(0, 0, -1);
525 glVertex3f(-PlankWidth, PlankHeight, -PlankThickness);
527 glVertex3f(PlankWidth, PlankHeight, -PlankThickness);
529 glVertex3f(PlankWidth, -PlankHeight, -PlankThickness);
531 glVertex3f(-PlankWidth, -PlankHeight, -PlankThickness);
534 glVertex3f(-PlankWidth, PlankHeight, PlankThickness);
536 glVertex3f(PlankWidth, PlankHeight, PlankThickness);
538 glVertex3f(PlankWidth, PlankHeight, -PlankThickness);
540 glVertex3f(-PlankWidth, PlankHeight, -PlankThickness);
541 glNormal3f(0, -1, 0);
543 glVertex3f(-PlankWidth, -PlankHeight, -PlankThickness);
545 glVertex3f(PlankWidth, -PlankHeight, -PlankThickness);
547 glVertex3f(PlankWidth, -PlankHeight, PlankThickness);
549 glVertex3f(-PlankWidth, -PlankHeight, PlankThickness);
552 glVertex3f(PlankWidth, -PlankHeight, PlankThickness);
554 glVertex3f(PlankWidth, -PlankHeight, -PlankThickness);
556 glVertex3f(PlankWidth, PlankHeight, -PlankThickness);
558 glVertex3f(PlankWidth, PlankHeight, PlankThickness);
559 glNormal3f(-1, 0, 0);
561 glVertex3f(-PlankWidth, PlankHeight, PlankThickness);
563 glVertex3f(-PlankWidth, PlankHeight, -PlankThickness);
565 glVertex3f(-PlankWidth, -PlankHeight, -PlankThickness);
567 glVertex3f(-PlankWidth, -PlankHeight, PlankThickness);
570 ep->AreObjectsDefined[ObjWoodPlank] = 1;
572 (void) printf("WoodPlank drawn SLOWLY\n");
575 glCallList(objects + ObjWoodPlank);
577 (void) printf("WoodPlank drawn quickly\n");
583 draw_impossiblecage(escherstruct * ep)
586 glRotatef(90, 0, 1, 0);
587 glTranslatef(0.0, PlankHeight - PlankWidth, -PlankThickness - PlankWidth);
591 glRotatef(90, 0, 0, 1);
592 glTranslatef(0.0, PlankHeight - PlankWidth, PlankWidth - PlankThickness);
596 glRotatef(90, 0, 1, 0);
597 glTranslatef(0.0, PlankWidth - PlankHeight, -PlankThickness - PlankWidth);
601 glTranslatef(0.0, PlankWidth - PlankHeight, 3 * PlankThickness - PlankWidth);
605 glRotatef(90, 0, 0, 1);
606 glTranslatef(0.0, PlankWidth - PlankHeight, PlankWidth - PlankThickness);
610 glTranslatef(0.0, PlankWidth - PlankHeight, PlankWidth - 3 * PlankThickness);
614 glTranslatef(0.0, PlankHeight - PlankWidth, 3 * PlankThickness - PlankWidth);
618 glRotatef(90, 0, 0, 1);
619 glTranslatef(0.0, PlankHeight - PlankWidth, PlankThickness - PlankWidth);
623 glTranslatef(0.0, PlankHeight - PlankWidth, PlankWidth - 3 * PlankThickness);
627 glRotatef(90, 0, 1, 0);
628 glTranslatef(0.0, PlankHeight - PlankWidth, PlankWidth + PlankThickness);
632 glRotatef(90, 0, 0, 1);
633 glTranslatef(0.0, PlankWidth - PlankHeight, PlankThickness - PlankWidth);
637 glRotatef(90, 0, 1, 0);
638 glTranslatef(0.0, PlankWidth - PlankHeight, PlankWidth + PlankThickness);
644 draw_escher(ModeInfo * mi)
646 escherstruct *ep = &escher[MI_SCREEN(mi)];
648 Display *display = MI_DISPLAY(mi);
649 Window window = MI_WINDOW(mi);
651 glXMakeCurrent(display, window, ep->glx_context);
653 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
657 glTranslatef(0.0, 0.0, -10.0);
659 if (!MI_WIN_IS_ICONIC(mi)) {
660 glScalef(Scale4Window * ep->WindH / ep->WindW, Scale4Window, Scale4Window);
662 glScalef(Scale4Iconic * ep->WindH / ep->WindW, Scale4Iconic, Scale4Iconic);
668 glRotatef(ep->step * 100, 1, 0, 0);
669 glRotatef(ep->step * 95, 0, 1, 0);
670 glRotatef(ep->step * 90, 0, 0, 1);
673 case 2: /* 196 - 213 */
674 glRotatef(ep->step * 100, 0, 0, 1);
675 glRotatef(25 + cos(ep->step * 5) * 6, 1, 0, 0);
676 glRotatef(204.5 - sin(ep->step * 5) * 8, 0, 1, 0);
677 draw_impossiblecage(ep);
685 glXSwapBuffers(display, window);
691 reshape(ModeInfo * mi, int width, int height)
693 escherstruct *ep = &escher[MI_SCREEN(mi)];
695 glViewport(0, 0, ep->WindW = (GLint) width, ep->WindH = (GLint) height);
696 glMatrixMode(GL_PROJECTION);
698 glFrustum(-1.0, 1.0, -1.0, 1.0, 5.0, 15.0);
699 glMatrixMode(GL_MODELVIEW);
703 } else if (width >= 512) {
710 ep->AreObjectsDefined[ObjMoebiusStrip] = 0;
711 ep->AreObjectsDefined[ObjAntBody] = 0;
712 ep->AreObjectsDefined[ObjWoodPlank] = 0;
718 escherstruct *ep = &escher[MI_SCREEN(mi)];
721 glClearColor(0.0, 0.0, 0.0, 1.0);
723 glLightfv(GL_LIGHT0, GL_AMBIENT, ambient);
724 glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse);
725 glLightfv(GL_LIGHT0, GL_POSITION, position0);
726 glLightfv(GL_LIGHT1, GL_AMBIENT, ambient);
727 glLightfv(GL_LIGHT1, GL_DIFFUSE, diffuse);
728 glLightfv(GL_LIGHT1, GL_POSITION, position1);
729 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient);
730 glLightModelfv(GL_LIGHT_MODEL_TWO_SIDE, lmodel_twoside);
731 glEnable(GL_LIGHTING);
734 glEnable(GL_NORMALIZE);
740 glShadeModel(GL_SMOOTH);
741 glEnable(GL_DEPTH_TEST);
742 glDisable(GL_TEXTURE_2D);
743 glDisable(GL_CULL_FACE);
746 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialWhite);
747 glShadeModel(GL_FLAT);
748 glDisable(GL_DEPTH_TEST);
749 glEnable(GL_TEXTURE_2D);
750 glEnable(GL_CULL_FACE);
754 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
755 gluBuild2DMipmaps(GL_TEXTURE_2D, 3, WoodTextureWidth, WoodTextureHeight,
756 GL_RGB, GL_UNSIGNED_BYTE, WoodTextureData);
757 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
758 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
759 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
760 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
761 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
763 glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, front_shininess);
764 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, front_specular);
768 init_escher(ModeInfo * mi)
770 int screen = MI_SCREEN(mi);
773 if (escher == NULL) {
774 if ((escher = (escherstruct *) calloc(MI_NUM_SCREENS(mi),
775 sizeof (escherstruct))) == NULL)
778 ep = &escher[screen];
779 ep->step = NRAND(90);
780 ep->ant_position = NRAND(90);
782 ep->glx_context = init_GL(mi);
784 reshape(mi, MI_WIN_WIDTH(mi), MI_WIN_HEIGHT(mi));
785 ep->scene = MI_BATCHCOUNT(mi);
786 if (ep->scene <= 0 || ep->scene > NUM_SCENES)
787 ep->scene = NRAND(NUM_SCENES) + 1;
788 glDrawBuffer(GL_BACK);
789 objects = glGenLists(3);
795 change_escher(ModeInfo * mi)
797 escherstruct *ep = &escher[MI_SCREEN(mi)];
799 ep->scene = (ep->scene) % NUM_SCENES + 1;
800 glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), ep->glx_context);
805 release_escher(ModeInfo * mi)
807 if (escher != NULL) {
808 (void) free((void *) escher);
811 glDeleteLists(objects, 3);