http://ftp.ksu.edu.tw/FTP/FreeBSD/distfiles/xscreensaver-4.20.tar.gz
[xscreensaver] / hacks / glx / boing.c
1 /* boing, Copyright (c) 2005 Jamie Zawinski <jwz@jwz.org>
2  *
3  * Permission to use, copy, modify, distribute, and sell this software and its
4  * documentation for any purpose is hereby granted without fee, provided that
5  * the above copyright notice appear in all copies and that both that
6  * copyright notice and this permission notice appear in supporting
7  * documentation.  No representations are made about the suitability of this
8  * software for any purpose.  It is provided "as is" without express or 
9  * implied warranty.
10  *
11  * A clone of the Amiga 1000 "Boing" demo.  This was the first graphics demo
12  * for the Amiga, written by Dale Luck and RJ Mical during a break at the 1984
13  * Consumer Electronics Show (or so the legend goes.)  The boing ball was
14  * briefly the official logo of Amiga Inc., until they were bought by
15  * Commodore later that year.
16  *
17  * With no arguments, this program looks a lot like the original Amiga demo.
18  * With "-smooth -lighting", it looks... less old.
19  *
20  * The amiga version made noise when the ball hit the walls.  This version
21  * does not, obviously.
22  */
23
24 #include <X11/Intrinsic.h>
25
26 extern XtAppContext app;
27
28 #define PROGCLASS       "Boing"
29 #define HACK_INIT       init_boing
30 #define HACK_DRAW       draw_boing
31 #define HACK_RESHAPE    reshape_boing
32 #define HACK_HANDLE_EVENT boing_handle_event
33 #define EVENT_MASK      PointerMotionMask
34 #define sws_opts        xlockmore_opts
35
36 #define DEF_SPIN        "True"
37 #define DEF_LIGHTING    "False"
38 #define DEF_SMOOTH      "False"
39 #define DEF_SCANLINES   "False"
40 #define DEF_SPEED       "1.0"
41 #define DEF_SIZE        "0.5"
42 #define DEF_ANGLE       "15"
43 #define DEF_MERIDIANS   "16"
44 #define DEF_PARALLELS   "8"
45 #define DEF_TILES       "12"
46 #define DEF_THICKNESS   "0.05"
47
48 #define DEF_BALL_COLOR1  "#CC1919"
49 #define DEF_BALL_COLOR2  "#F2F2F2"
50 #define DEF_GRID_COLOR   "#991999"
51 #define DEF_SHADOW_COLOR "#303030"
52 #define DEF_BACKGROUND   "#8C8C8C"
53
54 #define DEFAULTS        "*delay:        30000            \n" \
55                         "*showFPS:      False            \n" \
56                         "*wireframe:    False            \n" \
57                         "*spin:       " DEF_SPIN        "\n" \
58                         "*lighting:   " DEF_LIGHTING    "\n" \
59                         "*smooth:     " DEF_SMOOTH      "\n" \
60                         "*scanlines:  " DEF_SCANLINES   "\n" \
61                         "*speed:      " DEF_SPEED       "\n" \
62                         "*angle:      " DEF_ANGLE       "\n" \
63                         "*ballSize:   " DEF_SIZE        "\n" \
64                         "*meridians:  " DEF_MERIDIANS   "\n" \
65                         "*parallels:  " DEF_PARALLELS   "\n" \
66                         "*tiles:      " DEF_TILES       "\n" \
67                         "*thickness:  " DEF_THICKNESS   "\n" \
68                         "*ballColor1: " DEF_BALL_COLOR1 "\n" \
69                         "*ballColor2: " DEF_BALL_COLOR2 "\n" \
70                         "*gridColor:  " DEF_GRID_COLOR  "\n" \
71                         "*shadowColor:" DEF_SHADOW_COLOR"\n" \
72                         ".background: " DEF_BACKGROUND  "\n" \
73
74 #undef countof
75 #define countof(x) (sizeof((x))/sizeof((*x)))
76
77 #include "xlockmore.h"
78 #include "gltrackball.h"
79 #include <ctype.h>
80
81 #ifdef USE_GL /* whole file */
82
83 #include <GL/glu.h>
84
85 typedef struct { GLfloat x, y, z; } XYZ;
86
87 typedef struct {
88   GLXContext *glx_context;
89   trackball_state *trackball;
90   Bool button_down_p;
91
92   GLuint ball_list;
93   double ball_x,   ball_y,   ball_z,   ball_th;
94   double ball_dx,  ball_dy,  ball_dz,  ball_dth;
95   double ball_ddx, ball_ddy, ball_ddz;
96
97   GLfloat ball_color1[4], ball_color2[4], grid_color[4];
98   GLfloat bg_color[4], shadow_color[4];
99   GLfloat lightpos[4];
100
101 } boing_configuration;
102
103 static boing_configuration *bps = NULL;
104
105 static Bool spin;
106 static Bool lighting_p;
107 static Bool smooth_p;
108 static Bool scanlines_p;
109 static GLfloat speed;
110 static int angle;
111 static GLfloat ball_size;
112 static unsigned int meridians;
113 static unsigned int parallels;
114 static unsigned int tiles;
115 static GLfloat thickness;
116 static char *ball_color1_str, *ball_color2_str, *grid_color_str,
117   *shadow_str, *bg_str;
118
119 static XrmOptionDescRec opts[] = {
120   { "-spin",       ".spin",      XrmoptionNoArg,  "True"  },
121   { "+spin",       ".spin",      XrmoptionNoArg,  "False" },
122   { "-lighting",   ".lighting",  XrmoptionNoArg,  "True"  },
123   { "+lighting",   ".lighting",  XrmoptionNoArg,  "False" },
124   { "-smooth",     ".smooth",    XrmoptionNoArg,  "True"  },
125   { "+smooth",     ".smooth",    XrmoptionNoArg,  "False" },
126   { "-scanlines",  ".scanlines", XrmoptionNoArg,  "True"  },
127   { "+scanlines",  ".scanlines", XrmoptionNoArg,  "False" },
128   { "-speed",      ".speed",     XrmoptionSepArg, 0 },
129   { "-angle",      ".angle",     XrmoptionSepArg, 0 },
130   { "-size",       ".ballSize",  XrmoptionSepArg, 0 },
131   { "-meridians",  ".meridians", XrmoptionSepArg, 0 },
132   { "-parallels",  ".parallels", XrmoptionSepArg, 0 },
133   { "-tiles",      ".tiles",     XrmoptionSepArg, 0 },
134   { "-thickness",  ".thickness", XrmoptionSepArg, 0 },
135   { "-ball-color1",".ballColor1",XrmoptionSepArg, 0 },
136   { "-ball-color2",".ballColor2",XrmoptionSepArg, 0 },
137   { "-grid-color", ".gridColor", XrmoptionSepArg, 0 },
138   { "-shadow-color",".shadowColor",XrmoptionSepArg, 0 },
139 };
140
141 static argtype vars[] = {
142   {&spin,      "spin",      "Spin",       DEF_SPIN,      t_Bool},
143   {&lighting_p,"lighting",  "Lighting",   DEF_LIGHTING,  t_Bool},
144   {&smooth_p,  "smooth",    "Smooth",     DEF_SMOOTH,    t_Bool},
145   {&scanlines_p,"scanlines","Scanlines",  DEF_SCANLINES, t_Bool},
146   {&speed,     "speed",     "Speed",      DEF_SPEED,     t_Float},
147   {&angle,     "angle",     "Angle",      DEF_ANGLE,     t_Int},
148   {&ball_size, "ballSize",  "BallSize",   DEF_SIZE,      t_Float},
149   {&meridians, "meridians", "meridians",  DEF_MERIDIANS, t_Int},
150   {&parallels, "parallels", "parallels",  DEF_PARALLELS, t_Int},
151   {&tiles,     "tiles",     "Tiles",      DEF_TILES,     t_Int},
152   {&thickness, "thickness", "Thickness",  DEF_THICKNESS, t_Float},
153   {&ball_color1_str, "ballColor1", "BallColor1", DEF_BALL_COLOR1, t_String},
154   {&ball_color2_str, "ballColor2", "BallColor2", DEF_BALL_COLOR2, t_String},
155   {&grid_color_str,  "gridColor",  "GridColor",  DEF_GRID_COLOR,  t_String},
156   {&shadow_str,      "shadowColor","ShadowColor",DEF_SHADOW_COLOR,t_String},
157   {&bg_str,          "background", "Background", DEF_BACKGROUND,  t_String},
158 };
159
160 ModeSpecOpt sws_opts = {countof(opts), opts, countof(vars), vars, NULL};
161
162 static void
163 parse_color (ModeInfo *mi, const char *name, const char *s, GLfloat *a)
164 {
165   XColor c;
166   a[3] = 1.0;  /* alpha */
167
168   if (! XParseColor (MI_DISPLAY(mi), MI_COLORMAP(mi), s, &c))
169     {
170       fprintf (stderr, "%s: can't parse %s color %s", progname, name, s);
171       exit (1);
172     }
173   a[0] = c.red   / 65536.0;
174   a[1] = c.green / 65536.0;
175   a[2] = c.blue  / 65536.0;
176 }
177
178
179 static void
180 draw_grid (ModeInfo *mi)
181 {
182   boing_configuration *bp = &bps[MI_SCREEN(mi)];
183   int x, y;
184   GLfloat t2  = (GLfloat) tiles / 2;
185   GLfloat s = 1.0 / (tiles + thickness);
186   GLfloat z = 0;
187
188   GLfloat lw = MI_HEIGHT(mi) * 0.06 * thickness;
189
190   glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE, bp->grid_color);
191   glColor3fv (bp->grid_color);
192
193   glPushMatrix();
194   glScalef(s, s, s);
195   glTranslatef (-t2, -t2, 0);
196
197   glLineWidth (lw);
198   glBegin (GL_LINES);
199   for (y = 0; y <= tiles; y++)
200     {
201       glVertex3f (0,     y, z);
202       glVertex3f (tiles, y, z);
203       /*mi->polygon_count++;*/
204     }
205   for (x = 0; x <= tiles; x++)
206     {
207       glVertex3f (x, tiles, z);
208       glVertex3f (x, 0,     z);
209       /*mi->polygon_count++;*/
210     }
211
212   glEnd();
213   glPopMatrix();
214 }
215
216
217 static void
218 draw_box (ModeInfo *mi)
219 {
220   /* boing_configuration *bp = &bps[MI_SCREEN(mi)]; */
221   glPushMatrix();
222   glTranslatef (0, 0, -0.5);
223   glFrontFace (GL_CCW);
224   draw_grid (mi);
225   glPopMatrix();
226
227   glPushMatrix();
228   glRotatef (90, 1, 0, 0);
229   glTranslatef (0, 0, 0.5);
230   glFrontFace (GL_CW);
231   draw_grid (mi);
232   glPopMatrix();
233 }
234
235
236 static void
237 draw_ball (ModeInfo *mi)
238 {
239   boing_configuration *bp = &bps[MI_SCREEN(mi)];
240   int wire = MI_IS_WIREFRAME(mi);
241   int x, y;
242   int xx = meridians;
243   int yy = parallels;
244   int scale = (smooth_p ? 5 : 1);
245
246   if (lighting_p && !wire)
247     glEnable (GL_LIGHTING);
248
249   if (parallels < 3)
250     scale *= 2;
251
252   xx *= scale;
253   yy *= scale;
254
255   glFrontFace (GL_CW);
256
257   glPushMatrix();
258   glTranslatef (bp->ball_x, bp->ball_y, bp->ball_z);
259   glScalef (ball_size, ball_size, ball_size);
260   glRotatef (-angle,      0, 0, 1);
261   glRotatef (bp->ball_th, 0, 1, 0);
262
263   for (y = 0; y < yy; y++)
264     {
265       GLfloat thy0 = y     * (M_PI * 2) / (yy * 2) + M_PI_2;
266       GLfloat thy1 = (y+1) * (M_PI * 2) / (yy * 2) + M_PI_2;
267
268       for (x = 0; x < xx; x++)
269         {
270           GLfloat thx0 = x     * (M_PI * 2) / xx;
271           GLfloat thx1 = (x+1) * (M_PI * 2) / xx;
272           XYZ p;
273           Bool bgp = ((x/scale) & 1) ^ ((y/scale) & 1);
274
275           if (wire && bgp) continue;
276
277           glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE,
278                         (bgp ? bp->ball_color2 : bp->ball_color1));
279           glColor3fv (bgp ? bp->ball_color2 : bp->ball_color1);
280
281           glBegin (wire ? GL_LINE_LOOP : GL_QUADS);
282
283           if (!smooth_p)
284             {
285               p.x = cos((thy0+thy1)/2) * cos((thx0+thx1)/2);
286               p.y = sin((thy0+thy1)/2);
287               p.z = cos((thy0+thy1)/2) * sin((thx0+thx1)/2);
288               glNormal3f (-p.x, -p.y, -p.z);
289             }
290
291           p.x = cos(thy0) * cos(thx0) / 2;
292           p.y = sin(thy0)             / 2;
293           p.z = cos(thy0) * sin(thx0) / 2;
294           if (smooth_p)
295             glNormal3f (-p.x, -p.y, -p.z);
296           glVertex3f (p.x, p.y, p.z);
297
298           p.x = cos(thy1) * cos(thx0) / 2;
299           p.y = sin(thy1)             / 2;
300           p.z = cos(thy1) * sin(thx0) / 2;
301           if (smooth_p)
302             glNormal3f (-p.x, -p.y, -p.z);
303           glVertex3f (p.x, p.y, p.z);
304
305           p.x = cos(thy1) * cos(thx1) / 2;
306           p.y = sin(thy1)             / 2;
307           p.z = cos(thy1) * sin(thx1) / 2;
308           if (smooth_p)
309             glNormal3f (-p.x, -p.y, -p.z);
310           glVertex3f (p.x, p.y, p.z);
311
312           p.x = cos(thy0) * cos(thx1) / 2;
313           p.y = sin(thy0)             / 2;
314           p.z = cos(thy0) * sin(thx1) / 2;
315           if (smooth_p)
316             glNormal3f (-p.x, -p.y, -p.z);
317           glVertex3f (p.x, p.y, p.z);
318
319           glEnd ();
320           mi->polygon_count++;
321         }
322     }
323
324   glPopMatrix();
325
326   if (lighting_p && !wire)
327     glDisable(GL_LIGHTING);
328 }
329
330
331 static void
332 draw_shadow (ModeInfo *mi)
333 {
334   boing_configuration *bp = &bps[MI_SCREEN(mi)];
335   int wire = MI_IS_WIREFRAME(mi);
336   GLfloat xoff = 0.14;
337   GLfloat yoff = 0.07;
338   int y;
339   int yy = parallels;
340   int scale = (smooth_p ? 5 : 1);
341
342   if (lighting_p && !wire)
343     glEnable (GL_BLEND);
344
345   if (parallels < 3)
346     scale *= 2;
347
348   yy *= scale;
349
350   glPushMatrix();
351   glTranslatef (bp->ball_x + xoff, bp->ball_y + yoff, -0.49);
352   glScalef (ball_size, ball_size, ball_size);
353   glRotatef (-angle, 0, 0, 1);
354
355   glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE, bp->shadow_color);
356   glColor4fv (bp->shadow_color);
357
358   glFrontFace (GL_CCW);
359   glNormal3f (0, 0, 1);
360   glBegin (wire ? GL_LINE_LOOP : GL_TRIANGLE_FAN);
361   if (!wire) glVertex3f (0, 0, 0);
362
363   for (y = 0; y < yy*2+1; y++)
364     {
365       GLfloat thy0 = y * (M_PI * 2) / (yy * 2) + M_PI_2;
366       glVertex3f (cos(thy0) / 2, sin(thy0) / 2, 0);
367       mi->polygon_count++;
368     }
369
370   glEnd ();
371
372   glPopMatrix();
373
374   if (lighting_p && !wire)
375     glDisable (GL_BLEND);
376 }
377
378
379 static void
380 draw_scanlines (ModeInfo *mi)
381 {
382   /* boing_configuration *bp = &bps[MI_SCREEN(mi)]; */
383   int wire = MI_IS_WIREFRAME(mi);
384   int w = MI_WIDTH(mi);
385   int h = MI_HEIGHT(mi);
386
387   if (h <= 300) return;
388
389   if (!wire)
390     {
391       glEnable (GL_BLEND);
392       glDisable (GL_DEPTH_TEST);
393     }
394
395   glMatrixMode(GL_PROJECTION);
396   glPushMatrix();
397   {
398     glLoadIdentity();
399     glMatrixMode(GL_MODELVIEW);
400     glPushMatrix();
401     {
402       int lh, ls;
403       int y;
404       glLoadIdentity();
405       gluOrtho2D (0, w, 0, h);
406
407       if      (h > 500) lh = 4, ls = 4;
408       else if (h > 300) lh = 2, ls = 1;
409       else              lh = 1, ls = 1;
410
411       if (lh == 1)
412         glDisable (GL_BLEND);
413
414       glLineWidth (lh);
415       glColor4f (0, 0, 0, 0.3);
416
417       glBegin(GL_LINES);
418       for (y = 0; y < h; y += lh + ls)
419         {
420           glVertex3f (0, y, 0);
421           glVertex3f (w, y, 0);
422         }
423       glEnd();
424     }
425     glPopMatrix();
426   }
427   glMatrixMode(GL_PROJECTION);
428   glPopMatrix();
429   glMatrixMode(GL_MODELVIEW);
430
431   if (!wire)
432     {
433       glDisable (GL_BLEND);
434       glEnable (GL_DEPTH_TEST);
435     }
436 }
437
438
439
440 static void
441 tick_physics (ModeInfo *mi)
442 {
443   boing_configuration *bp = &bps[MI_SCREEN(mi)];
444   GLfloat s2 = ball_size / 2;
445   GLfloat max = 0.5 - s2;
446   GLfloat min = -max;
447
448   bp->ball_th += bp->ball_dth;
449   while (bp->ball_th > 360) bp->ball_th -= 360;
450   while (bp->ball_th < 0)   bp->ball_th += 360;
451
452   bp->ball_dx += bp->ball_ddx;
453   bp->ball_x  += bp->ball_dx;
454   if      (bp->ball_x < min) bp->ball_x = min, bp->ball_dx = -bp->ball_dx,
455     bp->ball_dth = -bp->ball_dth,
456     bp->ball_dx += (frand(speed/2) - speed);
457   else if (bp->ball_x > max) bp->ball_x = max, bp->ball_dx = -bp->ball_dx,
458     bp->ball_dth = -bp->ball_dth,
459     bp->ball_dx += (frand(speed/2) - speed);
460
461   bp->ball_dy += bp->ball_ddy;
462   bp->ball_y  += bp->ball_dy;
463   if      (bp->ball_y < min) bp->ball_y = min, bp->ball_dy = -bp->ball_dy;
464   else if (bp->ball_y > max) bp->ball_y = max, bp->ball_dy = -bp->ball_dy;
465
466   bp->ball_dz += bp->ball_ddz;
467   bp->ball_z  += bp->ball_dz;
468   if      (bp->ball_z < min) bp->ball_z = min, bp->ball_dz = -bp->ball_dz;
469   else if (bp->ball_z > max) bp->ball_z = max, bp->ball_dz = -bp->ball_dz;
470 }
471
472
473
474 /* Window management, etc
475  */
476 void
477 reshape_boing (ModeInfo *mi, int width, int height)
478 {
479   GLfloat h = (GLfloat) height / (GLfloat) width;
480
481   h *= 4.0 / 3.0;   /* Back in the caveman days we couldn't even afford
482                        square pixels! */
483
484   glViewport (0, 0, (GLint) width, (GLint) height);
485
486   glMatrixMode(GL_PROJECTION);
487   glLoadIdentity();
488   gluPerspective (8.0, 1/h, 1.0, 10.0);
489
490   glMatrixMode(GL_MODELVIEW);
491   glLoadIdentity();
492   gluLookAt (0.0, 0.0, 8.0,
493              0.0, 0.0, 0.0,
494              0.0, 1.0, 0.0);
495
496   glClear(GL_COLOR_BUFFER_BIT);
497 }
498
499
500 Bool
501 boing_handle_event (ModeInfo *mi, XEvent *event)
502 {
503   boing_configuration *bp = &bps[MI_SCREEN(mi)];
504
505   if (event->xany.type == ButtonPress &&
506       event->xbutton.button == Button1)
507     {
508       bp->button_down_p = True;
509       gltrackball_start (bp->trackball,
510                          event->xbutton.x, event->xbutton.y,
511                          MI_WIDTH (mi), MI_HEIGHT (mi));
512       return True;
513     }
514   else if (event->xany.type == ButtonRelease &&
515            event->xbutton.button == Button1)
516     {
517       bp->button_down_p = False;
518       return True;
519     }
520   else if (event->xany.type == ButtonPress &&
521            (event->xbutton.button == Button4 ||
522             event->xbutton.button == Button5))
523     {
524       gltrackball_mousewheel (bp->trackball, event->xbutton.button, 10,
525                               !!event->xbutton.state);
526       return True;
527     }
528   else if (event->xany.type == MotionNotify &&
529            bp->button_down_p)
530     {
531       gltrackball_track (bp->trackball,
532                          event->xmotion.x, event->xmotion.y,
533                          MI_WIDTH (mi), MI_HEIGHT (mi));
534       return True;
535     }
536
537   return False;
538 }
539
540
541 void 
542 init_boing (ModeInfo *mi)
543 {
544   boing_configuration *bp;
545   int wire = MI_IS_WIREFRAME(mi);
546
547   if (!bps) {
548     bps = (boing_configuration *)
549       calloc (MI_NUM_SCREENS(mi), sizeof (boing_configuration));
550     if (!bps) {
551       fprintf(stderr, "%s: out of memory\n", progname);
552       exit(1);
553     }
554
555     bp = &bps[MI_SCREEN(mi)];
556   }
557
558   bp = &bps[MI_SCREEN(mi)];
559
560   bp->glx_context = init_GL(mi);
561
562   if (tiles < 1) tiles = 1;
563
564   if (smooth_p)
565     {
566       if (meridians < 1) meridians = 1;
567       if (parallels < 1) parallels = 1;
568     }
569   else
570     {
571       if (meridians < 3) meridians = 3;
572       if (parallels < 2) parallels = 2;
573     }
574
575   if (meridians > 1 && meridians & 1) meridians++;  /* odd numbers look bad */
576
577
578   if (thickness <= 0) thickness = 0.001;
579   else if (thickness > 1) thickness = 1;
580
581   reshape_boing (mi, MI_WIDTH(mi), MI_HEIGHT(mi));
582
583   parse_color (mi, "ballColor1",  ball_color1_str,  bp->ball_color1);
584   parse_color (mi, "ballColor2",  ball_color2_str,  bp->ball_color2);
585   parse_color (mi, "gridColor",   grid_color_str,   bp->grid_color);
586   parse_color (mi, "shadowColor", shadow_str,       bp->shadow_color);
587   parse_color (mi, "background",  bg_str,           bp->bg_color);
588
589   bp->shadow_color[3] = 0.9;
590
591   glClearColor (bp->bg_color[0], bp->bg_color[1], bp->bg_color[2], 1);
592
593   if (!wire)
594     {
595       glEnable(GL_DEPTH_TEST);
596       glEnable(GL_CULL_FACE);
597     }
598
599   bp->lightpos[0] = 0.5;
600   bp->lightpos[1] = 0.5;
601   bp->lightpos[2] = -1;
602   bp->lightpos[3] = 0;
603
604   if (lighting_p && !wire)
605     {
606       GLfloat amb[4] = {0, 0, 0, 1};
607       GLfloat dif[4] = {1, 1, 1, 1};
608       GLfloat spc[4] = {1, 1, 1, 1};
609       glEnable(GL_LIGHT0);
610       glLightfv(GL_LIGHT0, GL_AMBIENT,  amb);
611       glLightfv(GL_LIGHT0, GL_DIFFUSE,  dif);
612       glLightfv(GL_LIGHT0, GL_SPECULAR, spc);
613     }
614
615   glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
616
617   speed = speed / 800.0;
618
619   bp->ball_dth = (spin ? -speed * 7 * 360 : 0);
620
621   bp->ball_x   = 0.5 - ((ball_size/2) + frand(1-ball_size));
622   bp->ball_y   = 0.2;
623   bp->ball_dx  = speed * 6 + frand(speed);
624   bp->ball_ddy = -speed;
625
626   bp->ball_dz  = speed * 6 + frand(speed);
627
628   bp->trackball = gltrackball_init ();
629 }
630
631
632 void
633 draw_boing (ModeInfo *mi)
634 {
635   boing_configuration *bp = &bps[MI_SCREEN(mi)];
636   Display *dpy = MI_DISPLAY(mi);
637   Window window = MI_WINDOW(mi);
638
639   if (!bp->glx_context)
640     return;
641
642   mi->polygon_count = 0;
643
644   glShadeModel(GL_SMOOTH);
645
646   glEnable(GL_NORMALIZE);
647   glEnable(GL_CULL_FACE);
648   glEnable (GL_DEPTH_TEST);
649
650   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
651
652   if (! bp->button_down_p)
653     tick_physics (mi);
654
655   glPushMatrix ();
656   gltrackball_rotate (bp->trackball);
657
658   glLightfv (GL_LIGHT0, GL_POSITION, bp->lightpos);
659
660   draw_box (mi);
661   draw_shadow (mi);
662   draw_ball (mi);
663   if (scanlines_p)
664     draw_scanlines (mi);
665
666   glPopMatrix ();
667
668   if (mi->fps_p) do_fps (mi);
669   glFinish();
670
671   glXSwapBuffers(dpy, window);
672 }
673
674 #endif /* USE_GL */