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