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