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