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