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