1 /* -*- Mode: C; tab-width: 4 -*- */
2 /* moebius --- Moebius Strip II, an Escher-like GL scene with ants. */
4 #if !defined( lint ) && !defined( SABER )
5 static const char sccsid[] = "@(#)moebius.c 4.08 97/01/04 xlockmore";
12 * Permission to use, copy, modify, and distribute this software and its
13 * documentation for any purpose and without fee is hereby granted,
14 * provided that the above copyright notice appear in all copies and that
15 * both that copyright notice and this permission notice appear in
16 * supporting documentation.
18 * This file is provided AS IS with no warranties of any kind. The author
19 * shall have no liability with respect to the infringement of copyrights,
20 * trade secrets or any patents by this file or any part thereof. In no
21 * event will the author be liable for any lost revenue or profits or
22 * other special, indirect and consequential damages.
24 * The RotateAroundU() routine was adapted from the book
25 * "Computer Graphics Principles and Practice
26 * Foley - vanDam - Feiner - Hughes
27 * Second Edition" Pag. 227, exercise 5.15.
29 * This mode shows some interesting scenes that are impossible OR very
30 * wierd to build in the real universe. Much of the scenes are inspirated
31 * on Mauritz Cornelis Escher's works which derivated the mode's name.
32 * M.C. Escher (1898-1972) was a dutch artist and many people prefer to
33 * say he was a mathematician.
35 * Thanks goes to Brian Paul for making it possible and inexpensive to use
38 * Since I'm not a native English speaker, my apologies for any grammatical
41 * My e-mail address is
44 * Marcelo F. Vianna (Jun-01-1997)
47 * 01-Jan-98: Mode separated from escher and renamed
48 * 08-Jun-97: New scene implemented: "Impossible Cage" based in a M.C. Escher's
49 * painting with the same name (quite similar). The first GL mode
50 * to use texture mapping.
51 * The "Impossible Cage" scene doesn't use DEPTH BUFFER, the
52 * wood planks are drawn consistently using GL_CULL_FACE, and
53 * the painter's algorithm is used to sort the planks.
55 * 07-Jun-97: Speed ups in Moebius Strip using GL_CULL_FACE.
57 * 03-Jun-97: Initial Release (Only one scene: "Moebius Strip")
58 * The Moebius Strip scene was inspirated in a M.C. Escher's
59 * painting named Moebius Strip II in wich ants walk across a
60 * Moebius Strip path, sometimes meeting each other and sometimes
61 * being in "opposite faces" (note that the moebius strip has
62 * only one face and one edge).
68 * Texture mapping is only available on RGBA contexts, Mono and color index
69 * visuals DO NOT support texture mapping in OpenGL.
71 * BUT Mesa do implements RGBA contexts in pseudo color visuals, so texture
72 * mapping shuld work on PseudoColor, DirectColor, TrueColor using Mesa. Mono
73 * is not officially supported for both OpenGL and Mesa, but seems to not crash
76 * In real OpenGL, PseudoColor DO NOT support texture map (as far as I know).
79 #include <X11/Intrinsic.h>
82 # define PROGCLASS "Moebius"
83 # define HACK_INIT init_moebius
84 # define HACK_DRAW draw_moebius
85 # define HACK_RESHAPE reshape_moebius
86 # define moebius_opts xlockmore_opts
87 # define DEFAULTS "*cycles: 1 \n" \
89 "*showFPS: False \n" \
90 "*wireframe: False \n"
91 # include "xlockmore.h" /* from the xscreensaver distribution */
92 #else /* !STANDALONE */
93 # include "xlock.h" /* from the xlockmore distribution */
95 #endif /* !STANDALONE */
101 #include "e_textures.h"
103 #define DEF_SOLIDMOEBIUS "False"
104 #define DEF_NOANTS "False"
106 static int solidmoebius;
109 static XrmOptionDescRec opts[] =
111 {"-solidmoebius", ".moebius.solidmoebius", XrmoptionNoArg, (caddr_t) "on"},
112 {"+solidmoebius", ".moebius.solidmoebius", XrmoptionNoArg, (caddr_t) "off"},
113 {"-noants", ".moebius.noants", XrmoptionNoArg, (caddr_t) "on"},
114 {"+noants", ".moebius.noants", XrmoptionNoArg, (caddr_t) "off"}
116 static argtype vars[] =
118 {(caddr_t *) & solidmoebius, "solidmoebius", "Solidmoebius", DEF_SOLIDMOEBIUS, t_Bool},
119 {(caddr_t *) & noants, "noants", "Noants", DEF_NOANTS, t_Bool}
121 static OptionStruct desc[] =
123 {"-/+solidmoebius", "select between a SOLID or a NET Moebius Strip"},
124 {"-/+noants", "turn on/off walking ants"}
127 ModeSpecOpt moebius_opts =
128 {sizeof opts / sizeof opts[0], opts, sizeof vars / sizeof vars[0], vars, desc};
131 ModStruct moebius_description =
132 {"moebius", "init_moebius", "draw_moebius", "release_moebius",
133 "draw_moebius", "change_moebius", NULL, &moebius_opts,
134 1000, 1, 1, 1, 4, 1.0, "",
135 "Shows Moebius Strip II, an Escher-like GL scene with ants", 0, NULL};
139 #define Scale4Window 0.3
140 #define Scale4Iconic 0.4
142 #define sqr(A) ((A)*(A))
148 /*************************************************************************/
153 GLfloat ant_position;
154 int AreObjectsDefined[2];
155 GLXContext *glx_context;
157 GLfloat rotx, roty, rotz; /* current object rotation */
158 GLfloat dx, dy, dz; /* current rotational velocity */
159 GLfloat ddx, ddy, ddz; /* current rotational acceleration */
160 GLfloat d_max; /* max velocity */
164 static float front_shininess[] =
166 static float front_specular[] =
167 {0.7, 0.7, 0.7, 1.0};
168 static float ambient[] =
169 {0.0, 0.0, 0.0, 1.0};
170 static float diffuse[] =
171 {1.0, 1.0, 1.0, 1.0};
172 static float position0[] =
173 {1.0, 1.0, 1.0, 0.0};
174 static float position1[] =
175 {-1.0, -1.0, 1.0, 0.0};
176 static float lmodel_ambient[] =
177 {0.5, 0.5, 0.5, 1.0};
178 static float lmodel_twoside[] =
181 static float MaterialRed[] =
182 {0.7, 0.0, 0.0, 1.0};
183 static float MaterialGreen[] =
184 {0.1, 0.5, 0.2, 1.0};
185 static float MaterialBlue[] =
186 {0.0, 0.0, 0.7, 1.0};
187 static float MaterialCyan[] =
188 {0.2, 0.5, 0.7, 1.0};
189 static float MaterialYellow[] =
190 {0.7, 0.7, 0.0, 1.0};
191 static float MaterialMagenta[] =
192 {0.6, 0.2, 0.5, 1.0};
193 static float MaterialWhite[] =
194 {0.7, 0.7, 0.7, 1.0};
195 static float MaterialGray[] =
196 {0.2, 0.2, 0.2, 1.0};
197 static float MaterialGray5[] =
198 {0.5, 0.5, 0.5, 1.0};
199 static float MaterialGray6[] =
200 {0.6, 0.6, 0.6, 1.0};
201 static float MaterialGray8[] =
202 {0.8, 0.8, 0.8, 1.0};
204 static moebiusstruct *moebius = NULL;
205 static GLuint objects;
209 #define ObjMoebiusStrip 0
213 mySphere(float radius)
215 GLUquadricObj *quadObj;
217 quadObj = gluNewQuadric();
218 gluQuadricDrawStyle(quadObj, (GLenum) GLU_FILL);
219 gluSphere(quadObj, radius, 16, 16);
220 gluDeleteQuadric(quadObj);
226 GLUquadricObj *quadObj;
228 quadObj = gluNewQuadric();
229 gluQuadricDrawStyle(quadObj, (GLenum) GLU_FILL);
230 gluCylinder(quadObj, radius, 0, radius * 3, 8, 1);
231 gluDeleteQuadric(quadObj);
235 draw_moebius_ant(moebiusstruct * mp, float *Material, int mono)
237 static float ant_step = 0;
238 float cos1 = cos(ant_step);
239 float cos2 = cos(ant_step + 2 * Pi / 3);
240 float cos3 = cos(ant_step + 4 * Pi / 3);
241 float sin1 = sin(ant_step);
242 float sin2 = sin(ant_step + 2 * Pi / 3);
243 float sin3 = sin(ant_step + 4 * Pi / 3);
246 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialGray5);
248 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, Material);
249 if (!mp->AreObjectsDefined[ObjAntBody]) {
250 glNewList(objects + ObjAntBody, GL_COMPILE_AND_EXECUTE);
251 glEnable(GL_CULL_FACE);
255 glScalef(1, 1 / 1.3, 1);
256 glTranslatef(0.00, 0.30, 0.00);
259 glTranslatef(-0.05, 0.17, 0.05);
260 glRotatef(-90, 1, 0, 0);
261 glRotatef(-25, 0, 1, 0);
263 glTranslatef(0.00, 0.10, 0.00);
265 glRotatef(25, 0, 1, 0);
266 glRotatef(90, 1, 0, 0);
269 glTranslatef(0.15, -0.65, 0.05);
271 glScalef(1, 1 / 1.3, 1);
273 glDisable(GL_CULL_FACE);
275 mp->AreObjectsDefined[ObjAntBody] = 1;
277 (void) printf("Ant drawn SLOWLY\n");
280 glCallList(objects + ObjAntBody);
282 (void) printf("Ant drawn quickly\n");
286 glDisable(GL_LIGHTING);
290 glColor3fv(MaterialGray5);
292 glColor3fv(Material);
293 glVertex3f(0.00, 0.30, 0.00);
294 glColor3fv(MaterialGray);
295 glVertex3f(0.40, 0.70, 0.40);
297 glColor3fv(MaterialGray5);
299 glColor3fv(Material);
300 glVertex3f(0.00, 0.30, 0.00);
301 glColor3fv(MaterialGray);
302 glVertex3f(0.40, 0.70, -0.40);
306 glColor3fv(MaterialGray6);
308 glColor3fv(MaterialRed);
309 glVertex3f(0.40, 0.70, 0.40);
310 glVertex3f(0.40, 0.70, -0.40);
314 glBegin(GL_LINE_STRIP);
316 glColor3fv(MaterialGray5);
318 glColor3fv(Material);
319 glVertex3f(0.00, 0.05, 0.18);
320 glVertex3f(0.35 + 0.05 * cos1, 0.15, 0.25);
321 glColor3fv(MaterialGray);
322 glVertex3f(-0.20 + 0.05 * cos1, 0.25 + 0.1 * sin1, 0.45);
325 /* LEFT-CENTER ARM */
326 glBegin(GL_LINE_STRIP);
328 glColor3fv(MaterialGray5);
330 glColor3fv(Material);
331 glVertex3f(0.00, 0.00, 0.18);
332 glVertex3f(0.35 + 0.05 * cos2, 0.00, 0.25);
333 glColor3fv(MaterialGray);
334 glVertex3f(-0.20 + 0.05 * cos2, 0.00 + 0.1 * sin2, 0.45);
338 glBegin(GL_LINE_STRIP);
340 glColor3fv(MaterialGray5);
342 glColor3fv(Material);
343 glVertex3f(0.00, -0.05, 0.18);
344 glVertex3f(0.35 + 0.05 * cos3, -0.15, 0.25);
345 glColor3fv(MaterialGray);
346 glVertex3f(-0.20 + 0.05 * cos3, -0.25 + 0.1 * sin3, 0.45);
349 /* RIGHT-FRONT ARM */
350 glBegin(GL_LINE_STRIP);
352 glColor3fv(MaterialGray5);
354 glColor3fv(Material);
355 glVertex3f(0.00, 0.05, -0.18);
356 glVertex3f(0.35 - 0.05 * sin1, 0.15, -0.25);
357 glColor3fv(MaterialGray);
358 glVertex3f(-0.20 - 0.05 * sin1, 0.25 + 0.1 * cos1, -0.45);
361 /* RIGHT-CENTER ARM */
362 glBegin(GL_LINE_STRIP);
364 glColor3fv(MaterialGray5);
366 glColor3fv(Material);
367 glVertex3f(0.00, 0.00, -0.18);
368 glVertex3f(0.35 - 0.05 * sin2, 0.00, -0.25);
369 glColor3fv(MaterialGray);
370 glVertex3f(-0.20 - 0.05 * sin2, 0.00 + 0.1 * cos2, -0.45);
374 glBegin(GL_LINE_STRIP);
376 glColor3fv(MaterialGray5);
378 glColor3fv(Material);
379 glVertex3f(0.00, -0.05, -0.18);
380 glVertex3f(0.35 - 0.05 * sin3, -0.15, -0.25);
381 glColor3fv(MaterialGray);
382 glVertex3f(-0.20 - 0.05 * sin3, -0.25 + 0.1 * cos3, -0.45);
387 glColor3fv(MaterialGray8);
389 glColor3fv(MaterialMagenta);
390 glVertex3f(-0.20 + 0.05 * cos1, 0.25 + 0.1 * sin1, 0.45);
391 glVertex3f(-0.20 + 0.05 * cos2, 0.00 + 0.1 * sin2, 0.45);
392 glVertex3f(-0.20 + 0.05 * cos3, -0.25 + 0.1 * sin3, 0.45);
393 glVertex3f(-0.20 - 0.05 * sin1, 0.25 + 0.1 * cos1, -0.45);
394 glVertex3f(-0.20 - 0.05 * sin2, 0.00 + 0.1 * cos2, -0.45);
395 glVertex3f(-0.20 - 0.05 * sin3, -0.25 + 0.1 * cos3, -0.45);
398 glEnable(GL_LIGHTING);
404 RotateAaroundU(float Ax, float Ay, float Az,
405 float Ux, float Uy, float Uz,
406 float *Cx, float *Cy, float *Cz,
409 float cosO = cos(Theta);
410 float sinO = sin(Theta);
411 float one_cosO = 1 - cosO;
415 float UxUy = Ux * Uy;
416 float UxUz = Ux * Uz;
417 float UyUz = Uy * Uz;
419 *Cx = (Ux2 + cosO * (1 - Ux2)) * Ax + (UxUy * one_cosO - Uz * sinO) * Ay + (UxUz * one_cosO + Uy * sinO) * Az;
420 *Cy = (UxUy * one_cosO + Uz * sinO) * Ax + (Uy2 + cosO * (1 - Uy2)) * Ay + (UyUz * one_cosO - Ux * sinO) * Az;
421 *Cz = (UxUz * one_cosO - Uy * sinO) * Ax + (UyUz * one_cosO + Ux * sinO) * Ay + (Uz2 + cosO * (1 - Uz2)) * Az;
424 #define MoebiusDivisions 40
425 #define MoebiusTransversals 4
427 draw_moebius_strip(ModeInfo * mi)
431 moebiusstruct *mp = &moebius[MI_SCREEN(mi)];
433 int mono = MI_IS_MONO(mi);
437 if (!mp->AreObjectsDefined[ObjMoebiusStrip]) {
438 glNewList(objects + ObjMoebiusStrip, GL_COMPILE_AND_EXECUTE);
441 glBegin(GL_QUAD_STRIP);
444 while (i < (MoebiusDivisions * 2 + 1)) {
451 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialWhite);
453 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialRed);
455 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialGray);
457 RotateAaroundU(cPhi, sPhi, 0, -sPhi, cPhi, 0, &Cx, &Cy, &Cz, Theta);
458 glNormal3f(Cx, Cy, Cz);
459 RotateAaroundU(0, 0, 1, -sPhi, cPhi, 0, &Cx, &Cy, &Cz, Theta);
460 glVertex3f(cPhi * 3 + Cx, sPhi * 3 + Cy, +Cz);
461 glVertex3f(cPhi * 3 - Cx, sPhi * 3 - Cy, -Cz);
463 Phi += Pi / MoebiusDivisions;
467 for (j = -MoebiusTransversals; j < MoebiusTransversals; j++) {
468 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
469 glBegin(GL_QUAD_STRIP);
472 while (i < (MoebiusDivisions * 2 + 1)) {
477 RotateAaroundU(cPhi, sPhi, 0, -sPhi, cPhi, 0, &Cx, &Cy, &Cz, Theta);
478 glNormal3f(Cx, Cy, Cz);
479 RotateAaroundU(0, 0, 1, -sPhi, cPhi, 0, &Cx, &Cy, &Cz, Theta);
481 if (j == MoebiusTransversals || mono)
482 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialWhite);
484 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialRed);
486 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialGray);
487 glVertex3f(cPhi * 3 + Cx / MoebiusTransversals * j, sPhi * 3 + Cy / MoebiusTransversals * j, +Cz / MoebiusTransversals * j);
489 if (j == -MoebiusTransversals || mono)
490 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialWhite);
492 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialRed);
494 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialGray);
495 glVertex3f(cPhi * 3 + Cx / MoebiusTransversals * j, sPhi * 3 + Cy / MoebiusTransversals * j, +Cz / MoebiusTransversals * j);
497 Phi += Pi / MoebiusDivisions;
502 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
506 mp->AreObjectsDefined[ObjMoebiusStrip] = 1;
508 (void) printf("Strip drawn SLOWLY\n");
511 glCallList(objects + ObjMoebiusStrip);
513 (void) printf("Strip drawn quickly\n");
520 glRotatef(mp->ant_position + 180, 0, 0, 1);
521 glTranslatef(3, 0, 0);
522 glRotatef(mp->ant_position / 2 + 90, 0, 1, 0);
523 glTranslatef(0.28, 0, -0.45);
524 draw_moebius_ant(mp, MaterialYellow, mono);
527 /* DRAW YELLOW ANT */
529 glRotatef(mp->ant_position, 0, 0, 1);
530 glTranslatef(3, 0, 0);
531 glRotatef(mp->ant_position / 2, 0, 1, 0);
532 glTranslatef(0.28, 0, -0.45);
533 draw_moebius_ant(mp, MaterialBlue, mono);
538 glRotatef(-mp->ant_position, 0, 0, 1);
539 glTranslatef(3, 0, 0);
540 glRotatef(-mp->ant_position / 2, 0, 1, 0);
541 glTranslatef(0.28, 0, 0.45);
542 glRotatef(180, 1, 0, 0);
543 draw_moebius_ant(mp, MaterialGreen, mono);
548 glRotatef(-mp->ant_position + 180, 0, 0, 1);
549 glTranslatef(3, 0, 0);
550 glRotatef(-mp->ant_position / 2 + 90, 0, 1, 0);
551 glTranslatef(0.28, 0, 0.45);
552 glRotatef(180, 1, 0, 0);
553 draw_moebius_ant(mp, MaterialCyan, mono);
556 mp->ant_position += 1;
558 #undef MoebiusDivisions
559 #undef MoebiusTransversals
562 reshape_moebius(ModeInfo * mi, int width, int height)
564 moebiusstruct *mp = &moebius[MI_SCREEN(mi)];
566 glViewport(0, 0, mp->WindW = (GLint) width, mp->WindH = (GLint) height);
567 glMatrixMode(GL_PROJECTION);
569 glFrustum(-1.0, 1.0, -1.0, 1.0, 5.0, 15.0);
570 glMatrixMode(GL_MODELVIEW);
574 } else if (width >= 512) {
581 mp->AreObjectsDefined[ObjMoebiusStrip] = 0;
582 mp->AreObjectsDefined[ObjAntBody] = 0;
589 glClearColor(0.0, 0.0, 0.0, 1.0);
591 glLightfv(GL_LIGHT0, GL_AMBIENT, ambient);
592 glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse);
593 glLightfv(GL_LIGHT0, GL_POSITION, position0);
594 glLightfv(GL_LIGHT1, GL_AMBIENT, ambient);
595 glLightfv(GL_LIGHT1, GL_DIFFUSE, diffuse);
596 glLightfv(GL_LIGHT1, GL_POSITION, position1);
597 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient);
598 glLightModelfv(GL_LIGHT_MODEL_TWO_SIDE, lmodel_twoside);
599 glEnable(GL_LIGHTING);
602 glEnable(GL_NORMALIZE);
607 glShadeModel(GL_SMOOTH);
608 glEnable(GL_DEPTH_TEST);
609 glDisable(GL_TEXTURE_2D);
610 glDisable(GL_CULL_FACE);
612 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
613 gluBuild2DMipmaps(GL_TEXTURE_2D, 3, WoodTextureWidth, WoodTextureHeight,
614 GL_RGB, GL_UNSIGNED_BYTE, WoodTextureData);
615 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
616 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
617 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
618 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
619 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
621 glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, front_shininess);
622 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, front_specular);
627 /* lifted from lament.c */
628 #define RAND(n) ((long) ((random() & 0x7fffffff) % ((long) (n))))
629 #define RANDSIGN() ((random() & 1) ? 1 : -1)
632 rotate(GLfloat *pos, GLfloat *v, GLfloat *dv, GLfloat max_v)
647 if (ppos < 0) abort();
648 if (ppos > 1.0) abort();
649 *pos = (*pos > 0 ? ppos : -ppos);
655 if (*v > max_v || *v < -max_v)
659 /* If it stops, start it going in the other direction. */
666 /* keep going in the same direction */
681 /* Alter direction of rotational acceleration randomly. */
682 if (! (random() % 120))
685 /* Change acceleration very occasionally. */
686 if (! (random() % 200))
690 else if (random() & 1)
699 init_moebius(ModeInfo * mi)
701 int screen = MI_SCREEN(mi);
704 if (moebius == NULL) {
705 if ((moebius = (moebiusstruct *) calloc(MI_NUM_SCREENS(mi),
706 sizeof (moebiusstruct))) == NULL)
709 mp = &moebius[screen];
710 mp->step = NRAND(90);
711 mp->ant_position = NRAND(90);
713 mp->rotx = frand(1.0) * RANDSIGN();
714 mp->roty = frand(1.0) * RANDSIGN();
715 mp->rotz = frand(1.0) * RANDSIGN();
717 /* bell curve from 0-1.5 degrees, avg 0.75 */
718 mp->dx = (frand(1) + frand(1) + frand(1)) / (360*2);
719 mp->dy = (frand(1) + frand(1) + frand(1)) / (360*2);
720 mp->dz = (frand(1) + frand(1) + frand(1)) / (360*2);
722 mp->d_max = mp->dx * 2;
724 mp->ddx = 0.00006 + frand(0.00003);
725 mp->ddy = 0.00006 + frand(0.00003);
726 mp->ddz = 0.00006 + frand(0.00003);
728 if ((mp->glx_context = init_GL(mi)) != NULL) {
730 reshape_moebius(mi, MI_WIDTH(mi), MI_HEIGHT(mi));
731 glDrawBuffer(GL_BACK);
732 if (!glIsList(objects))
733 objects = glGenLists(3);
741 draw_moebius(ModeInfo * mi)
743 moebiusstruct *mp = &moebius[MI_SCREEN(mi)];
745 Display *display = MI_DISPLAY(mi);
746 Window window = MI_WINDOW(mi);
748 if (!mp->glx_context)
751 glXMakeCurrent(display, window, *(mp->glx_context));
753 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
757 glTranslatef(0.0, 0.0, -10.0);
759 if (!MI_IS_ICONIC(mi)) {
760 glScalef(Scale4Window * mp->WindH / mp->WindW, Scale4Window, Scale4Window);
762 glScalef(Scale4Iconic * mp->WindH / mp->WindW, Scale4Iconic, Scale4Iconic);
766 GLfloat x = mp->rotx;
767 GLfloat y = mp->roty;
768 GLfloat z = mp->rotz;
769 if (x < 0) x = 1 - (x + 1);
770 if (y < 0) y = 1 - (y + 1);
771 if (z < 0) z = 1 - (z + 1);
772 glRotatef(x * 360, 1.0, 0.0, 0.0);
773 glRotatef(y * 360, 0.0, 1.0, 0.0);
774 glRotatef(z * 360, 0.0, 0.0, 1.0);
778 draw_moebius_strip(mi);
782 rotate(&mp->rotx, &mp->dx, &mp->ddx, mp->d_max);
783 rotate(&mp->roty, &mp->dy, &mp->ddy, mp->d_max);
784 rotate(&mp->rotz, &mp->dz, &mp->ddz, mp->d_max);
786 if (mi->fps_p) do_fps (mi);
789 glXSwapBuffers(display, window);
795 change_moebius(ModeInfo * mi)
797 moebiusstruct *mp = &moebius[MI_SCREEN(mi)];
799 if (!mp->glx_context)
802 glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(mp->glx_context));
807 release_moebius(ModeInfo * mi)
809 if (moebius != NULL) {
810 (void) free((void *) moebius);
813 if (glIsList(objects)) {
814 glDeleteLists(objects, 3);