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