1 /* -*- Mode: C; tab-width: 4 -*- */
2 /* sproingies.c - 3D sproingies */
5 static const char sccsid[] = "@(#)sproingies.c 4.04 97/07/28 xlockmore";
9 * sproingies.c - Copyright 1996 by Ed Mackey, freely distributable.
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.
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.
29 #endif /* HAVE_CONFIG_H */
32 # include "xlockmoreI.h" /* from the xscreensaver distribution */
33 #else /* !STANDALONE */
34 # include "xlock.h" /* from the xlockmore distribution */
35 #endif /* !STANDALONE */
40 # include <OpenGL/glu.h>
46 #include "sproingies.h"
48 #define MAXSPROING 100
53 int x, y, z, frame, life;
58 int rotx, roty, dist, wireframe, flatshade, groundlevel,
60 int sframe, target_rx, target_ry, target_dist, target_count;
61 const struct gllist *sproingies[6];
62 const struct gllist *SproingieBoom;
64 struct sPosColor *positions;
67 static sp_instance *si_list = NULL;
68 static int active_screens = 0;
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;
81 return ((int) (((float) range) * LRAND() / (MAXRAND)));
85 build_TopsSides(int wireframe)
88 GLfloat mat_color[4] =
91 dl_num = glGenLists(2);
93 return (0); /* 0 means out of display lists. */
96 glNewList(dl_num, GL_COMPILE);
97 mat_color[0] = 0.392157;
98 mat_color[1] = 0.784314;
99 mat_color[2] = 0.941176;
101 glColor3fv(mat_color);
103 glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, mat_color);
108 glNewList(dl_num + 1, GL_COMPILE);
110 glColor3fv(mat_color);
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);
123 LayGround(int sx, int sy, int sz, int width, int height, sp_instance * si)
126 GLenum begin_polygon;
129 begin_polygon = GL_LINE_LOOP;
131 begin_polygon = GL_POLYGON;
133 if (!si->wireframe) {
135 glCallList(si->TopsSides); /* Render the tops */
136 glNormal3f(0.0, 1.0, 0.0);
138 for (h = 0; h < height; ++h) {
142 for (w = 0; w < width; ++w) {
143 glBegin(begin_polygon);
145 glVertex3i(x, y, z - 1);
146 glVertex3i(x + 1, y, z - 1);
147 glVertex3i(x + 1, y, z);
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);
161 glCallList(si->TopsSides + 1); /* Render the sides */
163 glNormal3f(0.0, 0.0, 1.0);
165 for (h = 0; h < height; ++h) {
169 for (w = 0; w < width; ++w) {
170 glBegin(begin_polygon);
172 glVertex3i(x + 1, y, z);
173 glVertex3i(x + 1, y - 1, z);
174 glVertex3i(x, y - 1, z);
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);
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. */
190 /* Render the other sides */
192 glNormal3f(1.0, 0.0, 0.0);
194 for (h = 0; h < height; ++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);
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);
218 glCallList(si->TopsSides); /* Render the tops */
220 for (h = 0; h < height; ++h) {
224 for (w = 0; w < width; ++w) {
225 glBegin(begin_polygon);
227 glVertex3i(x, y, z - 1);
228 glVertex3i(x + 1, y, z - 1);
229 glVertex3i(x + 1, y, z);
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);
244 #define RESET_SPROINGIE (-30 + myrand(28))
247 AdvanceSproingie(int t, sp_instance * si)
249 int g_higher, g_back, t2;
250 struct sPosColor *thisSproingie = &(si->positions[t]);
251 struct sPosColor *S2 = &(si->positions[0]);
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;
267 thisSproingie->x += 1;
268 thisSproingie->y -= 2;
269 thisSproingie->z += 1;
270 thisSproingie->frame = 0;
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)) {
277 if (thisSproingie->life > S2->life) {
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;
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;
306 } /* else wait here for frame 0 to come about. */
307 } else if (++(thisSproingie->life) >= 0) {
309 g_higher = -3 + myrand(5);
310 g_back = -2 + myrand(5);
312 g_higher = -2 + myrand(3);
313 g_back = -1 + myrand(3);
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;
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;
341 NextSproingie(int screen)
343 sp_instance *si = &si_list[screen];
345 struct sPosColor *thisSproingie = &(si->positions[0]);
347 if (++si->sframe > 11) {
349 for (t = 0; t < si->maxsproingies; ++t) {
350 thisSproingie->x -= 1;
351 thisSproingie->y += 2;
352 thisSproingie->z -= 1;
356 for (t = 0; t < si->maxsproingies; ++t) {
357 AdvanceSproingie(t, si);
360 if (si->target_count < 0) { /* track to current target */
361 if (si->target_rx < si->rotx)
363 else if (si->target_rx > si->rotx)
366 if (si->target_ry < si->roty)
368 else if (si->target_ry > si->roty)
371 ddx = (si->target_dist - si->dist) / 8;
374 else if (si->target_dist < si->dist)
376 else if (si->target_dist > si->dist)
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;
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) */
390 if (si->target_dist >= si->dist) /* no duplicate distances */
391 si->target_dist <<= 1;
393 /* Otherwise just hang loose for a while here */
402 for (t = 0; t < maxsproingies; ++t) {
403 if (positions[t].life > 0)
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);
415 for (t = 0; t < maxsproingies; ++t) {
419 positions[t].life = -2;
420 positions[t].frame = 0;
427 if (dist < (1 << 16 << 4))
441 rotx = (rotx + 5) % 360;
447 rotx = (rotx - 5) % 360;
453 roty = (roty + 5) % 360;
459 roty = (roty - 5) % 360;
465 rotx = (rotx + 45) % 360;
471 rotx = (rotx - 45) % 360;
477 roty = (roty + 45) % 360;
483 roty = (roty - 45) % 360;
489 RenderSproingie(int t, sp_instance * si)
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]);
497 if (thisSproingie->life < 1)
503 mat_color[0] = thisSproingie->r;
504 mat_color[1] = thisSproingie->g;
505 mat_color[2] = thisSproingie->b;
507 glColor3fv(mat_color);
509 glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, mat_color);
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) {
532 glColor3fv(mat_color);
533 glDisable(GL_LIGHTING);
535 pointsize = (GLfloat) ((BOOM_FRAME + 8) - thisSproingie->frame) -
537 glPointSize((pointsize < 1.0) ? 1.0 : pointsize);
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);
544 if (!si->wireframe) {
545 glEnable(GL_LIGHTING);
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);
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);
565 ComputeGround(sp_instance * si)
567 int g_higher, g_back, g_width, g_height;
569 /* higher: x-1, y+2, z-1 */
570 /* back: x-1, y, z+1 */
572 if (si->groundlevel == 0) {
575 } else if (si->groundlevel == 1) {
583 if ((g_higher = si->dist >> 3) < 4)
587 g_height = g_higher << 1;
590 g_higher += (g_higher >> 2);
591 else if (si->rotx > 10)
592 g_higher -= (g_higher >> 2);
595 if (si->dist > 128) {
599 } else if (si->dist > 64) {
602 } else if (si->dist > 32) {
603 /* nothing special */
606 g_higher = g_back = 4;
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);
617 DisplaySproingies(int screen,int pause)
619 sp_instance *si = &si_list[screen];
622 {8.0, 5.0, -2.0, 0.1};
625 glClear(GL_COLOR_BUFFER_BIT);
627 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
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);
635 glLightfv(GL_LIGHT0, GL_POSITION, position);
637 #if 0 /* Show light pos */
639 glTranslatef(position[0], position[1], position[2]);
640 glColor3f(1.0, 1.0, 1.0);
641 if (!si->wireframe) {
642 glDisable(GL_LIGHTING);
644 glCallList(si->SproingieBoom);
645 if (!si->wireframe) {
646 glEnable(GL_LIGHTING);
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);
658 for (t = 0; t < si->maxsproingies; ++t) {
659 RenderSproingie(t, si);
670 NextSproingieDisplay(int screen,int pause)
672 NextSproingie(screen);
673 /* if (pause) usleep(pause); don't do this! -jwz */
674 DisplaySproingies(screen,pause);
678 ReshapeSproingies(int w, int h)
680 glViewport(0, 0, w, h);
681 glMatrixMode(GL_PROJECTION);
683 gluPerspective(65.0, (GLfloat) w / (GLfloat) h, 0.1, 2000.0); /* was 200000.0 */
684 glMatrixMode(GL_MODELVIEW);
689 CleanupSproingies(int screen)
691 sp_instance *si = &si_list[screen];
694 if (si->SproingieBoom) {
695 for (t = 0; t < 6; ++t)
696 glDeleteLists(si->sproingies[t], 1);
698 glDeleteLists(si->TopsSides, 2);
699 glDeleteLists(si->SproingieBoom, 1);
702 si->SproingieBoom = 0;
706 glDeleteLists(si->TopsSides, 2);
709 (void) free((void *) (si->positions));
710 si->positions = NULL;
712 if ((active_screens == 0) && si_list) {
713 (void) free((void *) (si_list));
719 InitSproingies(int wfmode, int grnd, int mspr, int screen, int numscreens,
723 {0.2, 0.2, 0.2, 1.0};
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[] =
736 if (si_list == NULL) {
737 if ((si_list = (sp_instance *) calloc(numscreens,
738 sizeof (sp_instance))) == NULL)
741 si = &si_list[screen];
744 CleanupSproingies(screen);
748 if (mspr >= MAXSPROING)
749 mspr = MAXSPROING - 1;
753 si->dist = (16 << 2);
755 si->target_count = 0;
758 si->wireframe = si->flatshade = 0;
765 si->groundlevel = grnd;
766 si->maxsproingies = mspr;
768 if (si->maxsproingies) {
769 si->positions = (struct sPosColor *) calloc(si->maxsproingies,
770 sizeof (struct sPosColor));
772 if (!(si->positions))
773 si->maxsproingies = 0;
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;
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;
794 if (!(si->TopsSides = build_TopsSides(si->wireframe)))
795 (void) fprintf(stderr, "build_TopsSides\n");
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");
810 if (!(si->SproingieBoom = BuildLWO(si->wireframe, &LWO_s1_b)))
811 (void) fprintf(stderr, "BuildLWO - b\n");
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;
822 glShadeModel(GL_FLAT);
823 glDisable(GL_LIGHTING);
826 glShadeModel(GL_FLAT);
830 glEnable(GL_LIGHTING);
832 glDepthFunc(GL_LEQUAL);
833 glEnable(GL_DEPTH_TEST);
835 glLightfv(GL_LIGHT0, GL_AMBIENT, ambient);
836 glLightfv(GL_LIGHT0, GL_POSITION, position);
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);
842 /* glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE); */
844 glEnable(GL_CULL_FACE);
847 /* glEnable(GL_NORMALIZE); */
853 /* End of sproingies.c */