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