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