ftp://ftp.krokus.ru/pub/OpenBSD/distfiles/xscreensaver-4.22.tar.gz
[xscreensaver] / hacks / glx / antmaze.c
1 /*
2  * Permission to use, copy, modify, and distribute this software and its
3  * documentation for any purpose and without fee is hereby granted,
4  * provided that the above copyright notice appear in all copies and that
5  * both that copyright notice and this permission notice appear in
6  * supporting documentation.
7  *
8  * This file is provided AS IS with no warranties of any kind.  The author
9  * shall have no liability with respect to the infringement of copyrights,
10  * trade secrets or any patents by this file or any part thereof.  In no
11  * event will the author be liable for any lost revenue or profits or
12  * other special, indirect and consequential damages.
13  *
14  * Copyright 2004 Blair Tennessy
15  * tennessy@cs.ubc.ca
16  */
17
18 #if !defined( lint ) && !defined( SABER )
19 static const char sccsid[] = "@(#)moebius.c     5.01 2001/03/01 xlockmore";
20 #endif
21
22 #ifdef VMS
23 #include <X11/Intrinsic.h>
24 #endif
25
26 #ifdef STANDALONE
27 # define MODE_moebius
28 # define PROGCLASS                      "AntMaze2"
29 # define HACK_INIT                      init_moebius
30 # define HACK_DRAW                      draw_moebius
31 # define HACK_RESHAPE           reshape_moebius
32 # define HACK_HANDLE_EVENT      moebius_handle_event
33 # define EVENT_MASK                     PointerMotionMask
34 # define moebius_opts           xlockmore_opts
35 # define DEFAULTS                       "*delay:                20000   \n"                     \
36                                                         "*showFPS:      False   \n"                     \
37                                                         "*wireframe:    False   \n"
38 # include "xlockmore.h"         /* from the xscreensaver distribution */
39 #else /* !STANDALONE */
40 # include "xlock.h"             /* from the xlockmore distribution */
41
42 #endif /* !STANDALONE */
43
44 #ifdef MODE_moebius
45
46
47 #include <GL/glu.h>
48 #include "rotator.h"
49 #include "gltrackball.h"
50
51 #define DEF_SOLIDMOEBIUS  "False"
52 #define DEF_NOANTS  "False"
53
54 static int  solidmoebius;
55 static int  noants;
56
57 static XrmOptionDescRec opts[] =
58 {
59   {(char *) "-solidmoebius", (char *) ".moebius.solidmoebius", XrmoptionNoArg, (caddr_t) "on"},
60   {(char *) "+solidmoebius", (char *) ".moebius.solidmoebius", XrmoptionNoArg, (caddr_t) "off"},
61   {(char *) "-noants", (char *) ".moebius.noants", XrmoptionNoArg, (caddr_t) "on"},
62   {(char *) "+noants", (char *) ".moebius.noants", XrmoptionNoArg, (caddr_t) "off"}
63 };
64 static argtype vars[] =
65 {
66   {(caddr_t *) & solidmoebius, (char *) "solidmoebius", (char *) "Solidmoebius", (char *) DEF_SOLIDMOEBIUS, t_Bool},
67   {(caddr_t *) & noants, (char *) "noants", (char *) "Noants", (char *) DEF_NOANTS, t_Bool}
68
69 };
70 static OptionStruct desc[] =
71 {
72         {(char *) "-/+solidmoebius", (char *) "select between a SOLID or a NET Moebius Strip"},
73         {(char *) "-/+noants", (char *) "turn on/off walking ants"}
74 };
75
76 ModeSpecOpt moebius_opts =
77 {sizeof opts / sizeof opts[0], opts, sizeof vars / sizeof vars[0], vars, desc};
78
79 #ifdef USE_MODULES
80 ModStruct   moebius_description =
81 {"moebius", "init_moebius", "draw_moebius", "release_moebius",
82  "draw_moebius", "change_moebius", (char *) NULL, &moebius_opts,
83  1000, 1, 1, 1, 4, 1.0, "",
84  "draws some ants", 0, NULL};
85
86 #endif
87
88 #define Scale4Window               0.3
89 #define Scale4Iconic               0.4
90
91 #define sqr(A)                     ((A)*(A))
92
93 #ifndef Pi
94 #define Pi                         M_PI
95 #endif
96
97 #define ObjMoebiusStrip 0
98 #define ObjAntBody      1
99 #define MaxObj          2
100
101 /*************************************************************************/
102
103 typedef struct {
104   GLint       WindH, WindW;
105   GLfloat     step;
106   GLfloat     ant_position;
107   GLXContext *glx_context;
108   rotator    *rot;
109   trackball_state *trackball;
110   Bool        button_down_p;
111 } moebiusstruct;
112
113 #include "ants.h"
114
115 static GLfloat MaterialRed[] = {0.6, 0.0, 0.0, 1.0};
116 static GLfloat MaterialMagenta[] = {0.6, 0.2, 0.5, 1.0};
117 static GLfloat MaterialGray8[] = {0.8, 0.8, 0.8, 1.0};
118 static GLfloat MaterialGray35[] = {0.30, 0.30, 0.30, 1.0};
119 static GLfloat MaterialGray4[] = {0.40, 0.40, 0.40, 1.0};
120 static GLfloat MaterialOrange[] = {1.0, 0.69, 0.00, 1.0};
121 static GLfloat MaterialGreen[] = {0.1, 0.4, 0.2, 1.0};
122
123 /* lighting variables */
124 GLfloat front_shininess[] = {60.0};
125 GLfloat front_specular[] = {0.8, 0.8, 0.8, 1.0};
126 GLfloat ambient[] = {0.1, 0.1, 0.1, 1.0};
127 GLfloat ambient2[] = {0.0, 0.0, 0.0, 0.0};
128 GLfloat diffuse[] = {0.8, 0.8, 0.8, 1.0};
129 GLfloat position0[] = {1.0, 5.0, 1.0, 1.0};
130 GLfloat position1[] = {-1.0, -5.0, 1.0, 1.0};
131 GLfloat lmodel_ambient[] = {0.8, 0.8, 0.8, 1.0};
132 GLfloat lmodel_twoside[] = {GL_TRUE};
133 GLfloat spotlight_ambient[] = { 0.0, 0.0, 0.0, 1.0 };
134 GLfloat spotlight_diffuse[] = { 1.0, 1.0, 1.0, 1.0 };
135
136 static moebiusstruct *moebius = (moebiusstruct *) NULL;
137
138 #define NUM_SCENES      2
139
140 /* filled sphere */
141 static Bool mySphere(float radius) {
142   GLUquadricObj *quadObj;
143
144   if((quadObj = gluNewQuadric()) == 0)
145         return False;
146   gluQuadricDrawStyle(quadObj, (GLenum) GLU_FILL);
147   gluSphere(quadObj, radius, 16, 16);
148   gluDeleteQuadric(quadObj);
149
150   return True;
151 }
152
153 /* silhouette sphere */
154 static Bool mySphere2(float radius) {
155   GLUquadricObj *quadObj;
156
157   if((quadObj = gluNewQuadric()) == 0)
158         return False;
159   gluQuadricDrawStyle(quadObj, (GLenum) GLU_SILHOUETTE);
160   gluSphere(quadObj, radius, 16, 8);
161   gluDeleteQuadric(quadObj);
162
163   return True;
164 }
165
166 /* textured sphere */
167 static Bool mySphereTex(float radius) {
168   GLUquadricObj *quadObj;
169   
170   if((quadObj = gluNewQuadric()) == 0)
171         return False;
172   gluQuadricDrawStyle(quadObj, (GLenum) GLU_FILL);
173   gluQuadricTexture(quadObj, GL_TRUE);
174   gluQuadricNormals(quadObj, GLU_SMOOTH);
175   gluSphere(quadObj, radius, 32, 16);
176   gluDeleteQuadric(quadObj);
177
178   return True;
179 }
180
181 /* filled cone */
182 static Bool myCone(float radius) {
183   GLUquadricObj *quadObj;
184   
185   if ((quadObj = gluNewQuadric()) == 0)
186     return False;
187   gluQuadricDrawStyle(quadObj, (GLenum) GLU_FILL);
188   gluCylinder(quadObj, radius, 0, radius * 2, 8, 1);
189   gluDeleteQuadric(quadObj);
190   return True;
191 }
192
193 /* no cone */
194 static Bool myCone2(float radius) { return True; }
195
196 #define ANTCOUNT 4
197 #define PI 3.14157
198
199 static int focus = 0;
200
201 #define MATERIALS 4
202 static float* antmaterial[ANTCOUNT] = 
203   {MaterialRed, MaterialGray35, MaterialGray4, MaterialOrange, MaterialGreen};
204
205 static float* materials[MATERIALS] = 
206   {MaterialRed, MaterialGray35, MaterialGray4, MaterialOrange};
207
208 static double antdirection[ANTCOUNT] = {PI/2.0, PI/2.0, 0.0, PI/2.0, PI/2.0};
209
210 static double antposition[ANTCOUNT][3] = {{-4.0, 5.0, 0.15},
211                                           {-4.0, 3.0, 0.15},
212                                           {-1.0, -2.0, 0.15},
213                                           {-3.9, 6.0, 0.15}, 
214                                           {2.0, -2.0, 0.15}};
215
216 static int anton[ANTCOUNT] = {1, 0, 0, 0};
217
218 static double antvelocity[ANTCOUNT] = {0.02,
219                                        0.02,
220                                        0.02,
221                                        0.02};
222
223 static double antsize[ANTCOUNT] = {1.0,
224                                    1.0,
225                                    1.0,
226                                    1.0};
227
228 #define EPSILON 0.01
229 #define BOARDSIZE 10
230
231 int bposition[ANTCOUNT][2] = {{0, 8},
232                               {9, 1},
233                               {1, 1},
234                               {4, 8},
235                               {2, 1},};
236
237 #define BOARDCOUNT 2
238 int currentboard = 0;
239
240 int board[BOARDCOUNT][10][10];/*  = {1, 1, 1, 1, 1, 1, 1, 1, 0, 1, */
241 /*                   1, 0, 1, 0, 1, 0, 1, 1, 0, 1, */
242 /*                   1, 0, 0, 0, 1, 0, 0, 0, 0, 1, */
243 /*                   1, 0, 1, 1, 0, 0, 1, 1, 0, 1, */
244 /*                   1, 0, 1, 1, 0, 1, 1, 0, 0, 1, */
245 /*                   1, 0, 1, 0, 0, 1, 0, 0, 1, 1, */
246 /*                   1, 0, 0, 0, 1, 1, 0, 1, 0, 1, */
247 /*                   1, 0, 1, 0, 1, 1, 0, 0, 0, 1, */
248 /*                   1, 0, 1, 0, 0, 0, 1, 0, 1, 1, */
249 /*                   1, 0, 1, 1, 1, 1, 1, 1, 1, 1,}; */
250
251 #define PARTS 20
252 int part[ANTCOUNT] = {0, 1, 5, 1, 3};
253 double antpath[ANTCOUNT][PARTS][2];/*  = {{-4.0, 5.0}, */
254 int antpathlength[ANTCOUNT];
255 /*                                    {-4.0, 1.0}, */
256 /*                                    {-2.0, 1.0}, */
257 /*                                    {-2.0, 0.0}, */
258 /*                                    {-1.0, 0.0}, */
259 /*                                    {-1.0, -2.0}, */
260 /*                                    { 0.0, -2.0}, */
261 /*                                    { 0.0, -3.0}, */
262 /*                                    { 3.0, -3.0}, */
263 /*                                    { 3.0, -6.0},}; */
264
265 #define checkImageWidth 64
266 #define checkImageHeight 64
267 GLubyte checkers[checkImageWidth][checkImageHeight][3];
268 GLuint checktexture, brushedtexture;
269 double elevator = 0.0;
270
271 void makeCheckImage(void) {
272   int i, j, r, c, k;
273   
274   for (i = 0; i < checkImageWidth; i++) {
275     for (j = 0; j < checkImageHeight; j++) {
276       if((((i&0x8)==0)^((j&0x8))==0)) {
277         int c = 102 + random()%32;
278         checkers[i][j][0] = c;
279         checkers[i][j][1] = c;
280         checkers[i][j][2] = c;
281       }
282       else {
283         int c = 153 + random()%32;
284         checkers[i][j][0] = c;/*153;*/
285         checkers[i][j][1] = c;/*c;*//*0;*/
286         checkers[i][j][2] = c;/*c;*//*0;*/
287       }
288     }
289   }
290
291   glGenTextures(1, &checktexture);
292   glBindTexture(GL_TEXTURE_2D, checktexture);
293
294   glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
295   glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
296   glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
297   glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
298   glTexImage2D(GL_TEXTURE_2D, 0, 3, checkImageWidth, 
299                checkImageHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, 
300                &checkers[0][0]);
301   glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
302 }
303
304 void makeBrushedImage(void) {
305   int i, j, r, c, k;
306
307   for(i = 0; i < checkImageWidth; ++i)
308     for(j = 0; j < checkImageHeight; ++j) {
309
310       c = 102+102*fabs(sin(2.0*i / Pi)*sin(2.0*j/Pi)) + random()%51;
311
312 /*       c = (i+j)%8==0 || (i+j+5)%8==0 ? 153 : 102; */
313
314       checkers[i][j][0] = c;
315       checkers[i][j][1] = c;
316       checkers[i][j][2] = c;
317     }
318   
319 /*   for (i = 0; i < checkImageWidth; i++) { */
320 /*     for (j = 0; j < checkImageHeight; j++) { */
321 /*       int c = 102 + pow((random()%1000)/1000.0, 4)*103; */
322 /*       checkers[i][j][0] = c; */
323 /*       checkers[i][j][1] = c; */
324 /*       checkers[i][j][2] = c; */
325 /*     } */
326 /*   } */
327
328 /*   /\* smooth *\/ */
329 /*   for (i = 0; i < checkImageWidth; i++) { */
330 /*     for (j = 0; j < checkImageHeight; j++) { */
331 /*       int a = checkers[(i+checkImageWidth+1)%checkImageWidth][j][0] +  */
332 /*      4*checkers[i][j][0] + checkers[(i+1)%checkImageWidth][j][0]; */
333 /*       a /= 6; */
334 /*       checkers[i][j][0] = a; */
335 /*       checkers[i][j][1] = a; */
336 /*       checkers[i][j][2] = a; */
337 /*     } */
338 /*   } */
339
340   glGenTextures(1, &brushedtexture);
341   glBindTexture(GL_TEXTURE_2D, brushedtexture);
342
343   glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
344   glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
345   glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
346   glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
347   glTexImage2D(GL_TEXTURE_2D, 0, 3, checkImageWidth, 
348                checkImageHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, 
349                &checkers[0][0]);
350   glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
351 }
352
353 void draw_wall(double x1, double z1, double x2, double z2) {
354   float x = fabs(x2 - x1)/2.0;
355
356   glBegin(GL_QUADS);
357
358   /* draw top */
359   glNormal3f(0.0, 1.0, 0.0);
360   glTexCoord2f(0.0, 0.0);
361   glVertex3f(x1, 1.0, z1+0.25);
362   glTexCoord2f(x, 0.0);
363   glVertex3f(x2, 1.0, z2+0.25);
364   glTexCoord2f(x, 0.25);
365   glVertex3f(x2, 1.0, z2-0.25);
366   glTexCoord2f(0.0, 0.25);
367   glVertex3f(x1, 1.0, z1-0.25);
368
369   /* draw sides */
370   glNormal3f(0.0, 0.0, 1.0);
371   glTexCoord2f(0.0, 0.0);
372   glVertex3f(x1, 0.0, z1+0.25);
373   glTexCoord2f(x, 0.0);
374   glVertex3f(x2, 0.0, z2+0.25);
375   glTexCoord2f(x, 0.5);
376   glVertex3f(x2, 1.0, z2+0.25);
377   glTexCoord2f(0.0, 0.5);
378   glVertex3f(x1, 1.0, z1+0.25);
379
380   glNormal3f(0.0, 0.0, -1.0);
381   glTexCoord2f(0.0, 0.0);
382   glVertex3f(x1, 0.0, z1-0.25);
383   glTexCoord2f(x, 0.0);
384   glVertex3f(x2, 0.0, z2-0.25);
385   glTexCoord2f(x, 0.5);
386   glVertex3f(x2, 1.0, z2-0.25);
387   glTexCoord2f(0.0, 0.5);
388   glVertex3f(x1, 1.0, z1-0.25);
389
390   /* draw ends */
391   glNormal3f(1.0, 0.0, 0.0);
392   glTexCoord2f(0.0, 0.0);
393   glVertex3f(x2, 0.0, z2+0.25);
394   glTexCoord2f(0.25, 0.0);
395   glVertex3f(x2, 0.0, z2-0.25);
396   glTexCoord2f(0.25, 0.5);
397   glVertex3f(x2, 1.0, z2-0.25);
398   glTexCoord2f(0.0, 0.5);
399   glVertex3f(x2, 1.0, z2+0.25);
400
401   glNormal3f(-1.0, 0.0, 0.0);
402   glTexCoord2f(0.0, 0.0);
403   glVertex3f(x1, 0.0, z1-0.25);
404   glTexCoord2f(0.25, 0.0);
405   glVertex3f(x1, 0.0, z1+0.25);
406   glTexCoord2f(0.25, 0.5);
407   glVertex3f(x1, 1.0, z1+0.25);
408   glTexCoord2f(0.0, 0.5);
409   glVertex3f(x1, 1.0, z1-0.25);
410
411   glEnd();
412 }
413
414 int pastfirst = 0;
415
416 void draw_board(void) {
417
418   int i, j;
419   double h = 0.5;
420   double stf = 0.0625;
421
422   glBindTexture(GL_TEXTURE_2D, checktexture);
423
424   glBegin(GL_QUADS);
425
426   for(i = 0; i < BOARDSIZE; ++i)
427     for(j = 0; j < BOARDSIZE; ++j) {
428       if(board[currentboard][j][i]) {
429
430 /*      /\* draw top *\/ */
431 /*      glNormal3f(0.0, 1.0, 0.0); */
432 /*      glTexCoord2f(0.0 + stf, 0.0 + stf); */
433 /*      glVertex3f(i-0.5, h, j+0.5); */
434 /*      glTexCoord2f(1.0 + stf, 0.0 + stf); */
435 /*      glVertex3f(i+0.5, h, j+0.5); */
436 /*      glTexCoord2f(1.0 + stf, 1.0 + stf); */
437 /*      glVertex3f(i+0.5, h, j-0.5); */
438 /*      glTexCoord2f(0.0 + stf, 1.0 + stf); */
439 /*      glVertex3f(i-0.5, h, j-0.5); */
440
441         /* draw top */
442         glNormal3f(0.0, 1.0, 0.0);
443         glTexCoord2f(0.0 + stf, 0.0 + stf);
444         glVertex3f(i-0.5, h, j+0.5);
445         glTexCoord2f(1.0 + stf, 0.0 + stf);
446         glVertex3f(i+0.5, h, j+0.5);
447         glTexCoord2f(1.0 + stf, 1.0 + stf);
448         glVertex3f(i+0.5, h, j-0.5);
449         glTexCoord2f(0.0 + stf, 1.0 + stf);
450         glVertex3f(i-0.5, h, j-0.5);
451
452         /* draw south face */
453         if(j == 9 || !board[currentboard][j+1][i]) {
454           glNormal3f(0.0, 0.0, 1.0);
455           glTexCoord2f(0.0 + stf, 0.0 + stf);
456           glVertex3f(i-0.5, 0.0, j+0.5);
457           glTexCoord2f(1.0 + stf, 0.0 + stf);
458           glVertex3f(i+0.5, 0.0, j+0.5);
459           glTexCoord2f(1.0 + stf, h + stf);
460           glVertex3f(i+0.5, h, j+0.5);
461           glTexCoord2f(0.0 + stf, h + stf);
462           glVertex3f(i-0.5, h, j+0.5);
463         }
464
465         /* draw north face */
466         if(j == 0 || !board[currentboard][j-1][i]) {
467           glNormal3f(0.0, 0.0, -1.0);
468           glTexCoord2f(0.0 + stf, 0.0 + stf);
469           glVertex3f(i+0.5, 0.0, j-0.5);
470           glTexCoord2f(1.0 + stf, 0.0 + stf);
471           glVertex3f(i-0.5, 0.0, j-0.5);
472           glTexCoord2f(1.0 + stf, h + stf);
473           glVertex3f(i-0.5, h, j-0.5);
474           glTexCoord2f(0.0 + stf, h + stf);
475           glVertex3f(i+0.5, h, j-0.5);
476         }
477
478         /* draw east face */
479         if(i == 9 || !board[currentboard][j][i+1]) {
480           glNormal3f(1.0, 0.0, 0.0);
481           glTexCoord2f(0.0 + stf, 0.0 + stf);
482           glVertex3f(i+0.5, 0.0, j+0.5);
483           glTexCoord2f(1.0 + stf, 0.0 + stf);
484           glVertex3f(i+0.5, 0.0, j-0.5);
485           glTexCoord2f(1.0 + stf, h + stf);
486           glVertex3f(i+0.5, h, j-0.5);
487           glTexCoord2f(0.0 + stf, h + stf);
488           glVertex3f(i+0.5, h, j+0.5);
489         }
490
491         /* draw west face */
492         if(i == 0 || !board[currentboard][j][i-1]) {
493           glNormal3f(-1.0, 0.0, 0.0);
494           glTexCoord2f(0.0 + stf, 0.0 + stf);
495           glVertex3f(i-0.5, 0.0, j-0.5);
496           glTexCoord2f(1.0 + stf, 0.0 + stf);
497           glVertex3f(i-0.5, 0.0, j+0.5);
498           glTexCoord2f(1.0 + stf, h + stf);
499           glVertex3f(i-0.5, h, j+0.5);
500           glTexCoord2f(0.0 + stf, h + stf);
501           glVertex3f(i-0.5, h, j-0.5);
502         }
503       }
504       else {
505         double tx = 2.0;
506         glNormal3f(0.0, 1.0, 0.0);
507         glTexCoord2f(0.0, 0.0);
508         glVertex3f(i-0.5, 0.0, j+0.5);
509         glTexCoord2f(tx, 0.0);
510         glVertex3f(i+0.5, 0.0, j+0.5);
511         glTexCoord2f(tx, tx);
512         glVertex3f(i+0.5, 0.0, j-0.5);
513         glTexCoord2f(0.0, tx);
514         glVertex3f(i-0.5, 0.0, j-0.5);
515       }
516     }
517   glEnd();
518
519 /*   /\* draw elevator *\/ */
520 /*   glBindTexture(GL_TEXTURE_2D, brushedtexture); */
521
522 /*   glBegin(GL_QUADS); */
523
524 /*   glNormal3f(0.0, 1.0, 0.0); */
525
526 /*   if(pastfirst) { */
527 /*       /\* source *\/ */
528 /*       glTexCoord2f(0.0, 0.0); */
529 /*       glVertex3f(0.5, 0.0, BOARDSIZE - 0.5 + 0.2); */
530 /*       glTexCoord2f(1.0, 0.0); */
531 /*       glVertex3f(1.5, 0.0, BOARDSIZE - 0.5 + 0.2); */
532 /*       glTexCoord2f(1.0, 1.5); */
533 /*       glVertex3f(1.5, 0.0, BOARDSIZE + 1.0 + 0.2); */
534 /*       glTexCoord2f(0.0, 1.5); */
535 /*       glVertex3f(0.5, 0.0, BOARDSIZE + 1.0 + 0.2); */
536 /*   } */
537
538 /*   /\* destination *\/ */
539 /*   glTexCoord2f(0.0, 0.0); */
540 /*   glVertex3f(BOARDSIZE - 2.5, elevator, -2.0 - 0.2); */
541 /*   glTexCoord2f(1.0, 0.0); */
542 /*   glVertex3f(BOARDSIZE - 1.5, elevator, -2.0 - 0.2); */
543 /*   glTexCoord2f(1.0, 1.5); */
544 /*   glVertex3f(BOARDSIZE - 1.5, elevator, -0.5 - 0.2); */
545 /*   glTexCoord2f(0.0, 1.5); */
546 /*   glVertex3f(BOARDSIZE - 2.5, elevator, -0.5 - 0.2); */
547
548 /*   glEnd(); */
549
550 /*   for(i = 0; i < BOARDSIZE; ++i) */
551 /*     for(j = 0; j < BOARDSIZE; ++j) { */
552 /*       if(board[j][i]) { */
553
554 /*      /\* draw brushed boxtop *\/ */
555 /*      glNormal3f(0.0, 1.0, 0.0); */
556 /*      glTexCoord2f(0.0 + stf, 0.0 + stf); */
557 /*      glVertex3f(i-0.5 + stf, h+0.001, j+0.5 - stf); */
558 /*      glTexCoord2f(1.0 + stf, 0.0 + stf); */
559 /*      glVertex3f(i+0.5 - stf, h+0.001, j+0.5 - stf); */
560 /*      glTexCoord2f(1.0 + stf, 1.0 + stf); */
561 /*      glVertex3f(i+0.5 - stf, h+0.001, j-0.5 + stf); */
562 /*      glTexCoord2f(0.0 + stf, 1.0 + stf); */
563 /*      glVertex3f(i-0.5 + stf, h+0.001, j-0.5 + stf); */
564 /*       } */
565 /*     } */
566   
567 /*   glEnd(); */
568 }
569
570 void build_board(int b) {
571   int i, j;
572
573   for(i = 0; i < BOARDSIZE; ++i)
574     for(j = 0; j < BOARDSIZE; ++j)
575       board[b][i][j] = 1;
576   
577 /*   for(i = 0; i < BOARDSIZE; ++i) { */
578 /*     board[0][i] = 1; */
579 /*     board[i][0] = 1; */
580 /*     board[BOARDSIZE-1][BOARDSIZE-i] = 1; */
581 /*     board[BOARDSIZE-i][BOARDSIZE-1] = 1; */
582 /*   } */
583
584 /*   board[0][BOARDSIZE-2] = 0; */
585 /*   board[BOARDSIZE-1][1] = 0; */
586
587
588   board[b][BOARDSIZE-1][1] = 0;
589   board[b][0][BOARDSIZE-2] = 0;
590
591   /* build the ant paths */
592   if(currentboard == b) {
593     for(i = 0; i < ANTCOUNT; ++i) {
594       int sx = BOARDSIZE-2;
595       int sy = 1;
596       
597       for(j = 0; ; ++j) {
598         board[b][sx][sy] = 0;
599         antpath[i][j][0] = sy - 5.0;
600         antpath[i][j][1] = sx - 5.0;
601         
602         if(random()%2) {
603           if(sx > 1)
604             sx -= 1;
605           else if(sy < BOARDSIZE-2)
606             sy += 1;
607           else
608             break;
609         }
610         else {
611           if(sy < BOARDSIZE-2)
612             sy += 1;
613           else if(sx > 1)
614             sx -= 1;
615           else
616             break;
617         }
618       }
619       
620       ++j;
621       antpath[i][j][0] = BOARDSIZE-7.0;
622       antpath[i][j][1] = -7.0;
623       antpathlength[i] = j;
624     }
625   }
626
627 /*   for(i = 0; i < 20; ++i) { */
628 /*     int x = 1 + random()%(BOARDSIZE-2); */
629 /*     int y = 1 + random()%(BOARDSIZE-2); */
630 /*     board[x][y] = 1; */
631 /*   } */
632 }
633
634 /* compute nearness */
635 int near(double a[2], double b[2]) {
636   return fabs(a[0] - b[0]) < 0.5 && fabs(a[1] - b[1]) < 0.5;
637 }
638
639 double sign(double d) {
640   return d < 0.0 ? -1.0 : 1.0;
641 }
642
643 double min(double a, double b) {
644   return a < b ? a : b;
645 }
646
647 /* draw method for ant */
648 Bool draw_ant(float *Material, int mono, int shadow,
649               float ant_step, Bool (*sphere)(float), Bool (*cone)(float)) {
650   
651   float cos1 = cos(ant_step);
652   float cos2 = cos(ant_step + 2 * Pi / 3);
653   float cos3 = cos(ant_step + 4 * Pi / 3);
654   float sin1 = sin(ant_step);
655   float sin2 = sin(ant_step + 2 * Pi / 3);
656   float sin3 = sin(ant_step + 4 * Pi / 3);
657   
658   glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mono ? MaterialGray5 : Material);
659
660 /*   glEnable(GL_CULL_FACE); */
661
662   glPushMatrix();
663   glScalef(1, 1.3, 1);
664   if(!((*sphere)(0.18)))
665     return False;
666   glScalef(1, 1 / 1.3, 1);
667   glTranslatef(0.00, 0.30, 0.00);
668   if(!((*sphere)(0.2)))
669     return False;
670   
671   glTranslatef(-0.05, 0.17, 0.05);
672   glRotatef(-90, 1, 0, 0);
673   glRotatef(-25, 0, 1, 0);
674   if(!((*cone)(0.05)))
675     return False;
676   glTranslatef(0.00, 0.10, 0.00);
677   if(!((*cone)(0.05)))
678     return False;
679   glRotatef(25, 0, 1, 0);
680   glRotatef(90, 1, 0, 0);
681   
682   glScalef(1, 1.3, 1);
683   glTranslatef(0.15, -0.65, 0.05);
684   if(!((*sphere)(0.25)))
685     return False;
686   glScalef(1, 1 / 1.3, 1);
687   glPopMatrix();
688
689 /*   glDisable(GL_CULL_FACE); */
690   
691   glDisable(GL_LIGHTING);
692
693   /* ANTENNAS */
694   glBegin(GL_LINES);
695   glColor3fv(mono ? MaterialGray5 : Material);
696   glVertex3f(0.00, 0.30, 0.00);
697   glColor3fv(MaterialGray);
698   glVertex3f(0.40, 0.70, 0.40);
699   glColor3fv(mono ? MaterialGray5 : Material);
700   glVertex3f(0.00, 0.30, 0.00);
701   glColor3fv(MaterialGray);
702   glVertex3f(0.40, 0.70, -0.40);
703   glEnd();
704
705   if(!shadow) {
706     glBegin(GL_POINTS);
707     glColor3fv(mono ? MaterialGray6 : MaterialRed);
708     glVertex3f(0.40, 0.70, 0.40);
709     glVertex3f(0.40, 0.70, -0.40);
710     glEnd();
711   }
712
713   /* LEFT-FRONT ARM */
714   glBegin(GL_LINE_STRIP);
715   glColor3fv(mono ? MaterialGray5 : Material);
716   glVertex3f(0.00, 0.05, 0.18);
717   glVertex3f(0.35 + 0.05 * cos1, 0.15, 0.25);
718   glColor3fv(MaterialGray);
719   glVertex3f(-0.20 + 0.05 * cos1, 0.25 + 0.1 * sin1, 0.45);
720   glEnd();
721
722   /* LEFT-CENTER ARM */
723   glBegin(GL_LINE_STRIP);
724   glColor3fv(mono ? MaterialGray5 : Material);
725   glVertex3f(0.00, 0.00, 0.18);
726   glVertex3f(0.35 + 0.05 * cos2, 0.00, 0.25);
727   glColor3fv(MaterialGray);
728   glVertex3f(-0.20 + 0.05 * cos2, 0.00 + 0.1 * sin2, 0.45);
729   glEnd();
730
731   /* LEFT-BACK ARM */
732   glBegin(GL_LINE_STRIP);
733   glColor3fv(mono ? MaterialGray5 : Material);
734   glVertex3f(0.00, -0.05, 0.18);
735   glVertex3f(0.35 + 0.05 * cos3, -0.15, 0.25);
736   glColor3fv(MaterialGray);
737   glVertex3f(-0.20 + 0.05 * cos3, -0.25 + 0.1 * sin3, 0.45);
738   glEnd();
739
740   /* RIGHT-FRONT ARM */
741   glBegin(GL_LINE_STRIP);
742   glColor3fv(mono ? MaterialGray5 : Material);
743   glVertex3f(0.00, 0.05, -0.18);
744   glVertex3f(0.35 - 0.05 * sin1, 0.15, -0.25);
745   glColor3fv(MaterialGray);
746   glVertex3f(-0.20 - 0.05 * sin1, 0.25 + 0.1 * cos1, -0.45);
747   glEnd();
748
749   /* RIGHT-CENTER ARM */
750   glBegin(GL_LINE_STRIP);
751   glColor3fv(mono ? MaterialGray5 : Material);
752   glVertex3f(0.00, 0.00, -0.18);
753   glVertex3f(0.35 - 0.05 * sin2, 0.00, -0.25);
754   glColor3fv(MaterialGray);
755   glVertex3f(-0.20 - 0.05 * sin2, 0.00 + 0.1 * cos2, -0.45);
756   glEnd();
757
758   /* RIGHT-BACK ARM */
759   glBegin(GL_LINE_STRIP);
760   glColor3fv(mono ? MaterialGray5 : Material);
761   glVertex3f(0.00, -0.05, -0.18);
762   glVertex3f(0.35 - 0.05 * sin3, -0.15, -0.25);
763   glColor3fv(MaterialGray);
764   glVertex3f(-0.20 - 0.05 * sin3, -0.25 + 0.1 * cos3, -0.45);
765   glEnd();
766
767   if(!shadow) {
768     glBegin(GL_POINTS);
769     glColor3fv(mono ? MaterialGray8 : MaterialGray35);
770     glVertex3f(-0.20 + 0.05 * cos1, 0.25 + 0.1 * sin1, 0.45);
771     glVertex3f(-0.20 + 0.05 * cos2, 0.00 + 0.1 * sin2, 0.45);
772     glVertex3f(-0.20 + 0.05 * cos3, -0.25 + 0.1 * sin3, 0.45);
773     glVertex3f(-0.20 - 0.05 * sin1, 0.25 + 0.1 * cos1, -0.45);
774     glVertex3f(-0.20 - 0.05 * sin2, 0.00 + 0.1 * cos2, -0.45);
775     glVertex3f(-0.20 - 0.05 * sin3, -0.25 + 0.1 * cos3, -0.45);
776     glEnd();
777   }
778
779   glEnable(GL_LIGHTING);
780
781   return True;
782 }
783
784 double ant_step = 0.0;
785 double first_ant_step = 0.0;
786 int started = 0;
787 int introduced = 300;
788 int fir = 0;
789 int makenew = 1;
790 int entroducing = 12;
791
792 static Bool draw_moebius_strip(ModeInfo * mi) {
793   moebiusstruct *mp = &moebius[MI_SCREEN(mi)];
794   int i;
795   int mono = MI_IS_MONO(mi);
796
797 /*   glMatrixMode(GL_MODELVIEW); */
798 /*   glLoadIdentity(); */
799 /*   glPushMatrix(); */
800
801   glEnable(GL_LIGHTING);
802 /*   glDisable(GL_BLEND); */
803   glEnable(GL_LIGHT0);
804   glEnable(GL_LIGHT1);
805
806   /* set light */
807 /*   double l1 = 1.0 - (elevator < 1.0 ? elevator : 2.0 - elevator); */
808 /*   GLfloat df[4] = {0.8*l1, 0.8*l1, 0.8*l1, 1.0}; */
809 /*   glLightfv(GL_LIGHT0, GL_DIFFUSE, df); */
810 /*   glLightfv(GL_LIGHT1, GL_DIFFUSE, df); */
811
812   /* draw board */
813   if(elevator < 1.0) {
814     glEnable(GL_TEXTURE_2D);
815     glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialGray6);
816     glTranslatef(-(BOARDSIZE-1)/2.0, 0.0, -(BOARDSIZE-1)/2.0);
817     draw_board();
818     glTranslatef(BOARDSIZE/2.0, 0.0, BOARDSIZE/2.0);
819     glDisable(GL_TEXTURE_2D);
820   }
821
822   introduced--;
823
824   glTranslatef(0.0, -0.1, 0.0);
825
826   for(i = 0; i < ANTCOUNT; ++i) {
827
828 /*     glLightfv(GL_LIGHT0, GL_DIFFUSE, df); */
829 /*     glLightfv(GL_LIGHT1, GL_DIFFUSE, df); */
830
831     if(!anton[i]) { continue; }
832
833     /* determine location, move to goal */
834     glPushMatrix();
835     glTranslatef(0.0, 0.01, 0.0);
836     glTranslatef(antposition[i][0], antposition[i][2], antposition[i][1]);
837 /*     glScalef(1.0, 0.01, 1.0); */
838     glScalef(0.6, 0.01, 0.6);
839     glRotatef(180.0 + antdirection[i]*180.0/PI, 0.0, 1.0, 0.0);
840     glRotatef(90.0, 0.0, 0.0, 1.0);
841     glDisable(GL_LIGHTING);
842     glEnable(GL_BLEND);
843     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
844     glColor4fv(MaterialGrayB);
845
846     glScalef(antsize[i], antsize[i], antsize[i]);
847
848     /* slow down first ant */
849     if(i == 0 && part[i] == antpathlength[i])
850       draw_ant(MaterialGrayB, mono, 1, first_ant_step, mySphere, myCone);
851     else
852       draw_ant(MaterialGrayB, mono, 1, ant_step, mySphere, myCone);
853
854     glPopMatrix();
855
856     glDisable(GL_BLEND);
857     glEnable(GL_LIGHTING);
858     
859     glPushMatrix();
860 /*     glTranslatef(0.0, 0.18, 0.0); */
861     glTranslatef(0.0, 0.12, 0.0);
862     glTranslatef(antposition[i][0], antposition[i][2], antposition[i][1]);
863     glRotatef(180.0 + antdirection[i]*180.0/PI, 0.0, 1.0, 0.0);
864     glRotatef(90.0, 0.0, 0.0, 1.0);
865     glScalef(0.6, 0.6, 0.6);
866
867     glScalef(antsize[i], antsize[i], antsize[i]);
868
869 /*     glEnable(GL_TEXTURE_2D); */
870 /*     glBindTexture(GL_TEXTURE_2D, brushedtexture); */
871
872 /*     glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialRed); */
873
874     /* slow down first ant */    
875     if(i == 0 && part[i] == antpathlength[i] && elevator > 0.0) {
876       glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse);
877       glLightfv(GL_LIGHT1, GL_DIFFUSE, diffuse);
878       draw_ant(antmaterial[i], mono, 1, first_ant_step, mySphere, myCone);
879     }
880     else {
881 /*       glLightfv(GL_LIGHT0, GL_DIFFUSE, df); */
882 /*       glLightfv(GL_LIGHT1, GL_DIFFUSE, df); */
883
884       glEnable(GL_TEXTURE_2D);
885       glBindTexture(GL_TEXTURE_2D, brushedtexture);
886       draw_ant(antmaterial[i], mono, 1, ant_step, mySphereTex, myCone);
887       glDisable(GL_TEXTURE_2D);
888     }
889
890
891 /*     draw_ant(antmaterial[i], mono, 0, ant_step, mySphereTex, myCone); */
892 /*     glDisable(GL_TEXTURE_2D); */
893     glPopMatrix();
894   }
895
896 /*   glPopMatrix(); */
897
898 /*   /\* now draw overlay *\/ */
899 /*   glDisable(GL_LIGHTING); */
900 /*   glDisable(GL_BLEND); */
901
902 /*   /\* go to ortho mode *\/ */
903 /*   glMatrixMode(GL_PROJECTION); */
904 /*   glPushMatrix(); */
905 /*   glLoadIdentity(); */
906 /*   glOrtho(-4.0, 4.0, -3.0, 3.0, -100.0, 100.0); */
907   
908 /*   /\* translate to corner *\/ */
909 /*   glTranslatef(4.0-1.2, 3.0-1.2, 0.0); */
910
911 /*   glDisable(GL_LIGHTING); */
912 /*   glEnable(GL_BLEND); */
913
914 /*   /\* draw the 2d board *\/ */
915 /*   glBegin(GL_QUADS); */
916 /*   { */
917 /*     int i, j; */
918 /*     double sz = 1.0; */
919 /*     for(i = 0; i < BOARDSIZE; ++i) */
920 /*       for(j = 0; j < BOARDSIZE; ++j) { */
921 /*      int par = board[i][j]; */
922 /*      glColor4f(par ? 0.4 : 0.6, */
923 /*                par ? 0.4 : 0.6, */
924 /*                par ? 0.4 : 0.6, */
925 /*                0.5); */
926 /*      glNormal3f(0.0, 0.0, 1.0); */
927 /*      glVertex3f((sz*(i+1))/BOARDSIZE,     (sz*(j+1))/BOARDSIZE, 0.0); */
928 /*      glVertex3f((sz*i)/BOARDSIZE, (sz*(j+1))/BOARDSIZE, 0.0); */
929 /*      glVertex3f((sz*i)/BOARDSIZE, (sz*j)/BOARDSIZE, 0.0); */
930 /*      glVertex3f((sz*(i+1))/BOARDSIZE, (sz*j)/BOARDSIZE, 0.0); */
931 /*       } */
932 /*   } */
933 /*   glEnd(); */
934   
935 /*   glPopMatrix(); */
936
937
938   /* but the step size is the same! */
939   ant_step += 0.18;
940 /*   if(ant_step > 2*Pi) { */
941 /*     ant_step = 0.0; */
942 /*   } */
943
944   if(ant_step > 5*Pi)
945     started = 1;
946
947   mp->ant_position += 1;
948   return True;
949 }
950 #undef MoebiusDivisions
951 #undef MoebiusTransversals
952
953 void reshape_moebius(ModeInfo * mi, int width, int height) {
954   double h = (GLfloat) height / (GLfloat) width;  
955   int size = (width / 512) + 1;
956   moebiusstruct *mp = &moebius[MI_SCREEN(mi)];
957
958   glViewport(0, 0, mp->WindW = (GLint) width, mp->WindH = (GLint) height);
959   glMatrixMode(GL_PROJECTION);
960   glLoadIdentity();
961
962   gluPerspective(45, 1/h, 0.001, 25.0);
963
964   glMatrixMode(GL_MODELVIEW);
965 /*   glLineWidth(3.0); */
966    glLineWidth(size);
967   glPointSize(size);
968 }
969
970 double fadeout = 1.0;
971 double fadeoutspeed = 0.0;
972
973 void update_ants(void) {
974   int i;
975
976   /* fade out */
977   if(fadeoutspeed < -0.00001) {
978
979     if(fadeout <= 0.0) {
980       /* switch boards: rebuild old board, increment current */
981       currentboard = (currentboard+1)%BOARDCOUNT;
982       build_board(currentboard);
983       fadeoutspeed = 0.02;
984     }
985     
986     fadeout += fadeoutspeed;
987
988     GLfloat df[4] = {0.8*fadeout, 0.8*fadeout, 0.8*fadeout, 1.0};
989     glLightfv(GL_LIGHT0, GL_DIFFUSE, df);
990     glLightfv(GL_LIGHT1, GL_DIFFUSE, df);
991   }
992
993   /* fade in */
994   if(fadeoutspeed > 0.0001) {
995     fadeout += fadeoutspeed;
996     if(fadeout >= 1.0) {
997       fadeout = 1.0;
998       fadeoutspeed = 0.0;
999       entroducing = 12;
1000     }
1001     GLfloat df[4] = {0.8*fadeout, 0.8*fadeout, 0.8*fadeout, 1.0};
1002     glLightfv(GL_LIGHT0, GL_DIFFUSE, df);
1003     glLightfv(GL_LIGHT1, GL_DIFFUSE, df);    
1004   }
1005
1006   for(i = 0; i < ANTCOUNT; ++i) {
1007
1008     if(!anton[i] && elevator < 1.0) {
1009
1010       /* turn on ant */
1011       if(entroducing > 0 && introduced <= 0 && random()%100 == 0) {
1012         anton[i] = 1;
1013         part[i] = 0;
1014         antsize[i] = 0.0;
1015         antposition[i][0] = -4.0;
1016         antposition[i][1] = 5.0;
1017         antdirection[i] = PI/2.0;
1018         bposition[i][0] = 0;
1019         bposition[i][1] = 8;
1020         introduced = 300;
1021         entroducing--;
1022       }
1023
1024       continue;
1025     }
1026
1027     if(part[i] == 0 && antsize[i] < 1.0) {
1028       antsize[i] += 0.02;
1029       continue;
1030     }
1031
1032     if(part[i] > antpathlength[i] && antsize[i] > 0.0) {
1033       antsize[i] -= 0.02;
1034       if(antvelocity[i] > 0.0) {
1035         antvelocity[i] -= 0.02;
1036       }
1037       else { antvelocity[i] = 0.0; }
1038
1039       continue;
1040     }
1041
1042     if(part[i] > antpathlength[i] && antsize[i] <= 0.0) {
1043       antvelocity[i] = 0.02;
1044       
1045       /*        if(i != 0) { */
1046       antmaterial[i] = materials[random()%MATERIALS];
1047       /*        } */
1048       
1049       antdirection[i] = PI/2.0;
1050       bposition[i][0] = 0;
1051       bposition[i][1] = 8;
1052       part[i] = 0;
1053       
1054       antsize[i] = 0.0;
1055       
1056       anton[i] = 0;
1057       
1058       antposition[i][0] = -4.0;
1059       antposition[i][1] = 5.0;
1060       
1061       /*        /\* reset camera *\/ */
1062       /*        if(i == focus) { */
1063       /*          started = 0; */
1064       /*          ant_step = 0.0; */
1065       /*        } */
1066       
1067       /* check for the end */
1068       if(entroducing <= 0) {
1069         int ao = 0, z = 0;
1070         for(z = 0; z < ANTCOUNT; ++z) {
1071           if(anton[z]) { ao = 1; break; }
1072         }
1073
1074         if(ao == 0) {
1075           fadeoutspeed = -0.02;
1076         }
1077       }
1078
1079     }
1080     
1081     /* near goal, bend path towards next step */
1082     if(near(antposition[i], antpath[i][part[i]])) {
1083       
1084       ++part[i];
1085
1086 /*       /\* special first ant *\/ */
1087 /*       if(i == 0 && part[i] > antpathlength[i]) { */
1088 /*      if(fir) */
1089 /*        first_ant_step = ant_step; */
1090
1091 /*      antvelocity[i] = 0.0; */
1092 /* /\*  antposition[i][2] += 0.025; *\/ */
1093 /*      elevator += 0.025; */
1094
1095 /*      /\* set light *\/ */
1096 /*      double l1 = 1.0 - (elevator < 1.0 ? elevator : 2.0 - elevator); */
1097 /*      GLfloat df[4] = {0.8*l1, 0.8*l1, 0.8*l1, 1.0}; */
1098 /*      glLightfv(GL_LIGHT0, GL_DIFFUSE, df); */
1099 /*      glLightfv(GL_LIGHT1, GL_DIFFUSE, df); */
1100
1101 /*      /\* draw next board *\/ */
1102 /*      if(elevator > 1.0) { */
1103
1104 /*        if(makenew == 1) { */
1105 /*          int re; */
1106           
1107 /*          /\* switch boards: rebuild old board, increment current *\/ */
1108 /*          currentboard = (currentboard+1)%BOARDCOUNT; */
1109 /*          build_board(currentboard); */
1110
1111 /*          for(re = 1; re < ANTCOUNT; ++re) { */
1112 /*            anton[re] = 0; */
1113 /*            antmaterial[re] = materials[random()%MATERIALS]; */
1114 /*          } */
1115
1116 /*          makenew = 0; */
1117
1118 /*        } */
1119
1120 /*        /\* draw the other board *\/ */
1121 /*        glEnable(GL_TEXTURE_2D); */
1122 /*        glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialGray6); */
1123
1124 /*        glPushMatrix(); */
1125 /*        glTranslatef(-(-(BOARDSIZE-3.5)+(BOARDSIZE-1)/2.0), 0.0,  */
1126 /*                     -(2.4+BOARDSIZE+(BOARDSIZE-1)/2.0)); */
1127 /*        draw_board(); */
1128 /*        glPopMatrix(); */
1129 /*        glDisable(GL_TEXTURE_2D); */
1130 /*      } */
1131 /*      /\* reset *\/ */
1132 /*      if(elevator > 2.0) { */
1133 /*        antposition[i][0] = -4.0;/\*-= -(-(BOARDSIZE-3.5)+(BOARDSIZE-1)/2.0);*\//\*= -4.0;*\/ */
1134 /*        antposition[i][1] = 5.5;/\*-(2.4+BOARDSIZE+(BOARDSIZE-1)/2.0);*\/ */
1135 /* /\*    antposition[i][2] = 0.15; *\/ */
1136 /*        antdirection[i] = PI/2.0; */
1137 /*        bposition[i][0] = 0; */
1138 /*        bposition[i][1] = 8; */
1139 /*        part[i] = 0; */
1140 /*        antvelocity[i] = 0.02; */
1141 /*        fir = 0; */
1142 /*        antmaterial[i] = MaterialRed; */
1143
1144 /*        makenew = 1; */
1145
1146 /*        elevator = 0.0; */
1147 /*        introduced = 200; */
1148 /*      } */
1149 /*      else { */
1150 /*        part[i]--; */
1151 /*      } */
1152 /*       } */
1153     
1154     }
1155     
1156     /* move toward goal, correct ant direction if required */
1157     else {
1158       
1159       /* difference */
1160       double dx = antpath[i][part[i]][0] - antposition[i][0];
1161       double dz = - antpath[i][part[i]][1] + antposition[i][1];
1162       double theta, ideal;
1163
1164       if(dz > EPSILON)
1165         theta = atan(dz/dx);
1166       else
1167         theta = dx > EPSILON ? 0.0 : PI;
1168       
1169       ideal = theta - antdirection[i];
1170       if(ideal < -Pi/2.0)
1171         ideal += Pi;
1172
1173       /* compute correction */
1174       double dt = sign(ideal) * min(fabs(ideal), PI/90.0);
1175       antdirection[i] += dt;
1176       if(antdirection[i] > 2.0*PI)
1177         antdirection[i] = 0.0;
1178     }
1179     
1180     antposition[i][0] += antvelocity[i] * cos(antdirection[i]);
1181     antposition[i][1] += antvelocity[i] * sin(-antdirection[i]);
1182   }
1183 }
1184
1185 static void pinit(void) {
1186   int status;
1187   glClearDepth(1.0);
1188   glClearColor(0.0, 0.0, 0.0, 1.0);
1189   
1190   glLightfv(GL_LIGHT0, GL_AMBIENT, ambient);
1191   glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse);
1192   glLightfv(GL_LIGHT0, GL_POSITION, position0);
1193   glLightfv(GL_LIGHT1, GL_AMBIENT, ambient);
1194   glLightfv(GL_LIGHT1, GL_DIFFUSE, diffuse);
1195   glLightfv(GL_LIGHT1, GL_POSITION, position1);
1196
1197   glLightf(GL_LIGHT0, GL_LINEAR_ATTENUATION, 0.05);
1198   glLightf(GL_LIGHT0, GL_QUADRATIC_ATTENUATION, 0.001);
1199   glLightf(GL_LIGHT0, GL_CONSTANT_ATTENUATION, 0.1);
1200
1201   glLightf(GL_LIGHT1, GL_LINEAR_ATTENUATION, 0.05);
1202   glLightf(GL_LIGHT1, GL_QUADRATIC_ATTENUATION, 0.001);
1203   glLightf(GL_LIGHT1, GL_CONSTANT_ATTENUATION, 0.1);
1204
1205
1206 /*   glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient); */
1207 /*   glLightModelfv(GL_LIGHT_MODEL_TWO_SIDE, lmodel_twoside); */
1208   glEnable(GL_LIGHTING);
1209   glEnable(GL_LIGHT0);
1210   glEnable(GL_LIGHT1);
1211   glEnable(GL_NORMALIZE);
1212   glFrontFace(GL_CCW);
1213   glCullFace(GL_BACK);
1214   
1215   /* moebius */
1216   glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, front_shininess);
1217   glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, front_specular);
1218
1219   glShadeModel(GL_SMOOTH);
1220   glEnable(GL_DEPTH_TEST);
1221   glDisable(GL_TEXTURE_2D);
1222
1223   /* setup textures */
1224   makeCheckImage();
1225   makeBrushedImage();
1226
1227   build_board(0);
1228   build_board(1);
1229
1230 /*   makeCheckImage(); */
1231 /*   glPixelStorei(GL_UNPACK_ALIGNMENT, 1); */
1232 /*   glTexImage2D(GL_TEXTURE_2D, 0, 3, checkImageWidth,  */
1233 /*             checkImageHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, checkers); */
1234 /*   glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); */
1235 /*   glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); */
1236
1237 /*   glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); */
1238 /*   glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); */
1239 /*   glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); */
1240   glEnable(GL_TEXTURE_2D);
1241     
1242 /*   glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, front_shininess); */
1243 /*   glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, front_specular); */
1244 }
1245
1246 void release_moebius(ModeInfo * mi) {
1247   if(moebius) {
1248         free((void *) moebius);
1249         moebius = (moebiusstruct *) NULL;
1250   }
1251   FreeAllGL(mi);
1252 }
1253
1254 int mag = 4.0;
1255 #define MAX_MAGNIFICATION 10
1256 #define max(a, b) a < b ? b : a
1257 #define min(a, b) a < b ? a : b
1258
1259 Bool moebius_handle_event (ModeInfo *mi, XEvent *event) {
1260   moebiusstruct *mp = &moebius[MI_SCREEN(mi)];
1261
1262   switch(event->xany.type) {
1263   case ButtonPress:
1264
1265     switch(event->xbutton.button) {
1266
1267     case Button1:
1268       mp->button_down_p = True;
1269       gltrackball_start(mp->trackball, 
1270                         event->xbutton.x, event->xbutton.y,
1271                         MI_WIDTH (mi), MI_HEIGHT (mi));
1272       break;
1273
1274     case Button3:
1275       focus = (focus + 1) % ANTCOUNT;
1276       break;
1277       
1278     case Button4:
1279       mag = max(mag-1, 1);
1280       break;
1281
1282     case Button5:
1283       mag = min(mag+1, MAX_MAGNIFICATION);
1284       break;
1285     }
1286
1287     break;
1288     
1289   case ButtonRelease:
1290
1291     switch(event->xbutton.button) {
1292     case Button1:
1293       mp->button_down_p = False;
1294       break;
1295     }
1296
1297     break;
1298
1299   case MotionNotify:
1300     if(mp->button_down_p)
1301       gltrackball_track(mp->trackball,
1302                         event->xmotion.x, event->xmotion.y,
1303                         MI_WIDTH (mi), MI_HEIGHT (mi));
1304     break;
1305     
1306   default:
1307     return False;
1308   }
1309
1310   return True;
1311 }
1312
1313 void init_moebius(ModeInfo * mi) {
1314   double rot_speed = 0.3;
1315
1316   moebiusstruct *mp;
1317   
1318   if (moebius == NULL) {
1319         if ((moebius = (moebiusstruct *) calloc(MI_NUM_SCREENS(mi),
1320                                                 sizeof (moebiusstruct))) == NULL)
1321           return;
1322   }
1323   mp = &moebius[MI_SCREEN(mi)];
1324   mp->step = NRAND(90);
1325   mp->ant_position = NRAND(90);
1326
1327   mp->rot = make_rotator (rot_speed, rot_speed, rot_speed, 1, 0, True);
1328   mp->trackball = gltrackball_init ();
1329   
1330   if ((mp->glx_context = init_GL(mi)) != NULL) {
1331     reshape_moebius(mi, MI_WIDTH(mi), MI_HEIGHT(mi));
1332     glDrawBuffer(GL_BACK);
1333     pinit();
1334   } 
1335   else
1336     MI_CLEARWINDOW(mi);
1337 }
1338
1339 void draw_moebius(ModeInfo * mi) {
1340   double h = (GLfloat) MI_HEIGHT(mi) / (GLfloat) MI_WIDTH(mi);
1341
1342   moebiusstruct *mp;
1343   
1344   Display    *display = MI_DISPLAY(mi);
1345   Window      window = MI_WINDOW(mi);
1346   
1347   if(!moebius)
1348         return;
1349   mp = &moebius[MI_SCREEN(mi)];
1350   
1351   MI_IS_DRAWN(mi) = True;
1352   
1353   if(!mp->glx_context)
1354         return;
1355   
1356   glXMakeCurrent(display, window, *(mp->glx_context));
1357
1358   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1359
1360   /* first panel */
1361   glPushMatrix();
1362 /*   h = ((GLfloat) MI_HEIGHT(mi)/2) / (3*(GLfloat)MI_WIDTH(mi)/4); */
1363   glViewport(MI_WIDTH(mi)/32, MI_HEIGHT(mi)/8, (9*MI_WIDTH(mi))/16, 3*MI_HEIGHT(mi)/4);
1364   glMatrixMode(GL_PROJECTION);
1365   glLoadIdentity();
1366
1367 /*   h = (3*MI_HEIGHT(mi)/4) / (3*MI_WIDTH(mi)/4); */
1368   gluPerspective(45, 1/h, 0.001, 25.0);
1369
1370   glMatrixMode(GL_MODELVIEW);
1371   glLoadIdentity();
1372
1373   glPushMatrix();
1374
1375   /* follow focused ant */
1376   glTranslatef(0.0, 0.0, -mag - 5.0);
1377   glRotatef(20.0+5.0*sin(ant_step/40.0), 1.0, 0.0, 0.0);
1378 /*   glTranslatef(0.0,  */
1379 /*             started ? -mag : -8.0 + 4.0*fabs(sin(ant_step/10.0)),  */
1380 /*             started ? -mag : -8.0 + 4.0*fabs(sin(ant_step/10.0))); */
1381
1382   gltrackball_rotate(mp->trackball);
1383
1384   glRotatef(ant_step*0.6, 0.0, 1.0, 0.0);
1385
1386 /*   glRotatef(90.0, 0.0, 0.0, 1.0); */
1387
1388 /*   glTranslatef(-antposition[0][0]-0.5, 0.0, -antposition[focus][1]); */
1389   /*-elevator*/
1390
1391   /* sync */
1392   if(!draw_moebius_strip(mi)) {
1393     release_moebius(mi);
1394     return;
1395   }
1396
1397   glPopMatrix();
1398   glPopMatrix();
1399
1400   h = (GLfloat) (3*MI_HEIGHT(mi)/8) / (GLfloat) (MI_WIDTH(mi)/2);
1401
1402   /* draw overhead */
1403   glPushMatrix();
1404   glViewport((17*MI_WIDTH(mi))/32, MI_HEIGHT(mi)/2, MI_WIDTH(mi)/2, 3*MI_HEIGHT(mi)/8);
1405   glMatrixMode(GL_PROJECTION);
1406   glLoadIdentity();
1407   gluPerspective(45, 1/h, 0.001, 25.0);
1408   glMatrixMode(GL_MODELVIEW);
1409     
1410   /* twist scene */
1411   glTranslatef(0.0, 0.0, -16.0);
1412   glRotatef(60.0, 1.0, 0.0, 0.0);
1413   glRotatef(-15.0 + ant_step/10.0, 0.0, 1.0, 0.0);
1414   gltrackball_rotate(mp->trackball);
1415
1416   /* sync */
1417   if(!draw_moebius_strip(mi)) {
1418     release_moebius(mi);
1419     return;
1420   }
1421
1422   glPopMatrix();
1423
1424   /* draw ant display */
1425   glPushMatrix();
1426   glViewport((5*MI_WIDTH(mi))/8, MI_HEIGHT(mi)/8, (11*MI_WIDTH(mi))/32, 3*MI_HEIGHT(mi)/8);
1427   glMatrixMode(GL_PROJECTION);
1428   glLoadIdentity();
1429   gluPerspective(45, 1/h, 0.001, 25.0);
1430   glMatrixMode(GL_MODELVIEW);
1431     
1432   /* twist scene */
1433   glTranslatef(0.0, 0.0, -1.6);
1434   glRotatef(30.0, 1.0, 0.0, 0.0);
1435   glRotatef(ant_step, 0.0, 1.0, 0.0);
1436   glRotatef(90.0, 0.0, 0.0, 1.0);
1437   
1438 /*   /\* draw ant shadow *\/ */
1439 /*   glPushMatrix(); */
1440 /*   glScalef(1.0, 0.01, 1.0); */
1441 /*   glRotatef(90.0, 0.0, 0.0, 1.0); */
1442 /*   glRotatef(90.0, 0.0, 1.0, 0.0); */
1443 /*   glDisable(GL_LIGHTING); */
1444 /*   glColor4fv(MaterialGray6); */
1445   
1446 /*   /\* slow down first ant *\/ */
1447 /*   draw_ant(MaterialGrayB, 0, 1, first_ant_step, mySphere, myCone); */
1448 /*   glPopMatrix(); */
1449
1450   /* draw ant body */
1451   glEnable(GL_TEXTURE_2D);
1452   glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse);
1453   glLightfv(GL_LIGHT1, GL_DIFFUSE, diffuse);
1454   glBindTexture(GL_TEXTURE_2D, brushedtexture);
1455   draw_ant(MaterialGray35, 0, 1, ant_step/2.0, mySphereTex, myCone2);
1456   glDisable(GL_TEXTURE_2D);
1457
1458   glPopMatrix();
1459
1460 /*   /\* draw overlay *\/ */
1461 /*   glPushMatrix(); */
1462
1463 /*   /\* go to ortho mode *\/ */
1464 /*   glViewport(MI_WIDTH(mi)/2, MI_HEIGHT(mi)/8, MI_WIDTH(mi)/2, 3*MI_HEIGHT(mi)/8); */
1465
1466 /*   glMatrixMode(GL_PROJECTION); */
1467 /*   glLoadIdentity(); */
1468
1469 /*   glPushMatrix (); */
1470 /*   glOrtho(-4.0, 4.0, -3.0, 3.0, -100.0, 100.0); */
1471
1472 /*   glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialGrayB); */
1473 /*   glColor4fv(MaterialGrayB); */
1474
1475 /*   glDisable(GL_LIGHTING); */
1476 /*   glEnable(GL_BLEND); */
1477
1478 /*   glBegin(GL_QUADS); */
1479 /*   glNormal3f(0.0, 0.0, 1.0); */
1480 /*   glVertex3f(4.0, 3.0, 0.0); */
1481 /*   glVertex3f(2.0, 3.0, 0.0); */
1482 /*   glVertex3f(2.0, -3.0, 0.0); */
1483 /*   glVertex3f(4.0, -3.0, 0.0); */
1484 /*   glEnd(); */
1485
1486 /*   glEnable(GL_LIGHTING); */
1487 /*   glDisable(GL_BLEND); */
1488
1489 /*   glPopMatrix(); */
1490 /*   glPopMatrix(); */
1491   
1492   if (MI_IS_FPS(mi)) do_fps (mi);
1493   glFlush();
1494   
1495   glXSwapBuffers(display, window);
1496   
1497   update_ants();
1498
1499   mp->step += 0.025;
1500 }
1501
1502 void change_moebius(ModeInfo * mi) {
1503   moebiusstruct *mp = &moebius[MI_SCREEN(mi)];
1504   
1505   if (!mp->glx_context)
1506         return;
1507   
1508   glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(mp->glx_context));
1509   pinit();
1510 }
1511
1512 #endif