1 /* -*- Mode: C; tab-width: 4 -*-
2 * sproingies.c --- 3D sproingies
4 #if !defined( lint ) && !defined( SABER )
5 static const char sccsid[] = "@(#)sproingies.c 4.04 97/07/26 xlockmore";
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.
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.
22 # include "xlockmoreI.h" /* from the xscreensaver distribution */
23 #else /* !STANDALONE */
24 # include "xlock.h" /* from the xlockmore distribution */
25 #endif /* !STANDALONE */
33 #define MAXSPROING 100
38 int x, y, z, frame, life;
43 int rotx, roty, dist, wireframe, flatshade, groundlevel,
45 int sframe, target_rx, target_ry, target_dist, target_count;
46 GLuint sproingies[6], TopsSides, SproingieBoom;
47 struct sPosColor *positions;
50 static sp_instance *si_list = NULL;
51 static int active_screens = 0;
53 void SproingieSwap(void);
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;
61 return ((int) (((float) range) * LRAND() / (MAXRAND)));
65 build_TopsSides(int wireframe)
68 GLfloat mat_color[4] =
71 dl_num = glGenLists(2);
73 return (0); /* 0 means out of display lists. */
76 glNewList(dl_num, GL_COMPILE);
77 mat_color[0] = 0.392157;
78 mat_color[1] = 0.784314;
79 mat_color[2] = 0.941176;
81 glColor3fv(mat_color);
83 glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, mat_color);
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;
93 glColor3fv(mat_color);
95 glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, mat_color);
102 LayGround(int sx, int sy, int sz, int width, int height, sp_instance * si)
105 GLenum begin_polygon;
108 begin_polygon = GL_LINE_LOOP;
110 begin_polygon = GL_POLYGON;
112 if (!si->wireframe) {
114 glCallList(si->TopsSides); /* Render the tops */
115 glNormal3f(0.0, 1.0, 0.0);
117 for (h = 0; h < height; ++h) {
121 for (w = 0; w < width; ++w) {
122 glBegin(begin_polygon);
124 glVertex3i(x, y, z - 1);
125 glVertex3i(x + 1, y, z - 1);
126 glVertex3i(x + 1, y, z);
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);
140 glCallList(si->TopsSides + 1); /* Render the sides */
142 glNormal3f(0.0, 0.0, 1.0);
144 for (h = 0; h < height; ++h) {
148 for (w = 0; w < width; ++w) {
149 glBegin(begin_polygon);
151 glVertex3i(x + 1, y, z);
152 glVertex3i(x + 1, y - 1, z);
153 glVertex3i(x, y - 1, z);
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);
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. */
169 /* Render the other sides */
171 glNormal3f(1.0, 0.0, 0.0);
173 for (h = 0; h < height; ++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);
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);
197 glCallList(si->TopsSides); /* Render the tops */
199 for (h = 0; h < height; ++h) {
203 for (w = 0; w < width; ++w) {
204 glBegin(begin_polygon);
206 glVertex3i(x, y, z - 1);
207 glVertex3i(x + 1, y, z - 1);
208 glVertex3i(x + 1, y, z);
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);
223 #define RESET_SPROINGIE (-30 + myrand(28))
226 AdvanceSproingie(int t, sp_instance * si)
228 int g_higher, g_back, t2;
229 struct sPosColor *thisSproingie = &(si->positions[t]);
230 struct sPosColor *S2 = &(si->positions[0]);
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;
246 thisSproingie->x += 1;
247 thisSproingie->y -= 2;
248 thisSproingie->z += 1;
249 thisSproingie->frame = 0;
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)) {
256 if (thisSproingie->life > S2->life) {
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;
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;
285 } /* else wait here for frame 0 to come about. */
286 } else if (++(thisSproingie->life) >= 0) {
288 g_higher = -3 + myrand(5);
289 g_back = -2 + myrand(5);
291 g_higher = -2 + myrand(3);
292 g_back = -1 + myrand(3);
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;
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;
320 NextSproingie(int screen)
322 sp_instance *si = &si_list[screen];
324 struct sPosColor *thisSproingie = &(si->positions[0]);
326 if (++si->sframe > 11) {
328 for (t = 0; t < si->maxsproingies; ++t) {
329 thisSproingie->x -= 1;
330 thisSproingie->y += 2;
331 thisSproingie->z -= 1;
335 for (t = 0; t < si->maxsproingies; ++t) {
336 AdvanceSproingie(t, si);
339 if (si->target_count < 0) { /* track to current target */
340 if (si->target_rx < si->rotx)
342 else if (si->target_rx > si->rotx)
345 if (si->target_ry < si->roty)
347 else if (si->target_ry > si->roty)
350 ddx = (si->target_dist - si->dist) / 8;
353 else if (si->target_dist < si->dist)
355 else if (si->target_dist > si->dist)
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;
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) */
369 if (si->target_dist >= si->dist) /* no duplicate distances */
370 si->target_dist <<= 1;
372 /* Otherwise just hang loose for a while here */
381 for (t = 0; t < maxsproingies; ++t) {
382 if (positions[t].life > 0)
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);
394 for (t = 0; t < maxsproingies; ++t) {
398 positions[t].life = -2;
399 positions[t].frame = 0;
406 if (dist < (1 << 16 << 4))
420 rotx = (rotx + 5) % 360;
426 rotx = (rotx - 5) % 360;
432 roty = (roty + 5) % 360;
438 roty = (roty - 5) % 360;
444 rotx = (rotx + 45) % 360;
450 rotx = (rotx - 45) % 360;
456 roty = (roty + 45) % 360;
462 roty = (roty - 45) % 360;
468 RenderSproingie(int t, sp_instance * si)
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]);
476 if (thisSproingie->life < 1)
482 mat_color[0] = thisSproingie->r;
483 mat_color[1] = thisSproingie->g;
484 mat_color[2] = thisSproingie->b;
486 glColor3fv(mat_color);
488 glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, mat_color);
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) {
510 glColor3fv(mat_color);
511 glDisable(GL_LIGHTING);
513 pointsize = (GLfloat) ((BOOM_FRAME + 8) - thisSproingie->frame) -
515 glPointSize((pointsize < 1.0) ? 1.0 : pointsize);
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);
521 if (!si->wireframe) {
522 glEnable(GL_LIGHTING);
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]);
530 glTranslatef((GLfloat) (thisSproingie->x), (GLfloat) (thisSproingie->y),
531 (GLfloat) (thisSproingie->z));
532 glCallList(si->sproingies[thisSproingie->frame]);
540 ComputeGround(sp_instance * si)
542 int g_higher, g_back, g_width, g_height;
544 /* higher: x-1, y+2, z-1 */
545 /* back: x-1, y, z+1 */
547 if (si->groundlevel == 0) {
550 } else if (si->groundlevel == 1) {
558 if ((g_higher = si->dist >> 3) < 4)
562 g_height = g_higher << 1;
565 g_higher += (g_higher >> 2);
566 else if (si->rotx > 10)
567 g_higher -= (g_higher >> 2);
570 if (si->dist > 128) {
574 } else if (si->dist > 64) {
577 } else if (si->dist > 32) {
578 /* nothing special */
581 g_higher = g_back = 4;
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);
592 DisplaySproingies(int screen)
594 sp_instance *si = &si_list[screen];
597 {8.0, 5.0, -2.0, 0.1};
600 glClear(GL_COLOR_BUFFER_BIT);
602 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
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);
610 glLightfv(GL_LIGHT0, GL_POSITION, position);
612 #if 0 /* Show light pos */
614 glTranslatef(position[0], position[1], position[2]);
615 glColor3f(1.0, 1.0, 1.0);
616 if (!si->wireframe) {
617 glDisable(GL_LIGHTING);
619 glCallList(si->SproingieBoom);
620 if (!si->wireframe) {
621 glEnable(GL_LIGHTING);
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);
633 for (t = 0; t < si->maxsproingies; ++t) {
634 RenderSproingie(t, si);
647 NextSproingieDisplay(int screen)
649 NextSproingie(screen);
650 DisplaySproingies(screen);
655 ReshapeSproingies(int w, int h)
657 glViewport(0, 0, w, h);
658 glMatrixMode(GL_PROJECTION);
660 gluPerspective(65.0, (GLfloat) w / (GLfloat) h, 0.1, 2000.0); /* was 200000.0 */
661 glMatrixMode(GL_MODELVIEW);
668 CleanupSproingies(int screen)
670 sp_instance *si = &si_list[screen];
673 if (si->SproingieBoom) {
674 for (t = 0; t < 6; ++t)
675 glDeleteLists(si->sproingies[t], 1);
677 glDeleteLists(si->TopsSides, 2);
678 glDeleteLists(si->SproingieBoom, 1);
681 si->SproingieBoom = 0;
684 (void) free((void *) (si->positions));
685 si->positions = NULL;
687 if ((active_screens == 0) && si_list) {
688 (void) free((void *) (si_list));
694 InitSproingies(int wfmode, int grnd, int mspr, int screen, int numscreens,
698 {0.2, 0.2, 0.2, 1.0};
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[] =
711 if (si_list == NULL) {
712 if ((si_list = (sp_instance *) calloc(numscreens,
713 sizeof (sp_instance))) == NULL)
716 si = &si_list[screen];
719 CleanupSproingies(screen);
723 if (mspr >= MAXSPROING)
724 mspr = MAXSPROING - 1;
728 si->dist = (16 << 2);
730 si->target_count = 0;
733 si->wireframe = si->flatshade = 0;
740 si->groundlevel = grnd;
741 si->maxsproingies = mspr;
743 if (si->maxsproingies) {
744 si->positions = (struct sPosColor *) calloc(si->maxsproingies,
745 sizeof (struct sPosColor));
747 if (!(si->positions))
748 si->maxsproingies = 0;
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;
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;
769 if (!(si->TopsSides = build_TopsSides(si->wireframe)))
770 (void) fprintf(stderr, "build_TopsSides\n");
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");
785 if (!(si->SproingieBoom = BuildLWO(si->wireframe, &LWO_s1_b)))
786 (void) fprintf(stderr, "BuildLWO - b\n");
789 glShadeModel(GL_FLAT);
790 glDisable(GL_LIGHTING);
793 glShadeModel(GL_FLAT);
797 glEnable(GL_LIGHTING);
799 glDepthFunc(GL_LEQUAL);
800 glEnable(GL_DEPTH_TEST);
802 glLightfv(GL_LIGHT0, GL_AMBIENT, ambient);
803 glLightfv(GL_LIGHT0, GL_POSITION, position);
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);
809 /* glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE); */
811 glEnable(GL_CULL_FACE);
814 /* glEnable(GL_NORMALIZE); */
820 /* End of sproingies.c */