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