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.
28 # include "xlockmoreI.h" /* from the xscreensaver distribution */
29 #else /* !STANDALONE */
30 # include "xlock.h" /* from the xlockmore distribution */
31 #endif /* !STANDALONE */
39 #define MAXSPROING 100
44 int x, y, z, frame, life;
49 int rotx, roty, dist, wireframe, flatshade, groundlevel,
51 int sframe, target_rx, target_ry, target_dist, target_count;
52 struct gllist *sproingies[6];
53 struct gllist *SproingieBoom;
55 struct sPosColor *positions;
58 static sp_instance *si_list = NULL;
59 static int active_screens = 0;
61 void SproingieSwap(void);
63 extern struct gllist *s1_1;
64 extern struct gllist *s1_2;
65 extern struct gllist *s1_3;
66 extern struct gllist *s1_4;
67 extern struct gllist *s1_5;
68 extern struct gllist *s1_6;
69 extern struct gllist *s1_b;
74 return ((int) (((float) range) * LRAND() / (MAXRAND)));
78 build_TopsSides(int wireframe)
81 GLfloat mat_color[4] =
84 dl_num = glGenLists(2);
86 return (0); /* 0 means out of display lists. */
89 glNewList(dl_num, GL_COMPILE);
90 mat_color[0] = 0.392157;
91 mat_color[1] = 0.784314;
92 mat_color[2] = 0.941176;
94 glColor3fv(mat_color);
96 glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, mat_color);
101 glNewList(dl_num + 1, GL_COMPILE);
103 glColor3fv(mat_color);
105 /* jwz: in wireframe mode, color tops and sides the same. */
106 mat_color[0] = 0.156863;
107 mat_color[1] = 0.156863;
108 mat_color[2] = 0.392157;
109 glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, mat_color);
116 LayGround(int sx, int sy, int sz, int width, int height, sp_instance * si)
119 GLenum begin_polygon;
122 begin_polygon = GL_LINE_LOOP;
124 begin_polygon = GL_POLYGON;
126 if (!si->wireframe) {
128 glCallList(si->TopsSides); /* Render the tops */
129 glNormal3f(0.0, 1.0, 0.0);
131 for (h = 0; h < height; ++h) {
135 for (w = 0; w < width; ++w) {
136 glBegin(begin_polygon);
138 glVertex3i(x, y, z - 1);
139 glVertex3i(x + 1, y, z - 1);
140 glVertex3i(x + 1, y, z);
142 glBegin(begin_polygon);
143 glVertex3i(x + 1, y - 1, z);
144 glVertex3i(x + 1, y - 1, z - 1);
145 glVertex3i(x + 2, y - 1, z - 1);
146 glVertex3i(x + 2, y - 1, z);
154 glCallList(si->TopsSides + 1); /* Render the sides */
156 glNormal3f(0.0, 0.0, 1.0);
158 for (h = 0; h < height; ++h) {
162 for (w = 0; w < width; ++w) {
163 glBegin(begin_polygon);
165 glVertex3i(x + 1, y, z);
166 glVertex3i(x + 1, y - 1, z);
167 glVertex3i(x, y - 1, z);
169 glBegin(begin_polygon);
170 glVertex3i(x + 1, y - 1, z);
171 glVertex3i(x + 2, y - 1, z);
172 glVertex3i(x + 2, y - 2, z);
173 glVertex3i(x + 1, y - 2, z);
175 * PURIFY 4.0.1 reports an unitialized memory read on the next line when using
176 * MesaGL 2.2 and -mono. This has been fixed in MesaGL 2.3 and later. */
183 /* Render the other sides */
185 glNormal3f(1.0, 0.0, 0.0);
187 for (h = 0; h < height; ++h) {
191 for (w = 0; w < width; ++w) {
192 glBegin(begin_polygon);
193 glVertex3i(x + 1, y, z);
194 glVertex3i(x + 1, y, z - 1);
195 glVertex3i(x + 1, y - 1, z - 1);
196 glVertex3i(x + 1, y - 1, z);
198 glBegin(begin_polygon);
199 glVertex3i(x + 2, y - 1, z);
200 glVertex3i(x + 2, y - 1, z - 1);
201 glVertex3i(x + 2, y - 2, z - 1);
202 glVertex3i(x + 2, y - 2, z);
211 glCallList(si->TopsSides); /* Render the tops */
213 for (h = 0; h < height; ++h) {
217 for (w = 0; w < width; ++w) {
218 glBegin(begin_polygon);
220 glVertex3i(x, y, z - 1);
221 glVertex3i(x + 1, y, z - 1);
222 glVertex3i(x + 1, y, z);
224 glBegin(begin_polygon);
225 glVertex3i(x + 1, y - 1, z);
226 glVertex3i(x + 1, y - 1, z - 1);
227 glVertex3i(x + 2, y - 1, z - 1);
228 glVertex3i(x + 2, y - 1, z);
237 #define RESET_SPROINGIE (-30 + myrand(28))
240 AdvanceSproingie(int t, sp_instance * si)
242 int g_higher, g_back, t2;
243 struct sPosColor *thisSproingie = &(si->positions[t]);
244 struct sPosColor *S2 = &(si->positions[0]);
246 if (thisSproingie->life > 0) {
247 if ((++(thisSproingie->frame)) > 11) {
248 if (thisSproingie->frame >= BOOM_FRAME) {
249 if ((thisSproingie->r -= 0.08) < 0.0)
250 thisSproingie->r = 0.0;
251 if ((thisSproingie->g -= 0.08) < 0.0)
252 thisSproingie->g = 0.0;
253 if ((thisSproingie->b -= 0.08) < 0.0)
254 thisSproingie->b = 0.0;
255 if ((--(thisSproingie->life)) < 1) {
256 thisSproingie->life = RESET_SPROINGIE;
260 thisSproingie->x += 1;
261 thisSproingie->y -= 2;
262 thisSproingie->z += 1;
263 thisSproingie->frame = 0;
265 for (t2 = 0; t2 < si->maxsproingies; ++t2) {
266 if ((t2 != t) && (thisSproingie->x == S2->x) &&
267 (thisSproingie->y == S2->y) && (thisSproingie->z == S2->z) &&
268 (S2->life > 10) && (S2->frame < 6)) {
270 if (thisSproingie->life > S2->life) {
274 if (thisSproingie->life > 10) {
275 thisSproingie->life = 10;
276 thisSproingie->frame = BOOM_FRAME;
277 if ((thisSproingie->r += 0.5) > 1.0)
278 thisSproingie->r = 1.0;
279 if ((thisSproingie->g += 0.5) > 1.0)
280 thisSproingie->g = 1.0;
281 if ((thisSproingie->b += 0.5) > 1.0)
282 thisSproingie->b = 1.0;
291 if (!((thisSproingie->life == 10) &&
292 (thisSproingie->frame > 0) &&
293 (thisSproingie->frame < BOOM_FRAME))) {
294 if ((--(thisSproingie->life)) < 1) {
295 thisSproingie->life = RESET_SPROINGIE;
296 } else if (thisSproingie->life < 9) {
297 thisSproingie->frame -= 2;
299 } /* else wait here for frame 0 to come about. */
300 } else if (++(thisSproingie->life) >= 0) {
302 g_higher = -3 + myrand(5);
303 g_back = -2 + myrand(5);
305 g_higher = -2 + myrand(3);
306 g_back = -1 + myrand(3);
312 thisSproingie->x = (-g_higher - g_back);
313 thisSproingie->y = (g_higher << 1);
314 thisSproingie->z = (g_back - g_higher);
315 thisSproingie->life = 40 + myrand(200);
316 thisSproingie->frame = -10;
317 thisSproingie->r = (GLfloat) (40 + myrand(200)) / 255.0;
318 thisSproingie->g = (GLfloat) (40 + myrand(200)) / 255.0;
319 thisSproingie->b = (GLfloat) (40 + myrand(200)) / 255.0;
321 for (t2 = 0; t2 < si->maxsproingies; ++t2) {
322 if ((t2 != t) && (thisSproingie->x == S2->x) &&
323 (thisSproingie->y == S2->y) && (thisSproingie->z == S2->z) &&
324 (S2->life > 10) && (S2->frame < 0)) {
325 /* If one is already being born, just wait. */
326 thisSproingie->life = -1;
334 NextSproingie(int screen)
336 sp_instance *si = &si_list[screen];
338 struct sPosColor *thisSproingie = &(si->positions[0]);
340 if (++si->sframe > 11) {
342 for (t = 0; t < si->maxsproingies; ++t) {
343 thisSproingie->x -= 1;
344 thisSproingie->y += 2;
345 thisSproingie->z -= 1;
349 for (t = 0; t < si->maxsproingies; ++t) {
350 AdvanceSproingie(t, si);
353 if (si->target_count < 0) { /* track to current target */
354 if (si->target_rx < si->rotx)
356 else if (si->target_rx > si->rotx)
359 if (si->target_ry < si->roty)
361 else if (si->target_ry > si->roty)
364 ddx = (si->target_dist - si->dist) / 8;
367 else if (si->target_dist < si->dist)
369 else if (si->target_dist > si->dist)
372 if ((si->target_rx == si->rotx) && (si->target_ry == si->roty) &&
373 (si->target_dist == si->dist)) {
374 si->target_count = T_COUNT;
375 if (si->target_dist <= 32)
376 si->target_count >>= 2;
378 } else if (--si->target_count < 0) { /* make up new target */
379 si->target_rx = myrand(100) - 35;
380 si->target_ry = -myrand(90);
381 si->target_dist = 32 << myrand(2); /* could be 32, 64, or 128, (previously or 256) */
383 if (si->target_dist >= si->dist) /* no duplicate distances */
384 si->target_dist <<= 1;
386 /* Otherwise just hang loose for a while here */
395 for (t = 0; t < maxsproingies; ++t) {
396 if (positions[t].life > 0)
399 (void) printf("RotX: %d, RotY: %d, Dist: %d. Targets: X %d, Y %d, D %d. Visible: %d\n",
400 rotx, roty, dist, target_rx, target_ry, target_dist, count);
408 for (t = 0; t < maxsproingies; ++t) {
412 positions[t].life = -2;
413 positions[t].frame = 0;
420 if (dist < (1 << 16 << 4))
434 rotx = (rotx + 5) % 360;
440 rotx = (rotx - 5) % 360;
446 roty = (roty + 5) % 360;
452 roty = (roty - 5) % 360;
458 rotx = (rotx + 45) % 360;
464 rotx = (rotx - 45) % 360;
470 roty = (roty + 45) % 360;
476 roty = (roty - 45) % 360;
482 RenderSproingie(int t, sp_instance * si)
484 GLfloat scale, pointsize, mat_color[4] =
485 {0.0, 0.0, 0.0, 1.0};
486 GLdouble clipplane[4] =
487 {0.0, 1.0, 0.0, 0.0};
488 struct sPosColor *thisSproingie = &(si->positions[t]);
490 if (thisSproingie->life < 1)
496 mat_color[0] = thisSproingie->r;
497 mat_color[1] = thisSproingie->g;
498 mat_color[2] = thisSproingie->b;
500 glColor3fv(mat_color);
502 glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, mat_color);
505 if (thisSproingie->frame < 0) {
506 glEnable(GL_CLIP_PLANE0);
507 glTranslatef((GLfloat) (thisSproingie->x),
508 (GLfloat) (thisSproingie->y) +
509 ((GLfloat) (thisSproingie->frame) / 9.0),
510 (GLfloat) (thisSproingie->z));
511 clipplane[3] = ((GLdouble) (thisSproingie->frame) / 9.0) +
512 (si->wireframe ? 0.0 : 0.1);
513 glClipPlane(GL_CLIP_PLANE0, clipplane);
514 /** glCallList(si->sproingies[0]);*/
515 /**/ renderList(si->sproingies[0]);
516 glDisable(GL_CLIP_PLANE0);
517 } else if (thisSproingie->frame >= BOOM_FRAME) {
518 glTranslatef((GLfloat) (thisSproingie->x) + 0.5,
519 (GLfloat) (thisSproingie->y) + 0.5,
520 (GLfloat) (thisSproingie->z) - 0.5);
521 scale = (GLfloat) (1 << (thisSproingie->frame - BOOM_FRAME));
522 glScalef(scale, scale, scale);
523 if (!si->wireframe) {
525 glColor3fv(mat_color);
526 glDisable(GL_LIGHTING);
528 pointsize = (GLfloat) ((BOOM_FRAME + 8) - thisSproingie->frame) -
530 glPointSize((pointsize < 1.0) ? 1.0 : pointsize);
532 * PURIFY 4.0.1 reports an unitialized memory read on the next line when using
533 * MesaGL 2.2. This has been tracked to MesaGL 2.2 src/points.c line 313. */
534 /** glCallList(si->SproingieBoom);*/
535 /**/ renderList(si->SproingieBoom);
537 if (!si->wireframe) {
538 glEnable(GL_LIGHTING);
540 } else if (thisSproingie->frame > 5) {
541 glTranslatef((GLfloat) (thisSproingie->x + 1),
542 (GLfloat) (thisSproingie->y - 1), (GLfloat) (thisSproingie->z - 1));
543 glRotatef((GLfloat) - 90.0, 0.0, 1.0, 0.0);
544 /** glCallList(si->sproingies[thisSproingie->frame - 6]);*/
545 /**/ renderList(si->sproingies[thisSproingie->frame - 6]);
547 glTranslatef((GLfloat) (thisSproingie->x), (GLfloat) (thisSproingie->y),
548 (GLfloat) (thisSproingie->z));
549 /** glCallList(si->sproingies[thisSproingie->frame]);*/
550 /**/ renderList(si->sproingies[thisSproingie->frame]);
558 ComputeGround(sp_instance * si)
560 int g_higher, g_back, g_width, g_height;
562 /* higher: x-1, y+2, z-1 */
563 /* back: x-1, y, z+1 */
565 if (si->groundlevel == 0) {
568 } else if (si->groundlevel == 1) {
576 if ((g_higher = si->dist >> 3) < 4)
580 g_height = g_higher << 1;
583 g_higher += (g_higher >> 2);
584 else if (si->rotx > 10)
585 g_higher -= (g_higher >> 2);
588 if (si->dist > 128) {
592 } else if (si->dist > 64) {
595 } else if (si->dist > 32) {
596 /* nothing special */
599 g_higher = g_back = 4;
604 /* startx, starty, startz, width, height */
605 LayGround((-g_higher - g_back), (g_higher << 1), (g_back - g_higher),
606 (g_width), (g_height), si);
610 DisplaySproingies(int screen,int pause)
612 sp_instance *si = &si_list[screen];
615 {8.0, 5.0, -2.0, 0.1};
618 glClear(GL_COLOR_BUFFER_BIT);
620 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
623 glTranslatef(0.0, 0.0, -(GLfloat) (si->dist) / 16.0); /* viewing transform */
624 glRotatef((GLfloat) si->rotx, 1.0, 0.0, 0.0);
625 glRotatef((GLfloat) si->roty, 0.0, 1.0, 0.0);
628 glLightfv(GL_LIGHT0, GL_POSITION, position);
630 #if 0 /* Show light pos */
632 glTranslatef(position[0], position[1], position[2]);
633 glColor3f(1.0, 1.0, 1.0);
634 if (!si->wireframe) {
635 glDisable(GL_LIGHTING);
637 glCallList(si->SproingieBoom);
638 if (!si->wireframe) {
639 glEnable(GL_LIGHTING);
644 glTranslatef((GLfloat) si->sframe * (-1.0 / 12.0) - 0.75,
645 (GLfloat) si->sframe * (2.0 / 12.0) - 0.5,
646 (GLfloat) si->sframe * (-1.0 / 12.0) + 0.75);
651 for (t = 0; t < si->maxsproingies; ++t) {
652 RenderSproingie(t, si);
665 NextSproingieDisplay(int screen,int pause)
667 NextSproingie(screen);
668 if (pause) usleep(pause);
669 DisplaySproingies(screen,pause);
673 ReshapeSproingies(int w, int h)
675 glViewport(0, 0, w, h);
676 glMatrixMode(GL_PROJECTION);
678 gluPerspective(65.0, (GLfloat) w / (GLfloat) h, 0.1, 2000.0); /* was 200000.0 */
679 glMatrixMode(GL_MODELVIEW);
684 CleanupSproingies(int screen)
686 sp_instance *si = &si_list[screen];
689 if (si->SproingieBoom) {
690 for (t = 0; t < 6; ++t)
691 glDeleteLists(si->sproingies[t], 1);
693 glDeleteLists(si->TopsSides, 2);
694 glDeleteLists(si->SproingieBoom, 1);
697 si->SproingieBoom = 0;
701 glDeleteLists(si->TopsSides, 2);
704 (void) free((void *) (si->positions));
705 si->positions = NULL;
707 if ((active_screens == 0) && si_list) {
708 (void) free((void *) (si_list));
714 InitSproingies(int wfmode, int grnd, int mspr, int screen, int numscreens,
718 {0.2, 0.2, 0.2, 1.0};
720 {10.0, 1.0, 1.0, 10.0};
721 GLfloat mat_diffuse[] =
722 {0.6, 0.6, 0.6, 1.0};
723 GLfloat mat_specular[] =
724 {0.8, 0.8, 0.8, 1.0};
725 GLfloat mat_shininess[] =
731 if (si_list == NULL) {
732 if ((si_list = (sp_instance *) calloc(numscreens,
733 sizeof (sp_instance))) == NULL)
736 si = &si_list[screen];
739 CleanupSproingies(screen);
743 if (mspr >= MAXSPROING)
744 mspr = MAXSPROING - 1;
748 si->dist = (16 << 2);
750 si->target_count = 0;
753 si->wireframe = si->flatshade = 0;
760 si->groundlevel = grnd;
761 si->maxsproingies = mspr;
763 if (si->maxsproingies) {
764 si->positions = (struct sPosColor *) calloc(si->maxsproingies,
765 sizeof (struct sPosColor));
767 if (!(si->positions))
768 si->maxsproingies = 0;
770 for (t = 0; t < si->maxsproingies; ++t) {
771 si->positions[t].x = 0;
772 si->positions[t].y = 0;
773 si->positions[t].z = 0;
774 si->positions[t].life = (-t * ((si->maxsproingies > 19) ? 1 : 4)) - 2;
775 si->positions[t].frame = 0;
778 #if 0 /* Test boom */
779 si->positions[0].x = 0;
780 si->positions[0].y = 0;
781 si->positions[0].z = 0;
782 si->positions[0].life = 10;
783 si->positions[0].frame = BOOM_FRAME;
784 si->positions[0].r = 0.656863;
785 si->positions[0].g = 1.0;
786 si->positions[0].b = 0.656863;
789 if (!(si->TopsSides = build_TopsSides(si->wireframe)))
790 (void) fprintf(stderr, "build_TopsSides\n");
792 if (!(si->sproingies[0] = BuildLWO(si->wireframe, &LWO_s1_1)))
793 (void) fprintf(stderr, "BuildLWO - 1\n");
794 if (!(si->sproingies[1] = BuildLWO(si->wireframe, &LWO_s1_2)))
795 (void) fprintf(stderr, "BuildLWO - 2\n");
796 if (!(si->sproingies[2] = BuildLWO(si->wireframe, &LWO_s1_3)))
797 (void) fprintf(stderr, "BuildLWO - 3\n");
798 if (!(si->sproingies[3] = BuildLWO(si->wireframe, &LWO_s1_4)))
799 (void) fprintf(stderr, "BuildLWO - 4\n");
800 if (!(si->sproingies[4] = BuildLWO(si->wireframe, &LWO_s1_5)))
801 (void) fprintf(stderr, "BuildLWO - 5\n");
802 if (!(si->sproingies[5] = BuildLWO(si->wireframe, &LWO_s1_6)))
803 (void) fprintf(stderr, "BuildLWO - 6\n");
805 if (!(si->SproingieBoom = BuildLWO(si->wireframe, &LWO_s1_b)))
806 (void) fprintf(stderr, "BuildLWO - b\n");
808 si->sproingies[0]=s1_1;
809 si->sproingies[1]=s1_2;
810 si->sproingies[2]=s1_3;
811 si->sproingies[3]=s1_4;
812 si->sproingies[4]=s1_5;
813 si->sproingies[5]=s1_6;
814 si->SproingieBoom=s1_b;
817 glShadeModel(GL_FLAT);
818 glDisable(GL_LIGHTING);
821 glShadeModel(GL_FLAT);
825 glEnable(GL_LIGHTING);
827 glDepthFunc(GL_LEQUAL);
828 glEnable(GL_DEPTH_TEST);
830 glLightfv(GL_LIGHT0, GL_AMBIENT, ambient);
831 glLightfv(GL_LIGHT0, GL_POSITION, position);
833 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mat_diffuse);
834 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mat_specular);
835 glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, mat_shininess);
837 /* glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE); */
839 glEnable(GL_CULL_FACE);
842 /* glEnable(GL_NORMALIZE); */
848 /* End of sproingies.c */