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).
81 #include <X11/Intrinsic.h>
86 # define PROGCLASS "Moebius"
87 # define HACK_INIT init_moebius
88 # define HACK_DRAW draw_moebius
89 # define HACK_RESHAPE reshape_moebius
90 # define HACK_HANDLE_EVENT moebius_handle_event
91 # define EVENT_MASK PointerMotionMask
92 # define moebius_opts xlockmore_opts
93 # define DEFAULTS "*delay: 20000 \n" \
95 # include "xlockmore.h" /* from the xscreensaver distribution */
96 #else /* !STANDALONE */
97 # include "xlock.h" /* from the xlockmore distribution */
99 #endif /* !STANDALONE */
105 #include "e_textures.h"
107 #include "gltrackball.h"
109 #define DEF_SOLIDMOEBIUS "False"
110 #define DEF_NOANTS "False"
112 static int solidmoebius;
115 static XrmOptionDescRec opts[] =
117 {"-solidmoebius", ".moebius.solidmoebius", XrmoptionNoArg, "on"},
118 {"+solidmoebius", ".moebius.solidmoebius", XrmoptionNoArg, "off"},
119 {"-noants", ".moebius.noants", XrmoptionNoArg, "on"},
120 {"+noants", ".moebius.noants", XrmoptionNoArg, "off"}
122 static argtype vars[] =
124 {&solidmoebius, "solidmoebius", "Solidmoebius", DEF_SOLIDMOEBIUS, t_Bool},
125 {&noants, "noants", "Noants", DEF_NOANTS, t_Bool}
128 static OptionStruct desc[] =
130 {"-/+solidmoebius", "select between a SOLID or a NET Moebius Strip"},
131 {"-/+noants", "turn on/off walking ants"}
134 ModeSpecOpt moebius_opts =
135 {sizeof opts / sizeof opts[0], opts, sizeof vars / sizeof vars[0], vars, desc};
138 ModStruct moebius_description =
139 {"moebius", "init_moebius", "draw_moebius", "release_moebius",
140 "draw_moebius", "change_moebius", (char *) NULL, &moebius_opts,
141 1000, 1, 1, 1, 4, 1.0, "",
142 "Shows Moebius Strip II, an Escher-like GL scene with ants", 0, NULL};
146 #define Scale4Window 0.3
147 #define Scale4Iconic 0.4
149 #define sqr(A) ((A)*(A))
155 #define ObjMoebiusStrip 0
159 /*************************************************************************/
164 GLfloat ant_position;
165 GLXContext *glx_context;
167 trackball_state *trackball;
171 static float front_shininess[] =
173 static float front_specular[] =
174 {0.7, 0.7, 0.7, 1.0};
175 static float ambient[] =
176 {0.0, 0.0, 0.0, 1.0};
177 static float diffuse[] =
178 {1.0, 1.0, 1.0, 1.0};
179 static float position0[] =
180 {1.0, 1.0, 1.0, 0.0};
181 static float position1[] =
182 {-1.0, -1.0, 1.0, 0.0};
183 static float lmodel_ambient[] =
184 {0.5, 0.5, 0.5, 1.0};
185 static float lmodel_twoside[] =
188 static float MaterialRed[] =
189 {0.7, 0.0, 0.0, 1.0};
190 static float MaterialGreen[] =
191 {0.1, 0.5, 0.2, 1.0};
192 static float MaterialBlue[] =
193 {0.0, 0.0, 0.7, 1.0};
194 static float MaterialCyan[] =
195 {0.2, 0.5, 0.7, 1.0};
196 static float MaterialYellow[] =
197 {0.7, 0.7, 0.0, 1.0};
198 static float MaterialMagenta[] =
199 {0.6, 0.2, 0.5, 1.0};
200 static float MaterialWhite[] =
201 {0.7, 0.7, 0.7, 1.0};
202 static float MaterialGray[] =
203 {0.2, 0.2, 0.2, 1.0};
204 static float MaterialGray5[] =
205 {0.5, 0.5, 0.5, 1.0};
206 static float MaterialGray6[] =
207 {0.6, 0.6, 0.6, 1.0};
208 static float MaterialGray8[] =
209 {0.8, 0.8, 0.8, 1.0};
211 static moebiusstruct *moebius = (moebiusstruct *) NULL;
216 mySphere(float radius)
218 GLUquadricObj *quadObj;
220 if ((quadObj = gluNewQuadric()) == 0)
222 gluQuadricDrawStyle(quadObj, (GLenum) GLU_FILL);
223 gluSphere(quadObj, radius, 16, 16);
224 gluDeleteQuadric(quadObj);
231 GLUquadricObj *quadObj;
233 if ((quadObj = gluNewQuadric()) == 0)
235 gluQuadricDrawStyle(quadObj, (GLenum) GLU_FILL);
236 gluCylinder(quadObj, radius, 0, radius * 3, 8, 1);
237 gluDeleteQuadric(quadObj);
242 draw_moebius_ant(moebiusstruct * mp, float *Material, int mono)
244 static float ant_step = 0;
245 float cos1 = cos(ant_step);
246 float cos2 = cos(ant_step + 2 * Pi / 3);
247 float cos3 = cos(ant_step + 4 * Pi / 3);
248 float sin1 = sin(ant_step);
249 float sin2 = sin(ant_step + 2 * Pi / 3);
250 float sin3 = sin(ant_step + 4 * Pi / 3);
253 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialGray5);
255 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, Material);
256 glEnable(GL_CULL_FACE);
261 glScalef(1, 1 / 1.3, 1);
262 glTranslatef(0.00, 0.30, 0.00);
266 glTranslatef(-0.05, 0.17, 0.05);
267 glRotatef(-90, 1, 0, 0);
268 glRotatef(-25, 0, 1, 0);
271 glTranslatef(0.00, 0.10, 0.00);
274 glRotatef(25, 0, 1, 0);
275 glRotatef(90, 1, 0, 0);
278 glTranslatef(0.15, -0.65, 0.05);
281 glScalef(1, 1 / 1.3, 1);
283 glDisable(GL_CULL_FACE);
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);
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);
438 glBegin(GL_QUAD_STRIP);
441 while (i < (MoebiusDivisions * 2 + 1)) {
448 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialWhite);
450 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialRed);
452 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialGray);
454 RotateAaroundU(cPhi, sPhi, 0, -sPhi, cPhi, 0, &Cx, &Cy, &Cz, Theta);
455 glNormal3f(Cx, Cy, Cz);
456 RotateAaroundU(0, 0, 1, -sPhi, cPhi, 0, &Cx, &Cy, &Cz, Theta);
457 glVertex3f(cPhi * 3 + Cx, sPhi * 3 + Cy, +Cz);
458 glVertex3f(cPhi * 3 - Cx, sPhi * 3 - Cy, -Cz);
460 Phi += Pi / MoebiusDivisions;
464 for (j = -MoebiusTransversals; j < MoebiusTransversals; j++) {
465 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
466 glBegin(GL_QUAD_STRIP);
469 while (i < (MoebiusDivisions * 2 + 1)) {
474 RotateAaroundU(cPhi, sPhi, 0, -sPhi, cPhi, 0, &Cx, &Cy, &Cz, Theta);
475 glNormal3f(Cx, Cy, Cz);
476 RotateAaroundU(0, 0, 1, -sPhi, cPhi, 0, &Cx, &Cy, &Cz, Theta);
478 if (j == MoebiusTransversals || mono)
479 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialWhite);
481 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialRed);
483 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialGray);
484 glVertex3f(cPhi * 3 + Cx / MoebiusTransversals * j, sPhi * 3 + Cy / MoebiusTransversals * j, +Cz / MoebiusTransversals * j);
486 if (j == -MoebiusTransversals || mono)
487 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialWhite);
489 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialRed);
491 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialGray);
492 glVertex3f(cPhi * 3 + Cx / MoebiusTransversals * j, sPhi * 3 + Cy / MoebiusTransversals * j, +Cz / MoebiusTransversals * j);
494 Phi += Pi / MoebiusDivisions;
499 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
505 glRotatef(mp->ant_position + 180, 0, 0, 1);
506 glTranslatef(3, 0, 0);
507 glRotatef(mp->ant_position / 2 + 90, 0, 1, 0);
508 glTranslatef(0.28, 0, -0.45);
509 if (!draw_moebius_ant(mp, MaterialYellow, mono))
513 /* DRAW YELLOW ANT */
515 glRotatef(mp->ant_position, 0, 0, 1);
516 glTranslatef(3, 0, 0);
517 glRotatef(mp->ant_position / 2, 0, 1, 0);
518 glTranslatef(0.28, 0, -0.45);
519 if (!draw_moebius_ant(mp, MaterialBlue, mono))
525 glRotatef(-mp->ant_position, 0, 0, 1);
526 glTranslatef(3, 0, 0);
527 glRotatef(-mp->ant_position / 2, 0, 1, 0);
528 glTranslatef(0.28, 0, 0.45);
529 glRotatef(180, 1, 0, 0);
530 if (!draw_moebius_ant(mp, MaterialGreen, mono))
536 glRotatef(-mp->ant_position + 180, 0, 0, 1);
537 glTranslatef(3, 0, 0);
538 glRotatef(-mp->ant_position / 2 + 90, 0, 1, 0);
539 glTranslatef(0.28, 0, 0.45);
540 glRotatef(180, 1, 0, 0);
541 if (!draw_moebius_ant(mp, MaterialCyan, mono))
545 mp->ant_position += 1;
548 #undef MoebiusDivisions
549 #undef MoebiusTransversals
552 reshape_moebius(ModeInfo * mi, int width, int height)
554 moebiusstruct *mp = &moebius[MI_SCREEN(mi)];
556 glViewport(0, 0, mp->WindW = (GLint) width, mp->WindH = (GLint) height);
557 glMatrixMode(GL_PROJECTION);
559 glFrustum(-1.0, 1.0, -1.0, 1.0, 5.0, 15.0);
560 glMatrixMode(GL_MODELVIEW);
564 } else if (width >= 512) {
578 glClearColor(0.0, 0.0, 0.0, 1.0);
580 glLightfv(GL_LIGHT0, GL_AMBIENT, ambient);
581 glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse);
582 glLightfv(GL_LIGHT0, GL_POSITION, position0);
583 glLightfv(GL_LIGHT1, GL_AMBIENT, ambient);
584 glLightfv(GL_LIGHT1, GL_DIFFUSE, diffuse);
585 glLightfv(GL_LIGHT1, GL_POSITION, position1);
586 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient);
587 glLightModelfv(GL_LIGHT_MODEL_TWO_SIDE, lmodel_twoside);
588 glEnable(GL_LIGHTING);
591 glEnable(GL_NORMALIZE);
596 glShadeModel(GL_SMOOTH);
597 glEnable(GL_DEPTH_TEST);
598 glDisable(GL_TEXTURE_2D);
599 glDisable(GL_CULL_FACE);
601 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
604 status = gluBuild2DMipmaps(GL_TEXTURE_2D, 3,
605 WoodTextureWidth, WoodTextureHeight,
606 GL_RGB, GL_UNSIGNED_BYTE, WoodTextureData);
609 const char *s = (char *) gluErrorString (status);
610 fprintf (stderr, "%s: error mipmapping %dx%d texture: %s\n",
611 progname, WoodTextureWidth, WoodTextureHeight,
612 (s ? s : "(unknown)"));
615 check_gl_error("mipmapping");
617 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
618 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
619 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
620 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
621 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
623 glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, front_shininess);
624 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, front_specular);
630 release_moebius(ModeInfo * mi)
632 if (moebius != NULL) {
633 (void) free((void *) moebius);
634 moebius = (moebiusstruct *) NULL;
640 moebius_handle_event (ModeInfo *mi, XEvent *event)
642 moebiusstruct *mp = &moebius[MI_SCREEN(mi)];
644 if (event->xany.type == ButtonPress &&
645 event->xbutton.button == Button1)
647 mp->button_down_p = True;
648 gltrackball_start (mp->trackball,
649 event->xbutton.x, event->xbutton.y,
650 MI_WIDTH (mi), MI_HEIGHT (mi));
653 else if (event->xany.type == ButtonRelease &&
654 event->xbutton.button == Button1)
656 mp->button_down_p = False;
659 else if (event->xany.type == ButtonPress &&
660 (event->xbutton.button == Button4 ||
661 event->xbutton.button == Button5))
663 gltrackball_mousewheel (mp->trackball, event->xbutton.button, 10,
664 !!event->xbutton.state);
667 else if (event->xany.type == MotionNotify &&
670 gltrackball_track (mp->trackball,
671 event->xmotion.x, event->xmotion.y,
672 MI_WIDTH (mi), MI_HEIGHT (mi));
681 init_moebius(ModeInfo * mi)
685 if (moebius == NULL) {
686 if ((moebius = (moebiusstruct *) calloc(MI_NUM_SCREENS(mi),
687 sizeof (moebiusstruct))) == NULL)
690 mp = &moebius[MI_SCREEN(mi)];
691 mp->step = NRAND(90);
692 mp->ant_position = NRAND(90);
695 double rot_speed = 0.3;
696 mp->rot = make_rotator (rot_speed, rot_speed, rot_speed, 1, 0, True);
697 mp->trackball = gltrackball_init ();
700 if ((mp->glx_context = init_GL(mi)) != NULL) {
702 reshape_moebius(mi, MI_WIDTH(mi), MI_HEIGHT(mi));
703 glDrawBuffer(GL_BACK);
711 draw_moebius(ModeInfo * mi)
715 Display *display = MI_DISPLAY(mi);
716 Window window = MI_WINDOW(mi);
720 mp = &moebius[MI_SCREEN(mi)];
722 MI_IS_DRAWN(mi) = True;
724 if (!mp->glx_context)
727 glXMakeCurrent(display, window, *(mp->glx_context));
729 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
733 glTranslatef(0.0, 0.0, -10.0);
735 gltrackball_rotate (mp->trackball);
737 if (!MI_IS_ICONIC(mi)) {
738 glScalef(Scale4Window * mp->WindH / mp->WindW, Scale4Window, Scale4Window);
740 glScalef(Scale4Iconic * mp->WindH / mp->WindW, Scale4Iconic, Scale4Iconic);
745 get_rotation (mp->rot, &x, &y, &z, !mp->button_down_p);
746 glRotatef (x * 360, 1.0, 0.0, 0.0);
747 glRotatef (y * 360, 0.0, 1.0, 0.0);
748 glRotatef (z * 360, 0.0, 0.0, 1.0);
752 if (!draw_moebius_strip(mi)) {
759 if (MI_IS_FPS(mi)) do_fps (mi);
762 glXSwapBuffers(display, window);
768 change_moebius(ModeInfo * mi)
770 moebiusstruct *mp = &moebius[MI_SCREEN(mi)];
772 if (!mp->glx_context)
775 glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(mp->glx_context));