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