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