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 free_moebius 0
83 # define release_moebius 0
84 # define DEFAULTS "*delay: 20000 \n" \
85 "*showFPS: False \n" \
86 "*suppressRotationAnimation: True\n" \
88 # include "xlockmore.h" /* from the xscreensaver distribution */
89 #else /* !STANDALONE */
90 # include "xlock.h" /* from the xlockmore distribution */
91 #endif /* !STANDALONE */
96 # include <X11/Xlib.h>
102 # include "jwzgles.h"
103 #endif /* HAVE_JWZGLES */
107 #if 0 /* Hey, this never actually used the texture at all! */
109 #include "e_textures.h"
111 #include "ximage-loader.h"
112 #include "images/gen/wood_png.h"
120 #include "gltrackball.h"
122 #define DEF_SOLIDMOEBIUS "False"
123 #define DEF_DRAWANTS "True"
125 static int solidmoebius;
128 static XrmOptionDescRec opts[] =
130 {"-solidmoebius", ".moebius.solidmoebius", XrmoptionNoArg, "on"},
131 {"+solidmoebius", ".moebius.solidmoebius", XrmoptionNoArg, "off"},
132 {"-ants", ".moebius.drawants", XrmoptionNoArg, "on"},
133 {"+ants", ".moebius.drawants", XrmoptionNoArg, "off"}
135 static argtype vars[] =
137 {&solidmoebius, "solidmoebius", "Solidmoebius", DEF_SOLIDMOEBIUS, t_Bool},
138 {&drawants, "drawants", "Drawants", DEF_DRAWANTS, t_Bool}
141 static OptionStruct desc[] =
143 {"-/+solidmoebius", "select between a SOLID or a NET Moebius Strip"},
144 {"-/+drawants", "turn on/off walking ants"}
147 ENTRYPOINT ModeSpecOpt moebius_opts =
148 {sizeof opts / sizeof opts[0], opts, sizeof vars / sizeof vars[0], vars, desc};
151 ModStruct moebius_description =
152 {"moebius", "init_moebius", "draw_moebius", (char *) NULL,
153 "draw_moebius", "change_moebius", (char *) NULL, &moebius_opts,
154 1000, 1, 1, 1, 4, 1.0, "",
155 "Shows Moebius Strip II, an Escher-like GL scene with ants", 0, NULL};
159 #define Scale4Window 0.3
160 #define Scale4Iconic 0.4
162 #define sqr(A) ((A)*(A))
168 #define ObjMoebiusStrip 0
172 /*************************************************************************/
177 GLfloat ant_position;
179 GLXContext *glx_context;
181 trackball_state *trackball;
185 static const float front_shininess[] = {60.0};
186 static const float front_specular[] = {0.7, 0.7, 0.7, 1.0};
187 static const float ambient[] = {0.0, 0.0, 0.0, 1.0};
188 static const float diffuse[] = {1.0, 1.0, 1.0, 1.0};
189 static const float position0[] = {1.0, 1.0, 1.0, 0.0};
190 static const float position1[] = {-1.0, -1.0, 1.0, 0.0};
191 static const float lmodel_ambient[] = {0.5, 0.5, 0.5, 1.0};
192 static const float lmodel_twoside[] = {GL_TRUE};
194 static const float MaterialRed[] = {0.7, 0.0, 0.0, 1.0};
195 static const float MaterialGreen[] = {0.1, 0.5, 0.2, 1.0};
196 static const float MaterialBlue[] = {0.0, 0.0, 0.7, 1.0};
197 static const float MaterialCyan[] = {0.2, 0.5, 0.7, 1.0};
198 static const float MaterialYellow[] = {0.7, 0.7, 0.0, 1.0};
199 static const float MaterialMagenta[] = {0.6, 0.2, 0.5, 1.0};
200 static const float MaterialWhite[] = {0.7, 0.7, 0.7, 1.0};
201 static const float MaterialGray[] = {0.2, 0.2, 0.2, 1.0};
202 static const float MaterialGray5[] = {0.5, 0.5, 0.5, 1.0};
203 static const float MaterialGray6[] = {0.6, 0.6, 0.6, 1.0};
204 static const float MaterialGray8[] = {0.8, 0.8, 0.8, 1.0};
206 static moebiusstruct *moebius = (moebiusstruct *) NULL;
211 mySphere(float radius)
214 GLUquadricObj *quadObj;
216 if ((quadObj = gluNewQuadric()) == 0)
218 gluQuadricDrawStyle(quadObj, (GLenum) GLU_FILL);
219 gluSphere(quadObj, radius, 16, 16);
220 gluDeleteQuadric(quadObj);
223 glScalef (radius, radius, radius);
224 unit_sphere (16, 16, False);
234 GLUquadricObj *quadObj;
236 if ((quadObj = gluNewQuadric()) == 0)
238 gluQuadricDrawStyle(quadObj, (GLenum) GLU_FILL);
239 gluCylinder(quadObj, radius, 0, radius * 3, 8, 1);
240 gluDeleteQuadric(quadObj);
245 8, True, True, False);
251 draw_moebius_ant(moebiusstruct * mp, const float *Material, int mono)
253 float cos1 = cos(mp->ant_step);
254 float cos2 = cos(mp->ant_step + 2 * Pi / 3);
255 float cos3 = cos(mp->ant_step + 4 * Pi / 3);
256 float sin1 = sin(mp->ant_step);
257 float sin2 = sin(mp->ant_step + 2 * Pi / 3);
258 float sin3 = sin(mp->ant_step + 4 * Pi / 3);
261 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialGray5);
263 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, Material);
264 glEnable(GL_CULL_FACE);
269 glScalef(1, 1 / 1.3, 1);
270 glTranslatef(0.00, 0.30, 0.00);
274 glTranslatef(-0.05, 0.17, 0.05);
275 glRotatef(-90, 1, 0, 0);
276 glRotatef(-25, 0, 1, 0);
279 glTranslatef(0.00, 0.10, 0.00);
282 glRotatef(25, 0, 1, 0);
283 glRotatef(90, 1, 0, 0);
286 glTranslatef(0.15, -0.65, 0.05);
289 glScalef(1, 1 / 1.3, 1);
291 glDisable(GL_CULL_FACE);
293 glDisable(GL_LIGHTING);
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);
304 glColor3fv(MaterialGray5);
306 glColor3fv(Material);
307 glVertex3f(0.00, 0.30, 0.00);
308 glColor3fv(MaterialGray);
309 glVertex3f(0.40, 0.70, -0.40);
313 glColor3fv(MaterialGray6);
315 glColor3fv(MaterialRed);
316 glVertex3f(0.40, 0.70, 0.40);
317 glVertex3f(0.40, 0.70, -0.40);
321 glBegin(GL_LINE_STRIP);
323 glColor3fv(MaterialGray5);
325 glColor3fv(Material);
326 glVertex3f(0.00, 0.05, 0.18);
327 glVertex3f(0.35 + 0.05 * cos1, 0.15, 0.25);
328 glColor3fv(MaterialGray);
329 glVertex3f(-0.20 + 0.05 * cos1, 0.25 + 0.1 * sin1, 0.45);
332 /* LEFT-CENTER ARM */
333 glBegin(GL_LINE_STRIP);
335 glColor3fv(MaterialGray5);
337 glColor3fv(Material);
338 glVertex3f(0.00, 0.00, 0.18);
339 glVertex3f(0.35 + 0.05 * cos2, 0.00, 0.25);
340 glColor3fv(MaterialGray);
341 glVertex3f(-0.20 + 0.05 * cos2, 0.00 + 0.1 * sin2, 0.45);
345 glBegin(GL_LINE_STRIP);
347 glColor3fv(MaterialGray5);
349 glColor3fv(Material);
350 glVertex3f(0.00, -0.05, 0.18);
351 glVertex3f(0.35 + 0.05 * cos3, -0.15, 0.25);
352 glColor3fv(MaterialGray);
353 glVertex3f(-0.20 + 0.05 * cos3, -0.25 + 0.1 * sin3, 0.45);
356 /* RIGHT-FRONT ARM */
357 glBegin(GL_LINE_STRIP);
359 glColor3fv(MaterialGray5);
361 glColor3fv(Material);
362 glVertex3f(0.00, 0.05, -0.18);
363 glVertex3f(0.35 - 0.05 * sin1, 0.15, -0.25);
364 glColor3fv(MaterialGray);
365 glVertex3f(-0.20 - 0.05 * sin1, 0.25 + 0.1 * cos1, -0.45);
368 /* RIGHT-CENTER ARM */
369 glBegin(GL_LINE_STRIP);
371 glColor3fv(MaterialGray5);
373 glColor3fv(Material);
374 glVertex3f(0.00, 0.00, -0.18);
375 glVertex3f(0.35 - 0.05 * sin2, 0.00, -0.25);
376 glColor3fv(MaterialGray);
377 glVertex3f(-0.20 - 0.05 * sin2, 0.00 + 0.1 * cos2, -0.45);
381 glBegin(GL_LINE_STRIP);
383 glColor3fv(MaterialGray5);
385 glColor3fv(Material);
386 glVertex3f(0.00, -0.05, -0.18);
387 glVertex3f(0.35 - 0.05 * sin3, -0.15, -0.25);
388 glColor3fv(MaterialGray);
389 glVertex3f(-0.20 - 0.05 * sin3, -0.25 + 0.1 * cos3, -0.45);
394 glColor3fv(MaterialGray8);
396 glColor3fv(MaterialMagenta);
397 glVertex3f(-0.20 + 0.05 * cos1, 0.25 + 0.1 * sin1, 0.45);
398 glVertex3f(-0.20 + 0.05 * cos2, 0.00 + 0.1 * sin2, 0.45);
399 glVertex3f(-0.20 + 0.05 * cos3, -0.25 + 0.1 * sin3, 0.45);
400 glVertex3f(-0.20 - 0.05 * sin1, 0.25 + 0.1 * cos1, -0.45);
401 glVertex3f(-0.20 - 0.05 * sin2, 0.00 + 0.1 * cos2, -0.45);
402 glVertex3f(-0.20 - 0.05 * sin3, -0.25 + 0.1 * cos3, -0.45);
405 glEnable(GL_LIGHTING);
412 RotateAaroundU(float Ax, float Ay, float Az,
413 float Ux, float Uy, float Uz,
414 float *Cx, float *Cy, float *Cz,
417 float cosO = cos(Theta);
418 float sinO = sin(Theta);
419 float one_cosO = 1 - cosO;
423 float UxUy = Ux * Uy;
424 float UxUz = Ux * Uz;
425 float UyUz = Uy * Uz;
427 *Cx = (Ux2 + cosO * (1 - Ux2)) * Ax + (UxUy * one_cosO - Uz * sinO) * Ay + (UxUz * one_cosO + Uy * sinO) * Az;
428 *Cy = (UxUy * one_cosO + Uz * sinO) * Ax + (Uy2 + cosO * (1 - Uy2)) * Ay + (UyUz * one_cosO - Ux * sinO) * Az;
429 *Cz = (UxUz * one_cosO - Uy * sinO) * Ax + (UyUz * one_cosO + Ux * sinO) * Ay + (Uz2 + cosO * (1 - Uz2)) * Az;
432 #define MoebiusDivisions 40
433 #define MoebiusTransversals 4
435 draw_moebius_strip(ModeInfo * mi)
439 moebiusstruct *mp = &moebius[MI_SCREEN(mi)];
441 int mono = MI_IS_MONO(mi);
445 #ifdef HAVE_JWZGLES /* #### glPolygonMode other than GL_FILL unimplemented */
450 glBegin(GL_QUAD_STRIP);
453 while (i < (MoebiusDivisions * 2 + 1)) {
460 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialWhite);
462 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialRed);
464 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialGray);
466 RotateAaroundU(cPhi, sPhi, 0, -sPhi, cPhi, 0, &Cx, &Cy, &Cz, Theta);
467 glNormal3f(Cx, Cy, Cz);
468 RotateAaroundU(0, 0, 1, -sPhi, cPhi, 0, &Cx, &Cy, &Cz, Theta);
469 glVertex3f(cPhi * 3 + Cx, sPhi * 3 + Cy, +Cz);
470 glVertex3f(cPhi * 3 - Cx, sPhi * 3 - Cy, -Cz);
472 Phi += Pi / MoebiusDivisions;
476 for (j = -MoebiusTransversals; j < MoebiusTransversals; j++) {
477 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
478 glBegin(GL_QUAD_STRIP);
481 while (i < (MoebiusDivisions * 2 + 1)) {
486 RotateAaroundU(cPhi, sPhi, 0, -sPhi, cPhi, 0, &Cx, &Cy, &Cz, Theta);
487 glNormal3f(Cx, Cy, Cz);
488 RotateAaroundU(0, 0, 1, -sPhi, cPhi, 0, &Cx, &Cy, &Cz, Theta);
490 if (j == MoebiusTransversals || mono)
491 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialWhite);
493 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialRed);
495 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialGray);
496 glVertex3f(cPhi * 3 + Cx / MoebiusTransversals * j, sPhi * 3 + Cy / MoebiusTransversals * j, +Cz / MoebiusTransversals * j);
498 if (j == -MoebiusTransversals || mono)
499 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialWhite);
501 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialRed);
503 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialGray);
504 glVertex3f(cPhi * 3 + Cx / MoebiusTransversals * j, sPhi * 3 + Cy / MoebiusTransversals * j, +Cz / MoebiusTransversals * j);
506 Phi += Pi / MoebiusDivisions;
511 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
517 glRotatef(mp->ant_position + 180, 0, 0, 1);
518 glTranslatef(3, 0, 0);
519 glRotatef(mp->ant_position / 2 + 90, 0, 1, 0);
520 glTranslatef(0.28, 0, -0.45);
521 if (!draw_moebius_ant(mp, MaterialYellow, mono))
525 /* DRAW YELLOW ANT */
527 glRotatef(mp->ant_position, 0, 0, 1);
528 glTranslatef(3, 0, 0);
529 glRotatef(mp->ant_position / 2, 0, 1, 0);
530 glTranslatef(0.28, 0, -0.45);
531 if (!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 if (!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 if (!draw_moebius_ant(mp, MaterialCyan, mono))
557 mp->ant_position += 1;
560 #undef MoebiusDivisions
561 #undef MoebiusTransversals
564 reshape_moebius (ModeInfo * mi, int width, int height)
566 moebiusstruct *mp = &moebius[MI_SCREEN(mi)];
569 if (width > height * 5) { /* tiny window: show middle */
574 glViewport(0, y, mp->WindW = (GLint) width, mp->WindH = (GLint) height);
575 glMatrixMode(GL_PROJECTION);
577 glFrustum(-1.0, 1.0, -1.0, 1.0, 5.0, 15.0);
578 glMatrixMode(GL_MODELVIEW);
582 } else if (width >= 512) {
596 glLightfv(GL_LIGHT0, GL_AMBIENT, ambient);
597 glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse);
598 glLightfv(GL_LIGHT0, GL_POSITION, position0);
599 glLightfv(GL_LIGHT1, GL_AMBIENT, ambient);
600 glLightfv(GL_LIGHT1, GL_DIFFUSE, diffuse);
601 glLightfv(GL_LIGHT1, GL_POSITION, position1);
602 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient);
603 glLightModelfv(GL_LIGHT_MODEL_TWO_SIDE, lmodel_twoside);
604 glEnable(GL_LIGHTING);
607 glEnable(GL_NORMALIZE);
612 glShadeModel(GL_SMOOTH);
613 glEnable(GL_DEPTH_TEST);
614 glDisable(GL_CULL_FACE);
617 glEnable(GL_TEXTURE_2D);
618 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
622 status = gluBuild2DMipmaps(GL_TEXTURE_2D, 3,
623 WoodTextureWidth, WoodTextureHeight,
624 GL_RGB, GL_UNSIGNED_BYTE, WoodTextureData);
627 const char *s = (char *) gluErrorString (status);
628 fprintf (stderr, "%s: error mipmapping %dx%d texture: %s\n",
629 progname, WoodTextureWidth, WoodTextureHeight,
630 (s ? s : "(unknown)"));
633 check_gl_error("mipmapping");
636 XImage *img = image_data_to_ximage (mi->dpy, mi->xgwa.visual,
637 wood_png, sizeof(wood_png));
638 glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA,
639 img->width, img->height, 0,
641 /* GL_UNSIGNED_BYTE, */
642 GL_UNSIGNED_INT_8_8_8_8_REV,
644 check_gl_error("texture");
649 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
650 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
651 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
652 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
653 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
656 glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, front_shininess);
657 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, front_specular);
662 moebius_handle_event (ModeInfo *mi, XEvent *event)
664 moebiusstruct *mp = &moebius[MI_SCREEN(mi)];
666 if (gltrackball_event_handler (event, mp->trackball,
667 MI_WIDTH (mi), MI_HEIGHT (mi),
676 init_moebius (ModeInfo * mi)
680 MI_INIT (mi, moebius);
681 mp = &moebius[MI_SCREEN(mi)];
682 mp->step = NRAND(90);
683 mp->ant_position = NRAND(90);
686 double rot_speed = 0.3;
687 mp->rot = make_rotator (rot_speed, rot_speed, rot_speed, 1, 0, True);
688 mp->trackball = gltrackball_init (True);
691 if ((mp->glx_context = init_GL(mi)) != NULL) {
693 reshape_moebius(mi, MI_WIDTH(mi), MI_HEIGHT(mi));
694 glDrawBuffer(GL_BACK);
702 draw_moebius (ModeInfo * mi)
706 Display *display = MI_DISPLAY(mi);
707 Window window = MI_WINDOW(mi);
711 mp = &moebius[MI_SCREEN(mi)];
713 MI_IS_DRAWN(mi) = True;
715 if (!mp->glx_context)
718 glXMakeCurrent(display, window, *(mp->glx_context));
720 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
725 glTranslatef(0.0, 0.0, -10.0);
727 gltrackball_rotate (mp->trackball);
729 if (!MI_IS_ICONIC(mi)) {
730 glScalef(Scale4Window * mp->WindH / mp->WindW, Scale4Window, Scale4Window);
732 glScalef(Scale4Iconic * mp->WindH / mp->WindW, Scale4Iconic, Scale4Iconic);
735 # ifdef HAVE_MOBILE /* Keep it the same relative size when rotated. */
737 GLfloat h = MI_HEIGHT(mi) / (GLfloat) MI_WIDTH(mi);
738 int o = (int) current_device_rotation();
739 if (o != 0 && o != 180 && o != -180) {
740 glScalef (1/h, h, 1); /* #### not quite right */
749 get_rotation (mp->rot, &x, &y, &z, !mp->button_down_p);
750 glRotatef (x * 360, 1.0, 0.0, 0.0);
751 glRotatef (y * 360, 0.0, 1.0, 0.0);
752 glRotatef (z * 360, 0.0, 0.0, 1.0);
756 if (!draw_moebius_strip(mi)) {
763 if (MI_IS_FPS(mi)) do_fps (mi);
766 glXSwapBuffers(display, window);
773 change_moebius (ModeInfo * mi)
775 moebiusstruct *mp = &moebius[MI_SCREEN(mi)];
777 if (!mp->glx_context)
780 glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(mp->glx_context));
783 #endif /* !STANDALONE */
786 XSCREENSAVER_MODULE ("Moebius", moebius)