From http://www.jwz.org/xscreensaver/xscreensaver-5.38.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 free_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   int y = 0;
553   antinspectstruct *mp = &antinspect[MI_SCREEN(mi)];
554   mp->linewidth = (width / 512) + 1;
555
556   if (width > height * 5) {   /* tiny window: show middle */
557     height = width * 9/16;
558     y = -height/2;
559     h = height / (GLfloat) width;
560   }
561
562   glViewport(0, y, mp->WindW = (GLint) width, mp->WindH = (GLint) height);
563   glMatrixMode(GL_PROJECTION);
564   glLoadIdentity();
565
566   gluPerspective(45, 1/h, 7.0, 20.0);
567
568   glMatrixMode(GL_MODELVIEW);
569   glLineWidth(mp->linewidth);
570   glPointSize(mp->linewidth);
571 }
572
573 static void pinit(void) 
574 {
575   glClearDepth(1.0);
576   glLightfv(GL_LIGHT0, GL_AMBIENT, ambient);
577   glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse);
578   glLightfv(GL_LIGHT0, GL_POSITION, position0);
579   glLightfv(GL_LIGHT1, GL_AMBIENT, ambient);
580   glLightfv(GL_LIGHT1, GL_DIFFUSE, diffuse);
581   glLightfv(GL_LIGHT1, GL_POSITION, position1);
582   glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient);
583   glLightModelfv(GL_LIGHT_MODEL_TWO_SIDE, lmodel_twoside);
584   glEnable(GL_LIGHTING);
585   glEnable(GL_LIGHT0);
586   glEnable(GL_LIGHT1);
587   glEnable(GL_NORMALIZE);
588   glFrontFace(GL_CCW);
589   
590   /* antinspect */
591   glShadeModel(GL_SMOOTH);
592   glEnable(GL_DEPTH_TEST);
593   glDisable(GL_TEXTURE_2D);
594
595   glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, front_shininess);
596   glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, front_specular);
597 }
598
599 ENTRYPOINT Bool antinspect_handle_event (ModeInfo *mi, XEvent *event) 
600 {
601   antinspectstruct *mp = &antinspect[MI_SCREEN(mi)];
602   
603   if (gltrackball_event_handler (event, mp->trackball,
604                                  MI_WIDTH (mi), MI_HEIGHT (mi),
605                                  &mp->button_down_p))
606     return True;
607   
608   return False;
609 }
610
611 ENTRYPOINT void init_antinspect(ModeInfo * mi) 
612 {
613   antinspectstruct *mp;
614   
615   MI_INIT(mi, antinspect);
616   mp = &antinspect[MI_SCREEN(mi)];
617   mp->step = NRAND(90);
618   mp->ant_position = NRAND(90);
619   mp->trackball = gltrackball_init (False);
620   
621   if ((mp->glx_context = init_GL(mi)) != NULL) {
622     reshape_antinspect(mi, MI_WIDTH(mi), MI_HEIGHT(mi));
623     glDrawBuffer(GL_BACK);
624     pinit();
625   } 
626   else
627     MI_CLEARWINDOW(mi);
628
629   glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
630 }
631
632 ENTRYPOINT void draw_antinspect(ModeInfo * mi) 
633 {
634   antinspectstruct *mp;
635   
636   Display    *display = MI_DISPLAY(mi);
637   Window      window = MI_WINDOW(mi);
638   
639   if(!antinspect)
640     return;
641   mp = &antinspect[MI_SCREEN(mi)];
642   
643   MI_IS_DRAWN(mi) = True;
644   
645   if(!mp->glx_context)
646         return;
647   
648   glXMakeCurrent(display, window, *(mp->glx_context));
649   
650   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
651
652   glPushMatrix();
653
654   mi->polygon_count = 0;
655
656   /* position camera --- this works well, we can peer inside 
657      the antbubble */
658   glTranslatef(0.0, 0.0, -10.0);
659
660 # ifdef HAVE_MOBILE     /* Keep it the same relative size when rotated. */
661   {
662     GLfloat h = MI_HEIGHT(mi) / (GLfloat) MI_WIDTH(mi);
663     int o = (int) current_device_rotation();
664     if (o != 0 && o != 180 && o != -180)
665       glScalef (1/h, 1/h, 1/h);
666     glRotatef(o, 0, 0, 1);
667   }
668 # endif
669
670   gltrackball_rotate(mp->trackball);
671   glRotatef((15.0/2.0 + 15.0*sin(mp->ant_step/100.0)), 1.0, 0.0, 0.0);
672   glRotatef(30.0, 1.0, 0.0, 0.0);
673   glRotatef(180.0, 0.0, 1.0, 0.0);
674   
675   if (!draw_antinspect_strip(mi)) {
676         MI_ABORT(mi);
677         return;
678   }
679   
680   glPopMatrix();
681   
682   if (MI_IS_FPS(mi)) do_fps (mi);
683   glFlush();
684   
685   glXSwapBuffers(display, window);
686   
687   mp->step += 0.025;
688 }
689
690 #ifndef STANDALONE
691 ENTRYPOINT void change_antinspect(ModeInfo * mi) 
692 {
693   antinspectstruct *mp = &antinspect[MI_SCREEN(mi)];
694   
695   if (!mp->glx_context)
696         return;
697   
698   glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(mp->glx_context));
699   pinit();
700 }
701 #endif /* !STANDALONE */
702
703
704 XSCREENSAVER_MODULE ("AntInspect", antinspect)