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