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