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 2003 Blair Tennessy
15 */
16
17 #ifdef STANDALONE
18 #define DEFAULTS "*delay: 20000 \n" \
19 "*showFPS: False \n" \
20 "*useSHM: True \n"
21
22 # define release_antspotlight 0
23 #include "xlockmore.h"
24 #else
25 #include "xlock.h"
26 #endif
27
28 #ifdef HAVE_JWXYZ
29 # include "jwxyz.h"
30 #else
31 # include <X11/Xlib.h>
32 # include <GL/gl.h>
33 # include <GL/glu.h>
34 #endif
35
36 #ifdef HAVE_JWZGLES
37 # include "jwzgles.h"
38 #endif /* HAVE_JWZGLES */
39
40 #include "sphere.h"
41 #include "tube.h"
42 #include "rotator.h"
43 #include "gltrackball.h"
44
45 ENTRYPOINT ModeSpecOpt antspotlight_opts = {
46 0, NULL, 0, NULL, NULL
47 };
48
49 #ifdef USE_MODULES
50 ModStruct antspotlight_description = {
51 "antspotlight", "init_antspotlight", "draw_antspotlight",
52 (char *) NULL, "draw_antspotlight", "change_antspotlight",
53 (char *) NULL, &antspotlight_opts, 1000, 1, 1, 1, 4, 1.0, "",
54 "draws an ant scoping the screen", 0, NULL
55 };
56 #endif
57
58 #define Scale4Window 0.3
59 #define Scale4Iconic 0.4
60
61 #define sqr(A) ((A)*(A))
62
63 #ifndef Pi
64 #define Pi M_PI
65 #endif
66
67 #include "ants.h"
68 #include "grab-ximage.h"
69
70 typedef struct {
71 GLXContext *glx_context;
72 rotator *rot;
73 trackball_state *trackball;
74 Bool button_down_p;
75
76 GLfloat max_tx, max_ty;
77 int mono, wire, ticks;
78 GLuint screentexture;
79
80 Ant *ant;
81 double boardsize;
82 GLfloat spot_direction[3];
83 int mag;
84
85 Bool mipmap_p;
86 Bool waiting_for_image_p;
87
88 } antspotlightstruct;
89
90 static antspotlightstruct *antspotlight = (antspotlightstruct *) NULL;
91
92 #define NUM_SCENES 2
93
94 /* draw method for ant */
draw_ant(ModeInfo * mi,antspotlightstruct * mp,const GLfloat * Material,int mono,int shadow,float ant_step,Bool (* sphere)(float),Bool (* cone)(float))95 static Bool draw_ant(ModeInfo *mi, antspotlightstruct *mp,
96 const GLfloat *Material, int mono, int shadow,
97 float ant_step, Bool (*sphere)(float), Bool (*cone)(float))
98 {
99
100 float cos1 = cos(ant_step);
101 float cos2 = cos(ant_step + 2 * Pi / 3);
102 float cos3 = cos(ant_step + 4 * Pi / 3);
103 float sin1 = sin(ant_step);
104 float sin2 = sin(ant_step + 2 * Pi / 3);
105 float sin3 = sin(ant_step + 4 * Pi / 3);
106
107 /* Apparently this is a performance killer on many systems...
108 glEnable(GL_POLYGON_SMOOTH);
109 */
110 glEnable(GL_BLEND);
111 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
112
113 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mp->mono ? MaterialGray5 : Material);
114 glEnable(GL_CULL_FACE);
115 glPushMatrix();
116 glScalef(1, 1.3, 1);
117 if(!((*sphere)(0.18)))
118 return False;
119 glScalef(1, 1 / 1.3, 1);
120 glTranslatef(0.00, 0.30, 0.00);
121 if(!((*sphere)(0.2)))
122 return False;
123
124 glTranslatef(-0.05, 0.17, 0.05);
125 glRotatef(-90, 1, 0, 0);
126 glRotatef(-25, 0, 1, 0);
127 if(!((*cone)(0.05)))
128 return False;
129 glTranslatef(0.00, 0.10, 0.00);
130 if(!((*cone)(0.05)))
131 return False;
132 glRotatef(25, 0, 1, 0);
133 glRotatef(90, 1, 0, 0);
134
135 glScalef(1, 1.3, 1);
136 glTranslatef(0.15, -0.65, 0.05);
137 if(!((*sphere)(0.25)))
138 return False;
139 glScalef(1, 1 / 1.3, 1);
140 glPopMatrix();
141 glDisable(GL_CULL_FACE);
142
143 glDisable(GL_LIGHTING);
144
145 /* ANTENNAS */
146 glEnable(GL_LINE_SMOOTH);
147 glEnable(GL_BLEND);
148 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
149
150 glBegin(GL_LINES);
151 glColor3fv(mp->mono ? MaterialGray5 : Material);
152 glVertex3f(0.00, 0.30, 0.00);
153 glColor3fv(MaterialGray);
154 glVertex3f(0.40, 0.70, 0.40);
155 mi->polygon_count++;
156 glColor3fv(mp->mono ? MaterialGray5 : Material);
157 glVertex3f(0.00, 0.30, 0.00);
158 glColor3fv(MaterialGray);
159 glVertex3f(0.40, 0.70, -0.40);
160 mi->polygon_count++;
161 glEnd();
162
163 if(!shadow) {
164 glBegin(GL_POINTS);
165 glColor3fv(mp->mono ? MaterialGray6 : MaterialGray5);
166 glVertex3f(0.40, 0.70, 0.40);
167 mi->polygon_count++;
168 glVertex3f(0.40, 0.70, -0.40);
169 mi->polygon_count++;
170 glEnd();
171 }
172
173 /* LEFT-FRONT ARM */
174 glBegin(GL_LINE_STRIP);
175 glColor3fv(mp->mono ? MaterialGray5 : Material);
176 glVertex3f(0.00, 0.05, 0.18);
177 glVertex3f(0.35 + 0.05 * cos1, 0.15, 0.25);
178 mi->polygon_count++;
179 glColor3fv(MaterialGray);
180 glVertex3f(-0.20 + 0.05 * cos1, 0.25 + 0.1 * sin1, 0.45);
181 mi->polygon_count++;
182 glEnd();
183
184 /* LEFT-CENTER ARM */
185 glBegin(GL_LINE_STRIP);
186 glColor3fv(mp->mono ? MaterialGray5 : Material);
187 glVertex3f(0.00, 0.00, 0.18);
188 glVertex3f(0.35 + 0.05 * cos2, 0.00, 0.25);
189 mi->polygon_count++;
190 glColor3fv(MaterialGray);
191 glVertex3f(-0.20 + 0.05 * cos2, 0.00 + 0.1 * sin2, 0.45);
192 mi->polygon_count++;
193 glEnd();
194
195 /* LEFT-BACK ARM */
196 glBegin(GL_LINE_STRIP);
197 glColor3fv(mp->mono ? MaterialGray5 : Material);
198 glVertex3f(0.00, -0.05, 0.18);
199 glVertex3f(0.35 + 0.05 * cos3, -0.15, 0.25);
200 mi->polygon_count++;
201 glColor3fv(MaterialGray);
202 glVertex3f(-0.20 + 0.05 * cos3, -0.25 + 0.1 * sin3, 0.45);
203 mi->polygon_count++;
204 glEnd();
205
206 /* RIGHT-FRONT ARM */
207 glBegin(GL_LINE_STRIP);
208 glColor3fv(mp->mono ? MaterialGray5 : Material);
209 glVertex3f(0.00, 0.05, -0.18);
210 glVertex3f(0.35 - 0.05 * sin1, 0.15, -0.25);
211 mi->polygon_count++;
212 glColor3fv(MaterialGray);
213 glVertex3f(-0.20 - 0.05 * sin1, 0.25 + 0.1 * cos1, -0.45);
214 mi->polygon_count++;
215 glEnd();
216
217 /* RIGHT-CENTER ARM */
218 glBegin(GL_LINE_STRIP);
219 glColor3fv(mp->mono ? MaterialGray5 : Material);
220 glVertex3f(0.00, 0.00, -0.18);
221 glVertex3f(0.35 - 0.05 * sin2, 0.00, -0.25);
222 mi->polygon_count++;
223 glColor3fv(MaterialGray);
224 glVertex3f(-0.20 - 0.05 * sin2, 0.00 + 0.1 * cos2, -0.45);
225 mi->polygon_count++;
226 glEnd();
227
228 /* RIGHT-BACK ARM */
229 glBegin(GL_LINE_STRIP);
230 glColor3fv(mp->mono ? MaterialGray5 : Material);
231 glVertex3f(0.00, -0.05, -0.18);
232 glVertex3f(0.35 - 0.05 * sin3, -0.15, -0.25);
233 mi->polygon_count++;
234 glColor3fv(MaterialGray);
235 glVertex3f(-0.20 - 0.05 * sin3, -0.25 + 0.1 * cos3, -0.45);
236 mi->polygon_count++;
237 glEnd();
238
239 if(!shadow) {
240 glBegin(GL_POINTS);
241 glColor3fv(MaterialGray5);
242 glVertex3f(-0.20 + 0.05 * cos1, 0.25 + 0.1 * sin1, 0.45);
243 glVertex3f(-0.20 + 0.05 * cos2, 0.00 + 0.1 * sin2, 0.45);
244 glVertex3f(-0.20 + 0.05 * cos3, -0.25 + 0.1 * sin3, 0.45);
245 glVertex3f(-0.20 - 0.05 * sin1, 0.25 + 0.1 * cos1, -0.45);
246 glVertex3f(-0.20 - 0.05 * sin2, 0.00 + 0.1 * cos2, -0.45);
247 glVertex3f(-0.20 - 0.05 * sin3, -0.25 + 0.1 * cos3, -0.45);
248 mi->polygon_count += 6;
249 glEnd();
250 }
251
252 glEnable(GL_LIGHTING);
253
254 return True;
255 }
256
257 /* filled sphere */
mySphere(float radius)258 static Bool mySphere(float radius)
259 {
260 #if 0
261 GLUquadricObj *quadObj;
262
263 if((quadObj = gluNewQuadric()) == 0)
264 return False;
265
266 gluQuadricDrawStyle(quadObj, (GLenum) GLU_FILL);
267 gluSphere(quadObj, radius, 16, 16);
268 gluDeleteQuadric(quadObj);
269 #else
270 glPushMatrix();
271 glScalef (radius, radius, radius);
272 glRotatef (90, 1, 0, 0);
273 unit_sphere (16, 16, False);
274 glPopMatrix();
275 #endif
276 return True;
277 }
278
279 /* silhouette sphere */
mySphere2(float radius)280 static Bool mySphere2(float radius)
281 {
282 #if 0
283 GLUquadricObj *quadObj;
284
285 if((quadObj = gluNewQuadric()) == 0)
286 return False;
287 gluQuadricDrawStyle(quadObj, (GLenum) GLU_LINE);
288 gluSphere(quadObj, radius, 16, 8);
289 gluDeleteQuadric(quadObj);
290 #else
291 /* #### no GLU_LINE */
292 glPushMatrix();
293 glScalef (radius, radius, radius);
294 glRotatef (90, 1, 0, 0);
295 unit_sphere (16, 16, True);
296 glPopMatrix();
297 #endif
298 return True;
299 }
300
301 /* no cone */
myCone2(float radius)302 static Bool myCone2(float radius) { return True; }
303
draw_board(ModeInfo * mi,antspotlightstruct * mp)304 static void draw_board(ModeInfo *mi, antspotlightstruct *mp)
305 {
306 int i, j;
307 double cutoff = Pi/3.0;
308 double center[3];
309 double centertex[2];
310
311 glEnable(GL_TEXTURE_2D);
312 glBindTexture(GL_TEXTURE_2D, mp->screentexture);
313 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialGray6);
314
315 /* draw mesh */
316
317 /* center is roughly spotlight position */
318 center[0] = mp->ant->position[0];/* + cos(ant->direction); */
319 center[1] = 0.0;
320 center[2] = mp->ant->position[2];/* - 0.7*sin(ant->direction);*/
321
322 centertex[0] = (mp->boardsize/2.0+center[0]) * mp->max_tx / mp->boardsize;
323 centertex[1] = mp->max_ty - ((mp->boardsize/2.0+center[2]) * mp->max_ty / mp->boardsize);
324
325 /* glPolygonMode(GL_FRONT, GL_LINE); */
326 /* glDisable(GL_TEXTURE_2D); */
327
328 /*
329 the vertices determined here should correspond to the illuminated
330 board. ideally the code adapts vertex distribution to the
331 intensity and shape of the light.
332
333 i should be finding the intersection of the cone of light and
334 the board-plane.
335 */
336 for(i = -12; i < 12; ++i) {
337
338 double theta1, theta2;
339
340 glBegin(GL_TRIANGLE_STRIP);
341 glNormal3f(0.0, 1.0, 0.0);
342
343 glTexCoord2f(centertex[0], centertex[1]);
344 glVertex3f(center[0], 0.01, center[2]);
345
346 /* watch those constants */
347 theta1 = mp->ant->direction + i*(cutoff/8);
348 theta2 = mp->ant->direction + (i+1)*(cutoff/8);
349
350 for(j = 1; j <= 64; ++j) {
351 double point[3], tex[2];
352 /* double fj = pow(1.05, j) - 1.0;*/
353 double fj = j / 6.0;
354 point[0] = center[0] + fj*cos(theta1);
355 point[1] = 0.0;
356 point[2] = center[2] - fj*sin(theta1);
357
358 tex[0] = (mp->boardsize/2.0+point[0]) * mp->max_tx / mp->boardsize;
359 tex[1] = (mp->boardsize/2.0+point[2]) * mp->max_ty / mp->boardsize;
360
361 glTexCoord2f(tex[0], tex[1]);
362 glVertex3f(point[0], point[1], point[2]);
363
364 point[0] = center[0] + fj*cos(theta2);
365 point[1] = 0.0;
366 point[2] = center[2] - fj*sin(theta2);
367
368 tex[0] = (mp->boardsize/2.0+point[0]) * mp->max_tx / mp->boardsize;
369 tex[1] = (mp->boardsize/2.0+point[2]) * mp->max_ty / mp->boardsize;
370
371 glTexCoord2f(tex[0], tex[1]);
372 glVertex3f(point[0], point[1], point[2]);
373 mi->polygon_count++;
374 }
375
376 glEnd();
377 }
378
379 glDisable(GL_TEXTURE_2D);
380 }
381
382 /* return euclidean distance between two points */
distance(double x[3],double y[3])383 static double distance(double x[3], double y[3])
384 {
385 double dx = x[0] - y[0];
386 double dz = x[2] - y[2];
387 return sqrt(dx*dx + dz*dz);
388 }
389
390 /* determine a new goal */
find_goal(antspotlightstruct * mp)391 static void find_goal(antspotlightstruct *mp)
392 {
393 do {
394 mp->ant->goal[0] = random()%((int)(mp->boardsize+0.5)-2) - mp->boardsize/2.0 + 1.0;
395 mp->ant->goal[1] = 0.0;
396 mp->ant->goal[2] = random()%((int)(mp->boardsize+0.5)-2) - mp->boardsize/2.0 + 1.0;
397 }
398 while(distance(mp->ant->position, mp->ant->goal) < 2.0);
399 }
400
401 /* construct our ant */
build_ant(antspotlightstruct * mp)402 static void build_ant(antspotlightstruct *mp)
403 {
404 mp->ant = (Ant *) malloc(sizeof (Ant));
405 mp->ant->position[0] = 0.0;
406 mp->ant->position[1] = 0.0;
407 mp->ant->position[2] = 0.0;
408 mp->ant->direction = 0.0;
409 mp->ant->velocity = 0.02;
410 mp->ant->material = MaterialGray5;
411 mp->ant->step = 0;
412 find_goal(mp);
413 }
414
415 #define EPSILON 0.01
416
sign(double d)417 static double sign(double d)
418 {
419 return d < 0.0 ? -1.0 : 1.0;
420 }
421
min(double a,double b)422 static double min(double a, double b)
423 {
424 return a < b ? a : b;
425 }
426
427 /*
428 static double max(double a, double b)
429 {
430 return a > b ? a : b;
431 }
432 */
433
434 /* find a new goal and reset steps */
reset_ant(antspotlightstruct * mp)435 static void reset_ant(antspotlightstruct *mp)
436 {
437 find_goal(mp);
438 }
439
440 /* draw ant composed of skeleton and glass */
show_ant(ModeInfo * mi,antspotlightstruct * mp)441 static void show_ant(ModeInfo *mi, antspotlightstruct *mp)
442 {
443
444 glPushMatrix();
445
446 /* move into position */
447 glTranslatef(mp->ant->position[0], 0.33, mp->ant->position[2]);
448 glRotatef(180.0 + mp->ant->direction*180.0/Pi, 0.0, 1.0, 0.0);
449 glRotatef(90.0, 0.0, 0.0, 1.0);
450
451 /* draw skeleton */
452 draw_ant(mi, mp, mp->ant->material, mp->mono, 0, mp->ant->step, mySphere2, myCone2);
453
454 /* draw glass */
455 if(!mp->wire && !mp->mono) {
456 glEnable(GL_BLEND);
457 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialGrayB);
458 glColor4fv(MaterialGrayB);
459 draw_ant(mi, mp, MaterialGrayB, mp->mono, 0, mp->ant->step, mySphere, myCone2);
460 glDisable(GL_BLEND);
461 }
462
463 glPopMatrix();
464 }
465
draw_antspotlight_strip(ModeInfo * mi)466 static void draw_antspotlight_strip(ModeInfo *mi)
467 {
468 antspotlightstruct *mp = &antspotlight[MI_SCREEN(mi)];
469
470 /* compute spotlight position and direction */
471 GLfloat light1_position[4];
472
473 light1_position[0] = mp->ant->position[0] + 0.7*cos(mp->ant->direction);
474 light1_position[1] = 0.5;
475 light1_position[2] = mp->ant->position[2] - 0.7*sin(mp->ant->direction);
476 light1_position[3] = 1.0;
477
478 mp->spot_direction[0] = cos(mp->ant->direction);
479 mp->spot_direction[1] = -0.5;
480 mp->spot_direction[2] = -sin(mp->ant->direction);
481
482 glLightfv(GL_LIGHT2, GL_POSITION, light1_position);
483 glLightfv(GL_LIGHT2, GL_SPOT_DIRECTION, mp->spot_direction);
484
485 glEnable(GL_LIGHT2);
486 glDisable(GL_LIGHT0);
487 glDisable(GL_LIGHT1);
488
489 /* draw board */
490 if(mp->wire)
491 ;
492 else
493 draw_board(mi, mp);
494
495 glDisable(GL_LIGHT2);
496 glEnable(GL_LIGHT0);
497 glEnable(GL_LIGHT1);
498
499 /* now modify ant */
500 show_ant(mi, mp);
501
502 /* near goal, bend path towards next step */
503 if(distance(mp->ant->position, mp->ant->goal) < 0.2) {
504 reset_ant(mp);
505 }
506
507 if(random()%100 == 0) {
508 reset_ant(mp);
509 }
510
511
512 /* move toward goal, correct ant direction if required */
513 else {
514
515 /* difference */
516 double dx = mp->ant->goal[0] - mp->ant->position[0];
517 double dz = -(mp->ant->goal[2] - mp->ant->position[2]);
518 double theta, ideal, dt;
519
520 if(fabs(dx) > EPSILON) {
521 theta = atan(dz/dx);
522 if(dx < 0.0)
523 theta += Pi;
524 }
525 else
526 theta = dz > 0.0 ? (1.0/2.0)*Pi : (3.0/2.0)*Pi;
527
528 if(theta < 0.0)
529 theta += 2*Pi;
530
531 ideal = theta - mp->ant->direction;
532 if(ideal > Pi)
533 ideal -= 2*Pi;
534
535 /* compute correction */
536 dt = sign(ideal) * min(fabs(ideal), Pi/100.0);
537 mp->ant->direction += dt;
538 while(mp->ant->direction < 0.0)
539 mp->ant->direction += 2*Pi;
540 while(mp->ant->direction > 2*Pi)
541 mp->ant->direction -= 2*Pi;
542 }
543
544 mp->ant->position[0] += mp->ant->velocity * cos(mp->ant->direction);
545 mp->ant->position[2] += mp->ant->velocity * sin(-mp->ant->direction);
546 mp->ant->step += 10*mp->ant->velocity;
547 while(mp->ant->step > 2*Pi)
548 mp->ant->step -= 2*Pi;
549 }
550
reshape_antspotlight(ModeInfo * mi,int width,int height)551 ENTRYPOINT void reshape_antspotlight(ModeInfo * mi, int width, int height)
552 {
553 double h = (GLfloat) height / (GLfloat) width;
554 int y = 0;
555 int size = 2;
556
557 if (width > height * 5) { /* tiny window: show middle */
558 height = width * 9/16;
559 y = -height/2;
560 h = height / (GLfloat) width;
561 }
562
563 glViewport(0, y, width, height);
564 glMatrixMode(GL_PROJECTION);
565 glLoadIdentity();
566
567 gluPerspective(45, 1/h, 1.0, 25.0);
568
569 glMatrixMode(GL_MODELVIEW);
570 glLineWidth(size);
571 glPointSize(size);
572 }
573
574 /* lighting variables */
575 static const GLfloat front_shininess[] = {60.0};
576 static const GLfloat front_specular[] = {0.8, 0.8, 0.8, 1.0};
577 static const GLfloat ambient[] = {0.4, 0.4, 0.4, 1.0};
578 /*static const GLfloat ambient2[] = {0.0, 0.0, 0.0, 0.0};*/
579 static const GLfloat diffuse[] = {1.0, 1.0, 1.0, 1.0};
580 static const GLfloat position0[] = {1.0, 5.0, 1.0, 0.0};
581 static const GLfloat position1[] = {-1.0, -5.0, 1.0, 0.0};
582 /*static const GLfloat lmodel_ambient[] = {0.8, 0.8, 0.8, 1.0};*/
583 static const GLfloat lmodel_twoside[] = {GL_TRUE};
584 static const GLfloat spotlight_ambient[] = { 0.0, 0.0, 0.0, 1.0 };
585 static const GLfloat spotlight_diffuse[] = { 1.0, 1.0, 1.0, 1.0 };
586
pinit(void)587 static void pinit(void)
588 {
589 glClearDepth(1.0);
590
591 /* setup twoside lighting */
592 glLightfv(GL_LIGHT0, GL_AMBIENT, ambient);
593 glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse);
594 glLightfv(GL_LIGHT0, GL_POSITION, position0);
595 glLightfv(GL_LIGHT1, GL_AMBIENT, ambient);
596 glLightfv(GL_LIGHT1, GL_DIFFUSE, diffuse);
597 glLightfv(GL_LIGHT1, GL_POSITION, position1);
598
599 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, spotlight_ambient);
600 glLightModelfv(GL_LIGHT_MODEL_TWO_SIDE, lmodel_twoside);
601 glEnable(GL_LIGHTING);
602 glEnable(GL_LIGHT0);
603 glEnable(GL_LIGHT1);
604
605 /* setup spotlight */
606 glLightfv(GL_LIGHT2, GL_AMBIENT, spotlight_ambient);
607 glLightfv(GL_LIGHT2, GL_DIFFUSE, spotlight_diffuse);
608 glLightf(GL_LIGHT2, GL_CONSTANT_ATTENUATION, 0.1);
609 glLightf(GL_LIGHT2, GL_LINEAR_ATTENUATION, 0.05);
610 glLightf(GL_LIGHT2, GL_QUADRATIC_ATTENUATION, 0.0);
611 glLightf(GL_LIGHT2, GL_SPOT_CUTOFF, 60.0);
612 glLightf(GL_LIGHT2, GL_SPOT_EXPONENT, 3.0);
613
614 glEnable(GL_NORMALIZE);
615 glFrontFace(GL_CCW);
616 glCullFace(GL_BACK);
617
618 /* setup material properties */
619 glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, front_shininess);
620 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, front_specular);
621
622 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
623 glShadeModel(GL_SMOOTH);
624 /* glShadeModel(GL_FLAT); */
625 glEnable(GL_DEPTH_TEST);
626 }
627
628 #define MAX_MAGNIFICATION 10
629 #define max(a, b) a < b ? b : a
630 #define min(a, b) a < b ? a : b
631
632 /* event handling */
antspotlight_handle_event(ModeInfo * mi,XEvent * event)633 ENTRYPOINT Bool antspotlight_handle_event(ModeInfo *mi, XEvent *event)
634 {
635 antspotlightstruct *mp = &antspotlight[MI_SCREEN(mi)];
636
637 if (gltrackball_event_handler (event, mp->trackball,
638 MI_WIDTH (mi), MI_HEIGHT (mi),
639 &mp->button_down_p))
640 return True;
641
642 if (event->xany.type == ButtonPress)
643 {
644 switch(event->xbutton.button) {
645
646 case Button1:
647 mp->button_down_p = True;
648 gltrackball_start(mp->trackball,
649 event->xbutton.x, event->xbutton.y,
650 MI_WIDTH (mi), MI_HEIGHT (mi));
651 return True;
652
653 case Button4:
654 mp->mag = max(mp->mag-1, 1);
655 return True;
656
657 case Button5:
658 mp->mag = min(mp->mag+1, MAX_MAGNIFICATION);
659 return True;
660 }
661 }
662
663 return False;
664 }
665
666 static void
image_loaded_cb(const char * filename,XRectangle * geometry,int image_width,int image_height,int texture_width,int texture_height,void * closure)667 image_loaded_cb (const char *filename, XRectangle *geometry,
668 int image_width, int image_height,
669 int texture_width, int texture_height,
670 void *closure)
671 {
672 antspotlightstruct *mp = (antspotlightstruct *) closure;
673
674 mp->max_tx = (GLfloat) image_width / texture_width;
675 mp->max_ty = (GLfloat) image_height / texture_height;
676
677 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
678 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
679 (mp->mipmap_p ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR));
680
681 mp->waiting_for_image_p = False;
682 }
683
684
685 /* get screenshot */
get_snapshot(ModeInfo * modeinfo)686 static void get_snapshot(ModeInfo *modeinfo)
687 {
688 antspotlightstruct *mp = &antspotlight[MI_SCREEN(modeinfo)];
689
690 if (MI_IS_WIREFRAME(modeinfo))
691 return;
692
693 mp->waiting_for_image_p = True;
694 mp->mipmap_p = True;
695 load_texture_async (modeinfo->xgwa.screen, modeinfo->window,
696 *mp->glx_context, 0, 0, mp->mipmap_p,
697 mp->screentexture, image_loaded_cb, mp);
698 }
699
700
init_antspotlight(ModeInfo * mi)701 ENTRYPOINT void init_antspotlight(ModeInfo *mi)
702 {
703 double rot_speed = 0.3;
704
705 antspotlightstruct *mp;
706
707 MI_INIT(mi, antspotlight);
708 mp = &antspotlight[MI_SCREEN(mi)];
709 mp->rot = make_rotator (rot_speed, rot_speed, rot_speed, 1, 0, True);
710 mp->trackball = gltrackball_init (False);
711
712 if((mp->glx_context = init_GL(mi)) != NULL) {
713 reshape_antspotlight(mi, MI_WIDTH(mi), MI_HEIGHT(mi));
714 glDrawBuffer(GL_BACK);
715 pinit();
716 }
717 else
718 MI_CLEARWINDOW(mi);
719
720 glGenTextures(1, &mp->screentexture);
721 glBindTexture(GL_TEXTURE_2D, mp->screentexture);
722 get_snapshot(mi);
723
724 build_ant(mp);
725 mp->mono = MI_IS_MONO(mi);
726 mp->wire = MI_IS_WIREFRAME(mi);
727 mp->boardsize = 8.0;
728 mp->mag = 1;
729 }
730
draw_antspotlight(ModeInfo * mi)731 ENTRYPOINT void draw_antspotlight(ModeInfo * mi)
732 {
733 antspotlightstruct *mp;
734
735 Display *display = MI_DISPLAY(mi);
736 Window window = MI_WINDOW(mi);
737
738 if(!antspotlight)
739 return;
740 mp = &antspotlight[MI_SCREEN(mi)];
741
742 MI_IS_DRAWN(mi) = True;
743
744 if(!mp->glx_context)
745 return;
746
747 mi->polygon_count = 0;
748
749 /* Just keep running before the texture has come in. */
750 /* if (mp->waiting_for_image_p) return; */
751
752 glXMakeCurrent(display, window, *mp->glx_context);
753
754 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
755
756 glPushMatrix();
757 glRotatef(current_device_rotation(), 0, 0, 1);
758
759 /* position camera */
760
761 /* follow focused ant */
762 glTranslatef(0.0, 0.0, -6.0 - mp->mag);
763 glRotatef(35.0, 1.0, 0.0, 0.0);
764 gltrackball_rotate(mp->trackball);
765 glTranslatef(-mp->ant->position[0], mp->ant->position[1], -mp->ant->position[2]);
766
767 /* stable position */
768 /* glTranslatef(0.0, 0.0, -10.0 - mag); */
769 /* gltrackball_rotate(mp->trackball); */
770 /* glRotatef(40.0, 1.0, 0.0, 0.0); */
771 /* glRotatef(20.0, 0.0, 1.0, 0.0); */
772
773 draw_antspotlight_strip(mi);
774
775 ++mp->ticks;
776
777 glPopMatrix();
778
779 if (MI_IS_FPS(mi)) do_fps (mi);
780 glFlush();
781
782 glXSwapBuffers(display, window);
783 }
784
785 #ifndef STANDALONE
change_antspotlight(ModeInfo * mi)786 ENTRYPOINT void change_antspotlight(ModeInfo * mi)
787 {
788 antspotlightstruct *mp = &antspotlight[MI_SCREEN(mi)];
789
790 if (!mp->glx_context)
791 return;
792
793 glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *mp->glx_context);
794 pinit();
795 }
796 #endif /* !STANDALONE */
797
free_antspotlight(ModeInfo * mi)798 ENTRYPOINT void free_antspotlight(ModeInfo * mi)
799 {
800 antspotlightstruct *mp = &antspotlight[MI_SCREEN(mi)];
801 if (!mp->glx_context) return;
802 glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *mp->glx_context);
803 gltrackball_free (mp->trackball);
804 free_rotator (mp->rot);
805 if (mp->screentexture) glDeleteTextures (1, &mp->screentexture);
806 }
807
808 XSCREENSAVER_MODULE ("AntSpotlight", antspotlight)
809