0d50467146e400b79a98d4e2ac5ea322bf7eb7f7
[xscreensaver] / hacks / glx / antinspect.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 #include <X11/Intrinsic.h>
19
20 #ifdef STANDALONE
21 #define PROGCLASS           "AntInspect"
22 #define HACK_INIT           init_antinspect
23 #define HACK_DRAW           draw_antinspect
24 #define HACK_RESHAPE        reshape_antinspect
25 #define HACK_HANDLE_EVENT   antinspect_handle_event
26 #define EVENT_MASK          PointerMotionMask
27 #define antinspect_opts     xlockmore_opts
28 #define DEFAULTS            "*delay:   20000   \n" \
29                             "*showFPS: False   \n" \
30                             "*wireframe: False \n"
31
32 #include "xlockmore.h"
33 #else
34 #include "xlock.h"
35 #endif
36
37 #include <GL/glu.h>
38 #include "gltrackball.h"
39
40 #define DEF_SHADOWS  "True"
41
42 static int shadows;
43
44 static XrmOptionDescRec opts[] = {
45   {(char *) "-shadows", 
46    (char *) ".antinspect.shadows", XrmoptionNoArg, (caddr_t) "on"},
47
48   {(char *) "+shadows", 
49    (char *) ".antinspect.shadows", XrmoptionNoArg, (caddr_t) "off"}
50 };
51
52 static argtype vars[] = {
53   {(caddr_t *) &shadows, 
54    (char *) "shadows", (char *) "Shadows", (char *) DEF_SHADOWS, t_Bool}
55 };
56
57 static OptionStruct desc[] = {
58   {(char *) "-/+shadows", 
59    (char *) "turn on/off ant shadows"}
60 };
61
62 ModeSpecOpt antinspect_opts = {sizeof opts / sizeof opts[0], 
63                             opts, 
64                             sizeof vars / sizeof vars[0], 
65                             vars, 
66                             desc};
67
68 #ifdef USE_MODULES
69 ModStruct   antinspect_description =
70   {"antinspect", "init_antinspect", "draw_antinspect", "release_antinspect",
71    "draw_antinspect", "change_antinspect", (char *) NULL, &antinspect_opts,
72    1000, 1, 1, 1, 4, 1.0, "",
73    "draws some ants", 0, NULL};
74 #endif
75
76 #define Scale4Window               0.3
77 #define Scale4Iconic               0.4
78
79 #define sqr(A)                     ((A)*(A))
80
81 #ifndef Pi
82 #define Pi                         M_PI
83 #endif
84
85 #define ObjAntinspectStrip 0
86 #define ObjAntBody      1
87 #define MaxObj          2
88
89 /*************************************************************************/
90
91 typedef struct {
92   GLint       WindH, WindW;
93   GLfloat     step;
94   GLfloat     ant_position;
95   GLXContext *glx_context;
96   trackball_state *trackball;
97   Bool        button_down_p;
98 } antinspectstruct;
99
100 static float front_shininess[] = {60.0};
101 static float front_specular[] =  {0.7, 0.7, 0.7, 1.0};
102 static float ambient[] = {0.0, 0.0, 0.0, 1.0};
103 static float diffuse[] = {1.0, 1.0, 1.0, 1.0};
104 static float position0[] = {0.0, 3.0, 0.0, 1.0};
105 static float position1[] = {-1.0, -3.0, 1.0, 0.0};
106 static float lmodel_ambient[] = {0.5, 0.5, 0.5, 1.0};
107 static float lmodel_twoside[] = {GL_TRUE};
108
109 static float MaterialRed[] =     {0.6, 0.0, 0.0, 1.0};
110 static float MaterialOrange[] =  {1.0, 0.69, 0.00, 1.0};
111 static float MaterialGray[] =    {0.2, 0.2, 0.2, 1.0};
112 static float MaterialBlack[] =   {0.1, 0.1, 0.1, 0.4};
113 static float MaterialShadow[] =   {0.3, 0.3, 0.3, 0.3};
114 static float MaterialGray5[] =   {0.5, 0.5, 0.5, 0.3};
115 static float MaterialGray6[] =   {0.6, 0.6, 0.6, 1.0};
116
117 static antinspectstruct *antinspect = (antinspectstruct *) NULL;
118
119 #define NUM_SCENES      2
120
121 enum {X, Y, Z, W};
122 enum {A, B, C, D};
123
124 /* create a matrix that will project the desired shadow */
125 void shadowmatrix(GLfloat shadowMat[4][4],
126                   GLfloat groundplane[4],
127                   GLfloat lightpos[4]) {
128   GLfloat dot;
129
130   /* find dot product between light position vector and ground plane normal */
131   dot = groundplane[X] * lightpos[X] +
132         groundplane[Y] * lightpos[Y] +
133         groundplane[Z] * lightpos[Z] +
134         groundplane[W] * lightpos[W];
135
136   shadowMat[0][0] = dot - lightpos[X] * groundplane[X];
137   shadowMat[1][0] = 0.f - lightpos[X] * groundplane[Y];
138   shadowMat[2][0] = 0.f - lightpos[X] * groundplane[Z];
139   shadowMat[3][0] = 0.f - lightpos[X] * groundplane[W];
140
141   shadowMat[X][1] = 0.f - lightpos[Y] * groundplane[X];
142   shadowMat[1][1] = dot - lightpos[Y] * groundplane[Y];
143   shadowMat[2][1] = 0.f - lightpos[Y] * groundplane[Z];
144   shadowMat[3][1] = 0.f - lightpos[Y] * groundplane[W];
145
146   shadowMat[X][2] = 0.f - lightpos[Z] * groundplane[X];
147   shadowMat[1][2] = 0.f - lightpos[Z] * groundplane[Y];
148   shadowMat[2][2] = dot - lightpos[Z] * groundplane[Z];
149   shadowMat[3][2] = 0.f - lightpos[Z] * groundplane[W];
150
151   shadowMat[X][3] = 0.f - lightpos[W] * groundplane[X];
152   shadowMat[1][3] = 0.f - lightpos[W] * groundplane[Y];
153   shadowMat[2][3] = 0.f - lightpos[W] * groundplane[Z];
154   shadowMat[3][3] = dot - lightpos[W] * groundplane[W];
155 }
156
157 GLfloat ground[4] = {0.0, 1.0, 0.0, -0.00001};
158
159 /* simple filled sphere */
160 static Bool mySphere(float radius) {
161   GLUquadricObj *quadObj;
162
163   if((quadObj = gluNewQuadric()) == 0)
164     return False;
165   gluQuadricDrawStyle(quadObj, (GLenum) GLU_FILL);
166   gluSphere(quadObj, radius, 16, 16);
167   gluDeleteQuadric(quadObj);
168
169   return True;
170 }
171
172 /* caged sphere */
173 static Bool mySphere2(float radius) {
174   GLUquadricObj *quadObj;
175
176   if((quadObj = gluNewQuadric()) == 0)
177     return False;
178   gluQuadricDrawStyle(quadObj, (GLenum) GLU_LINE);/*GLU_SILHOUETTE);*/
179   gluSphere(quadObj, radius, 16, 8);
180   gluDeleteQuadric(quadObj);
181
182   return True;
183 }
184
185 /* null cone */
186 static Bool myCone2(float radius) { 
187   return True; 
188 }
189
190 int linewidth = 1;
191 static float ant_step = 0;
192
193 /* draw an ant */
194 static Bool draw_antinspect_ant(antinspectstruct * mp, float *Material, int mono,
195                              Bool (*sphere)(float), Bool (*cone)(float)) {
196   float       cos1 = cos(ant_step);
197   float       cos2 = cos(ant_step + 2 * Pi / 3);
198   float       cos3 = cos(ant_step + 4 * Pi / 3);
199   float       sin1 = sin(ant_step);
200   float       sin2 = sin(ant_step + 2 * Pi / 3);
201   float       sin3 = sin(ant_step + 4 * Pi / 3);
202   
203   if (mono)
204     glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialGray5);
205   else
206     glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, Material);
207   glEnable(GL_CULL_FACE);
208   glPushMatrix();
209   glScalef(1, 1.3, 1);
210   if (!((*sphere)(0.18)))
211     return False;
212   glScalef(1, 1 / 1.3, 1);
213   glTranslatef(0.00, 0.30, 0.00);
214   if (!((*sphere)(0.2)))
215     return False;
216   
217   glTranslatef(-0.05, 0.17, 0.05);
218   glRotatef(-90, 1, 0, 0);
219   glRotatef(-25, 0, 1, 0);
220   if (!((*cone)(0.05)))
221     return False;
222   glTranslatef(0.00, 0.10, 0.00);
223   if (!((*cone)(0.05)))
224     return False;
225   glRotatef(25, 0, 1, 0);
226   glRotatef(90, 1, 0, 0);
227   
228   glScalef(1, 1.3, 1);
229   glTranslatef(0.15, -0.65, 0.05);
230   if (!((*sphere)(0.25)))
231     return False;
232   glScalef(1, 1 / 1.3, 1);
233   glPopMatrix();
234   glDisable(GL_CULL_FACE);
235   
236   glDisable(GL_LIGHTING);
237   
238   /* ANTENNAS */
239   glBegin(GL_LINES);
240   if (mono)
241     glColor3fv(MaterialGray5);
242   else
243     glColor3fv(Material);
244   glVertex3f(0.00, 0.30, 0.00);
245   glColor3fv(MaterialGray);
246   glVertex3f(0.40, 0.70, 0.40);
247   if (mono)
248     glColor3fv(MaterialGray5);
249   else
250     glColor3fv(Material);
251   glVertex3f(0.00, 0.30, 0.00);
252   glColor3fv(MaterialGray);
253   glVertex3f(0.40, 0.70, -0.40);
254   glEnd();
255   glBegin(GL_POINTS);
256   if (mono)
257     glColor3fv(MaterialGray6);
258   else
259     glColor3fv(Material);
260   glVertex3f(0.40, 0.70, 0.40);
261   glVertex3f(0.40, 0.70, -0.40);
262   glEnd();
263   
264   /* LEFT-FRONT ARM */
265   glBegin(GL_LINE_STRIP);
266   if (mono)
267     glColor3fv(MaterialGray5);
268   else
269     glColor3fv(Material);
270   glVertex3f(0.00, 0.05, 0.18);
271   glVertex3f(0.35 + 0.05 * cos1, 0.15, 0.25);
272   glColor3fv(MaterialGray);
273   glVertex3f(-0.20 + 0.05 * cos1, 0.25 + 0.1 * sin1, 0.45);
274   glEnd();
275   
276   /* LEFT-CENTER ARM */
277   glBegin(GL_LINE_STRIP);
278   if (mono)
279     glColor3fv(MaterialGray5);
280   else
281     glColor3fv(Material);
282   glVertex3f(0.00, 0.00, 0.18);
283   glVertex3f(0.35 + 0.05 * cos2, 0.00, 0.25);
284   glColor3fv(MaterialGray);
285   glVertex3f(-0.20 + 0.05 * cos2, 0.00 + 0.1 * sin2, 0.45);
286   glEnd();
287   
288   /* LEFT-BACK ARM */
289   glBegin(GL_LINE_STRIP);
290   if (mono)
291     glColor3fv(MaterialGray5);
292   else
293     glColor3fv(Material);
294   glVertex3f(0.00, -0.05, 0.18);
295   glVertex3f(0.35 + 0.05 * cos3, -0.15, 0.25);
296   glColor3fv(MaterialGray);
297   glVertex3f(-0.20 + 0.05 * cos3, -0.25 + 0.1 * sin3, 0.45);
298   glEnd();
299   
300   /* RIGHT-FRONT ARM */
301   glBegin(GL_LINE_STRIP);
302   if (mono)
303     glColor3fv(MaterialGray5);
304   else
305     glColor3fv(Material);
306   glVertex3f(0.00, 0.05, -0.18);
307   glVertex3f(0.35 - 0.05 * sin1, 0.15, -0.25);
308   glColor3fv(MaterialGray);
309   glVertex3f(-0.20 - 0.05 * sin1, 0.25 + 0.1 * cos1, -0.45);
310   glEnd();
311   
312   /* RIGHT-CENTER ARM */
313   glBegin(GL_LINE_STRIP);
314   if (mono)
315     glColor3fv(MaterialGray5);
316   else
317     glColor3fv(Material);
318   glVertex3f(0.00, 0.00, -0.18);
319   glVertex3f(0.35 - 0.05 * sin2, 0.00, -0.25);
320   glColor3fv(MaterialGray);
321   glVertex3f(-0.20 - 0.05 * sin2, 0.00 + 0.1 * cos2, -0.45);
322   glEnd();
323   
324   /* RIGHT-BACK ARM */
325   glBegin(GL_LINE_STRIP);
326   if (mono)
327     glColor3fv(MaterialGray5);
328   else
329     glColor3fv(Material);
330   glVertex3f(0.00, -0.05, -0.18);
331   glVertex3f(0.35 - 0.05 * sin3, -0.15, -0.25);
332   glColor3fv(MaterialGray);
333   glVertex3f(-0.20 - 0.05 * sin3, -0.25 + 0.1 * cos3, -0.45);
334   glEnd();
335     
336   glEnable(GL_LIGHTING);
337   
338   return True;
339 }
340
341 /* only works with 3 right now */
342 #define ANTCOUNT 3
343
344 float MaterialBen[4] = {0.25, 0.30, 0.46, 1.0};
345
346 static float* antmaterial[ANTCOUNT] = 
347   {MaterialRed, MaterialBen, MaterialOrange};
348 static double antposition[ANTCOUNT] = {0.0, 120.0, 240.0};
349 static double antvelocity[ANTCOUNT] = {0.3, 0.3, 0.3};
350 static double antsphere[ANTCOUNT] = {1.2, 1.2, 1.2};
351
352 /* permutations */
353 static double antorder[6][ANTCOUNT] = {{0, 1, 2},
354                                        {0, 2, 1},
355                                        {2, 0, 1},
356                                        {2, 1, 0},
357                                        {1, 2, 0},
358                                        {1, 0, 2}};
359
360 /* draw the scene */
361 static Bool draw_antinspect_strip(ModeInfo * mi) {
362   antinspectstruct *mp = &antinspect[MI_SCREEN(mi)];
363   int         i, j;
364   int         mono = MI_IS_MONO(mi);
365
366   int ro = (((int)antposition[1])/(360/(2*ANTCOUNT))) % (2*ANTCOUNT);
367
368   glEnable(GL_TEXTURE_2D);
369   position0[1] = 9.6;
370   glLightfv(GL_LIGHT0, GL_POSITION, position0);
371
372   glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialGray5);
373   glRotatef(-30.0, 0.0, 1.0, 0.0);
374
375   glDisable(GL_TEXTURE_2D);
376   glDisable(GL_BLEND);
377
378   /* render ground plane */
379   glBegin(GL_TRIANGLES);
380   glColor4fv(MaterialShadow);
381   glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialBlack);
382   glNormal3f(0.0, 1.0, 0.0);
383
384   /* middle tri */
385   glVertex3f(0.0, 0.0, -1.0);
386   glVertex3f(-sqrt(3.0)/2.0, 0.0, 0.5);
387   glVertex3f(sqrt(3.0)/2.0, 0.0, 0.5);
388   glEnd();
389
390   /* rotate */
391   for(i = 0; i < 3; ++i) {
392     glRotatef(120.0, 0.0, 1.0, 0.0);
393     glBegin(GL_TRIANGLES);
394     glVertex3f(0.0, 0.0, 1.0 + 3.0);
395     glVertex3f(sqrt(3.0)/2.0, 0.0, -0.5 + 3.0);
396     glVertex3f(-sqrt(3.0)/2.0, 0.0, -0.5 + 3.0);
397     glEnd();
398   }
399
400   /* first render shadows -- no depth required */
401   if(shadows) {
402     GLfloat m[4][4];
403     shadowmatrix(m, ground, position0);
404     
405     glColor4fv(MaterialShadow);
406     glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialShadow);
407     
408     glDisable(GL_BLEND);
409     glDisable(GL_LIGHTING);
410     
411     /* display ant shadow */
412     glPushMatrix();
413     glTranslatef(0.0, 0.001, 0.0);
414     glMultMatrixf(m[0]);
415
416     for(i = 0; i < ANTCOUNT; ++i) {
417
418       /* draw ant */
419       glPushMatrix();
420
421       /* center */
422       glRotatef(antposition[i], 0.0, 1.0, 0.0);
423       glTranslatef(2.4, 0.0, 0.0);
424       glTranslatef(0.0, antsphere[i], 0.0);
425       glRotatef(90.0, 0.0, 1.0, 0.0);
426
427       /* orient ant */
428       glRotatef(10.0, 0.0, 1.0, 0.0);
429       glRotatef(40.0, 0.0, 0.0, 1.0);
430       glTranslatef(0.0, -0.8, 0.0);
431       glRotatef(180.0, 0.0, 1.0, 0.0);
432       glRotatef(90.0, 0.0, 0.0, 1.0);
433
434       /* set colour */
435       glColor4fv(MaterialShadow);
436       glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialShadow);
437
438       if(antposition[i] > 360.0)
439         antposition[i] = 0.0;
440       draw_antinspect_ant(mp, MaterialShadow, mono, mySphere2, myCone2);
441
442       glDisable(GL_BLEND);
443       glDisable(GL_LIGHTING);
444
445       /* draw sphere */
446       glRotatef(-20.0, 1.0, 0.0, 0.0);
447       glRotatef(-ant_step*2, 0.0, 0.0, 1.0);
448       glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialShadow);
449       mySphere2(1.2);
450
451       glPopMatrix();
452     }
453   
454     glPopMatrix();
455   }
456
457   glEnable(GL_LIGHTING);
458
459   /* truants */
460   for(j = 0; j < ANTCOUNT; ++j) {
461     /* determine rendering order */
462     i = antorder[ro][j];
463
464     glPushMatrix();
465     
466     /* center */
467     glRotatef(antposition[i], 0.0, 1.0, 0.0);
468     glTranslatef(2.4, 0.0, 0.0);
469     glTranslatef(0.0, antsphere[i], 0.0);    
470     glRotatef(90.0, 0.0, 1.0, 0.0);
471
472     /* draw ant */
473     glPushMatrix();
474     glRotatef(10.0, 0.0, 1.0, 0.0);
475     glRotatef(40.0, 0.0, 0.0, 1.0);
476     glTranslatef(0.0, -0.8, 0.0);
477     glRotatef(180.0, 0.0, 1.0, 0.0);
478     glRotatef(90.0, 0.0, 0.0, 1.0);
479     if(antposition[i] > 360.0)
480       antposition[i] = 0.0;
481     glEnable(GL_BLEND);
482     draw_antinspect_ant(mp, antmaterial[i], mono, mySphere2, myCone2);
483     glDisable(GL_BLEND);
484     glPopMatrix();
485
486     /* draw sphere */
487     glRotatef(-20.0, 1.0, 0.0, 0.0);
488     glRotatef(-ant_step*2, 0.0, 0.0, 1.0);
489     glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mono ? MaterialGray5 : antmaterial[i]);
490     mySphere2(1.2);
491     glEnable(GL_BLEND);
492     glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialBlack);
493     mySphere(1.16);
494     glDisable(GL_BLEND);
495         
496     glPopMatrix();
497
498     /* finally, evolve */
499     antposition[i] += antvelocity[i];
500   }
501
502   /* but the step size is the same! */
503   ant_step += 0.2;
504   
505   mp->ant_position += 1;
506   return True;
507 }
508
509 void reshape_antinspect(ModeInfo * mi, int width, int height) {
510   double h = (GLfloat) height / (GLfloat) width;  
511   antinspectstruct *mp = &antinspect[MI_SCREEN(mi)];
512   linewidth = (width / 512) + 1;
513
514   glViewport(0, 0, mp->WindW = (GLint) width, mp->WindH = (GLint) height);
515   glMatrixMode(GL_PROJECTION);
516   glLoadIdentity();
517
518   gluPerspective(45, 1/h, 7.0, 20.0);
519
520   glMatrixMode(GL_MODELVIEW);
521   glLineWidth(linewidth);
522   glPointSize(linewidth);
523 }
524
525 static void pinit(void) {
526   glClearDepth(1.0);
527   glClearColor(0.0, 0.0, 0.0, 1.0);
528   
529   glLightfv(GL_LIGHT0, GL_AMBIENT, ambient);
530   glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse);
531   glLightfv(GL_LIGHT0, GL_POSITION, position0);
532   glLightfv(GL_LIGHT1, GL_AMBIENT, ambient);
533   glLightfv(GL_LIGHT1, GL_DIFFUSE, diffuse);
534   glLightfv(GL_LIGHT1, GL_POSITION, position1);
535   glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient);
536   glLightModelfv(GL_LIGHT_MODEL_TWO_SIDE, lmodel_twoside);
537   glEnable(GL_LIGHTING);
538   glEnable(GL_LIGHT0);
539   glEnable(GL_LIGHT1);
540   glEnable(GL_NORMALIZE);
541   glFrontFace(GL_CCW);
542   
543   /* antinspect */
544   glShadeModel(GL_SMOOTH);
545   glEnable(GL_DEPTH_TEST);
546   glDisable(GL_TEXTURE_2D);
547
548   glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, front_shininess);
549   glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, front_specular);
550 }
551
552 void release_antinspect(ModeInfo * mi) {
553   if(antinspect) {
554         free((void *) antinspect);
555         antinspect = (antinspectstruct *) NULL;
556   }
557   FreeAllGL(mi);
558 }
559
560 Bool antinspect_handle_event (ModeInfo *mi, XEvent *event) {
561   antinspectstruct *mp = &antinspect[MI_SCREEN(mi)];
562   
563   if(event->xany.type == ButtonPress && event->xbutton.button & Button1) {
564         mp->button_down_p = True;
565         gltrackball_start(mp->trackball,
566                                           event->xbutton.x, event->xbutton.y,
567                                           MI_WIDTH (mi), MI_HEIGHT (mi));
568         return True;
569   }
570   else if(event->xany.type == ButtonRelease && 
571                   event->xbutton.button & Button1) {
572         mp->button_down_p = False;
573         return True;
574   }
575   else if(event->xany.type == MotionNotify && mp->button_down_p) {
576         gltrackball_track (mp->trackball,
577                                            event->xmotion.x, event->xmotion.y,
578                                            MI_WIDTH (mi), MI_HEIGHT (mi));
579         return True;
580   }
581   
582   return False;
583 }
584
585 void init_antinspect(ModeInfo * mi) {
586   antinspectstruct *mp;
587   
588   if(antinspect == NULL) {
589     if((antinspect = (antinspectstruct *) calloc(MI_NUM_SCREENS(mi),
590                                                  sizeof (antinspectstruct))) == NULL)
591       return;
592   }
593   mp = &antinspect[MI_SCREEN(mi)];
594   mp->step = NRAND(90);
595   mp->ant_position = NRAND(90);
596   mp->trackball = gltrackball_init ();
597   
598   if ((mp->glx_context = init_GL(mi)) != NULL) {
599     reshape_antinspect(mi, MI_WIDTH(mi), MI_HEIGHT(mi));
600     glDrawBuffer(GL_BACK);
601     pinit();
602   } 
603   else
604     MI_CLEARWINDOW(mi);
605
606   glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
607 }
608
609 void draw_antinspect(ModeInfo * mi) {
610   antinspectstruct *mp;
611   
612   Display    *display = MI_DISPLAY(mi);
613   Window      window = MI_WINDOW(mi);
614   
615   if(!antinspect)
616     return;
617   mp = &antinspect[MI_SCREEN(mi)];
618   
619   MI_IS_DRAWN(mi) = True;
620   
621   if(!mp->glx_context)
622         return;
623   
624   glXMakeCurrent(display, window, *(mp->glx_context));
625   
626   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
627
628   glPushMatrix();
629
630   /* position camera --- this works well, we can peer inside 
631      the antbubble */
632   glTranslatef(0.0, 0.0, -10.0);
633   gltrackball_rotate(mp->trackball);
634   glRotatef((15.0/2.0 + 15.0*sin(ant_step/100.0)), 1.0, 0.0, 0.0);
635   glRotatef(30.0, 1.0, 0.0, 0.0);
636   glRotatef(180.0, 0.0, 1.0, 0.0);
637   
638   if (!draw_antinspect_strip(mi)) {
639         release_antinspect(mi);
640         return;
641   }
642   
643   glPopMatrix();
644   
645   if (MI_IS_FPS(mi)) do_fps (mi);
646   glFlush();
647   
648   glXSwapBuffers(display, window);
649   
650   mp->step += 0.025;
651 }
652
653 void change_antinspect(ModeInfo * mi) {
654   antinspectstruct *mp = &antinspect[MI_SCREEN(mi)];
655   
656   if (!mp->glx_context)
657         return;
658   
659   glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(mp->glx_context));
660   pinit();
661 }
662