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