1 /* -*- Mode: C; tab-width: 4 -*- */
2 /* moebius --- Moebius Strip II, an Escher-like GL scene with ants. */
5 static const char sccsid[] = "@(#)moebius.c 5.01 2001/03/01 xlockmore";
9 * Permission to use, copy, modify, and distribute this software and its
10 * documentation for any purpose and without fee is hereby granted,
11 * provided that the above copyright notice appear in all copies and that
12 * both that copyright notice and this permission notice appear in
13 * supporting documentation.
15 * This file is provided AS IS with no warranties of any kind. The author
16 * shall have no liability with respect to the infringement of copyrights,
17 * trade secrets or any patents by this file or any part thereof. In no
18 * event will the author be liable for any lost revenue or profits or
19 * other special, indirect and consequential damages.
21 * The RotateAroundU() routine was adapted from the book
22 * "Computer Graphics Principles and Practice
23 * Foley - vanDam - Feiner - Hughes
24 * Second Edition" Pag. 227, exercise 5.15.
26 * This mode shows some interesting scenes that are impossible OR very
27 * wierd to build in the real universe. Much of the scenes are inspirated
28 * on Mauritz Cornelis Escher's works which derivated the mode's name.
29 * M.C. Escher (1898-1972) was a dutch artist and many people prefer to
30 * say he was a mathematician.
32 * Thanks goes to Brian Paul for making it possible and inexpensive to use
35 * Since I'm not a native English speaker, my apologies for any grammatical
38 * My e-mail address is
39 * mfvianna@centroin.com.br
41 * Marcelo F. Vianna (Jun-01-1997)
44 * 05-Apr-2002: Removed all gllist uses (fix some bug with nvidia driver)
45 * 01-Mar-2001: backported from xscreensaver by lassauge@mail.dotcom.fr
46 * Feb-2001: Made motion and rotation be smoother Jamie Zawinski
48 * 01-Nov-2000: Allocation checks
49 * 01-Jan-1998: Mode separated from escher and renamed
50 * 08-Jun-1997: New scene implemented: "Impossible Cage" based in a M.C.
51 * Escher's painting with the same name (quite similar). The
52 * first GL mode to use texture mapping.
53 * The "Impossible Cage" scene doesn't use DEPTH BUFFER, the
54 * wood planks are drawn consistently using GL_CULL_FACE, and
55 * the painter's algorithm is used to sort the planks.
57 * 07-Jun-1997: Speed ups in Moebius Strip using GL_CULL_FACE.
59 * 03-Jun-1997: Initial Release (Only one scene: "Moebius Strip")
60 * The Moebius Strip scene was inspirated in a M.C. Escher's
61 * painting named Moebius Strip II in wich ants walk across a
62 * Moebius Strip path, sometimes meeting each other and sometimes
63 * being in "opposite faces" (note that the moebius strip has
64 * only one face and one edge).
69 * Texture mapping is only available on RGBA contexts, Mono and color index
70 * visuals DO NOT support texture mapping in OpenGL.
72 * BUT Mesa do implements RGBA contexts in pseudo color visuals, so texture
73 * mapping shuld work on PseudoColor, DirectColor, TrueColor using Mesa. Mono
74 * is not officially supported for both OpenGL and Mesa, but seems to not crash
77 * In real OpenGL, PseudoColor DO NOT support texture map (as far as I know).
82 # define refresh_moebius 0
83 # define DEFAULTS "*delay: 20000 \n" \
85 # include "xlockmore.h" /* from the xscreensaver distribution */
86 #else /* !STANDALONE */
87 # include "xlock.h" /* from the xlockmore distribution */
88 #endif /* !STANDALONE */
92 #include "e_textures.h"
94 #include "gltrackball.h"
96 #define DEF_SOLIDMOEBIUS "False"
97 #define DEF_DRAWANTS "True"
99 static int solidmoebius;
102 static XrmOptionDescRec opts[] =
104 {"-solidmoebius", ".moebius.solidmoebius", XrmoptionNoArg, "on"},
105 {"+solidmoebius", ".moebius.solidmoebius", XrmoptionNoArg, "off"},
106 {"-ants", ".moebius.drawants", XrmoptionNoArg, "on"},
107 {"+ants", ".moebius.drawants", XrmoptionNoArg, "off"}
109 static argtype vars[] =
111 {&solidmoebius, "solidmoebius", "Solidmoebius", DEF_SOLIDMOEBIUS, t_Bool},
112 {&drawants, "drawants", "Drawants", DEF_DRAWANTS, t_Bool}
115 static OptionStruct desc[] =
117 {"-/+solidmoebius", "select between a SOLID or a NET Moebius Strip"},
118 {"-/+drawants", "turn on/off walking ants"}
121 ENTRYPOINT ModeSpecOpt moebius_opts =
122 {sizeof opts / sizeof opts[0], opts, sizeof vars / sizeof vars[0], vars, desc};
125 ModStruct moebius_description =
126 {"moebius", "init_moebius", "draw_moebius", "release_moebius",
127 "draw_moebius", "change_moebius", (char *) NULL, &moebius_opts,
128 1000, 1, 1, 1, 4, 1.0, "",
129 "Shows Moebius Strip II, an Escher-like GL scene with ants", 0, NULL};
133 #define Scale4Window 0.3
134 #define Scale4Iconic 0.4
136 #define sqr(A) ((A)*(A))
142 #define ObjMoebiusStrip 0
146 /*************************************************************************/
151 GLfloat ant_position;
153 GLXContext *glx_context;
155 trackball_state *trackball;
159 static const float front_shininess[] = {60.0};
160 static const float front_specular[] = {0.7, 0.7, 0.7, 1.0};
161 static const float ambient[] = {0.0, 0.0, 0.0, 1.0};
162 static const float diffuse[] = {1.0, 1.0, 1.0, 1.0};
163 static const float position0[] = {1.0, 1.0, 1.0, 0.0};
164 static const float position1[] = {-1.0, -1.0, 1.0, 0.0};
165 static const float lmodel_ambient[] = {0.5, 0.5, 0.5, 1.0};
166 static const float lmodel_twoside[] = {GL_TRUE};
168 static const float MaterialRed[] = {0.7, 0.0, 0.0, 1.0};
169 static const float MaterialGreen[] = {0.1, 0.5, 0.2, 1.0};
170 static const float MaterialBlue[] = {0.0, 0.0, 0.7, 1.0};
171 static const float MaterialCyan[] = {0.2, 0.5, 0.7, 1.0};
172 static const float MaterialYellow[] = {0.7, 0.7, 0.0, 1.0};
173 static const float MaterialMagenta[] = {0.6, 0.2, 0.5, 1.0};
174 static const float MaterialWhite[] = {0.7, 0.7, 0.7, 1.0};
175 static const float MaterialGray[] = {0.2, 0.2, 0.2, 1.0};
176 static const float MaterialGray5[] = {0.5, 0.5, 0.5, 1.0};
177 static const float MaterialGray6[] = {0.6, 0.6, 0.6, 1.0};
178 static const float MaterialGray8[] = {0.8, 0.8, 0.8, 1.0};
180 static moebiusstruct *moebius = (moebiusstruct *) NULL;
185 mySphere(float radius)
187 GLUquadricObj *quadObj;
189 if ((quadObj = gluNewQuadric()) == 0)
191 gluQuadricDrawStyle(quadObj, (GLenum) GLU_FILL);
192 gluSphere(quadObj, radius, 16, 16);
193 gluDeleteQuadric(quadObj);
200 GLUquadricObj *quadObj;
202 if ((quadObj = gluNewQuadric()) == 0)
204 gluQuadricDrawStyle(quadObj, (GLenum) GLU_FILL);
205 gluCylinder(quadObj, radius, 0, radius * 3, 8, 1);
206 gluDeleteQuadric(quadObj);
211 draw_moebius_ant(moebiusstruct * mp, const float *Material, int mono)
213 float cos1 = cos(mp->ant_step);
214 float cos2 = cos(mp->ant_step + 2 * Pi / 3);
215 float cos3 = cos(mp->ant_step + 4 * Pi / 3);
216 float sin1 = sin(mp->ant_step);
217 float sin2 = sin(mp->ant_step + 2 * Pi / 3);
218 float sin3 = sin(mp->ant_step + 4 * Pi / 3);
221 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialGray5);
223 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, Material);
224 glEnable(GL_CULL_FACE);
229 glScalef(1, 1 / 1.3, 1);
230 glTranslatef(0.00, 0.30, 0.00);
234 glTranslatef(-0.05, 0.17, 0.05);
235 glRotatef(-90, 1, 0, 0);
236 glRotatef(-25, 0, 1, 0);
239 glTranslatef(0.00, 0.10, 0.00);
242 glRotatef(25, 0, 1, 0);
243 glRotatef(90, 1, 0, 0);
246 glTranslatef(0.15, -0.65, 0.05);
249 glScalef(1, 1 / 1.3, 1);
251 glDisable(GL_CULL_FACE);
253 glDisable(GL_LIGHTING);
257 glColor3fv(MaterialGray5);
259 glColor3fv(Material);
260 glVertex3f(0.00, 0.30, 0.00);
261 glColor3fv(MaterialGray);
262 glVertex3f(0.40, 0.70, 0.40);
264 glColor3fv(MaterialGray5);
266 glColor3fv(Material);
267 glVertex3f(0.00, 0.30, 0.00);
268 glColor3fv(MaterialGray);
269 glVertex3f(0.40, 0.70, -0.40);
273 glColor3fv(MaterialGray6);
275 glColor3fv(MaterialRed);
276 glVertex3f(0.40, 0.70, 0.40);
277 glVertex3f(0.40, 0.70, -0.40);
281 glBegin(GL_LINE_STRIP);
283 glColor3fv(MaterialGray5);
285 glColor3fv(Material);
286 glVertex3f(0.00, 0.05, 0.18);
287 glVertex3f(0.35 + 0.05 * cos1, 0.15, 0.25);
288 glColor3fv(MaterialGray);
289 glVertex3f(-0.20 + 0.05 * cos1, 0.25 + 0.1 * sin1, 0.45);
292 /* LEFT-CENTER ARM */
293 glBegin(GL_LINE_STRIP);
295 glColor3fv(MaterialGray5);
297 glColor3fv(Material);
298 glVertex3f(0.00, 0.00, 0.18);
299 glVertex3f(0.35 + 0.05 * cos2, 0.00, 0.25);
300 glColor3fv(MaterialGray);
301 glVertex3f(-0.20 + 0.05 * cos2, 0.00 + 0.1 * sin2, 0.45);
305 glBegin(GL_LINE_STRIP);
307 glColor3fv(MaterialGray5);
309 glColor3fv(Material);
310 glVertex3f(0.00, -0.05, 0.18);
311 glVertex3f(0.35 + 0.05 * cos3, -0.15, 0.25);
312 glColor3fv(MaterialGray);
313 glVertex3f(-0.20 + 0.05 * cos3, -0.25 + 0.1 * sin3, 0.45);
316 /* RIGHT-FRONT ARM */
317 glBegin(GL_LINE_STRIP);
319 glColor3fv(MaterialGray5);
321 glColor3fv(Material);
322 glVertex3f(0.00, 0.05, -0.18);
323 glVertex3f(0.35 - 0.05 * sin1, 0.15, -0.25);
324 glColor3fv(MaterialGray);
325 glVertex3f(-0.20 - 0.05 * sin1, 0.25 + 0.1 * cos1, -0.45);
328 /* RIGHT-CENTER ARM */
329 glBegin(GL_LINE_STRIP);
331 glColor3fv(MaterialGray5);
333 glColor3fv(Material);
334 glVertex3f(0.00, 0.00, -0.18);
335 glVertex3f(0.35 - 0.05 * sin2, 0.00, -0.25);
336 glColor3fv(MaterialGray);
337 glVertex3f(-0.20 - 0.05 * sin2, 0.00 + 0.1 * cos2, -0.45);
341 glBegin(GL_LINE_STRIP);
343 glColor3fv(MaterialGray5);
345 glColor3fv(Material);
346 glVertex3f(0.00, -0.05, -0.18);
347 glVertex3f(0.35 - 0.05 * sin3, -0.15, -0.25);
348 glColor3fv(MaterialGray);
349 glVertex3f(-0.20 - 0.05 * sin3, -0.25 + 0.1 * cos3, -0.45);
354 glColor3fv(MaterialGray8);
356 glColor3fv(MaterialMagenta);
357 glVertex3f(-0.20 + 0.05 * cos1, 0.25 + 0.1 * sin1, 0.45);
358 glVertex3f(-0.20 + 0.05 * cos2, 0.00 + 0.1 * sin2, 0.45);
359 glVertex3f(-0.20 + 0.05 * cos3, -0.25 + 0.1 * sin3, 0.45);
360 glVertex3f(-0.20 - 0.05 * sin1, 0.25 + 0.1 * cos1, -0.45);
361 glVertex3f(-0.20 - 0.05 * sin2, 0.00 + 0.1 * cos2, -0.45);
362 glVertex3f(-0.20 - 0.05 * sin3, -0.25 + 0.1 * cos3, -0.45);
365 glEnable(GL_LIGHTING);
372 RotateAaroundU(float Ax, float Ay, float Az,
373 float Ux, float Uy, float Uz,
374 float *Cx, float *Cy, float *Cz,
377 float cosO = cos(Theta);
378 float sinO = sin(Theta);
379 float one_cosO = 1 - cosO;
383 float UxUy = Ux * Uy;
384 float UxUz = Ux * Uz;
385 float UyUz = Uy * Uz;
387 *Cx = (Ux2 + cosO * (1 - Ux2)) * Ax + (UxUy * one_cosO - Uz * sinO) * Ay + (UxUz * one_cosO + Uy * sinO) * Az;
388 *Cy = (UxUy * one_cosO + Uz * sinO) * Ax + (Uy2 + cosO * (1 - Uy2)) * Ay + (UyUz * one_cosO - Ux * sinO) * Az;
389 *Cz = (UxUz * one_cosO - Uy * sinO) * Ax + (UyUz * one_cosO + Ux * sinO) * Ay + (Uz2 + cosO * (1 - Uz2)) * Az;
392 #define MoebiusDivisions 40
393 #define MoebiusTransversals 4
395 draw_moebius_strip(ModeInfo * mi)
399 moebiusstruct *mp = &moebius[MI_SCREEN(mi)];
401 int mono = MI_IS_MONO(mi);
406 glBegin(GL_QUAD_STRIP);
409 while (i < (MoebiusDivisions * 2 + 1)) {
416 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialWhite);
418 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialRed);
420 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialGray);
422 RotateAaroundU(cPhi, sPhi, 0, -sPhi, cPhi, 0, &Cx, &Cy, &Cz, Theta);
423 glNormal3f(Cx, Cy, Cz);
424 RotateAaroundU(0, 0, 1, -sPhi, cPhi, 0, &Cx, &Cy, &Cz, Theta);
425 glVertex3f(cPhi * 3 + Cx, sPhi * 3 + Cy, +Cz);
426 glVertex3f(cPhi * 3 - Cx, sPhi * 3 - Cy, -Cz);
428 Phi += Pi / MoebiusDivisions;
432 for (j = -MoebiusTransversals; j < MoebiusTransversals; j++) {
433 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
434 glBegin(GL_QUAD_STRIP);
437 while (i < (MoebiusDivisions * 2 + 1)) {
442 RotateAaroundU(cPhi, sPhi, 0, -sPhi, cPhi, 0, &Cx, &Cy, &Cz, Theta);
443 glNormal3f(Cx, Cy, Cz);
444 RotateAaroundU(0, 0, 1, -sPhi, cPhi, 0, &Cx, &Cy, &Cz, Theta);
446 if (j == MoebiusTransversals || mono)
447 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialWhite);
449 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialRed);
451 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialGray);
452 glVertex3f(cPhi * 3 + Cx / MoebiusTransversals * j, sPhi * 3 + Cy / MoebiusTransversals * j, +Cz / MoebiusTransversals * j);
454 if (j == -MoebiusTransversals || mono)
455 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialWhite);
457 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialRed);
459 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialGray);
460 glVertex3f(cPhi * 3 + Cx / MoebiusTransversals * j, sPhi * 3 + Cy / MoebiusTransversals * j, +Cz / MoebiusTransversals * j);
462 Phi += Pi / MoebiusDivisions;
467 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
473 glRotatef(mp->ant_position + 180, 0, 0, 1);
474 glTranslatef(3, 0, 0);
475 glRotatef(mp->ant_position / 2 + 90, 0, 1, 0);
476 glTranslatef(0.28, 0, -0.45);
477 if (!draw_moebius_ant(mp, MaterialYellow, mono))
481 /* DRAW YELLOW ANT */
483 glRotatef(mp->ant_position, 0, 0, 1);
484 glTranslatef(3, 0, 0);
485 glRotatef(mp->ant_position / 2, 0, 1, 0);
486 glTranslatef(0.28, 0, -0.45);
487 if (!draw_moebius_ant(mp, MaterialBlue, mono))
493 glRotatef(-mp->ant_position, 0, 0, 1);
494 glTranslatef(3, 0, 0);
495 glRotatef(-mp->ant_position / 2, 0, 1, 0);
496 glTranslatef(0.28, 0, 0.45);
497 glRotatef(180, 1, 0, 0);
498 if (!draw_moebius_ant(mp, MaterialGreen, mono))
504 glRotatef(-mp->ant_position + 180, 0, 0, 1);
505 glTranslatef(3, 0, 0);
506 glRotatef(-mp->ant_position / 2 + 90, 0, 1, 0);
507 glTranslatef(0.28, 0, 0.45);
508 glRotatef(180, 1, 0, 0);
509 if (!draw_moebius_ant(mp, MaterialCyan, mono))
513 mp->ant_position += 1;
516 #undef MoebiusDivisions
517 #undef MoebiusTransversals
520 reshape_moebius (ModeInfo * mi, int width, int height)
522 moebiusstruct *mp = &moebius[MI_SCREEN(mi)];
524 glViewport(0, 0, mp->WindW = (GLint) width, mp->WindH = (GLint) height);
525 glMatrixMode(GL_PROJECTION);
527 glFrustum(-1.0, 1.0, -1.0, 1.0, 5.0, 15.0);
528 glMatrixMode(GL_MODELVIEW);
532 } else if (width >= 512) {
546 glClearColor(0.0, 0.0, 0.0, 1.0);
548 glLightfv(GL_LIGHT0, GL_AMBIENT, ambient);
549 glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse);
550 glLightfv(GL_LIGHT0, GL_POSITION, position0);
551 glLightfv(GL_LIGHT1, GL_AMBIENT, ambient);
552 glLightfv(GL_LIGHT1, GL_DIFFUSE, diffuse);
553 glLightfv(GL_LIGHT1, GL_POSITION, position1);
554 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient);
555 glLightModelfv(GL_LIGHT_MODEL_TWO_SIDE, lmodel_twoside);
556 glEnable(GL_LIGHTING);
559 glEnable(GL_NORMALIZE);
564 glShadeModel(GL_SMOOTH);
565 glEnable(GL_DEPTH_TEST);
566 glDisable(GL_TEXTURE_2D);
567 glDisable(GL_CULL_FACE);
569 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
572 status = gluBuild2DMipmaps(GL_TEXTURE_2D, 3,
573 WoodTextureWidth, WoodTextureHeight,
574 GL_RGB, GL_UNSIGNED_BYTE, WoodTextureData);
577 const char *s = (char *) gluErrorString (status);
578 fprintf (stderr, "%s: error mipmapping %dx%d texture: %s\n",
579 progname, WoodTextureWidth, WoodTextureHeight,
580 (s ? s : "(unknown)"));
583 check_gl_error("mipmapping");
585 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
586 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
587 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
588 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
589 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
591 glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, front_shininess);
592 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, front_specular);
598 release_moebius (ModeInfo * mi)
600 if (moebius != NULL) {
601 (void) free((void *) moebius);
602 moebius = (moebiusstruct *) NULL;
608 moebius_handle_event (ModeInfo *mi, XEvent *event)
610 moebiusstruct *mp = &moebius[MI_SCREEN(mi)];
612 if (event->xany.type == ButtonPress &&
613 event->xbutton.button == Button1)
615 mp->button_down_p = True;
616 gltrackball_start (mp->trackball,
617 event->xbutton.x, event->xbutton.y,
618 MI_WIDTH (mi), MI_HEIGHT (mi));
621 else if (event->xany.type == ButtonRelease &&
622 event->xbutton.button == Button1)
624 mp->button_down_p = False;
627 else if (event->xany.type == ButtonPress &&
628 (event->xbutton.button == Button4 ||
629 event->xbutton.button == Button5 ||
630 event->xbutton.button == Button6 ||
631 event->xbutton.button == Button7))
633 gltrackball_mousewheel (mp->trackball, event->xbutton.button, 10,
634 !!event->xbutton.state);
637 else if (event->xany.type == MotionNotify &&
640 gltrackball_track (mp->trackball,
641 event->xmotion.x, event->xmotion.y,
642 MI_WIDTH (mi), MI_HEIGHT (mi));
651 init_moebius (ModeInfo * mi)
655 if (moebius == NULL) {
656 if ((moebius = (moebiusstruct *) calloc(MI_NUM_SCREENS(mi),
657 sizeof (moebiusstruct))) == NULL)
660 mp = &moebius[MI_SCREEN(mi)];
661 mp->step = NRAND(90);
662 mp->ant_position = NRAND(90);
665 double rot_speed = 0.3;
666 mp->rot = make_rotator (rot_speed, rot_speed, rot_speed, 1, 0, True);
667 mp->trackball = gltrackball_init ();
670 if ((mp->glx_context = init_GL(mi)) != NULL) {
672 reshape_moebius(mi, MI_WIDTH(mi), MI_HEIGHT(mi));
673 glDrawBuffer(GL_BACK);
681 draw_moebius (ModeInfo * mi)
685 Display *display = MI_DISPLAY(mi);
686 Window window = MI_WINDOW(mi);
690 mp = &moebius[MI_SCREEN(mi)];
692 MI_IS_DRAWN(mi) = True;
694 if (!mp->glx_context)
697 glXMakeCurrent(display, window, *(mp->glx_context));
699 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
703 glTranslatef(0.0, 0.0, -10.0);
705 gltrackball_rotate (mp->trackball);
707 if (!MI_IS_ICONIC(mi)) {
708 glScalef(Scale4Window * mp->WindH / mp->WindW, Scale4Window, Scale4Window);
710 glScalef(Scale4Iconic * mp->WindH / mp->WindW, Scale4Iconic, Scale4Iconic);
715 get_rotation (mp->rot, &x, &y, &z, !mp->button_down_p);
716 glRotatef (x * 360, 1.0, 0.0, 0.0);
717 glRotatef (y * 360, 0.0, 1.0, 0.0);
718 glRotatef (z * 360, 0.0, 0.0, 1.0);
722 if (!draw_moebius_strip(mi)) {
729 if (MI_IS_FPS(mi)) do_fps (mi);
732 glXSwapBuffers(display, window);
739 change_moebius (ModeInfo * mi)
741 moebiusstruct *mp = &moebius[MI_SCREEN(mi)];
743 if (!mp->glx_context)
746 glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(mp->glx_context));
749 #endif /* !STANDALONE */
752 XSCREENSAVER_MODULE ("Moebius", moebius)