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 "*delay: 20000 \n" \
88 "*showFPS: False \n" \
89 "*wireframe: False \n"
90 # include "xlockmore.h" /* from the xscreensaver distribution */
91 #else /* !STANDALONE */
92 # include "xlock.h" /* from the xlockmore distribution */
94 #endif /* !STANDALONE */
100 #include "e_textures.h"
102 #define DEF_SOLIDMOEBIUS "False"
103 #define DEF_NOANTS "False"
105 static int solidmoebius;
108 static XrmOptionDescRec opts[] =
110 {"-solidmoebius", ".moebius.solidmoebius", XrmoptionNoArg, (caddr_t) "on"},
111 {"+solidmoebius", ".moebius.solidmoebius", XrmoptionNoArg, (caddr_t) "off"},
112 {"-noants", ".moebius.noants", XrmoptionNoArg, (caddr_t) "on"},
113 {"+noants", ".moebius.noants", XrmoptionNoArg, (caddr_t) "off"}
115 static argtype vars[] =
117 {(caddr_t *) & solidmoebius, "solidmoebius", "Solidmoebius", DEF_SOLIDMOEBIUS, t_Bool},
118 {(caddr_t *) & noants, "noants", "Noants", DEF_NOANTS, t_Bool}
120 static OptionStruct desc[] =
122 {"-/+solidmoebius", "select between a SOLID or a NET Moebius Strip"},
123 {"-/+noants", "turn on/off walking ants"}
126 ModeSpecOpt moebius_opts =
127 {sizeof opts / sizeof opts[0], opts, sizeof vars / sizeof vars[0], vars, desc};
130 ModStruct moebius_description =
131 {"moebius", "init_moebius", "draw_moebius", "release_moebius",
132 "draw_moebius", "change_moebius", NULL, &moebius_opts,
133 1000, 1, 1, 1, 4, 1.0, "",
134 "Shows Moebius Strip II, an Escher-like GL scene with ants", 0, NULL};
138 #define Scale4Window 0.3
139 #define Scale4Iconic 0.4
141 #define sqr(A) ((A)*(A))
147 /*************************************************************************/
152 GLfloat ant_position;
153 int AreObjectsDefined[2];
154 GLXContext *glx_context;
156 GLfloat rotx, roty, rotz; /* current object rotation */
157 GLfloat dx, dy, dz; /* current rotational velocity */
158 GLfloat ddx, ddy, ddz; /* current rotational acceleration */
159 GLfloat d_max; /* max velocity */
163 static float front_shininess[] =
165 static float front_specular[] =
166 {0.7, 0.7, 0.7, 1.0};
167 static float ambient[] =
168 {0.0, 0.0, 0.0, 1.0};
169 static float diffuse[] =
170 {1.0, 1.0, 1.0, 1.0};
171 static float position0[] =
172 {1.0, 1.0, 1.0, 0.0};
173 static float position1[] =
174 {-1.0, -1.0, 1.0, 0.0};
175 static float lmodel_ambient[] =
176 {0.5, 0.5, 0.5, 1.0};
177 static float lmodel_twoside[] =
180 static float MaterialRed[] =
181 {0.7, 0.0, 0.0, 1.0};
182 static float MaterialGreen[] =
183 {0.1, 0.5, 0.2, 1.0};
184 static float MaterialBlue[] =
185 {0.0, 0.0, 0.7, 1.0};
186 static float MaterialCyan[] =
187 {0.2, 0.5, 0.7, 1.0};
188 static float MaterialYellow[] =
189 {0.7, 0.7, 0.0, 1.0};
190 static float MaterialMagenta[] =
191 {0.6, 0.2, 0.5, 1.0};
192 static float MaterialWhite[] =
193 {0.7, 0.7, 0.7, 1.0};
194 static float MaterialGray[] =
195 {0.2, 0.2, 0.2, 1.0};
196 static float MaterialGray5[] =
197 {0.5, 0.5, 0.5, 1.0};
198 static float MaterialGray6[] =
199 {0.6, 0.6, 0.6, 1.0};
200 static float MaterialGray8[] =
201 {0.8, 0.8, 0.8, 1.0};
203 static moebiusstruct *moebius = NULL;
204 static GLuint objects;
208 #define ObjMoebiusStrip 0
212 mySphere(float radius)
214 GLUquadricObj *quadObj;
216 quadObj = gluNewQuadric();
217 gluQuadricDrawStyle(quadObj, (GLenum) GLU_FILL);
218 gluSphere(quadObj, radius, 16, 16);
219 gluDeleteQuadric(quadObj);
225 GLUquadricObj *quadObj;
227 quadObj = gluNewQuadric();
228 gluQuadricDrawStyle(quadObj, (GLenum) GLU_FILL);
229 gluCylinder(quadObj, radius, 0, radius * 3, 8, 1);
230 gluDeleteQuadric(quadObj);
234 draw_moebius_ant(moebiusstruct * mp, float *Material, int mono)
236 static float ant_step = 0;
237 float cos1 = cos(ant_step);
238 float cos2 = cos(ant_step + 2 * Pi / 3);
239 float cos3 = cos(ant_step + 4 * Pi / 3);
240 float sin1 = sin(ant_step);
241 float sin2 = sin(ant_step + 2 * Pi / 3);
242 float sin3 = sin(ant_step + 4 * Pi / 3);
245 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialGray5);
247 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, Material);
248 if (!mp->AreObjectsDefined[ObjAntBody]) {
249 glNewList(objects + ObjAntBody, GL_COMPILE_AND_EXECUTE);
250 glEnable(GL_CULL_FACE);
254 glScalef(1, 1 / 1.3, 1);
255 glTranslatef(0.00, 0.30, 0.00);
258 glTranslatef(-0.05, 0.17, 0.05);
259 glRotatef(-90, 1, 0, 0);
260 glRotatef(-25, 0, 1, 0);
262 glTranslatef(0.00, 0.10, 0.00);
264 glRotatef(25, 0, 1, 0);
265 glRotatef(90, 1, 0, 0);
268 glTranslatef(0.15, -0.65, 0.05);
270 glScalef(1, 1 / 1.3, 1);
272 glDisable(GL_CULL_FACE);
274 mp->AreObjectsDefined[ObjAntBody] = 1;
276 (void) printf("Ant drawn SLOWLY\n");
279 glCallList(objects + ObjAntBody);
281 (void) printf("Ant drawn quickly\n");
285 glDisable(GL_LIGHTING);
289 glColor3fv(MaterialGray5);
291 glColor3fv(Material);
292 glVertex3f(0.00, 0.30, 0.00);
293 glColor3fv(MaterialGray);
294 glVertex3f(0.40, 0.70, 0.40);
296 glColor3fv(MaterialGray5);
298 glColor3fv(Material);
299 glVertex3f(0.00, 0.30, 0.00);
300 glColor3fv(MaterialGray);
301 glVertex3f(0.40, 0.70, -0.40);
305 glColor3fv(MaterialGray6);
307 glColor3fv(MaterialRed);
308 glVertex3f(0.40, 0.70, 0.40);
309 glVertex3f(0.40, 0.70, -0.40);
313 glBegin(GL_LINE_STRIP);
315 glColor3fv(MaterialGray5);
317 glColor3fv(Material);
318 glVertex3f(0.00, 0.05, 0.18);
319 glVertex3f(0.35 + 0.05 * cos1, 0.15, 0.25);
320 glColor3fv(MaterialGray);
321 glVertex3f(-0.20 + 0.05 * cos1, 0.25 + 0.1 * sin1, 0.45);
324 /* LEFT-CENTER ARM */
325 glBegin(GL_LINE_STRIP);
327 glColor3fv(MaterialGray5);
329 glColor3fv(Material);
330 glVertex3f(0.00, 0.00, 0.18);
331 glVertex3f(0.35 + 0.05 * cos2, 0.00, 0.25);
332 glColor3fv(MaterialGray);
333 glVertex3f(-0.20 + 0.05 * cos2, 0.00 + 0.1 * sin2, 0.45);
337 glBegin(GL_LINE_STRIP);
339 glColor3fv(MaterialGray5);
341 glColor3fv(Material);
342 glVertex3f(0.00, -0.05, 0.18);
343 glVertex3f(0.35 + 0.05 * cos3, -0.15, 0.25);
344 glColor3fv(MaterialGray);
345 glVertex3f(-0.20 + 0.05 * cos3, -0.25 + 0.1 * sin3, 0.45);
348 /* RIGHT-FRONT ARM */
349 glBegin(GL_LINE_STRIP);
351 glColor3fv(MaterialGray5);
353 glColor3fv(Material);
354 glVertex3f(0.00, 0.05, -0.18);
355 glVertex3f(0.35 - 0.05 * sin1, 0.15, -0.25);
356 glColor3fv(MaterialGray);
357 glVertex3f(-0.20 - 0.05 * sin1, 0.25 + 0.1 * cos1, -0.45);
360 /* RIGHT-CENTER ARM */
361 glBegin(GL_LINE_STRIP);
363 glColor3fv(MaterialGray5);
365 glColor3fv(Material);
366 glVertex3f(0.00, 0.00, -0.18);
367 glVertex3f(0.35 - 0.05 * sin2, 0.00, -0.25);
368 glColor3fv(MaterialGray);
369 glVertex3f(-0.20 - 0.05 * sin2, 0.00 + 0.1 * cos2, -0.45);
373 glBegin(GL_LINE_STRIP);
375 glColor3fv(MaterialGray5);
377 glColor3fv(Material);
378 glVertex3f(0.00, -0.05, -0.18);
379 glVertex3f(0.35 - 0.05 * sin3, -0.15, -0.25);
380 glColor3fv(MaterialGray);
381 glVertex3f(-0.20 - 0.05 * sin3, -0.25 + 0.1 * cos3, -0.45);
386 glColor3fv(MaterialGray8);
388 glColor3fv(MaterialMagenta);
389 glVertex3f(-0.20 + 0.05 * cos1, 0.25 + 0.1 * sin1, 0.45);
390 glVertex3f(-0.20 + 0.05 * cos2, 0.00 + 0.1 * sin2, 0.45);
391 glVertex3f(-0.20 + 0.05 * cos3, -0.25 + 0.1 * sin3, 0.45);
392 glVertex3f(-0.20 - 0.05 * sin1, 0.25 + 0.1 * cos1, -0.45);
393 glVertex3f(-0.20 - 0.05 * sin2, 0.00 + 0.1 * cos2, -0.45);
394 glVertex3f(-0.20 - 0.05 * sin3, -0.25 + 0.1 * cos3, -0.45);
397 glEnable(GL_LIGHTING);
403 RotateAaroundU(float Ax, float Ay, float Az,
404 float Ux, float Uy, float Uz,
405 float *Cx, float *Cy, float *Cz,
408 float cosO = cos(Theta);
409 float sinO = sin(Theta);
410 float one_cosO = 1 - cosO;
414 float UxUy = Ux * Uy;
415 float UxUz = Ux * Uz;
416 float UyUz = Uy * Uz;
418 *Cx = (Ux2 + cosO * (1 - Ux2)) * Ax + (UxUy * one_cosO - Uz * sinO) * Ay + (UxUz * one_cosO + Uy * sinO) * Az;
419 *Cy = (UxUy * one_cosO + Uz * sinO) * Ax + (Uy2 + cosO * (1 - Uy2)) * Ay + (UyUz * one_cosO - Ux * sinO) * Az;
420 *Cz = (UxUz * one_cosO - Uy * sinO) * Ax + (UyUz * one_cosO + Ux * sinO) * Ay + (Uz2 + cosO * (1 - Uz2)) * Az;
423 #define MoebiusDivisions 40
424 #define MoebiusTransversals 4
426 draw_moebius_strip(ModeInfo * mi)
430 moebiusstruct *mp = &moebius[MI_SCREEN(mi)];
432 int mono = MI_IS_MONO(mi);
436 if (!mp->AreObjectsDefined[ObjMoebiusStrip]) {
437 glNewList(objects + ObjMoebiusStrip, GL_COMPILE_AND_EXECUTE);
440 glBegin(GL_QUAD_STRIP);
443 while (i < (MoebiusDivisions * 2 + 1)) {
450 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialWhite);
452 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialRed);
454 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialGray);
456 RotateAaroundU(cPhi, sPhi, 0, -sPhi, cPhi, 0, &Cx, &Cy, &Cz, Theta);
457 glNormal3f(Cx, Cy, Cz);
458 RotateAaroundU(0, 0, 1, -sPhi, cPhi, 0, &Cx, &Cy, &Cz, Theta);
459 glVertex3f(cPhi * 3 + Cx, sPhi * 3 + Cy, +Cz);
460 glVertex3f(cPhi * 3 - Cx, sPhi * 3 - Cy, -Cz);
462 Phi += Pi / MoebiusDivisions;
466 for (j = -MoebiusTransversals; j < MoebiusTransversals; j++) {
467 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
468 glBegin(GL_QUAD_STRIP);
471 while (i < (MoebiusDivisions * 2 + 1)) {
476 RotateAaroundU(cPhi, sPhi, 0, -sPhi, cPhi, 0, &Cx, &Cy, &Cz, Theta);
477 glNormal3f(Cx, Cy, Cz);
478 RotateAaroundU(0, 0, 1, -sPhi, cPhi, 0, &Cx, &Cy, &Cz, Theta);
480 if (j == MoebiusTransversals || mono)
481 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialWhite);
483 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialRed);
485 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialGray);
486 glVertex3f(cPhi * 3 + Cx / MoebiusTransversals * j, sPhi * 3 + Cy / MoebiusTransversals * j, +Cz / MoebiusTransversals * j);
488 if (j == -MoebiusTransversals || mono)
489 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialWhite);
491 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialRed);
493 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialGray);
494 glVertex3f(cPhi * 3 + Cx / MoebiusTransversals * j, sPhi * 3 + Cy / MoebiusTransversals * j, +Cz / MoebiusTransversals * j);
496 Phi += Pi / MoebiusDivisions;
501 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
505 mp->AreObjectsDefined[ObjMoebiusStrip] = 1;
507 (void) printf("Strip drawn SLOWLY\n");
510 glCallList(objects + ObjMoebiusStrip);
512 (void) printf("Strip drawn quickly\n");
519 glRotatef(mp->ant_position + 180, 0, 0, 1);
520 glTranslatef(3, 0, 0);
521 glRotatef(mp->ant_position / 2 + 90, 0, 1, 0);
522 glTranslatef(0.28, 0, -0.45);
523 draw_moebius_ant(mp, MaterialYellow, mono);
526 /* DRAW YELLOW ANT */
528 glRotatef(mp->ant_position, 0, 0, 1);
529 glTranslatef(3, 0, 0);
530 glRotatef(mp->ant_position / 2, 0, 1, 0);
531 glTranslatef(0.28, 0, -0.45);
532 draw_moebius_ant(mp, MaterialBlue, mono);
537 glRotatef(-mp->ant_position, 0, 0, 1);
538 glTranslatef(3, 0, 0);
539 glRotatef(-mp->ant_position / 2, 0, 1, 0);
540 glTranslatef(0.28, 0, 0.45);
541 glRotatef(180, 1, 0, 0);
542 draw_moebius_ant(mp, MaterialGreen, mono);
547 glRotatef(-mp->ant_position + 180, 0, 0, 1);
548 glTranslatef(3, 0, 0);
549 glRotatef(-mp->ant_position / 2 + 90, 0, 1, 0);
550 glTranslatef(0.28, 0, 0.45);
551 glRotatef(180, 1, 0, 0);
552 draw_moebius_ant(mp, MaterialCyan, mono);
555 mp->ant_position += 1;
557 #undef MoebiusDivisions
558 #undef MoebiusTransversals
561 reshape_moebius(ModeInfo * mi, int width, int height)
563 moebiusstruct *mp = &moebius[MI_SCREEN(mi)];
565 glViewport(0, 0, mp->WindW = (GLint) width, mp->WindH = (GLint) height);
566 glMatrixMode(GL_PROJECTION);
568 glFrustum(-1.0, 1.0, -1.0, 1.0, 5.0, 15.0);
569 glMatrixMode(GL_MODELVIEW);
573 } else if (width >= 512) {
580 mp->AreObjectsDefined[ObjMoebiusStrip] = 0;
581 mp->AreObjectsDefined[ObjAntBody] = 0;
588 glClearColor(0.0, 0.0, 0.0, 1.0);
590 glLightfv(GL_LIGHT0, GL_AMBIENT, ambient);
591 glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse);
592 glLightfv(GL_LIGHT0, GL_POSITION, position0);
593 glLightfv(GL_LIGHT1, GL_AMBIENT, ambient);
594 glLightfv(GL_LIGHT1, GL_DIFFUSE, diffuse);
595 glLightfv(GL_LIGHT1, GL_POSITION, position1);
596 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient);
597 glLightModelfv(GL_LIGHT_MODEL_TWO_SIDE, lmodel_twoside);
598 glEnable(GL_LIGHTING);
601 glEnable(GL_NORMALIZE);
606 glShadeModel(GL_SMOOTH);
607 glEnable(GL_DEPTH_TEST);
608 glDisable(GL_TEXTURE_2D);
609 glDisable(GL_CULL_FACE);
611 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
612 gluBuild2DMipmaps(GL_TEXTURE_2D, 3, WoodTextureWidth, WoodTextureHeight,
613 GL_RGB, GL_UNSIGNED_BYTE, WoodTextureData);
614 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
615 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
616 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
617 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
618 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
620 glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, front_shininess);
621 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, front_specular);
626 /* lifted from lament.c */
627 #define RAND(n) ((long) ((random() & 0x7fffffff) % ((long) (n))))
628 #define RANDSIGN() ((random() & 1) ? 1 : -1)
631 rotate(GLfloat *pos, GLfloat *v, GLfloat *dv, GLfloat max_v)
646 if (ppos < 0) abort();
647 if (ppos > 1.0) abort();
648 *pos = (*pos > 0 ? ppos : -ppos);
654 if (*v > max_v || *v < -max_v)
658 /* If it stops, start it going in the other direction. */
665 /* keep going in the same direction */
680 /* Alter direction of rotational acceleration randomly. */
681 if (! (random() % 120))
684 /* Change acceleration very occasionally. */
685 if (! (random() % 200))
689 else if (random() & 1)
698 init_moebius(ModeInfo * mi)
700 int screen = MI_SCREEN(mi);
703 if (moebius == NULL) {
704 if ((moebius = (moebiusstruct *) calloc(MI_NUM_SCREENS(mi),
705 sizeof (moebiusstruct))) == NULL)
708 mp = &moebius[screen];
709 mp->step = NRAND(90);
710 mp->ant_position = NRAND(90);
712 mp->rotx = frand(1.0) * RANDSIGN();
713 mp->roty = frand(1.0) * RANDSIGN();
714 mp->rotz = frand(1.0) * RANDSIGN();
716 /* bell curve from 0-1.5 degrees, avg 0.75 */
717 mp->dx = (frand(1) + frand(1) + frand(1)) / (360*2);
718 mp->dy = (frand(1) + frand(1) + frand(1)) / (360*2);
719 mp->dz = (frand(1) + frand(1) + frand(1)) / (360*2);
721 mp->d_max = mp->dx * 2;
723 mp->ddx = 0.00006 + frand(0.00003);
724 mp->ddy = 0.00006 + frand(0.00003);
725 mp->ddz = 0.00006 + frand(0.00003);
727 if ((mp->glx_context = init_GL(mi)) != NULL) {
729 reshape_moebius(mi, MI_WIDTH(mi), MI_HEIGHT(mi));
730 glDrawBuffer(GL_BACK);
731 if (!glIsList(objects))
732 objects = glGenLists(3);
740 draw_moebius(ModeInfo * mi)
742 moebiusstruct *mp = &moebius[MI_SCREEN(mi)];
744 Display *display = MI_DISPLAY(mi);
745 Window window = MI_WINDOW(mi);
747 if (!mp->glx_context)
750 glXMakeCurrent(display, window, *(mp->glx_context));
752 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
756 glTranslatef(0.0, 0.0, -10.0);
758 if (!MI_IS_ICONIC(mi)) {
759 glScalef(Scale4Window * mp->WindH / mp->WindW, Scale4Window, Scale4Window);
761 glScalef(Scale4Iconic * mp->WindH / mp->WindW, Scale4Iconic, Scale4Iconic);
765 GLfloat x = mp->rotx;
766 GLfloat y = mp->roty;
767 GLfloat z = mp->rotz;
768 if (x < 0) x = 1 - (x + 1);
769 if (y < 0) y = 1 - (y + 1);
770 if (z < 0) z = 1 - (z + 1);
771 glRotatef(x * 360, 1.0, 0.0, 0.0);
772 glRotatef(y * 360, 0.0, 1.0, 0.0);
773 glRotatef(z * 360, 0.0, 0.0, 1.0);
777 draw_moebius_strip(mi);
781 rotate(&mp->rotx, &mp->dx, &mp->ddx, mp->d_max);
782 rotate(&mp->roty, &mp->dy, &mp->ddy, mp->d_max);
783 rotate(&mp->rotz, &mp->dz, &mp->ddz, mp->d_max);
785 if (mi->fps_p) do_fps (mi);
788 glXSwapBuffers(display, window);
794 change_moebius(ModeInfo * mi)
796 moebiusstruct *mp = &moebius[MI_SCREEN(mi)];
798 if (!mp->glx_context)
801 glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(mp->glx_context));
806 release_moebius(ModeInfo * mi)
808 if (moebius != NULL) {
809 (void) free((void *) moebius);
812 if (glIsList(objects)) {
813 glDeleteLists(objects, 3);