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