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