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