http://packetstormsecurity.org/UNIX/admin/xscreensaver-3.29.tar.gz
[xscreensaver] / hacks / glx / atlantis.c
1 /* atlantis --- Shows moving 3D sea animals */
2
3 #if !defined( lint ) && !defined( SABER )
4 static const char sccsid[] = "@(#)atlantis.c    1.3 98/06/18 xlockmore";
5
6 #endif
7
8 /* Copyright (c) E. Lassauge, 1998. */
9
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  * The original code for this mode was written by Mark J. Kilgard
24  * as a demo for openGL programming.
25  * 
26  * Porting it to xlock  was possible by comparing the original Mesa's morph3d 
27  * demo with it's ported version to xlock, so thanks for Marcelo F. Vianna 
28  * (look at morph3d.c) for his indirect help.
29  *
30  * Thanks goes also to Brian Paul for making it possible and inexpensive
31  * to use OpenGL at home.
32  *
33  * My e-mail address is lassauge@sagem.fr
34  *
35  * Eric Lassauge  (May-13-1998)
36  *
37  * REVISION HISTORY:
38  * 
39  * David A. Bagley - 98/06/17 : Add whalespeed option. Global options to
40  *                              initialize local variables are now:
41  *                              XLock.atlantis.cycles: 100      ! SharkSpeed
42  *                              XLock.atlantis.batchcount: 4    ! SharkNum
43  *                              XLock.atlantis.whalespeed: 250  ! WhaleSpeed
44  *                              XLock.atlantis.size: 6000       ! SharkSize
45  *                              Add random direction for whales/dolphins
46  * 
47  * E.Lassauge - 98/06/16: Use the following global options to initialize
48  *                        local variables :
49  *                              XLock.atlantis.delay: 100       ! SharkSpeed
50  *                              XLock.atlantis.batchcount: 4    ! SharkNum
51  *                              XLock.atlantis.cycles: 250      ! WhaleSpeed
52  *                              XLock.atlantis.size: 6000       ! SharkSize
53  *                        Add support for -/+ wireframe (t'was so easy to do!)
54  *
55  * TODO : 
56  *        - add a sort of background image or random bg color
57  *        - better handling of sizes and speeds
58  *        - test standalone and module modes
59  *        - purify it (!)
60  */
61
62 /* Copyright (c) Mark J. Kilgard, 1994. */
63
64 /**
65  * (c) Copyright 1993, 1994, Silicon Graphics, Inc.
66  * ALL RIGHTS RESERVED
67  * Permission to use, copy, modify, and distribute this software for
68  * any purpose and without fee is hereby granted, provided that the above
69  * copyright notice appear in all copies and that both the copyright notice
70  * and this permission notice appear in supporting documentation, and that
71  * the name of Silicon Graphics, Inc. not be used in advertising
72  * or publicity pertaining to distribution of the software without specific,
73  * written prior permission.
74  *
75  * THE MATERIAL EMBODIED ON THIS SOFTWARE IS PROVIDED TO YOU "AS-IS"
76  * AND WITHOUT WARRANTY OF ANY KIND, EXPRESS, IMPLIED OR OTHERWISE,
77  * INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY OR
78  * FITNESS FOR A PARTICULAR PURPOSE.  IN NO EVENT SHALL SILICON
79  * GRAPHICS, INC.  BE LIABLE TO YOU OR ANYONE ELSE FOR ANY DIRECT,
80  * SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY
81  * KIND, OR ANY DAMAGES WHATSOEVER, INCLUDING WITHOUT LIMITATION,
82  * LOSS OF PROFIT, LOSS OF USE, SAVINGS OR REVENUE, OR THE CLAIMS OF
83  * THIRD PARTIES, WHETHER OR NOT SILICON GRAPHICS, INC.  HAS BEEN
84  * ADVISED OF THE POSSIBILITY OF SUCH LOSS, HOWEVER CAUSED AND ON
85  * ANY THEORY OF LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE
86  * POSSESSION, USE OR PERFORMANCE OF THIS SOFTWARE.
87  *
88  * US Government Users Restricted Rights
89  * Use, duplication, or disclosure by the Government is subject to
90  * restrictions set forth in FAR 52.227.19(c)(2) or subparagraph
91  * (c)(1)(ii) of the Rights in Technical Data and Computer Software
92  * clause at DFARS 252.227-7013 and/or in similar or successor
93  * clauses in the FAR or the DOD or NASA FAR Supplement.
94  * Unpublished-- rights reserved under the copyright laws of the
95  * United States.  Contractor/manufacturer is Silicon Graphics,
96  * Inc., 2011 N.  Shoreline Blvd., Mountain View, CA 94039-7311.
97  *
98  * OpenGL(TM) is a trademark of Silicon Graphics, Inc.
99  */
100
101 #ifdef STANDALONE
102 # define PROGCLASS      "Atlantis"
103 # define HACK_INIT      init_atlantis
104 # define HACK_DRAW      draw_atlantis
105 # define HACK_RESHAPE   reshape_atlantis
106 # define atlantis_opts  xlockmore_opts
107 # define DEFAULTS       "*delay:       40000 \n" \
108                          "*count:          4 \n" \
109                          "*showFPS:    False \n" \
110                          "*cycles:       100 \n" \
111                          "*size:        6000 \n" \
112                          "*whalespeed:   250 \n"
113 # include "xlockmore.h"         /* from the xscreensaver distribution */
114 #else  /* !STANDALONE */
115 # include "xlock.h"             /* from the xlockmore distribution */
116 #include "vis.h"
117 #endif /* !STANDALONE */
118
119 #ifdef USE_GL
120
121 #include "atlantis.h"
122 #include <GL/glu.h>
123
124
125 #define DEF_WHALESPEED  "250"
126 static int  whalespeed;
127 static XrmOptionDescRec opts[] =
128 {
129      {"-whalespeed", ".atlantis.whalespeed", XrmoptionSepArg, (caddr_t) NULL}
130 };
131
132 static argtype vars[] =
133 {
134 {(caddr_t *) & whalespeed, "whalespeed", "WhaleSpeed", DEF_WHALESPEED, t_Int}
135 };
136
137 static OptionStruct desc[] =
138 {
139         {"-whalespeed num", "speed of whales and the dolphin"}
140 };
141
142 ModeSpecOpt atlantis_opts =
143 {sizeof opts / sizeof opts[0], opts, sizeof vars / sizeof vars[0], vars, desc};
144
145 #ifdef USE_MODULES
146 ModStruct   atlantis_description =
147 {"atlantis", "init_atlantis", "draw_atlantis", "release_atlantis",
148  "refresh_atlantis", "change_atlantis", NULL, &atlantis_opts,
149  1000, NUM_SHARKS, SHARKSPEED, SHARKSIZE, 64, 1.0, "",
150  "Shows moving sharks/whales/dolphin", 0, NULL};
151
152 #endif
153
154 static atlantisstruct *atlantis = NULL;
155
156 static void
157 InitFishs(atlantisstruct * ap)
158 {
159         int         i;
160
161         for (i = 0; i < ap->num_sharks; i++) {
162                 ap->sharks[i].x = 70000.0 + NRAND(ap->sharksize);
163                 ap->sharks[i].y = NRAND(ap->sharksize);
164                 ap->sharks[i].z = NRAND(ap->sharksize);
165                 ap->sharks[i].psi = NRAND(360) - 180.0;
166                 ap->sharks[i].v = 1.0;
167         }
168
169         /* Random whae direction */
170         ap->whaledir = LRAND() & 1;
171
172         ap->dolph.x = 30000.0;
173         ap->dolph.y = 0.0;
174         ap->dolph.z = (float) (ap->sharksize);
175         ap->dolph.psi = (ap->whaledir) ? 90.0 : -90.0;
176         ap->dolph.theta = 0.0;
177         ap->dolph.v = 6.0;
178
179         ap->momWhale.x = 70000.0;
180         ap->momWhale.y = 0.0;
181         ap->momWhale.z = 0.0;
182         ap->momWhale.psi = (ap->whaledir) ? 90.0 : -90.0;
183         ap->momWhale.theta = 0.0;
184         ap->momWhale.v = 3.0;
185
186         ap->babyWhale.x = 60000.0;
187         ap->babyWhale.y = -2000.0;
188         ap->babyWhale.z = -2000.0;
189         ap->babyWhale.psi = (ap->whaledir) ? 90.0 : -90.0;
190         ap->babyWhale.theta = 0.0;
191         ap->babyWhale.v = 3.0;
192 }
193
194 static void
195 Init(atlantisstruct * ap)
196 {
197         static float ambient[] =
198         {0.1, 0.1, 0.1, 1.0};
199         static float diffuse[] =
200         {1.0, 1.0, 1.0, 1.0};
201         static float position[] =
202         {0.0, 1.0, 0.0, 0.0};
203         static float mat_shininess[] =
204         {90.0};
205         static float mat_specular[] =
206         {0.8, 0.8, 0.8, 1.0};
207         static float mat_diffuse[] =
208         {0.46, 0.66, 0.795, 1.0};
209         static float mat_ambient[] =
210         {0.0, 0.1, 0.2, 1.0};
211         static float lmodel_ambient[] =
212         {0.4, 0.4, 0.4, 1.0};
213         static float lmodel_localviewer[] =
214         {0.0};
215         float       fblue = 0.0, fgreen;
216
217         glFrontFace(GL_CW);
218
219         glDepthFunc(GL_LEQUAL);
220         glEnable(GL_DEPTH_TEST);
221
222         glLightfv(GL_LIGHT0, GL_AMBIENT, ambient);
223         glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse);
224         glLightfv(GL_LIGHT0, GL_POSITION, position);
225         glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient);
226         glLightModelfv(GL_LIGHT_MODEL_LOCAL_VIEWER, lmodel_localviewer);
227         glEnable(GL_LIGHTING);
228         glEnable(GL_LIGHT0);
229
230         glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, mat_shininess);
231         glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mat_specular);
232         glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mat_diffuse);
233         glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, mat_ambient);
234
235         InitFishs(ap);
236
237         /* Add a little randomness */
238         fblue = ((float) (NRAND(50)) / 100.0) + 0.50;
239         fgreen = fblue * 0.56;
240         glClearColor(0.0, fgreen, fblue, 0.0);
241 }
242
243 void
244 reshape_atlantis(ModeInfo * mi, int width, int height)
245 {
246         atlantisstruct *ap = &atlantis[MI_SCREEN(mi)];
247
248         glViewport(0, 0, ap->WinW = (GLint) width, ap->WinH = (GLint) height);
249
250         glMatrixMode(GL_PROJECTION);
251         glLoadIdentity();
252         gluPerspective(400.0, (GLdouble) width / (GLdouble) height, 1.0, 2000000.0);
253         glMatrixMode(GL_MODELVIEW);
254 }
255
256 static void
257 Animate(atlantisstruct * ap)
258 {
259         int         i;
260
261         for (i = 0; i < ap->num_sharks; i++) {
262                 SharkPilot(&(ap->sharks[i]), ap->sharkspeed);
263                 SharkMiss(ap, i);
264         }
265         WhalePilot(&(ap->dolph), ap->whalespeed, ap->whaledir);
266         ap->dolph.phi++;
267         WhalePilot(&(ap->momWhale), ap->whalespeed, ap->whaledir);
268         ap->momWhale.phi++;
269         WhalePilot(&(ap->babyWhale), ap->whalespeed, ap->whaledir);
270         ap->babyWhale.phi++;
271 }
272
273 static void
274 AllDisplay(atlantisstruct * ap)
275 {
276         int         i;
277
278         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
279
280         for (i = 0; i < ap->num_sharks; i++) {
281                 glPushMatrix();
282                 FishTransform(&(ap->sharks[i]));
283                 DrawShark(&(ap->sharks[i]), ap->wire);
284                 glPopMatrix();
285         }
286
287         glPushMatrix();
288         FishTransform(&(ap->dolph));
289         DrawDolphin(&(ap->dolph), ap->wire);
290         glPopMatrix();
291
292         glPushMatrix();
293         FishTransform(&(ap->momWhale));
294         DrawWhale(&(ap->momWhale), ap->wire);
295         glPopMatrix();
296
297         glPushMatrix();
298         FishTransform(&(ap->babyWhale));
299         glScalef(0.45, 0.45, 0.3);
300         DrawWhale(&(ap->babyWhale), ap->wire);
301         glPopMatrix();
302 }
303
304 /*
305  *-----------------------------------------------------------------------------
306  *-----------------------------------------------------------------------------
307  *    Xlock hooks.
308  *-----------------------------------------------------------------------------
309  *-----------------------------------------------------------------------------
310  */
311
312 /*
313  *-----------------------------------------------------------------------------
314  *    Initialize atlantis.  Called each time the window changes.
315  *-----------------------------------------------------------------------------
316  */
317
318 void
319 init_atlantis(ModeInfo * mi)
320 {
321         int         screen = MI_SCREEN(mi);
322         atlantisstruct *ap;
323         Display    *display = MI_DISPLAY(mi);
324         Window      window = MI_WINDOW(mi);
325
326         if (atlantis == NULL) {
327                 if ((atlantis = (atlantisstruct *) calloc(MI_NUM_SCREENS(mi),
328                                            sizeof (atlantisstruct))) == NULL)
329                         return;
330         }
331         ap = &atlantis[screen];
332         ap->num_sharks = MI_COUNT(mi);
333         if (ap->sharks == NULL) {
334                 if ((ap->sharks = (fishRec *) calloc(ap->num_sharks,
335                                                 sizeof (fishRec))) == NULL) {
336                         /* free everything up to now */
337                         (void) free((void *) atlantis);
338                         atlantis = NULL;
339                         return;
340                 }
341         }
342         ap->sharkspeed = MI_CYCLES(mi);         /* has influence on the "width"
343                                                    of the movement */
344         ap->sharksize = MI_SIZE(mi);    /* has influence on the "distance"
345                                            of the sharks */
346         ap->whalespeed = whalespeed;
347         ap->wire = MI_IS_WIREFRAME(mi);
348
349         if (MI_IS_DEBUG(mi)) {
350                 (void) fprintf(stderr,
351                                "%s:\n\tnum_sharks=%d\n\tsharkspeed=%.1f\n\tsharksize=%d\n\twhalespeed=%.1f\n\twireframe=%s\n",
352                                MI_NAME(mi),
353                                ap->num_sharks,
354                                ap->sharkspeed,
355                                ap->sharksize,
356                                ap->whalespeed,
357                                ap->wire ? "yes" : "no"
358                         );
359         }
360         if ((ap->glx_context = init_GL(mi)) != NULL) {
361
362                 reshape_atlantis(mi, MI_WIDTH(mi), MI_HEIGHT(mi));
363                 glDrawBuffer(GL_BACK);
364                 Init(ap);
365                 AllDisplay(ap);
366                 glXSwapBuffers(display, window);
367
368         } else {
369                 MI_CLEARWINDOW(mi);
370         }
371 }
372
373 /*
374  *-----------------------------------------------------------------------------
375  *    Called by the mainline code periodically to update the display.
376  *-----------------------------------------------------------------------------
377  */
378 void
379 draw_atlantis(ModeInfo * mi)
380 {
381         atlantisstruct *ap = &atlantis[MI_SCREEN(mi)];
382
383         Display    *display = MI_DISPLAY(mi);
384         Window      window = MI_WINDOW(mi);
385
386         MI_IS_DRAWN(mi) = True;
387
388         if (!ap->glx_context)
389                 return;
390
391         glXMakeCurrent(display, window, *(ap->glx_context));
392
393         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
394
395         glPushMatrix();
396
397         AllDisplay(ap);
398         Animate(ap);
399
400         glPopMatrix();
401
402         if (mi->fps_p) do_fps (mi);
403         glXSwapBuffers(display, window);
404 }
405
406
407 /*
408  *-----------------------------------------------------------------------------
409  *    The display is being taken away from us.  Free up malloc'ed 
410  *      memory and X resources that we've alloc'ed.  Only called
411  *      once, we must zap everything for every screen.
412  *-----------------------------------------------------------------------------
413  */
414
415 void
416 release_atlantis(ModeInfo * mi)
417 {
418         int         screen;
419
420         if (atlantis != NULL) {
421                 for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++) {
422                         atlantisstruct *ap = &atlantis[screen];
423
424                         if (ap->sharks)
425                                 (void) free((void *) ap->sharks);
426                 }
427                 (void) free((void *) atlantis);
428                 atlantis = NULL;
429         }
430         FreeAllGL(mi);
431 }
432
433 void
434 refresh_atlantis(ModeInfo * mi)
435 {
436 }
437
438 void
439 change_atlantis(ModeInfo * mi)
440 {
441         atlantisstruct *ap = &atlantis[MI_SCREEN(mi)];
442
443         if (!ap->glx_context)
444                 return;
445
446         glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(ap->glx_context));
447         Init(ap);
448 }
449
450 #endif /* USE_GL */