f38385e4072026d0b42925876fa5b5cee3bf20c4
[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         {
189             gltrackball_mousewheel (c->trackball, event->xbutton.button, 5,
190                                     !event->xbutton.state);
191             return True;
192         }
193     else if (event->xany.type == MotionNotify &&
194              c->button_down_p)
195         {
196             gltrackball_track (c->trackball,
197                                event->xmotion.x, event->xmotion.y,
198                                MI_WIDTH (mi), MI_HEIGHT (mi));
199             return True;
200         }
201
202     return False;
203 }
204
205 /* draw board */
206 static void
207 drawBoard(Flipflopcreen *c)
208 {
209     int i;
210     for( i=0; i < (c->energy) ; i++ ) {
211         randsheet_new_move( c->sheet );
212         }
213     randsheet_move( c->sheet, c->flipspeed * 3.14159 );
214     randsheet_draw( c->sheet );
215 }
216
217
218 static void
219 display(Flipflopcreen *c)
220 {
221     GLfloat amb[] = { 0.8, 0.8, 0.8, 1.0 };
222
223
224     glClear(clearbits);
225     glMatrixMode(GL_MODELVIEW);
226     glLoadIdentity();
227
228     glLightf(GL_LIGHT0, GL_CONSTANT_ATTENUATION, 1.2);
229     glLightf(GL_LIGHT0, GL_LINEAR_ATTENUATION, 0.15/board_avg_size );
230     glLightf(GL_LIGHT0, GL_QUADRATIC_ATTENUATION, 0.15/board_avg_size );
231     glLightfv(GL_LIGHT0, GL_AMBIENT, amb);
232
233
234     /** setup perspectif */
235     glTranslatef(0.0, 0.0, -c->reldist*board_avg_size);
236     glRotatef(22.5, 1.0, 0.0, 0.0);  
237     gltrackball_rotate (c->trackball);
238     glRotatef(c->theta*100, 0.0, 1.0, 0.0);
239     glTranslatef(-0.5*board_x_size, 0.0, -0.5*board_y_size); /* Center the board */
240
241     drawBoard(c);
242
243     if (!c->button_down_p) {
244         c->theta += .01 * spin;
245         }
246
247 }
248
249 ENTRYPOINT void
250 reshape_flipflop(ModeInfo *mi, int width, int height)
251 {
252     GLfloat h = (GLfloat) height / (GLfloat) width;
253     glViewport(0,0, width, height);
254     glMatrixMode(GL_PROJECTION);
255     glLoadIdentity();
256     gluPerspective(45, 1/h, 1.0, 300.0);
257     glMatrixMode(GL_MODELVIEW);
258 }
259
260 ENTRYPOINT void
261 init_flipflop(ModeInfo *mi)
262 {
263         int screen; 
264     Flipflopcreen *c;
265
266         /* Set all constants to their correct values */
267         if (board_avg_size != 0) {  /* general size specified by user */
268                 board_x_size = board_avg_size;
269                 board_y_size = board_avg_size;
270         } else {
271                 board_avg_size = (board_x_size + board_y_size) / 2;
272         }
273         if ((numsquares == 0) && (freesquares != 0)) {
274                 numsquares = board_x_size * board_y_size - freesquares; 
275         }
276         if (strcmp(flipflopmode_str, "tiles")) {
277                 half_thick = 1.0 * DEF_STICK_THICK / 100.0; 
278                 if (numsquares == 0) {  /* No value defined by user */
279                         numsquares = board_x_size * board_y_size * DEF_STICK_RATIO / 100;
280                 }
281         } else {
282                 half_thick = 1.0 * DEF_TILE_THICK / 100.0; 
283                 if (numsquares == 0) {  /* No value defined by user */
284                         numsquares = board_x_size * board_y_size * DEF_TILE_RATIO/ 100;;
285                 }
286         }
287         if (board_avg_size < 2) {
288                 fprintf (stderr,"%s: the board must be at least 2x2.\n", progname);
289                 exit(1);
290         }
291         if ((board_x_size < 1) || (board_y_size < 1) || (numsquares < 1)) {
292                 fprintf (stderr,"%s: the number of elements ('-count') and the dimensions of the board ('-size-x', '-size-y') must be positive integers.\n", progname);
293                 exit(1);
294         }
295         if (board_x_size * board_y_size <= numsquares) {
296                 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);
297         }
298
299     screen = MI_SCREEN(mi);
300     wire = MI_IS_WIREFRAME(mi);
301
302     if(!qs &&
303        !(qs = (Flipflopcreen *) calloc(MI_NUM_SCREENS(mi), sizeof(Flipflopcreen))))
304         return;
305
306     c = &qs[screen];
307     c->window = MI_WINDOW(mi);
308     c->trackball = gltrackball_init ();
309
310     c->flipspeed = 0.03;
311     c->reldist = 1;
312     c->energy = 40;
313
314     if((c->glx_context = init_GL(mi)))
315         reshape_flipflop(mi, MI_WIDTH(mi), MI_HEIGHT(mi));
316     else
317         MI_CLEARWINDOW(mi);
318
319         /* At this point, all the constants have already been set, */
320         /* so we can create the board */
321     c->sheet = (randsheet*) malloc(sizeof(randsheet)); 
322     randsheet_create( c->sheet ); 
323
324     glClearColor(0.0, 0.0, 0.0, 0.0);
325
326     clearbits = GL_COLOR_BUFFER_BIT;
327
328     glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);
329     glEnable(GL_COLOR_MATERIAL);
330     setup_lights();
331
332     glEnable(GL_DEPTH_TEST);
333     clearbits |= GL_DEPTH_BUFFER_BIT;
334     glEnable(GL_CULL_FACE);
335     glCullFace(GL_BACK);
336     randsheet_initialize( c->sheet );
337 }
338
339 ENTRYPOINT void
340 draw_flipflop(ModeInfo *mi)
341 {
342     Flipflopcreen *c = &qs[MI_SCREEN(mi)];
343     Window w = MI_WINDOW(mi);
344     Display *disp = MI_DISPLAY(mi);
345
346     if(!c->glx_context)
347         return;
348
349     glXMakeCurrent(disp, w, *(c->glx_context));
350
351     display(c);
352
353     if(mi->fps_p){
354         do_fps(mi);
355     }
356
357     glFinish();
358     glXSwapBuffers(disp, w);
359
360
361 }
362
363 ENTRYPOINT void
364 release_flipflop(ModeInfo *mi)
365 {
366   if(qs) {
367     int screen;
368
369     for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++)
370     {
371       Flipflopcreen *c = &qs[MI_SCREEN(mi)];
372       if (c->glx_context)
373         c->glx_context = 0;
374       if (c->sheet) {
375         randsheet_free(c->sheet);
376         free (c->sheet);
377         c->sheet = 0;
378       }
379     }
380     free(qs);
381     qs = 0;
382   }
383
384   FreeAllGL(mi);
385 }
386
387 /*** ADDED RANDSHEET FUNCTIONS ***/
388
389 static void
390 draw_sheet(void)
391 {
392     glBegin( wire ? GL_LINE_LOOP : GL_QUADS );
393
394     glNormal3f( 0, -1, 0 );
395     glVertex3f( half_thick,  -half_thick,  half_thick );
396     glVertex3f( 1-half_thick,   -half_thick, half_thick );
397     glVertex3f( 1-half_thick, -half_thick,  1-half_thick);
398     glVertex3f( half_thick, -half_thick, 1-half_thick );
399
400     if (wire) { glEnd(); glBegin (GL_LINE_LOOP); }
401
402     /* back */
403     glNormal3f( 0, 1, 0 );
404     glVertex3f( half_thick, half_thick, 1-half_thick );
405     glVertex3f( 1-half_thick, half_thick,  1-half_thick);
406     glVertex3f( 1-half_thick,   half_thick, half_thick );
407     glVertex3f( half_thick,  half_thick,  half_thick );
408
409     if (wire) { glEnd(); return; }
410
411     /* 4 edges!!! weee.... */
412     glNormal3f( 0, 0, -1 );
413     glVertex3f( half_thick, half_thick, half_thick );
414     glVertex3f( 1-half_thick, half_thick, half_thick );
415     glVertex3f( 1-half_thick, -half_thick, half_thick );
416     glVertex3f( half_thick, -half_thick, half_thick );
417     glNormal3f( 0, 0, 1 );
418     glVertex3f( half_thick, half_thick, 1-half_thick );
419     glVertex3f( half_thick, -half_thick, 1-half_thick );
420     glVertex3f( 1-half_thick, -half_thick, 1-half_thick );
421     glVertex3f( 1-half_thick, half_thick, 1-half_thick );
422     glNormal3f( 1, 0, 0 );
423     glVertex3f( 1-half_thick, half_thick, 1-half_thick );
424     glVertex3f( 1-half_thick, -half_thick, 1-half_thick );
425     glVertex3f( 1-half_thick, -half_thick, half_thick );
426     glVertex3f( 1-half_thick, half_thick, half_thick );
427     glNormal3f( -1, 0, 0 );
428     glVertex3f( half_thick, half_thick, 1-half_thick );
429     glVertex3f( half_thick, half_thick, half_thick );
430     glVertex3f( half_thick, -half_thick, half_thick );
431     glVertex3f( half_thick, -half_thick, 1-half_thick );
432     glEnd();
433 }
434
435 /* Reserve memory for the randsheet */
436 static void
437 randsheet_create( randsheet *rs )
438 {
439         rs -> occupied  = (int*) malloc(board_x_size*board_y_size * sizeof(int));
440         rs -> xpos      = (int*) malloc(numsquares * sizeof(int));
441         rs -> ypos      = (int*) malloc(numsquares * sizeof(int));
442         rs -> direction = (int*) malloc(numsquares * sizeof(int));
443         rs -> angle     = (float*) malloc(numsquares * sizeof(float));
444         rs -> color     = (float*) malloc(numsquares*3 * sizeof(float));
445 }
446
447 /* Free reserved memory for the randsheet */
448 static void
449 randsheet_free( randsheet *rs )
450 {
451         free(rs->occupied);
452         free(rs->xpos);
453         free(rs->ypos);
454         free(rs->direction);
455         free(rs->angle);
456         free(rs->color);
457 }
458
459 static void
460 randsheet_initialize( randsheet *rs )
461 {
462     int i, j, index;
463     index = 0;
464     /* put the moving sheets on the board */
465     for( i = 0; i < board_x_size; i++ )
466         {
467             for( j = 0; j < board_y_size; j++ )
468                 {
469                     /* initially fill up a corner with the moving squares */
470                     if( index < numsquares )
471                         {
472                             rs->occupied[ i * board_y_size + j ] = index;
473                             rs->xpos[ index ] = i;
474                             rs->ypos[ index ] = j;
475                             /* have the square colors start out as a pattern */
476                             rs->color[ index*3 + 0 ] = ((i+j)%3 == 0)||((i+j+1)%3 == 0);
477                             rs->color[ index*3 + 1 ] = ((i+j+1)%3 == 0);
478                             rs->color[ index*3 + 2 ] = ((i+j+2)%3 == 0);
479                             index++;
480                         }
481                     /* leave everything else empty*/
482                     else
483                         {
484                             rs->occupied[ i * board_y_size + j ] = -1;
485                         }
486                 }
487         }
488     /* initially everything is at rest */
489     for( i=0; i<numsquares; i++ )
490         {
491             rs->direction[ i ] = 0;
492             rs->angle[ i ] = 0;
493         }
494 }
495
496 /* Pick and random square and direction and try to move it. */
497 /* May not actually move anything, just attempt a random move. */
498 /* Returns true if move was sucessful. */
499 /* This could probably be implemented faster in a dequeue */
500 /* to avoid trying to move a square which is already moving */
501 /* but speed is most likely bottlenecked by rendering anyway... */
502 static int
503 randsheet_new_move( randsheet* rs )
504 {
505     int i, j;
506     int num, dir;
507     /* pick a random square */
508     num = random( ) % numsquares;
509     i = rs->xpos[ num ];
510     j = rs->ypos[ num ];
511     /* pick a random direction */
512     dir = ( random( )% 4 ) + 1;
513
514     if( rs->direction[ num ] == 0 )
515         {
516             switch( dir )
517                 {
518                 case 1:
519                     /* move up in x */
520                     if( ( i + 1 ) < board_x_size )
521                         {
522                             if( rs->occupied[ (i + 1) * board_y_size + j ] == -1 )
523                                 {
524                                     rs->direction[ num ] = dir;
525                                     rs->occupied[ (i + 1) * board_y_size + j ] = num;
526                                     rs->occupied[ i * board_y_size + j ] = -1;
527                                     return 1;
528                                 }
529                         }
530                     return 0;
531                     break;
532                 case 2:
533                     /* move up in y */
534                     if( ( j + 1 ) < board_y_size )
535                         {
536                             if( rs->occupied[ i * board_y_size + (j + 1) ] == -1 )
537                                 {
538                                     rs->direction[ num ] = dir;
539                                     rs->occupied[ i * board_y_size + (j + 1) ] = num;
540                                     rs->occupied[ i * board_y_size + j ] = -1;
541                                     return 1;
542                                 }
543                         }
544                     return 0;
545                     break;
546                 case 3:
547                     /* move down in x */
548                     if( ( i - 1 ) >= 0 )
549                         {
550                             if( rs->occupied[ (i - 1) * board_y_size + j ] == -1 )
551                                 {
552                                     rs->direction[ num ] = dir;
553                                     rs->occupied[ (i - 1) * board_y_size + j ] = num;
554                                     rs->occupied[ i * board_y_size + j ] = -1;
555                                     return 1;
556                                 }
557                         }
558                     return 0;
559                     break;
560                 case 4:
561                     /* move down in y */
562                     if( ( j - 1 ) >= 0 )
563                         {
564                             if( rs->occupied[ i * board_y_size + (j - 1) ] == -1 )
565                                 {
566                                     rs->direction[ num ] = dir;
567                                     rs->occupied[ i * board_y_size + (j - 1) ] = num;
568                                     rs->occupied[ i * board_y_size + j ] = -1;
569                                     return 1;
570                                 }
571                         }
572                     return 0;
573                     break;
574                 default:
575                     break;
576                 }
577         }
578     return 0;
579 }
580
581 /*   move a single frame.  */
582 /*   Pass in the angle in rads the square rotates in a frame. */
583 static void
584 randsheet_move( randsheet *rs, float rot )
585 {
586     int i, j, index;
587     for( index = 0 ; index < numsquares; index++ )
588         {
589             i = rs->xpos[ index ];
590             j = rs->ypos[ index ];
591             switch( rs->direction[ index ] )
592                 {
593                 case 0:
594                     /* not moving */
595                     break;
596                 case 1:
597                     /* move up in x */
598                     rs->angle[ index ] += rot;
599                     /* check to see if we have finished moving */
600                     if( rs->angle[ index ] >= M_PI  )
601                         {
602                             rs->xpos[ index ] += 1;
603                             rs->direction[ index ] = 0;
604                             rs->angle[ index ] = 0;
605                         }
606                     break;
607                 case 2:
608                     /* move up in y */
609                     rs->angle[ index ] += rot;
610                     /* check to see if we have finished moving */
611                     if( rs->angle[ index ] >= M_PI  )
612                         {
613                             rs->ypos[ index ] += 1;
614                             rs->direction[ index ] = 0;
615                             rs->angle[ index ] = 0;
616                         }
617                     break;
618                 case 3:
619                     /* down in x */
620                     rs->angle[ index ] += rot;
621                     /* check to see if we have finished moving */
622                     if( rs->angle[ index ] >= M_PI  )
623                         {
624                             rs->xpos[ index ] -= 1;
625                             rs->direction[ index ] = 0;
626                             rs->angle[ index ] = 0;
627                         }
628                     break;
629                 case 4:
630                     /* up in x */
631                     rs->angle[ index ] += rot;
632                     /* check to see if we have finished moving */
633                     if( rs->angle[ index ] >= M_PI  )
634                         {
635                             rs->ypos[ index ] -= 1;
636                             rs->direction[ index ] = 0;
637                             rs->angle[ index ] = 0;
638                         }
639                     break;
640                 default:
641                     break;
642                 }
643         }
644 }
645
646
647 /* draw all the moving squares  */
648 static void
649 randsheet_draw( randsheet *rs )
650 {
651     int i, j;
652     int index;
653     /* for all moving squares ... */
654     for( index = 0; index < numsquares; index++ )
655         {
656             /* set color */
657             glColor3f( rs->color[ index*3 + 0 ],
658                        rs->color[ index*3 + 1 ],
659                        rs->color[ index*3 + 2 ] );
660             /* find x and y position */
661             i = rs->xpos[ index ];
662             j = rs->ypos[ index ];
663             glPushMatrix();
664             switch( rs->direction[ index ] )
665                 {
666                 case 0:
667
668                     /* not moving */
669                     /* front */
670                     glTranslatef( i, 0, j );
671                     break;
672                 case 1:
673                     glTranslatef( i+1, 0, j );
674                     glRotatef( 180 - rs->angle[ index ]*180/M_PI, 0, 0, 1 );
675
676                     break;
677                 case 2:
678                     glTranslatef( i, 0, j+1 );
679                     glRotatef( 180 - rs->angle[ index ]*180/M_PI, -1, 0, 0 );
680
681                     break;
682                 case 3:
683                     glTranslatef( i, 0, j );
684                     glRotatef( rs->angle[ index ]*180/M_PI, 0, 0, 1 );
685                     break;
686                 case 4:
687                     glTranslatef( i, 0, j );
688                     glRotatef( rs->angle[ index ]*180/M_PI, -1, 0, 0 );
689                     break;
690                 default:
691                     break;
692                 }
693             draw_sheet();
694             glPopMatrix();
695
696         }
697 }
698
699 /**** END RANDSHEET_BAK FUNCTIONS ***/
700
701 XSCREENSAVER_MODULE ("Flipflop", flipflop)
702
703 #endif /* USE_GL */