From http://www.jwz.org/xscreensaver/xscreensaver-5.30.tar.gz
[xscreensaver] / hacks / glx / sproingies.c
1 /* -*- Mode: C; tab-width: 4 -*- */
2 /* sproingies.c - 3D sproingies */
3
4 #if 0
5 static const char sccsid[] = "@(#)sproingies.c  4.04 97/07/28 xlockmore";
6 #endif
7
8 /*-
9  *  sproingies.c - Copyright 1996 by Ed Mackey, freely distributable.
10  *
11  * Permission to use, copy, modify, and distribute this software and its
12  * documentation for any purpose and without fee is hereby granted,
13  * provided that the above copyright notice appear in all copies and that
14  * both that copyright notice and this permission notice appear in
15  * supporting documentation.
16  *
17  * This file is provided AS IS with no warranties of any kind.  The author
18  * shall have no liability with respect to the infringement of copyrights,
19  * trade secrets or any patents by this file or any part thereof.  In no
20  * event will the author be liable for any lost revenue or profits or
21  * other special, indirect and consequential damages.
22  *
23  * Revision History:
24  * See sproingiewrap.c
25  */
26
27 #ifdef HAVE_CONFIG_H
28 # include "config.h"
29 #endif /* HAVE_CONFIG_H */
30
31 #ifdef STANDALONE
32 # include "xlockmoreI.h"                /* from the xscreensaver distribution */
33 #else /* !STANDALONE */
34 # include "xlock.h"            /* from the xlockmore distribution */
35 #endif /* !STANDALONE */
36
37 #ifdef USE_GL
38
39 #ifndef HAVE_COCOA
40 # include <GL/glu.h>
41 #endif
42
43 #include "gllist.h"
44 #include "sproingies.h"
45
46 #define MAXSPROING           100
47 #define TARGET_COUNT         40
48 #define BOOM_FRAME           50
49 #define NO_FRAME             (-10)
50 #define RESET_SPROINGIE_LIFE (-30 + myrand(28))
51 #define NEW_SPROINGIE_LIFE   (40 + myrand(200))
52 #define JUMP_LEFT            0
53 #define JUMP_RIGHT           1
54
55 #define FIRST_FRAME          0
56 #define LAST_FRAME           5 
57 /*-
58  * The sproingies have six "real" frames, (s1_1 to s1_6) that show a
59  * sproingie jumping off a block, headed down and to the right. 
60  * The frames are numbered from 0 (FIRST_FRAME) to 5 (LAST_FRAME). 
61  * 
62  * There are other frame numbers for special cases (e.g. BOOM_FRAME).
63  */
64 struct sPosColor {   /* Position and color of the sproingie     */
65         int x, y, z;     /*   Position                              */
66         int frame;       /*   Current frame (0-5)                   */
67         int life;        /*   Life points                           */
68         GLfloat r, g, b; /*   Color RGB                             */
69         int direction;   /*   Direction of next hop (left or right) */
70 };
71
72 typedef struct {
73         int         rotx, roty, dist, wireframe, flatshade, groundlevel,
74                     maxsproingies, mono;
75         int         sframe, target_rx, target_ry, target_dist, target_count;
76         const struct gllist *sproingies[6];
77         const struct gllist *SproingieBoom;
78         GLuint TopsSides;
79         struct sPosColor *positions;
80 } sp_instance;
81
82 static sp_instance *si_list = NULL;
83 static int  active_screens = 0;
84
85 extern const struct gllist *s1_1;
86 extern const struct gllist *s1_2;
87 extern const struct gllist *s1_3;
88 extern const struct gllist *s1_4;
89 extern const struct gllist *s1_5;
90 extern const struct gllist *s1_6;
91 extern const struct gllist *s1_b;
92
93 static int
94 myrand(int range)
95 {
96         return ((int) (((float) range) * LRAND() / (MAXRAND)));
97 }
98
99 static int smart_sproingies = 0;
100
101 static      GLuint
102 build_TopsSides(int wireframe)
103 {
104         GLuint      dl_num;
105         GLfloat     mat_color[4] =
106         {0.0, 0.0, 0.0, 1.0};
107
108         dl_num = glGenLists(2);
109         if (!dl_num)
110                 return (0);     /* 0 means out of display lists. */
111
112         /* Surface: Tops */
113         glNewList(dl_num, GL_COMPILE);
114         mat_color[0] = 0.392157;
115         mat_color[1] = 0.784314;
116         mat_color[2] = 0.941176;
117         if (wireframe)
118                 glColor3fv(mat_color);
119         else {
120                 glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, mat_color);
121         }
122         glEndList();
123
124         /* Surface: Sides */
125         glNewList(dl_num + 1, GL_COMPILE);
126         if (wireframe)
127                 glColor3fv(mat_color);
128         else {
129       /* jwz: in wireframe mode, color tops and sides the same. */
130       mat_color[0] = 0.156863;
131       mat_color[1] = 0.156863;
132       mat_color[2] = 0.392157;
133                 glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, mat_color);
134         }
135         glEndList();
136         return (dl_num);
137 }
138
139 static void
140 LayGround(int sx, int sy, int sz, int width, int height, sp_instance * si)
141 {
142         int         x, y, z, w, h;
143         GLenum      begin_polygon;
144
145         if (si->wireframe)
146                 begin_polygon = GL_LINE_LOOP;
147         else
148                 begin_polygon = GL_POLYGON;
149
150         if (!si->wireframe) {
151                 if (!si->mono)
152                         glCallList(si->TopsSides);      /* Render the tops */
153                 glNormal3f(0.0, 1.0, 0.0);
154
155                 for (h = 0; h < height; ++h) {
156                         x = sx + h;
157                         y = sy - (h << 1);
158                         z = sz + h;
159                         for (w = 0; w < width; ++w) {
160                                 glBegin(begin_polygon);
161                                 glVertex3i(x, y, z);
162                                 glVertex3i(x, y, z - 1);
163                                 glVertex3i(x + 1, y, z - 1);
164                                 glVertex3i(x + 1, y, z);
165                                 glEnd();
166                                 glBegin(begin_polygon);
167                                 glVertex3i(x + 1, y - 1, z);
168                                 glVertex3i(x + 1, y - 1, z - 1);
169                                 glVertex3i(x + 2, y - 1, z - 1);
170                                 glVertex3i(x + 2, y - 1, z);
171                                 glEnd();
172                                 ++x;
173                                 --z;
174                         }
175                 }
176         }
177         if (!si->mono)
178                 glCallList(si->TopsSides + 1);  /* Render the sides */
179         if (!si->wireframe)
180                 glNormal3f(0.0, 0.0, 1.0);
181
182         for (h = 0; h < height; ++h) {
183                 x = sx + h;
184                 y = sy - (h << 1);
185                 z = sz + h;
186                 for (w = 0; w < width; ++w) {
187                         glBegin(begin_polygon);
188                         glVertex3i(x, y, z);
189                         glVertex3i(x + 1, y, z);
190                         glVertex3i(x + 1, y - 1, z);
191                         glVertex3i(x, y - 1, z);
192                         glEnd();
193                         glBegin(begin_polygon);
194                         glVertex3i(x + 1, y - 1, z);
195                         glVertex3i(x + 2, y - 1, z);
196                         glVertex3i(x + 2, y - 2, z);
197                         glVertex3i(x + 1, y - 2, z);
198 /*-
199  * PURIFY 4.0.1 reports an unitialized memory read on the next line when using
200  * MesaGL 2.2 and -mono.  This has been fixed in MesaGL 2.3 and later. */
201                         glEnd();
202                         ++x;
203                         --z;
204                 }
205         }
206
207         /* Render the other sides */
208         if (!si->wireframe)
209                 glNormal3f(1.0, 0.0, 0.0);
210
211         for (h = 0; h < height; ++h) {
212                 x = sx + h;
213                 y = sy - (h << 1);
214                 z = sz + h;
215                 for (w = 0; w < width; ++w) {
216                         glBegin(begin_polygon);
217                         glVertex3i(x + 1, y, z);
218                         glVertex3i(x + 1, y, z - 1);
219                         glVertex3i(x + 1, y - 1, z - 1);
220                         glVertex3i(x + 1, y - 1, z);
221                         glEnd();
222                         glBegin(begin_polygon);
223                         glVertex3i(x + 2, y - 1, z);
224                         glVertex3i(x + 2, y - 1, z - 1);
225                         glVertex3i(x + 2, y - 2, z - 1);
226                         glVertex3i(x + 2, y - 2, z);
227                         glEnd();
228                         ++x;
229                         --z;
230                 }
231         }
232
233         if (si->wireframe) {
234                 if (!si->mono)
235                         glCallList(si->TopsSides);      /* Render the tops */
236
237                 for (h = 0; h < height; ++h) {
238                         x = sx + h;
239                         y = sy - (h << 1);
240                         z = sz + h;
241                         for (w = 0; w < width; ++w) {
242                                 glBegin(begin_polygon);
243                                 glVertex3i(x, y, z);
244                                 glVertex3i(x, y, z - 1);
245                                 glVertex3i(x + 1, y, z - 1);
246                                 glVertex3i(x + 1, y, z);
247                                 glEnd();
248                                 glBegin(begin_polygon);
249                                 glVertex3i(x + 1, y - 1, z);
250                                 glVertex3i(x + 1, y - 1, z - 1);
251                                 glVertex3i(x + 2, y - 1, z - 1);
252                                 glVertex3i(x + 2, y - 1, z);
253                                 glEnd();
254                                 ++x;
255                                 --z;
256                         }
257                 }
258         }
259 }
260
261 static void
262 AdvanceSproingie(int t, sp_instance * si)
263 {
264         int         g_higher, g_back, t2;
265         struct sPosColor *thisSproingie = &(si->positions[t]);
266         struct sPosColor *S2 = &(si->positions[0]);
267
268         if (thisSproingie->life > 0) {
269                 if ((++(thisSproingie->frame)) > LAST_FRAME) {
270                         if (thisSproingie->frame >= BOOM_FRAME) {
271                                 if ((thisSproingie->r -= 0.08) < 0.0)
272                                         thisSproingie->r = 0.0;
273                                 if ((thisSproingie->g -= 0.08) < 0.0)
274                                         thisSproingie->g = 0.0;
275                                 if ((thisSproingie->b -= 0.08) < 0.0)
276                                         thisSproingie->b = 0.0;
277                                 if ((--(thisSproingie->life)) < 1) {
278                                         thisSproingie->life = RESET_SPROINGIE_LIFE;
279                                 }
280                                 return;
281                         }
282                         thisSproingie->frame = FIRST_FRAME;
283
284                         /* Check for collisions */
285                         for (t2 = 0; t2 < si->maxsproingies; ++t2) {
286                                 if ((t2 != t) && (thisSproingie->x == S2->x) &&
287                                     (thisSproingie->y == S2->y) && (thisSproingie->z == S2->z) &&
288                                     (S2->life > 10) && (S2->frame < LAST_FRAME + 1)) {
289 #if 0
290                                         if (thisSproingie->life > S2->life) {
291                                                 S2->life = 10;
292                                         } else {
293 #endif
294                                                 if (thisSproingie->life > 10) {
295                                                         thisSproingie->life = 10;
296                                                         thisSproingie->frame = BOOM_FRAME;
297                                                         if ((thisSproingie->r += 0.5) > 1.0)
298                                                                 thisSproingie->r = 1.0;
299                                                         if ((thisSproingie->g += 0.5) > 1.0)
300                                                                 thisSproingie->g = 1.0;
301                                                         if ((thisSproingie->b += 0.5) > 1.0)
302                                                                 thisSproingie->b = 1.0;
303                                                 }
304 #if 0
305                                         }
306 #endif
307                                 }
308                                 ++S2;
309                         }
310                 }
311                 /* Time to disappear... */
312                 if (!((thisSproingie->life == 10) &&
313                       (thisSproingie->frame > FIRST_FRAME) &&
314                       (thisSproingie->frame < BOOM_FRAME))) {
315                         if ((--(thisSproingie->life)) < 1) {
316                                 thisSproingie->life = RESET_SPROINGIE_LIFE;
317                         } else if (thisSproingie->life < 9) {
318                                 thisSproingie->frame -= 2;
319                         } 
320                 }               /* ... else wait here for frame FIRST_FRAME to come about. */
321         } else if (++(thisSproingie->life) >= 0) {
322                 if (1 || t > 1) {
323                         g_higher = -3 + myrand(5);
324                         g_back = -2 + myrand(5);
325                 } else if (t == 1) {
326                         g_higher = -2 + myrand(3);
327                         g_back = -1 + myrand(3);
328                 } else {
329                         g_higher = -1;
330                         g_back = 0;
331                 }
332
333                 thisSproingie->x     = (-g_higher - g_back);
334                 thisSproingie->y     = (g_higher << 1);
335                 thisSproingie->z     = (g_back - g_higher);
336                 thisSproingie->life  = NEW_SPROINGIE_LIFE;
337                 thisSproingie->frame = NO_FRAME;
338                 thisSproingie->r     = (GLfloat) (40 + myrand(200)) / 255.0;
339                 thisSproingie->g     = (GLfloat) (40 + myrand(200)) / 255.0;
340                 thisSproingie->b     = (GLfloat) (40 + myrand(200)) / 255.0;
341
342                 for (t2 = 0; t2 < si->maxsproingies; ++t2) {
343                         if ((t2 != t) && (thisSproingie->x == S2->x) &&
344                             (thisSproingie->y == S2->y) && (thisSproingie->z == S2->z) &&
345                             (S2->life > 10) && (S2->frame < FIRST_FRAME)) {
346                                 /* If another is already on this place, wait. */
347                                 thisSproingie->life = -1;
348                         }
349                         ++S2;
350                 }
351         }
352 }
353
354 static void
355 NextSproingie(int screen)
356 {
357         sp_instance *si = &si_list[screen];
358         int         ddx, t;
359         struct sPosColor *thisSproingie = &(si->positions[0]);
360
361         /* Although the sproingies cycle has six frames, the blocks cycle  */
362         /* has twelve. After a full cycle (12 frames), re-center positions */
363         /* of sproingies                                                   */
364         if (++si->sframe > 11) {
365                 si->sframe = FIRST_FRAME;
366                 for (t = 0; t < si->maxsproingies; ++t) {
367                         thisSproingie->x -= 1;
368                         thisSproingie->y += 2;
369                         thisSproingie->z -= 1;
370                         ++thisSproingie;
371                 }
372         }
373
374         for (t = 0; t < si->maxsproingies; ++t) {
375                 AdvanceSproingie(t, si);
376         }
377
378         if (si->target_count < 0) {     /* track to current target */
379                 if (si->target_rx < si->rotx)
380                         --si->rotx;
381                 else if (si->target_rx > si->rotx)
382                         ++si->rotx;
383
384                 if (si->target_ry < si->roty)
385                         --si->roty;
386                 else if (si->target_ry > si->roty)
387                         ++si->roty;
388
389                 ddx = (si->target_dist - si->dist) / 8;
390                 if (ddx)
391                         si->dist += ddx;
392                 else if (si->target_dist < si->dist)
393                         --si->dist;
394                 else if (si->target_dist > si->dist)
395                         ++si->dist;
396
397                 if ((si->target_rx == si->rotx) && (si->target_ry == si->roty) &&
398                     (si->target_dist == si->dist)) {
399                         si->target_count = TARGET_COUNT;
400                         if (si->target_dist <= 32)
401                                 si->target_count >>= 2;
402                 }
403         } else if (--si->target_count < 0) {    /* make up new target */
404                 si->target_rx = myrand(100) - 35;
405                 si->target_ry = -myrand(90);
406                 si->target_dist = 32 << myrand(2);      /* could be 32, 64, or 128, (previously or 256) */
407
408                 if (si->target_dist >= si->dist)        /* no duplicate distances */
409                         si->target_dist <<= 1;
410         }
411         /* Otherwise just hang loose for a while here */
412 }
413
414 #ifdef __AUXFUNCS__
415 void
416 PrintEm(void)
417 {
418         int         t, count = 0;
419
420         for (t = 0; t < maxsproingies; ++t) {
421                 if (positions[t].life > 0)
422                         ++count;
423         }
424         (void) printf("RotX: %d, RotY: %d, Dist: %d.  Targets: X %d, Y %d, D %d.  Visible: %d\n",
425                  rotx, roty, dist, target_rx, target_ry, target_dist, count);
426 }
427
428 void
429 ResetEm(void)
430 {
431         int         t;
432
433         for (t = 0; t < maxsproingies; ++t) {
434                 positions[t].x = 0;
435                 positions[t].y = 0;
436                 positions[t].z = 0;
437                 positions[t].life = -2;
438                 positions[t].frame = FIRST_FRAME;
439         }
440 }
441
442 void
443 distAdd(void)
444 {
445         if (dist < (1 << 16 << 4))
446                 dist <<= 1;
447 }
448
449 void
450 distSubtract(void)
451 {
452         if (dist > 1)
453                 dist >>= 1;
454 }
455
456 void
457 rotxAdd(void)
458 {
459         rotx = (rotx + 5) % 360;
460 }
461
462 void
463 rotxSubtract(void)
464 {
465         rotx = (rotx - 5) % 360;
466 }
467
468 void
469 rotyAdd(void)
470 {
471         roty = (roty + 5) % 360;
472 }
473
474 void
475 rotySubtract(void)
476 {
477         roty = (roty - 5) % 360;
478 }
479
480 void
481 rotxBAdd(void)
482 {
483         rotx = (rotx + 45) % 360;
484 }
485
486 void
487 rotxBSubtract(void)
488 {
489         rotx = (rotx - 45) % 360;
490 }
491
492 void
493 rotyBAdd(void)
494 {
495         roty = (roty + 45) % 360;
496 }
497
498 void
499 rotyBSubtract(void)
500 {
501         roty = (roty - 45) % 360;
502 }
503
504 #endif /* __AUXFUNCS__ */
505
506 static void
507 RenderSproingie(int t, sp_instance * si)
508 {
509         GLfloat     scale, pointsize, mat_color[4] =
510         {0.0, 0.0, 0.0, 1.0};
511 #ifndef HAVE_JWZGLES
512         GLdouble    clipplane[4] =
513         {0.0, 1.0, 0.0, 0.0};
514 #endif
515         struct sPosColor *thisSproingie = &(si->positions[t]);
516
517         if (thisSproingie->life < 1)
518                 return;
519
520         glPushMatrix();
521
522         if (!si->mono) {
523                 mat_color[0] = thisSproingie->r;
524                 mat_color[1] = thisSproingie->g;
525                 mat_color[2] = thisSproingie->b;
526                 if (si->wireframe)
527                         glColor3fv(mat_color);
528                 else {
529                         glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, mat_color);
530                 }
531         }
532
533         if (thisSproingie->frame < FIRST_FRAME) {
534                 glEnable(GL_CLIP_PLANE0);
535                 glTranslatef((GLfloat) (thisSproingie->x),
536                              (GLfloat) (thisSproingie->y) +
537                              ((GLfloat) (thisSproingie->frame) / 9.0),
538                              (GLfloat) (thisSproingie->z));
539
540 #ifndef HAVE_JWZGLES
541         /* OpenGLES doesn't have this but it doesn't seem to matter */
542                 clipplane[3] = ((GLdouble) (thisSproingie->frame) / 9.0) +
543                         (si->wireframe ? 0.0 : 0.1);
544                 glClipPlane(GL_CLIP_PLANE0, clipplane);
545 #endif
546
547 /**             glCallList(si->sproingies[0]);*/
548 /**/    renderList(si->sproingies[0], si->wireframe);
549                 glDisable(GL_CLIP_PLANE0);
550         } else if (thisSproingie->frame >= BOOM_FRAME) {
551                 glTranslatef((GLfloat) (thisSproingie->x) + 0.5,
552                              (GLfloat) (thisSproingie->y) + 0.5,
553                              (GLfloat) (thisSproingie->z) - 0.5);
554                 {
555                         int boom_scale = thisSproingie->frame - BOOM_FRAME;
556                         if (boom_scale >= 31) boom_scale = 31;
557                         scale = (GLfloat) (1 << boom_scale);
558                 }
559                 glScalef(scale, scale, scale);
560                 if (!si->wireframe) {
561                         if (!si->mono)
562                                 glColor3fv(mat_color);
563                         glDisable(GL_LIGHTING);
564                 }
565                 pointsize = (GLfloat) ((BOOM_FRAME + 8) - thisSproingie->frame) -
566                         (si->dist / 64.0);
567                 glPointSize((pointsize < 1.0) ? 1.0 : pointsize);
568 /*-
569  * PURIFY 4.0.1 reports an unitialized memory read on the next line when using
570  * MesaGL 2.2.  This has been tracked to MesaGL 2.2 src/points.c line 313. */
571 /**             glCallList(si->SproingieBoom);*/
572 /**/    renderList(si->SproingieBoom, si->wireframe);
573                 glPointSize(1.0);
574                 if (!si->wireframe) {
575                         glEnable(GL_LIGHTING);
576                 }
577         } else {
578                 if (thisSproingie->direction == JUMP_LEFT) {
579                         /* When the sproingie jumps to the left, the frames must be */
580                         /* rotated and translated */
581                         glTranslatef((GLfloat) (thisSproingie->x    ),
582                                                  (GLfloat) (thisSproingie->y    ), 
583                                                  (GLfloat) (thisSproingie->z - 1));
584                         glRotatef((GLfloat) - 90.0, 0.0, 1.0, 0.0);
585                         if (thisSproingie->frame == LAST_FRAME) {
586                                 thisSproingie->x -= 0;
587                                 thisSproingie->y -= 1;
588                                 thisSproingie->z += 1;
589                         } 
590                 } else {
591                         glTranslatef((GLfloat) (thisSproingie->x),
592                                                  (GLfloat) (thisSproingie->y), 
593                                                  (GLfloat) (thisSproingie->z));
594                         glRotatef((GLfloat) - 0.0, 0.0, 1.0, 0.0);
595                         if (thisSproingie->frame == LAST_FRAME) {
596                                 thisSproingie->x += 1;
597                                 thisSproingie->y -= 1;
598                                 thisSproingie->z -= 0;
599                         }
600                 }
601 /*      } */
602 /**             glCallList(si->sproingies[thisSproingie->frame]);*/
603 /**/    renderList(si->sproingies[thisSproingie->frame], si->wireframe);
604
605                 /* Every 6 frame cycle... */
606                 if (thisSproingie->frame == LAST_FRAME) {
607                         /* ...check if the sproingies have gone out of the bricks */
608                         if (((thisSproingie->x - thisSproingie->z == 6) &&
609                                  (2*thisSproingie->x + thisSproingie->y == 6)) ||
610                                 ((thisSproingie->z - thisSproingie->x == 5) &&
611                                  (2*thisSproingie->x + thisSproingie->y == -5))) {
612                                 /* If they have, then they die */
613                                 if (thisSproingie->life > 0 && thisSproingie->frame < BOOM_FRAME && thisSproingie->frame > FIRST_FRAME) {
614                                         thisSproingie->frame = BOOM_FRAME;
615                                 }
616                         } else {
617                                 /* If not, they choose a direction for the next hop */
618                                 if (smart_sproingies) {
619                                         if ((thisSproingie->x - thisSproingie->z == 5) &&   
620                                                 (2*thisSproingie->x + thisSproingie->y == 5)) {
621                                                 thisSproingie->direction = JUMP_LEFT;
622                                         } else if ((thisSproingie->z - thisSproingie->x == 4) &&   
623                                                  (2*thisSproingie->x + thisSproingie->y == -4)) {
624                                                 thisSproingie->direction = JUMP_RIGHT;
625                                         } else {
626                                                 thisSproingie->direction = myrand(2);
627                                         }
628                                 } else {
629                                         thisSproingie->direction = myrand(2);
630                                 }
631                         }
632                 }
633         }
634
635         glPopMatrix();
636
637 }
638
639 static void
640 ComputeGround(sp_instance * si)
641 {
642         int         g_higher, g_back, g_width, g_height;
643
644         /* higher: x-1, y+2, z-1 */
645         /* back: x-1, y, z+1 */
646
647         if (si->groundlevel == 0) {
648                 g_back = 2;
649                 g_width = 5;
650         } else if (si->groundlevel == 1) {
651                 g_back = 4;
652                 g_width = 8;
653         } else {
654                 g_back = 8;
655                 g_width = 16;
656         }
657
658         if ((g_higher = si->dist >> 3) < 4)
659                 g_higher = 4;
660         if (g_higher > 16)
661                 g_higher = 16;
662         g_height = g_higher << 1;
663
664         if (si->rotx < -10)
665                 g_higher += (g_higher >> 2);
666         else if (si->rotx > 10)
667                 g_higher -= (g_higher >> 2);
668
669 #if 0
670         if (si->dist > 128) {
671                 ++g_higher;
672                 ++g_back;
673                 g_back <<= 1;
674         } else if (si->dist > 64) {
675                 ++g_higher;
676                 ++g_back;
677         } else if (si->dist > 32) {
678                 /* nothing special */
679         } else {
680                 if (g_higher > 2) {
681                         g_higher = g_back = 4;
682                 }
683         }
684 #endif
685
686         /* startx, starty, startz, width, height */
687         LayGround((-g_higher - g_back), (g_higher << 1), (g_back - g_higher),
688                   (g_width), (g_height), si);
689 }
690
691 void
692 DisplaySproingies(int screen,int pause)
693 {
694         sp_instance *si = &si_list[screen];
695         int         t;
696         GLfloat     position[] =
697         {8.0, 5.0, -2.0, 0.1};
698
699         if (si->wireframe)
700                 glClear(GL_COLOR_BUFFER_BIT);
701         else
702                 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
703
704         glPushMatrix();
705         glTranslatef(0.0, 0.0, -(GLfloat) (si->dist) / 16.0);   /* viewing transform  */
706         glRotatef((GLfloat) si->rotx, 1.0, 0.0, 0.0);
707         glRotatef((GLfloat) si->roty, 0.0, 1.0, 0.0);
708
709         if (!si->wireframe)
710                 glLightfv(GL_LIGHT0, GL_POSITION, position);
711
712 #if 0                           /* Show light pos */
713         glPushMatrix();
714         glTranslatef(position[0], position[1], position[2]);
715         glColor3f(1.0, 1.0, 1.0);
716         if (!si->wireframe) {
717                 glDisable(GL_LIGHTING);
718         }
719         glCallList(si->SproingieBoom);
720         if (!si->wireframe) {
721                 glEnable(GL_LIGHTING);
722         }
723         glPopMatrix();
724 #endif
725
726         glTranslatef((GLfloat) si->sframe * (-1.0 / 12.0) - 0.75,
727                      (GLfloat) si->sframe * (2.0 / 12.0) - 0.5,
728                      (GLfloat) si->sframe * (-1.0 / 12.0) + 0.75);
729
730         if (si->wireframe)
731                 ComputeGround(si);
732
733         for (t = 0; t < si->maxsproingies; ++t) {
734                 RenderSproingie(t, si);
735         }
736
737         if (!si->wireframe)
738                 ComputeGround(si);
739
740         glPopMatrix();
741         glFlush();
742 }
743
744 void
745 NextSproingieDisplay(int screen,int pause)
746 {
747         NextSproingie(screen);
748 /*        if (pause) usleep(pause);  don't do this! -jwz */
749         DisplaySproingies(screen,pause);
750 }
751
752 void
753 ReshapeSproingies(int w, int h)
754 {
755         glViewport(0, 0, w, h);
756         glMatrixMode(GL_PROJECTION);
757         glLoadIdentity();
758         gluPerspective(65.0, (GLfloat) w / (GLfloat) h, 0.1, 2000.0);   /* was 200000.0 */
759         glMatrixMode(GL_MODELVIEW);
760         glLoadIdentity();
761 }
762
763 void
764 CleanupSproingies(int screen)
765 {
766         sp_instance *si = &si_list[screen];
767 /*
768         int         t;
769         if (si->SproingieBoom) {
770                 for (t = 0; t < 6; ++t)
771                         glDeleteLists(si->sproingies[t], 1);
772
773                 glDeleteLists(si->TopsSides, 2);
774                 glDeleteLists(si->SproingieBoom, 1);
775
776                 --active_screens;
777                 si->SproingieBoom = 0;
778         }
779 */
780         if (si->TopsSides) {
781                 glDeleteLists(si->TopsSides, 2);
782         }
783         if (si->positions) {
784                 (void) free((void *) (si->positions));
785                 si->positions = NULL;
786         }
787         if ((active_screens == 0) && si_list) {
788                 (void) free((void *) (si_list));
789                 si_list = NULL;
790         }
791 }
792
793 void
794 InitSproingies(int wfmode, int grnd, int mspr, int smrtspr, 
795                            int screen, int numscreens, int mono)
796 {
797         GLfloat     ambient[] =
798         {0.2, 0.2, 0.2, 1.0};
799         GLfloat     position[] =
800         {10.0, 1.0, 1.0, 10.0};
801         GLfloat     mat_diffuse[] =
802         {0.6, 0.6, 0.6, 1.0};
803         GLfloat     mat_specular[] =
804         {0.8, 0.8, 0.8, 1.0};
805         GLfloat     mat_shininess[] =
806         {50.0};
807
808         sp_instance *si;
809         int         t;
810
811         if (si_list == NULL) {
812                 if ((si_list = (sp_instance *) calloc(numscreens,
813                                               sizeof (sp_instance))) == NULL)
814                         return;
815         }
816         si = &si_list[screen];
817
818         active_screens++;
819         CleanupSproingies(screen);
820
821         if (mspr < 0)
822                 mspr = 0;
823         if (mspr >= MAXSPROING)
824                 mspr = MAXSPROING - 1;
825
826         smart_sproingies = smrtspr; 
827
828         si->rotx = 0;
829         si->roty = -45;
830         si->dist = (16 << 2);
831         si->sframe = 0;
832         si->target_count = 0;
833         si->mono = mono;
834
835         si->wireframe = si->flatshade = 0;
836
837         if (wfmode == 2)
838                 si->flatshade = 1;
839         else if (wfmode)
840                 si->wireframe = 1;
841
842         si->groundlevel = grnd;
843         si->maxsproingies = mspr;
844
845         if (si->maxsproingies) {
846                 si->positions = (struct sPosColor *) calloc(si->maxsproingies,
847                                                   sizeof (struct sPosColor));
848
849                 if (!(si->positions))
850                         si->maxsproingies = 0;
851         }
852         for (t = 0; t < si->maxsproingies; ++t) {
853                 si->positions[t].x = 0;
854                 si->positions[t].y = 0;
855                 si->positions[t].z = 0;
856                 si->positions[t].life = (-t * ((si->maxsproingies > 19) ? 1 : 4)) - 2;
857                 si->positions[t].frame = FIRST_FRAME;
858                 si->positions[t].direction = myrand(2);
859         }
860
861 #if 0                           /* Test boom */
862         si->positions[0].x = 0;
863         si->positions[0].y = 0;
864         si->positions[0].z = 0;
865         si->positions[0].life = 10;
866         si->positions[0].frame = BOOM_FRAME;
867         si->positions[0].r = 0.656863;
868         si->positions[0].g = 1.0;
869         si->positions[0].b = 0.656863;
870 #endif
871
872         if (!(si->TopsSides = build_TopsSides(si->wireframe)))
873                 (void) fprintf(stderr, "build_TopsSides\n");
874 /*
875         if (!(si->sproingies[0] = BuildLWO(si->wireframe, &LWO_s1_1)))
876                 (void) fprintf(stderr, "BuildLWO - 1\n");
877         if (!(si->sproingies[1] = BuildLWO(si->wireframe, &LWO_s1_2)))
878                 (void) fprintf(stderr, "BuildLWO - 2\n");
879         if (!(si->sproingies[2] = BuildLWO(si->wireframe, &LWO_s1_3)))
880                 (void) fprintf(stderr, "BuildLWO - 3\n");
881         if (!(si->sproingies[3] = BuildLWO(si->wireframe, &LWO_s1_4)))
882                 (void) fprintf(stderr, "BuildLWO - 4\n");
883         if (!(si->sproingies[4] = BuildLWO(si->wireframe, &LWO_s1_5)))
884                 (void) fprintf(stderr, "BuildLWO - 5\n");
885         if (!(si->sproingies[5] = BuildLWO(si->wireframe, &LWO_s1_6)))
886                 (void) fprintf(stderr, "BuildLWO - 6\n");
887
888         if (!(si->SproingieBoom = BuildLWO(si->wireframe, &LWO_s1_b)))
889                 (void) fprintf(stderr, "BuildLWO - b\n");
890 */
891         si->sproingies[0]=s1_1;
892         si->sproingies[1]=s1_2;
893         si->sproingies[2]=s1_3;
894         si->sproingies[3]=s1_4;
895         si->sproingies[4]=s1_5;
896         si->sproingies[5]=s1_6;
897         si->SproingieBoom=s1_b;
898
899         if (si->wireframe) {
900                 glShadeModel(GL_FLAT);
901                 glDisable(GL_LIGHTING);
902         } else {
903                 if (si->flatshade) {
904                         glShadeModel(GL_FLAT);
905                         position[0] = 1.0;
906                         position[3] = 0.0;
907                 }
908                 glEnable(GL_LIGHTING);
909                 glEnable(GL_LIGHT0);
910                 glDepthFunc(GL_LEQUAL);
911                 glEnable(GL_DEPTH_TEST);
912
913                 glLightfv(GL_LIGHT0, GL_AMBIENT, ambient);
914                 glLightfv(GL_LIGHT0, GL_POSITION, position);
915
916                 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mat_diffuse);
917                 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mat_specular);
918                 glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, mat_shininess);
919
920                 /* glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE); */
921                 glCullFace(GL_BACK);
922                 glEnable(GL_CULL_FACE);
923
924                 glFrontFace(GL_CW);
925                 /* glEnable(GL_NORMALIZE); */
926         }
927 }
928
929 #endif /* USE_GL */
930
931 /* End of sproingies.c */
932