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 5.01 2001/03/01 xlockmore";
10 * Permission to use, copy, modify, and distribute this software and its
11 * documentation for any purpose and without fee is hereby granted,
12 * provided that the above copyright notice appear in all copies and that
13 * both that copyright notice and this permission notice appear in
14 * supporting documentation.
16 * This file is provided AS IS with no warranties of any kind. The author
17 * shall have no liability with respect to the infringement of copyrights,
18 * trade secrets or any patents by this file or any part thereof. In no
19 * event will the author be liable for any lost revenue or profits or
20 * other special, indirect and consequential damages.
22 * The RotateAroundU() routine was adapted from the book
23 * "Computer Graphics Principles and Practice
24 * Foley - vanDam - Feiner - Hughes
25 * Second Edition" Pag. 227, exercise 5.15.
27 * This mode shows some interesting scenes that are impossible OR very
28 * wierd to build in the real universe. Much of the scenes are inspirated
29 * on Mauritz Cornelis Escher's works which derivated the mode's name.
30 * M.C. Escher (1898-1972) was a dutch artist and many people prefer to
31 * say he was a mathematician.
33 * Thanks goes to Brian Paul for making it possible and inexpensive to use
36 * Since I'm not a native English speaker, my apologies for any grammatical
39 * My e-mail address is
40 * mfvianna@centroin.com.br
42 * Marcelo F. Vianna (Jun-01-1997)
45 * 05-Apr-2002: Removed all gllist uses (fix some bug with nvidia driver)
46 * 01-Mar-2001: backported from xscreensaver by lassauge@mail.dotcom.fr
47 * Feb-2001: Made motion and rotation be smoother Jamie Zawinski
49 * 01-Nov-2000: Allocation checks
50 * 01-Jan-1998: Mode separated from escher and renamed
51 * 08-Jun-1997: New scene implemented: "Impossible Cage" based in a M.C.
52 * Escher's painting with the same name (quite similar). The
53 * first GL mode to use texture mapping.
54 * The "Impossible Cage" scene doesn't use DEPTH BUFFER, the
55 * wood planks are drawn consistently using GL_CULL_FACE, and
56 * the painter's algorithm is used to sort the planks.
58 * 07-Jun-1997: Speed ups in Moebius Strip using GL_CULL_FACE.
60 * 03-Jun-1997: Initial Release (Only one scene: "Moebius Strip")
61 * The Moebius Strip scene was inspirated in a M.C. Escher's
62 * painting named Moebius Strip II in wich ants walk across a
63 * Moebius Strip path, sometimes meeting each other and sometimes
64 * being in "opposite faces" (note that the moebius strip has
65 * only one face and one edge).
70 * Texture mapping is only available on RGBA contexts, Mono and color index
71 * visuals DO NOT support texture mapping in OpenGL.
73 * BUT Mesa do implements RGBA contexts in pseudo color visuals, so texture
74 * mapping shuld work on PseudoColor, DirectColor, TrueColor using Mesa. Mono
75 * is not officially supported for both OpenGL and Mesa, but seems to not crash
78 * In real OpenGL, PseudoColor DO NOT support texture map (as far as I know).
82 #include <X11/Intrinsic.h>
87 # define PROGCLASS "Moebius"
88 # define HACK_INIT init_moebius
89 # define HACK_DRAW draw_moebius
90 # define HACK_RESHAPE reshape_moebius
91 # define moebius_opts xlockmore_opts
92 # define DEFAULTS "*delay: 20000 \n" \
93 "*showFPS: False \n" \
94 "*wireframe: False \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 #define DEF_SOLIDMOEBIUS "False"
108 #define DEF_NOANTS "False"
110 static int solidmoebius;
113 static XrmOptionDescRec opts[] =
115 {(char *) "-solidmoebius", (char *) ".moebius.solidmoebius", XrmoptionNoArg, (caddr_t) "on"},
116 {(char *) "+solidmoebius", (char *) ".moebius.solidmoebius", XrmoptionNoArg, (caddr_t) "off"},
117 {(char *) "-noants", (char *) ".moebius.noants", XrmoptionNoArg, (caddr_t) "on"},
118 {(char *) "+noants", (char *) ".moebius.noants", XrmoptionNoArg, (caddr_t) "off"}
120 static argtype vars[] =
122 {(caddr_t *) & solidmoebius, (char *) "solidmoebius", (char *) "Solidmoebius", (char *) DEF_SOLIDMOEBIUS, t_Bool},
123 {(caddr_t *) & noants, (char *) "noants", (char *) "Noants", (char *) DEF_NOANTS, t_Bool}
126 static OptionStruct desc[] =
128 {(char *) "-/+solidmoebius", (char *) "select between a SOLID or a NET Moebius Strip"},
129 {(char *) "-/+noants", (char *) "turn on/off walking ants"}
132 ModeSpecOpt moebius_opts =
133 {sizeof opts / sizeof opts[0], opts, sizeof vars / sizeof vars[0], vars, desc};
136 ModStruct moebius_description =
137 {"moebius", "init_moebius", "draw_moebius", "release_moebius",
138 "draw_moebius", "change_moebius", (char *) NULL, &moebius_opts,
139 1000, 1, 1, 1, 4, 1.0, "",
140 "Shows Moebius Strip II, an Escher-like GL scene with ants", 0, NULL};
144 #define Scale4Window 0.3
145 #define Scale4Iconic 0.4
147 #define sqr(A) ((A)*(A))
153 #define ObjMoebiusStrip 0
157 /*************************************************************************/
162 GLfloat ant_position;
163 GLXContext *glx_context;
165 GLfloat rotx, roty, rotz; /* current object rotation */
166 GLfloat dx, dy, dz; /* current rotational velocity */
167 GLfloat ddx, ddy, ddz; /* current rotational acceleration */
168 GLfloat d_max; /* max velocity */
172 static float front_shininess[] =
174 static float front_specular[] =
175 {0.7, 0.7, 0.7, 1.0};
176 static float ambient[] =
177 {0.0, 0.0, 0.0, 1.0};
178 static float diffuse[] =
179 {1.0, 1.0, 1.0, 1.0};
180 static float position0[] =
181 {1.0, 1.0, 1.0, 0.0};
182 static float position1[] =
183 {-1.0, -1.0, 1.0, 0.0};
184 static float lmodel_ambient[] =
185 {0.5, 0.5, 0.5, 1.0};
186 static float lmodel_twoside[] =
189 static float MaterialRed[] =
190 {0.7, 0.0, 0.0, 1.0};
191 static float MaterialGreen[] =
192 {0.1, 0.5, 0.2, 1.0};
193 static float MaterialBlue[] =
194 {0.0, 0.0, 0.7, 1.0};
195 static float MaterialCyan[] =
196 {0.2, 0.5, 0.7, 1.0};
197 static float MaterialYellow[] =
198 {0.7, 0.7, 0.0, 1.0};
199 static float MaterialMagenta[] =
200 {0.6, 0.2, 0.5, 1.0};
201 static float MaterialWhite[] =
202 {0.7, 0.7, 0.7, 1.0};
203 static float MaterialGray[] =
204 {0.2, 0.2, 0.2, 1.0};
205 static float MaterialGray5[] =
206 {0.5, 0.5, 0.5, 1.0};
207 static float MaterialGray6[] =
208 {0.6, 0.6, 0.6, 1.0};
209 static float MaterialGray8[] =
210 {0.8, 0.8, 0.8, 1.0};
212 static moebiusstruct *moebius = (moebiusstruct *) NULL;
217 mySphere(float radius)
219 GLUquadricObj *quadObj;
221 if ((quadObj = gluNewQuadric()) == 0)
223 gluQuadricDrawStyle(quadObj, (GLenum) GLU_FILL);
224 gluSphere(quadObj, radius, 16, 16);
225 gluDeleteQuadric(quadObj);
232 GLUquadricObj *quadObj;
234 if ((quadObj = gluNewQuadric()) == 0)
236 gluQuadricDrawStyle(quadObj, (GLenum) GLU_FILL);
237 gluCylinder(quadObj, radius, 0, radius * 3, 8, 1);
238 gluDeleteQuadric(quadObj);
243 draw_moebius_ant(moebiusstruct * mp, float *Material, int mono)
245 static float ant_step = 0;
246 float cos1 = cos(ant_step);
247 float cos2 = cos(ant_step + 2 * Pi / 3);
248 float cos3 = cos(ant_step + 4 * Pi / 3);
249 float sin1 = sin(ant_step);
250 float sin2 = sin(ant_step + 2 * Pi / 3);
251 float sin3 = sin(ant_step + 4 * Pi / 3);
254 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialGray5);
256 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, Material);
257 glEnable(GL_CULL_FACE);
262 glScalef(1, 1 / 1.3, 1);
263 glTranslatef(0.00, 0.30, 0.00);
267 glTranslatef(-0.05, 0.17, 0.05);
268 glRotatef(-90, 1, 0, 0);
269 glRotatef(-25, 0, 1, 0);
272 glTranslatef(0.00, 0.10, 0.00);
275 glRotatef(25, 0, 1, 0);
276 glRotatef(90, 1, 0, 0);
279 glTranslatef(0.15, -0.65, 0.05);
282 glScalef(1, 1 / 1.3, 1);
284 glDisable(GL_CULL_FACE);
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);
405 RotateAaroundU(float Ax, float Ay, float Az,
406 float Ux, float Uy, float Uz,
407 float *Cx, float *Cy, float *Cz,
410 float cosO = cos(Theta);
411 float sinO = sin(Theta);
412 float one_cosO = 1 - cosO;
416 float UxUy = Ux * Uy;
417 float UxUz = Ux * Uz;
418 float UyUz = Uy * Uz;
420 *Cx = (Ux2 + cosO * (1 - Ux2)) * Ax + (UxUy * one_cosO - Uz * sinO) * Ay + (UxUz * one_cosO + Uy * sinO) * Az;
421 *Cy = (UxUy * one_cosO + Uz * sinO) * Ax + (Uy2 + cosO * (1 - Uy2)) * Ay + (UyUz * one_cosO - Ux * sinO) * Az;
422 *Cz = (UxUz * one_cosO - Uy * sinO) * Ax + (UyUz * one_cosO + Ux * sinO) * Ay + (Uz2 + cosO * (1 - Uz2)) * Az;
425 #define MoebiusDivisions 40
426 #define MoebiusTransversals 4
428 draw_moebius_strip(ModeInfo * mi)
432 moebiusstruct *mp = &moebius[MI_SCREEN(mi)];
434 int mono = MI_IS_MONO(mi);
439 glBegin(GL_QUAD_STRIP);
442 while (i < (MoebiusDivisions * 2 + 1)) {
449 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialWhite);
451 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialRed);
453 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialGray);
455 RotateAaroundU(cPhi, sPhi, 0, -sPhi, cPhi, 0, &Cx, &Cy, &Cz, Theta);
456 glNormal3f(Cx, Cy, Cz);
457 RotateAaroundU(0, 0, 1, -sPhi, cPhi, 0, &Cx, &Cy, &Cz, Theta);
458 glVertex3f(cPhi * 3 + Cx, sPhi * 3 + Cy, +Cz);
459 glVertex3f(cPhi * 3 - Cx, sPhi * 3 - Cy, -Cz);
461 Phi += Pi / MoebiusDivisions;
465 for (j = -MoebiusTransversals; j < MoebiusTransversals; j++) {
466 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
467 glBegin(GL_QUAD_STRIP);
470 while (i < (MoebiusDivisions * 2 + 1)) {
475 RotateAaroundU(cPhi, sPhi, 0, -sPhi, cPhi, 0, &Cx, &Cy, &Cz, Theta);
476 glNormal3f(Cx, Cy, Cz);
477 RotateAaroundU(0, 0, 1, -sPhi, cPhi, 0, &Cx, &Cy, &Cz, Theta);
479 if (j == MoebiusTransversals || mono)
480 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialWhite);
482 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialRed);
484 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialGray);
485 glVertex3f(cPhi * 3 + Cx / MoebiusTransversals * j, sPhi * 3 + Cy / MoebiusTransversals * j, +Cz / MoebiusTransversals * j);
487 if (j == -MoebiusTransversals || mono)
488 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialWhite);
490 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialRed);
492 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialGray);
493 glVertex3f(cPhi * 3 + Cx / MoebiusTransversals * j, sPhi * 3 + Cy / MoebiusTransversals * j, +Cz / MoebiusTransversals * j);
495 Phi += Pi / MoebiusDivisions;
500 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
506 glRotatef(mp->ant_position + 180, 0, 0, 1);
507 glTranslatef(3, 0, 0);
508 glRotatef(mp->ant_position / 2 + 90, 0, 1, 0);
509 glTranslatef(0.28, 0, -0.45);
510 if (!draw_moebius_ant(mp, MaterialYellow, mono))
514 /* DRAW YELLOW ANT */
516 glRotatef(mp->ant_position, 0, 0, 1);
517 glTranslatef(3, 0, 0);
518 glRotatef(mp->ant_position / 2, 0, 1, 0);
519 glTranslatef(0.28, 0, -0.45);
520 if (!draw_moebius_ant(mp, MaterialBlue, mono))
526 glRotatef(-mp->ant_position, 0, 0, 1);
527 glTranslatef(3, 0, 0);
528 glRotatef(-mp->ant_position / 2, 0, 1, 0);
529 glTranslatef(0.28, 0, 0.45);
530 glRotatef(180, 1, 0, 0);
531 if (!draw_moebius_ant(mp, MaterialGreen, mono))
537 glRotatef(-mp->ant_position + 180, 0, 0, 1);
538 glTranslatef(3, 0, 0);
539 glRotatef(-mp->ant_position / 2 + 90, 0, 1, 0);
540 glTranslatef(0.28, 0, 0.45);
541 glRotatef(180, 1, 0, 0);
542 if (!draw_moebius_ant(mp, MaterialCyan, mono))
546 mp->ant_position += 1;
549 #undef MoebiusDivisions
550 #undef MoebiusTransversals
553 reshape_moebius(ModeInfo * mi, int width, int height)
555 moebiusstruct *mp = &moebius[MI_SCREEN(mi)];
557 glViewport(0, 0, mp->WindW = (GLint) width, mp->WindH = (GLint) height);
558 glMatrixMode(GL_PROJECTION);
560 glFrustum(-1.0, 1.0, -1.0, 1.0, 5.0, 15.0);
561 glMatrixMode(GL_MODELVIEW);
565 } else if (width >= 512) {
579 glClearColor(0.0, 0.0, 0.0, 1.0);
581 glLightfv(GL_LIGHT0, GL_AMBIENT, ambient);
582 glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse);
583 glLightfv(GL_LIGHT0, GL_POSITION, position0);
584 glLightfv(GL_LIGHT1, GL_AMBIENT, ambient);
585 glLightfv(GL_LIGHT1, GL_DIFFUSE, diffuse);
586 glLightfv(GL_LIGHT1, GL_POSITION, position1);
587 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient);
588 glLightModelfv(GL_LIGHT_MODEL_TWO_SIDE, lmodel_twoside);
589 glEnable(GL_LIGHTING);
592 glEnable(GL_NORMALIZE);
597 glShadeModel(GL_SMOOTH);
598 glEnable(GL_DEPTH_TEST);
599 glDisable(GL_TEXTURE_2D);
600 glDisable(GL_CULL_FACE);
602 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
605 status = gluBuild2DMipmaps(GL_TEXTURE_2D, 3,
606 WoodTextureWidth, WoodTextureHeight,
607 GL_RGB, GL_UNSIGNED_BYTE, WoodTextureData);
610 const char *s = gluErrorString (status);
611 fprintf (stderr, "%s: error mipmapping %dx%d texture: %s\n",
612 progname, WoodTextureWidth, WoodTextureHeight,
613 (s ? s : "(unknown)"));
616 check_gl_error("mipmapping");
618 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
619 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
620 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
621 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
622 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
624 glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, front_shininess);
625 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, front_specular);
630 /* lifted from lament.c */
631 #define RANDSIGN() ((LRAND() & 1) ? 1 : -1)
632 #define FLOATRAND(a) (((double)LRAND() / (double)MAXRAND) * a)
635 rotate(GLfloat *pos, GLfloat *v, GLfloat *dv, GLfloat max_v, Bool verbose)
650 if ((ppos < 0.0) || (ppos > 1.0)) {
652 (void) fprintf(stderr, "Weirdness in rotate()\n");
653 (void) fprintf(stderr, "ppos = %g\n", ppos);
658 *pos = (*pos > 0 ? ppos : -ppos);
664 if (*v > max_v || *v < -max_v)
668 /* If it stops, start it going in the other direction. */
675 /* keep going in the same direction */
690 /* Alter direction of rotational acceleration randomly. */
691 if (! (random() % 120))
694 /* Change acceleration very occasionally. */
695 if (! (random() % 200))
699 else if (random() & 1)
707 release_moebius(ModeInfo * mi)
709 if (moebius != NULL) {
710 (void) free((void *) moebius);
711 moebius = (moebiusstruct *) NULL;
717 init_moebius(ModeInfo * mi)
721 if (moebius == NULL) {
722 if ((moebius = (moebiusstruct *) calloc(MI_NUM_SCREENS(mi),
723 sizeof (moebiusstruct))) == NULL)
726 mp = &moebius[MI_SCREEN(mi)];
727 mp->step = NRAND(90);
728 mp->ant_position = NRAND(90);
730 mp->rotx = FLOATRAND(1.0) * RANDSIGN();
731 mp->roty = FLOATRAND(1.0) * RANDSIGN();
732 mp->rotz = FLOATRAND(1.0) * RANDSIGN();
734 /* bell curve from 0-1.5 degrees, avg 0.75 */
735 mp->dx = (FLOATRAND(1) + FLOATRAND(1) + FLOATRAND(1)) / (360*2);
736 mp->dy = (FLOATRAND(1) + FLOATRAND(1) + FLOATRAND(1)) / (360*2);
737 mp->dz = (FLOATRAND(1) + FLOATRAND(1) + FLOATRAND(1)) / (360*2);
739 mp->d_max = mp->dx * 2;
741 mp->ddx = 0.00006 + FLOATRAND(0.00003);
742 mp->ddy = 0.00006 + FLOATRAND(0.00003);
743 mp->ddz = 0.00006 + FLOATRAND(0.00003);
749 if ((mp->glx_context = init_GL(mi)) != NULL) {
751 reshape_moebius(mi, MI_WIDTH(mi), MI_HEIGHT(mi));
752 glDrawBuffer(GL_BACK);
760 draw_moebius(ModeInfo * mi)
764 Display *display = MI_DISPLAY(mi);
765 Window window = MI_WINDOW(mi);
769 mp = &moebius[MI_SCREEN(mi)];
771 MI_IS_DRAWN(mi) = True;
773 if (!mp->glx_context)
776 glXMakeCurrent(display, window, *(mp->glx_context));
778 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
782 glTranslatef(0.0, 0.0, -10.0);
784 if (!MI_IS_ICONIC(mi)) {
785 glScalef(Scale4Window * mp->WindH / mp->WindW, Scale4Window, Scale4Window);
787 glScalef(Scale4Iconic * mp->WindH / mp->WindW, Scale4Iconic, Scale4Iconic);
791 GLfloat x = mp->rotx;
792 GLfloat y = mp->roty;
793 GLfloat z = mp->rotz;
794 if (x < 0) x = 1 - (x + 1);
795 if (y < 0) y = 1 - (y + 1);
796 if (z < 0) z = 1 - (z + 1);
797 glRotatef(x * 360, 1.0, 0.0, 0.0);
798 glRotatef(y * 360, 0.0, 1.0, 0.0);
799 glRotatef(z * 360, 0.0, 0.0, 1.0);
803 if (!draw_moebius_strip(mi)) {
810 rotate(&mp->rotx, &mp->dx, &mp->ddx, mp->d_max, MI_IS_VERBOSE(mi));
811 rotate(&mp->roty, &mp->dy, &mp->ddy, mp->d_max, MI_IS_VERBOSE(mi));
812 rotate(&mp->rotz, &mp->dz, &mp->ddz, mp->d_max, MI_IS_VERBOSE(mi));
814 if (MI_IS_FPS(mi)) do_fps (mi);
817 glXSwapBuffers(display, window);
823 change_moebius(ModeInfo * mi)
825 moebiusstruct *mp = &moebius[MI_SCREEN(mi)];
827 if (!mp->glx_context)
830 glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(mp->glx_context));