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