http://www.tienza.es/crux/src/www.jwz.org/xscreensaver/xscreensaver-5.05.tar.gz
[xscreensaver] / hacks / glx / flipflop.c
1 /* flipflop, Copyright (c) 2003 Kevin Ogden <kogden1@hotmail.com>
2  *                     (c) 2006 Sergio GutiĆ©rrez "Sergut" <sergut@gmail.com>
3  *
4  * Permission to use, copy, modify, distribute, and sell this software and its
5  * documentation for any purpose is hereby granted without fee, provided that
6  * the above copyright notice appear in all copies and that both that
7  * copyright notice and this permission notice appear in supporting
8  * documentation.  No representations are made about the suitability of this
9  * software for any purpose.  It is provided "as is" without express or
10  * implied warranty.
11  *
12  *
13  * 2003 Kevin Odgen                  First version
14  * 2006 Sergio GutiĆ©rrez "Sergut"    Made several parameters dynamic and selectable
15  *                                   from the command line: size of the board, 
16  *                                   rotation speed and number of free squares; also
17  *                                   added the "sticks" mode.
18  *
19  */
20
21 #define DEF_FLIPFLOP_MODE  "tiles" /* Default mode (options: "tiles", "sticks") */
22 #define DEF_BOARD_X_SIZE   "9"     /* Default width of the board */
23 #define DEF_BOARD_Y_SIZE   "9"     /* Default length of the board */
24
25 #define DEF_BOARD_SIZE     "0"     /* "0" means "no value selected by user". It is changed */ 
26 #define DEF_NUMSQUARES     "0"     /* in function init_flipflop() to its correct value (that */ 
27 #define DEF_FREESQUARES    "0"     /* is a function of the size of the board and the mode)*/
28
29 #define DEF_SPIN           "0.1"   /* Default angular velocity: PI/10 rads/s    */
30
31 #define DEF_STICK_THICK   54       /* Thickness for the sticks mode (over 100)  */
32 #define DEF_STICK_RATIO   80       /* Ratio of sticks/total squares (over 100)  */
33 #define DEF_TILE_THICK     4       /* Thickness for the tiles mode (over 100)   */
34 #define DEF_TILE_RATIO    95       /* Ratio of tiles/total squares (over 100)   */
35
36 #ifdef STANDALONE
37 #define DEFAULTS       "*delay:     20000     \n" \
38                        "*showFPS:   False     \n" \
39                        "*wireframe: False     \n"
40
41 # define refresh_flipflop 0
42 # include "xlockmore.h"
43
44 #else
45 # include "xlock.h"
46 #endif /* STANDALONE */
47
48 #ifdef USE_GL
49
50 #include "gltrackball.h"
51
52 #undef countof
53 #define countof(x) (sizeof((x))/sizeof((*x)))
54
55 static XrmOptionDescRec opts[] = {
56     {"-sticks",         ".mode",            XrmoptionNoArg,  "sticks"},
57     {"-tiles",          ".mode",            XrmoptionNoArg,  "tiles" },
58     {"-mode",           ".mode",            XrmoptionSepArg, 0       },
59     {"-size",           ".size",            XrmoptionSepArg, 0       },
60     {"-size-x",         ".size_x",          XrmoptionSepArg, 0       },
61     {"-size-y",         ".size_y",          XrmoptionSepArg, 0       },
62     {"-count",          ".numsquares",      XrmoptionSepArg, 0       },
63     {"-free",           ".freesquares",     XrmoptionSepArg, 0       },
64     {"-spin",           ".spin",            XrmoptionSepArg, 0       },
65 };
66
67 static int wire, clearbits;
68 static int board_x_size, board_y_size, board_avg_size;
69 static int numsquares, freesquares;
70 static float half_thick;
71 static float spin;
72 static char* flipflopmode_str="tiles";
73
74 static argtype vars[] = {
75     { &flipflopmode_str, "mode",        "Mode",     DEF_FLIPFLOP_MODE,  t_String},
76     { &board_avg_size,   "size",        "Integer",  DEF_BOARD_SIZE,     t_Int},
77     { &board_x_size,     "size_x",      "Integer",  DEF_BOARD_X_SIZE,   t_Int},
78     { &board_y_size,     "size_y",      "Integer",  DEF_BOARD_Y_SIZE,   t_Int},
79     { &numsquares,       "numsquares",  "Integer",  DEF_NUMSQUARES,     t_Int},
80     { &freesquares,      "freesquares", "Integer",  DEF_NUMSQUARES,     t_Int},
81     { &spin,             "spin",        "Float",    DEF_SPIN,           t_Float},
82 };
83
84 ENTRYPOINT ModeSpecOpt flipflop_opts = {countof(opts), opts, countof(vars), vars, NULL};
85
86 #ifdef USE_MODULES
87 ModStruct   flipflop_description =
88     {"flipflop", "init_flipflop", "draw_flipflop", "release_flipflop",
89      "draw_flipflop", "init_flipflop", NULL, &flipflop_opts,
90      1000, 1, 2, 1, 4, 1.0, "",
91      "Flipflop", 0, NULL};
92
93 #endif /* USE_MODULES */
94
95 typedef struct {
96     /* array specifying which squares are where (to avoid collisions) */
97     /* -1 means empty otherwise integer represents square index 0 - n-1 */
98         /* occupied[x*board_y_size+y] is the tile [x][y] (i.e. that starts at column x and row y)*/
99     int *occupied; /* size: size_x * size_y */
100     /* an array of xpositions of the squares */
101     int *xpos; /* size: numsquares */
102     /* array of y positions of the squares */
103     int *ypos; /* size: numsquares */
104     /* integer representing the direction of movement of a square */
105     int *direction; /* 0 not, 1 x+, 2 y+, 3 x-, 4 y-*/ /* size: numsquares */
106     /* angle of moving square (during a flip) */
107     float *angle; /* size: numsquares */
108     /* array of colors for a square (RGB) */
109     /* eg. color[ 3*3 + 0 ] is the red   component of square 3 */
110     /* eg. color[ 4*3 + 1 ] is the green component of square 4 */
111     /* eg. color[ 5*3 + 2 ] is the blue  component of square 5 */
112     /*            ^-- n is the number of square */
113     float *color; /* size: numsquares * 3 */
114 } randsheet;    
115
116 typedef struct {
117     GLXContext *glx_context;
118     Window window;
119     trackball_state *trackball;
120     Bool button_down_p;
121
122         randsheet *sheet;
123
124     float theta;      /* angle of rotation of the board                */
125     float flipspeed;  /* amount of flip;  1 is a entire flip           */
126     float reldist;    /* relative distace of camera from center        */
127     float energy;     /* likelyhood that a square will attempt to move */
128
129 } Flipflopcreen;
130
131 static Flipflopcreen *qs = NULL;
132
133 static void randsheet_create( randsheet *rs );
134 static void randsheet_initialize( randsheet *rs );
135 static void randsheet_free( randsheet *rs );
136 static int  randsheet_new_move( randsheet* rs );
137 static void randsheet_move( randsheet *rs, float rot );
138 static void randsheet_draw( randsheet *rs );
139 static void setup_lights(void);
140 static void drawBoard(Flipflopcreen *);
141 static void display(Flipflopcreen *c);
142 static void draw_sheet(void);
143
144
145 /* configure lighting */
146 static void
147 setup_lights(void)
148 {
149     /*   GLfloat position0[] = { board_avg_size*0.5, board_avg_size*0.1, board_avg_size*0.5, 1.0 }; */
150
151     /*   GLfloat position0[] = { -board_avg_size*0.5, 0.2*board_avg_size, -board_avg_size*0.5, 1.0 }; */
152     GLfloat position0[4];
153     position0[0] = 0;
154     position0[1] = board_avg_size*0.3;
155     position0[2] = 0;
156     position0[3] = 1;
157
158     if (wire) return;
159
160     glEnable(GL_LIGHTING);
161     glLightfv(GL_LIGHT0, GL_POSITION, position0);
162     glEnable(GL_LIGHT0);
163 }
164
165 ENTRYPOINT Bool
166 flipflop_handle_event (ModeInfo *mi, XEvent *event)
167 {
168     Flipflopcreen *c = &qs[MI_SCREEN(mi)];
169
170     if (event->xany.type == ButtonPress &&
171         event->xbutton.button == Button1)
172         {
173             c->button_down_p = True;
174             gltrackball_start (c->trackball,
175                                event->xbutton.x, event->xbutton.y,
176                                MI_WIDTH (mi), MI_HEIGHT (mi));
177             return True;
178         }
179     else if (event->xany.type == ButtonRelease &&
180              event->xbutton.button == Button1)
181         {
182             c->button_down_p = False;
183             return True;
184         }
185     else if (event->xany.type == ButtonPress &&
186              (event->xbutton.button == Button4 ||
187               event->xbutton.button == Button5 ||
188               event->xbutton.button == Button6 ||
189               event->xbutton.button == Button7))
190         {
191             gltrackball_mousewheel (c->trackball, event->xbutton.button, 5,
192                                     !event->xbutton.state);
193             return True;
194         }
195     else if (event->xany.type == MotionNotify &&
196              c->button_down_p)
197         {
198             gltrackball_track (c->trackball,
199                                event->xmotion.x, event->xmotion.y,
200                                MI_WIDTH (mi), MI_HEIGHT (mi));
201             return True;
202         }
203
204     return False;
205 }
206
207 /* draw board */
208 static void
209 drawBoard(Flipflopcreen *c)
210 {
211     int i;
212     for( i=0; i < (c->energy) ; i++ ) {
213         randsheet_new_move( c->sheet );
214         }
215     randsheet_move( c->sheet, c->flipspeed * 3.14159 );
216     randsheet_draw( c->sheet );
217 }
218
219
220 static void
221 display(Flipflopcreen *c)
222 {
223     GLfloat amb[] = { 0.8, 0.8, 0.8, 1.0 };
224
225
226     glClear(clearbits);
227     glMatrixMode(GL_MODELVIEW);
228     glLoadIdentity();
229
230     glLightf(GL_LIGHT0, GL_CONSTANT_ATTENUATION, 1.2);
231     glLightf(GL_LIGHT0, GL_LINEAR_ATTENUATION, 0.15/board_avg_size );
232     glLightf(GL_LIGHT0, GL_QUADRATIC_ATTENUATION, 0.15/board_avg_size );
233     glLightfv(GL_LIGHT0, GL_AMBIENT, amb);
234
235
236     /** setup perspectif */
237     glTranslatef(0.0, 0.0, -c->reldist*board_avg_size);
238     glRotatef(22.5, 1.0, 0.0, 0.0);  
239     gltrackball_rotate (c->trackball);
240     glRotatef(c->theta*100, 0.0, 1.0, 0.0);
241     glTranslatef(-0.5*board_x_size, 0.0, -0.5*board_y_size); /* Center the board */
242
243     drawBoard(c);
244
245     if (!c->button_down_p) {
246         c->theta += .01 * spin;
247         }
248
249 }
250
251 ENTRYPOINT void
252 reshape_flipflop(ModeInfo *mi, int width, int height)
253 {
254     GLfloat h = (GLfloat) height / (GLfloat) width;
255     glViewport(0,0, width, height);
256     glMatrixMode(GL_PROJECTION);
257     glLoadIdentity();
258     gluPerspective(45, 1/h, 1.0, 300.0);
259     glMatrixMode(GL_MODELVIEW);
260 }
261
262 ENTRYPOINT void
263 init_flipflop(ModeInfo *mi)
264 {
265         int screen; 
266     Flipflopcreen *c;
267
268         /* Set all constants to their correct values */
269         if (board_avg_size != 0) {  /* general size specified by user */
270                 board_x_size = board_avg_size;
271                 board_y_size = board_avg_size;
272         } else {
273                 board_avg_size = (board_x_size + board_y_size) / 2;
274         }
275         if ((numsquares == 0) && (freesquares != 0)) {
276                 numsquares = board_x_size * board_y_size - freesquares; 
277         }
278         if (strcmp(flipflopmode_str, "tiles")) {
279                 half_thick = 1.0 * DEF_STICK_THICK / 100.0; 
280                 if (numsquares == 0) {  /* No value defined by user */
281                         numsquares = board_x_size * board_y_size * DEF_STICK_RATIO / 100;
282                 }
283         } else {
284                 half_thick = 1.0 * DEF_TILE_THICK / 100.0; 
285                 if (numsquares == 0) {  /* No value defined by user */
286                         numsquares = board_x_size * board_y_size * DEF_TILE_RATIO/ 100;;
287                 }
288         }
289         if (board_avg_size < 2) {
290                 fprintf (stderr,"%s: the board must be at least 2x2.\n", progname);
291                 exit(1);
292         }
293         if ((board_x_size < 1) || (board_y_size < 1) || (numsquares < 1)) {
294                 fprintf (stderr,"%s: the number of elements ('-count') and the dimensions of the board ('-size-x', '-size-y') must be positive integers.\n", progname);
295                 exit(1);
296         }
297         if (board_x_size * board_y_size <= numsquares) {
298                 fprintf (stderr,"%s: the number of elements ('-count') that you specified is too big \n for the dimensions of the board ('-size-x', '-size-y'). Nothing will move.\n", progname);
299         }
300
301     screen = MI_SCREEN(mi);
302     wire = MI_IS_WIREFRAME(mi);
303
304     if(!qs &&
305        !(qs = (Flipflopcreen *) calloc(MI_NUM_SCREENS(mi), sizeof(Flipflopcreen))))
306         return;
307
308     c = &qs[screen];
309     c->window = MI_WINDOW(mi);
310     c->trackball = gltrackball_init ();
311
312     c->flipspeed = 0.03;
313     c->reldist = 1;
314     c->energy = 40;
315
316     if((c->glx_context = init_GL(mi)))
317         reshape_flipflop(mi, MI_WIDTH(mi), MI_HEIGHT(mi));
318     else
319         MI_CLEARWINDOW(mi);
320
321         /* At this point, all the constants have already been set, */
322         /* so we can create the board */
323     c->sheet = (randsheet*) malloc(sizeof(randsheet)); 
324     randsheet_create( c->sheet ); 
325
326     glClearColor(0.0, 0.0, 0.0, 0.0);
327
328     clearbits = GL_COLOR_BUFFER_BIT;
329
330     glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);
331     glEnable(GL_COLOR_MATERIAL);
332     setup_lights();
333
334     glEnable(GL_DEPTH_TEST);
335     clearbits |= GL_DEPTH_BUFFER_BIT;
336     glEnable(GL_CULL_FACE);
337     glCullFace(GL_BACK);
338     randsheet_initialize( c->sheet );
339 }
340
341 ENTRYPOINT void
342 draw_flipflop(ModeInfo *mi)
343 {
344     Flipflopcreen *c = &qs[MI_SCREEN(mi)];
345     Window w = MI_WINDOW(mi);
346     Display *disp = MI_DISPLAY(mi);
347
348     if(!c->glx_context)
349         return;
350
351     glXMakeCurrent(disp, w, *(c->glx_context));
352
353     display(c);
354
355     if(mi->fps_p){
356         do_fps(mi);
357     }
358
359     glFinish();
360     glXSwapBuffers(disp, w);
361
362
363 }
364
365 ENTRYPOINT void
366 release_flipflop(ModeInfo *mi)
367 {
368   if(qs) {
369     int screen;
370
371     for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++)
372     {
373       Flipflopcreen *c = &qs[MI_SCREEN(mi)];
374       if (c->glx_context)
375         c->glx_context = 0;
376       if (c->sheet) {
377         randsheet_free(c->sheet);
378         free (c->sheet);
379         c->sheet = 0;
380       }
381     }
382     free(qs);
383     qs = 0;
384   }
385
386   FreeAllGL(mi);
387 }
388
389 /*** ADDED RANDSHEET FUNCTIONS ***/
390
391 static void
392 draw_sheet(void)
393 {
394     glBegin( wire ? GL_LINE_LOOP : GL_QUADS );
395
396     glNormal3f( 0, -1, 0 );
397     glVertex3f( half_thick,  -half_thick,  half_thick );
398     glVertex3f( 1-half_thick,   -half_thick, half_thick );
399     glVertex3f( 1-half_thick, -half_thick,  1-half_thick);
400     glVertex3f( half_thick, -half_thick, 1-half_thick );
401
402     if (wire) { glEnd(); glBegin (GL_LINE_LOOP); }
403
404     /* back */
405     glNormal3f( 0, 1, 0 );
406     glVertex3f( half_thick, half_thick, 1-half_thick );
407     glVertex3f( 1-half_thick, half_thick,  1-half_thick);
408     glVertex3f( 1-half_thick,   half_thick, half_thick );
409     glVertex3f( half_thick,  half_thick,  half_thick );
410
411     if (wire) { glEnd(); return; }
412
413     /* 4 edges!!! weee.... */
414     glNormal3f( 0, 0, -1 );
415     glVertex3f( half_thick, half_thick, half_thick );
416     glVertex3f( 1-half_thick, half_thick, half_thick );
417     glVertex3f( 1-half_thick, -half_thick, half_thick );
418     glVertex3f( half_thick, -half_thick, half_thick );
419     glNormal3f( 0, 0, 1 );
420     glVertex3f( half_thick, half_thick, 1-half_thick );
421     glVertex3f( half_thick, -half_thick, 1-half_thick );
422     glVertex3f( 1-half_thick, -half_thick, 1-half_thick );
423     glVertex3f( 1-half_thick, half_thick, 1-half_thick );
424     glNormal3f( 1, 0, 0 );
425     glVertex3f( 1-half_thick, half_thick, 1-half_thick );
426     glVertex3f( 1-half_thick, -half_thick, 1-half_thick );
427     glVertex3f( 1-half_thick, -half_thick, half_thick );
428     glVertex3f( 1-half_thick, half_thick, half_thick );
429     glNormal3f( -1, 0, 0 );
430     glVertex3f( half_thick, half_thick, 1-half_thick );
431     glVertex3f( half_thick, half_thick, half_thick );
432     glVertex3f( half_thick, -half_thick, half_thick );
433     glVertex3f( half_thick, -half_thick, 1-half_thick );
434     glEnd();
435 }
436
437 /* Reserve memory for the randsheet */
438 static void
439 randsheet_create( randsheet *rs )
440 {
441         rs -> occupied  = (int*) malloc(board_x_size*board_y_size * sizeof(int));
442         rs -> xpos      = (int*) malloc(numsquares * sizeof(int));
443         rs -> ypos      = (int*) malloc(numsquares * sizeof(int));
444         rs -> direction = (int*) malloc(numsquares * sizeof(int));
445         rs -> angle     = (float*) malloc(numsquares * sizeof(float));
446         rs -> color     = (float*) malloc(numsquares*3 * sizeof(float));
447 }
448
449 /* Free reserved memory for the randsheet */
450 static void
451 randsheet_free( randsheet *rs )
452 {
453         free(rs->occupied);
454         free(rs->xpos);
455         free(rs->ypos);
456         free(rs->direction);
457         free(rs->angle);
458         free(rs->color);
459 }
460
461 static void
462 randsheet_initialize( randsheet *rs )
463 {
464     int i, j, index;
465     index = 0;
466     /* put the moving sheets on the board */
467     for( i = 0; i < board_x_size; i++ )
468         {
469             for( j = 0; j < board_y_size; j++ )
470                 {
471                     /* initially fill up a corner with the moving squares */
472                     if( index < numsquares )
473                         {
474                             rs->occupied[ i * board_y_size + j ] = index;
475                             rs->xpos[ index ] = i;
476                             rs->ypos[ index ] = j;
477                             /* have the square colors start out as a pattern */
478                             rs->color[ index*3 + 0 ] = ((i+j)%3 == 0)||((i+j+1)%3 == 0);
479                             rs->color[ index*3 + 1 ] = ((i+j+1)%3 == 0);
480                             rs->color[ index*3 + 2 ] = ((i+j+2)%3 == 0);
481                             index++;
482                         }
483                     /* leave everything else empty*/
484                     else
485                         {
486                             rs->occupied[ i * board_y_size + j ] = -1;
487                         }
488                 }
489         }
490     /* initially everything is at rest */
491     for( i=0; i<numsquares; i++ )
492         {
493             rs->direction[ i ] = 0;
494             rs->angle[ i ] = 0;
495         }
496 }
497
498 /* Pick and random square and direction and try to move it. */
499 /* May not actually move anything, just attempt a random move. */
500 /* Returns true if move was sucessful. */
501 /* This could probably be implemented faster in a dequeue */
502 /* to avoid trying to move a square which is already moving */
503 /* but speed is most likely bottlenecked by rendering anyway... */
504 static int
505 randsheet_new_move( randsheet* rs )
506 {
507     int i, j;
508     int num, dir;
509     /* pick a random square */
510     num = random( ) % numsquares;
511     i = rs->xpos[ num ];
512     j = rs->ypos[ num ];
513     /* pick a random direction */
514     dir = ( random( )% 4 ) + 1;
515
516     if( rs->direction[ num ] == 0 )
517         {
518             switch( dir )
519                 {
520                 case 1:
521                     /* move up in x */
522                     if( ( i + 1 ) < board_x_size )
523                         {
524                             if( rs->occupied[ (i + 1) * board_y_size + j ] == -1 )
525                                 {
526                                     rs->direction[ num ] = dir;
527                                     rs->occupied[ (i + 1) * board_y_size + j ] = num;
528                                     rs->occupied[ i * board_y_size + j ] = -1;
529                                     return 1;
530                                 }
531                         }
532                     return 0;
533                     break;
534                 case 2:
535                     /* move up in y */
536                     if( ( j + 1 ) < board_y_size )
537                         {
538                             if( rs->occupied[ i * board_y_size + (j + 1) ] == -1 )
539                                 {
540                                     rs->direction[ num ] = dir;
541                                     rs->occupied[ i * board_y_size + (j + 1) ] = num;
542                                     rs->occupied[ i * board_y_size + j ] = -1;
543                                     return 1;
544                                 }
545                         }
546                     return 0;
547                     break;
548                 case 3:
549                     /* move down in x */
550                     if( ( i - 1 ) >= 0 )
551                         {
552                             if( rs->occupied[ (i - 1) * board_y_size + j ] == -1 )
553                                 {
554                                     rs->direction[ num ] = dir;
555                                     rs->occupied[ (i - 1) * board_y_size + j ] = num;
556                                     rs->occupied[ i * board_y_size + j ] = -1;
557                                     return 1;
558                                 }
559                         }
560                     return 0;
561                     break;
562                 case 4:
563                     /* move down in y */
564                     if( ( j - 1 ) >= 0 )
565                         {
566                             if( rs->occupied[ i * board_y_size + (j - 1) ] == -1 )
567                                 {
568                                     rs->direction[ num ] = dir;
569                                     rs->occupied[ i * board_y_size + (j - 1) ] = num;
570                                     rs->occupied[ i * board_y_size + j ] = -1;
571                                     return 1;
572                                 }
573                         }
574                     return 0;
575                     break;
576                 default:
577                     break;
578                 }
579         }
580     return 0;
581 }
582
583 /*   move a single frame.  */
584 /*   Pass in the angle in rads the square rotates in a frame. */
585 static void
586 randsheet_move( randsheet *rs, float rot )
587 {
588     int i, j, index;
589     for( index = 0 ; index < numsquares; index++ )
590         {
591             i = rs->xpos[ index ];
592             j = rs->ypos[ index ];
593             switch( rs->direction[ index ] )
594                 {
595                 case 0:
596                     /* not moving */
597                     break;
598                 case 1:
599                     /* move up in x */
600                     rs->angle[ index ] += rot;
601                     /* check to see if we have finished moving */
602                     if( rs->angle[ index ] >= M_PI  )
603                         {
604                             rs->xpos[ index ] += 1;
605                             rs->direction[ index ] = 0;
606                             rs->angle[ index ] = 0;
607                         }
608                     break;
609                 case 2:
610                     /* move up in y */
611                     rs->angle[ index ] += rot;
612                     /* check to see if we have finished moving */
613                     if( rs->angle[ index ] >= M_PI  )
614                         {
615                             rs->ypos[ index ] += 1;
616                             rs->direction[ index ] = 0;
617                             rs->angle[ index ] = 0;
618                         }
619                     break;
620                 case 3:
621                     /* down in x */
622                     rs->angle[ index ] += rot;
623                     /* check to see if we have finished moving */
624                     if( rs->angle[ index ] >= M_PI  )
625                         {
626                             rs->xpos[ index ] -= 1;
627                             rs->direction[ index ] = 0;
628                             rs->angle[ index ] = 0;
629                         }
630                     break;
631                 case 4:
632                     /* up in x */
633                     rs->angle[ index ] += rot;
634                     /* check to see if we have finished moving */
635                     if( rs->angle[ index ] >= M_PI  )
636                         {
637                             rs->ypos[ index ] -= 1;
638                             rs->direction[ index ] = 0;
639                             rs->angle[ index ] = 0;
640                         }
641                     break;
642                 default:
643                     break;
644                 }
645         }
646 }
647
648
649 /* draw all the moving squares  */
650 static void
651 randsheet_draw( randsheet *rs )
652 {
653     int i, j;
654     int index;
655     /* for all moving squares ... */
656     for( index = 0; index < numsquares; index++ )
657         {
658             /* set color */
659             glColor3f( rs->color[ index*3 + 0 ],
660                        rs->color[ index*3 + 1 ],
661                        rs->color[ index*3 + 2 ] );
662             /* find x and y position */
663             i = rs->xpos[ index ];
664             j = rs->ypos[ index ];
665             glPushMatrix();
666             switch( rs->direction[ index ] )
667                 {
668                 case 0:
669
670                     /* not moving */
671                     /* front */
672                     glTranslatef( i, 0, j );
673                     break;
674                 case 1:
675                     glTranslatef( i+1, 0, j );
676                     glRotatef( 180 - rs->angle[ index ]*180/M_PI, 0, 0, 1 );
677
678                     break;
679                 case 2:
680                     glTranslatef( i, 0, j+1 );
681                     glRotatef( 180 - rs->angle[ index ]*180/M_PI, -1, 0, 0 );
682
683                     break;
684                 case 3:
685                     glTranslatef( i, 0, j );
686                     glRotatef( rs->angle[ index ]*180/M_PI, 0, 0, 1 );
687                     break;
688                 case 4:
689                     glTranslatef( i, 0, j );
690                     glRotatef( rs->angle[ index ]*180/M_PI, -1, 0, 0 );
691                     break;
692                 default:
693                     break;
694                 }
695             draw_sheet();
696             glPopMatrix();
697
698         }
699 }
700
701 /**** END RANDSHEET_BAK FUNCTIONS ***/
702
703 XSCREENSAVER_MODULE ("Flipflop", flipflop)
704
705 #endif /* USE_GL */