http://ftp.x.org/contrib/applications/xscreensaver-2.17.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.1 98/05/13 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  * TODO : - use def_xxx options to initialize local variables (number of
38  *          sharks, etc...)
39  *        - test standalone mode
40  *        - better colormap handling (problems somewhere ?)
41  *        - purify it (!)
42  */
43
44 /* Copyright (c) Mark J. Kilgard, 1994. */
45
46 /**
47  * (c) Copyright 1993, 1994, Silicon Graphics, Inc.
48  * ALL RIGHTS RESERVED
49  * Permission to use, copy, modify, and distribute this software for
50  * any purpose and without fee is hereby granted, provided that the above
51  * copyright notice appear in all copies and that both the copyright notice
52  * and this permission notice appear in supporting documentation, and that
53  * the name of Silicon Graphics, Inc. not be used in advertising
54  * or publicity pertaining to distribution of the software without specific,
55  * written prior permission.
56  *
57  * THE MATERIAL EMBODIED ON THIS SOFTWARE IS PROVIDED TO YOU "AS-IS"
58  * AND WITHOUT WARRANTY OF ANY KIND, EXPRESS, IMPLIED OR OTHERWISE,
59  * INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY OR
60  * FITNESS FOR A PARTICULAR PURPOSE.  IN NO EVENT SHALL SILICON
61  * GRAPHICS, INC.  BE LIABLE TO YOU OR ANYONE ELSE FOR ANY DIRECT,
62  * SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY
63  * KIND, OR ANY DAMAGES WHATSOEVER, INCLUDING WITHOUT LIMITATION,
64  * LOSS OF PROFIT, LOSS OF USE, SAVINGS OR REVENUE, OR THE CLAIMS OF
65  * THIRD PARTIES, WHETHER OR NOT SILICON GRAPHICS, INC.  HAS BEEN
66  * ADVISED OF THE POSSIBILITY OF SUCH LOSS, HOWEVER CAUSED AND ON
67  * ANY THEORY OF LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE
68  * POSSESSION, USE OR PERFORMANCE OF THIS SOFTWARE.
69  *
70  * US Government Users Restricted Rights
71  * Use, duplication, or disclosure by the Government is subject to
72  * restrictions set forth in FAR 52.227.19(c)(2) or subparagraph
73  * (c)(1)(ii) of the Rights in Technical Data and Computer Software
74  * clause at DFARS 252.227-7013 and/or in similar or successor
75  * clauses in the FAR or the DOD or NASA FAR Supplement.
76  * Unpublished-- rights reserved under the copyright laws of the
77  * United States.  Contractor/manufacturer is Silicon Graphics,
78  * Inc., 2011 N.  Shoreline Blvd., Mountain View, CA 94039-7311.
79  *
80  * OpenGL(TM) is a trademark of Silicon Graphics, Inc.
81  */
82
83 #ifdef STANDALONE
84 # define PROGCLASS      "Atlantis"
85 # define HACK_INIT      init_atlantis
86 # define HACK_DRAW      draw_atlantis
87 # define atlantis_opts  xlockmore_opts
88 # define DEFAULTS       "*delay:        1000 \n"
89 # include "xlockmore.h"         /* from the xscreensaver distribution */
90 #else  /* !STANDALONE */
91 # include "xlock.h"             /* from the xlockmore distribution */
92
93 #endif /* !STANDALONE */
94
95 #ifdef USE_GL
96
97 #include <stdio.h>
98 #include <stdlib.h>
99 #include <string.h>
100 #include <math.h>
101 #include "atlantis.h"
102 #include <GL/glu.h>
103
104
105 ModeSpecOpt atlantis_opts =
106 {0, NULL, 0, NULL, NULL};
107
108 #ifdef USE_MODULES
109 ModStruct   atlantis_description =
110 {"atlantis", "init_atlantis", "draw_atlantis", "release_atlantis",
111  "refresh_atlantis", "change_atlantis", NULL, &atlantis_opts,
112  1000, 2, 5, 500, 64, 1.0, "",
113  "Shows moving sharks/whales/dolphin", 0, NULL};
114
115 #endif
116
117 static atlantisstruct *atlantis = NULL;
118
119 static void
120 InitFishs(atlantisstruct *ap)
121 {
122     int i;
123
124     for (i = 0; i < NUM_SHARKS; i++) {
125         ap->sharks[i].x = 70000.0 + NRAND(6000);
126         ap->sharks[i].y = NRAND(6000);
127         ap->sharks[i].z = NRAND(6000);
128         ap->sharks[i].psi = NRAND(360) - 180.0;
129         ap->sharks[i].v = 1.0;
130     }
131
132                 /* i = LRAND() & 1; */ /* Works the first time but they do not return */
133     ap->dolph.x = 30000.0;
134     ap->dolph.y = 0.0;
135     ap->dolph.z = 6000.0;
136     ap->dolph.psi = /* (i) ? 90.0 : - */ 90.0;
137     ap->dolph.theta = 0.0;
138     ap->dolph.v = 3.0;
139
140     ap->momWhale.x = 70000.0;
141     ap->momWhale.y = 0.0;
142     ap->momWhale.z = 0.0;
143     ap->momWhale.psi = /* (i) ? 90.0 : - */ 90.0;
144     ap->momWhale.theta = 0.0;
145     ap->momWhale.v = 3.0;
146
147     ap->babyWhale.x = 60000.0;
148     ap->babyWhale.y = -2000.0;
149     ap->babyWhale.z = -2000.0;
150     ap->babyWhale.psi = /* (i) ? 90.0 : - */ 90.0;
151     ap->babyWhale.theta = 0.0;
152     ap->babyWhale.v = 3.0;
153 }
154
155 static void
156 Init(atlantisstruct *ap)
157 {
158     static float ambient[] =
159     {0.1, 0.1, 0.1, 1.0};
160     static float diffuse[] =
161     {1.0, 1.0, 1.0, 1.0};
162     static float position[] =
163     {0.0, 1.0, 0.0, 0.0};
164     static float mat_shininess[] =
165     {90.0};
166     static float mat_specular[] =
167     {0.8, 0.8, 0.8, 1.0};
168     static float mat_diffuse[] =
169     {0.46, 0.66, 0.795, 1.0};
170     static float mat_ambient[] =
171     {0.0, 0.1, 0.2, 1.0};
172     static float lmodel_ambient[] =
173     {0.4, 0.4, 0.4, 1.0};
174     static float lmodel_localviewer[] =
175     {0.0};
176 #if 0
177     GLfloat map1[4] =
178     {0.0, 0.0, 0.0, 0.0};
179     GLfloat map2[4] =
180     {0.0, 0.0, 0.0, 0.0};
181 #endif
182
183     glFrontFace(GL_CW);
184
185     glDepthFunc(GL_LEQUAL);
186     glEnable(GL_DEPTH_TEST);
187
188     glLightfv(GL_LIGHT0, GL_AMBIENT, ambient);
189     glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse);
190     glLightfv(GL_LIGHT0, GL_POSITION, position);
191     glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient);
192     glLightModelfv(GL_LIGHT_MODEL_LOCAL_VIEWER, lmodel_localviewer);
193     glEnable(GL_LIGHTING);
194     glEnable(GL_LIGHT0);
195
196     glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, mat_shininess);
197     glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mat_specular);
198     glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mat_diffuse);
199     glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, mat_ambient);
200
201     InitFishs(ap);
202
203     glClearColor(0.0, 0.5, 0.9, 0.0);
204 }
205
206 static void
207 Reshape(ModeInfo *mi,int width, int height)
208 {
209     atlantisstruct *ap = &atlantis[MI_SCREEN(mi)];
210
211     glViewport(0, 0, ap->WinW= (GLint) width, ap->WinH= (GLint) height);
212
213     glMatrixMode(GL_PROJECTION);
214     glLoadIdentity();
215     gluPerspective(400.0, (GLdouble)width/(GLdouble)height, 1.0, 2000000.0);
216     glMatrixMode(GL_MODELVIEW);
217 }
218
219 static void
220 Animate(atlantisstruct *ap)
221 {
222     int i;
223
224     for (i = 0; i < NUM_SHARKS; i++) {
225         SharkPilot(&(ap->sharks[i]));
226         SharkMiss(ap,i);
227     }
228     WhalePilot(&(ap->dolph));
229     ap->dolph.phi++;
230     WhalePilot(&(ap->momWhale));
231     ap->momWhale.phi++;
232     WhalePilot(&(ap->babyWhale));
233     ap->babyWhale.phi++;
234 }
235
236 static void
237 AllDisplay(atlantisstruct *ap)
238 {
239     int i;
240
241     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
242
243     for (i = 0; i < NUM_SHARKS; i++) {
244         glPushMatrix();
245         FishTransform(&(ap->sharks[i]));
246         DrawShark(&(ap->sharks[i]));
247         glPopMatrix();
248     }
249
250     glPushMatrix();
251     FishTransform(&(ap->dolph));
252     DrawDolphin(&(ap->dolph));
253     glPopMatrix();
254
255     glPushMatrix();
256     FishTransform(&(ap->momWhale));
257     DrawWhale(&(ap->momWhale));
258     glPopMatrix();
259
260     glPushMatrix();
261     FishTransform(&(ap->babyWhale));
262     glScalef(0.45, 0.45, 0.3);
263     DrawWhale(&(ap->babyWhale));
264     glPopMatrix();
265 }
266
267 /*
268  *-----------------------------------------------------------------------------
269  *-----------------------------------------------------------------------------
270  *    Xlock hooks.
271  *-----------------------------------------------------------------------------
272  *-----------------------------------------------------------------------------
273  */
274
275 /*
276  *-----------------------------------------------------------------------------
277  *    Initialize atlantis.  Called each time the window changes.
278  *-----------------------------------------------------------------------------
279  */
280
281 void
282 init_atlantis(ModeInfo * mi)
283 {
284         int         screen = MI_SCREEN(mi);
285         atlantisstruct *ap;
286         Display    *display = MI_DISPLAY(mi);
287         Window      window = MI_WINDOW(mi);
288
289         if (atlantis == NULL) {
290                 if ((atlantis = (atlantisstruct *) calloc(MI_NUM_SCREENS(mi),
291                                                sizeof (atlantisstruct))) == NULL)
292                         return;
293         }
294         ap = &atlantis[screen];
295
296         if ((ap->glx_context = init_GL(mi)) != NULL) {
297
298                 Reshape(mi, MI_WIDTH(mi), MI_HEIGHT(mi));
299                 glDrawBuffer(GL_BACK);
300                 Init(ap);
301                 AllDisplay(ap);
302                 glXSwapBuffers(display, window);
303
304         } else {
305                 MI_CLEARWINDOW(mi);
306         }
307 }
308
309 /*
310  *-----------------------------------------------------------------------------
311  *    Called by the mainline code periodically to update the display.
312  *-----------------------------------------------------------------------------
313  */
314 void
315 draw_atlantis(ModeInfo * mi)
316 {
317         atlantisstruct *ap = &atlantis[MI_SCREEN(mi)];
318
319         Display    *display = MI_DISPLAY(mi);
320         Window      window = MI_WINDOW(mi);
321
322         if (!ap->glx_context)
323                 return;
324
325         glXMakeCurrent(display, window, *(ap->glx_context));
326
327         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
328
329         glPushMatrix();
330
331         AllDisplay(ap);
332         Animate(ap);
333
334         glXSwapBuffers(display, window);
335 }
336
337
338 /*
339  *-----------------------------------------------------------------------------
340  *    The display is being taken away from us.  Free up malloc'ed 
341  *      memory and X resources that we've alloc'ed.  Only called
342  *      once, we must zap everything for every screen.
343  *-----------------------------------------------------------------------------
344  */
345
346 void
347 release_atlantis(ModeInfo * mi)
348 {
349         if (atlantis != NULL) {
350                 (void) free((void *) atlantis);
351                 atlantis = NULL;
352         }
353         FreeAllGL(mi);
354 }
355
356 /*
357  *-----------------------------------------------------------------------------
358  *    Called when the mainline xlock code notices possible window
359  *      damage.  This hook should take steps to repaint the entire
360  *      window (no specific damage area information is provided).
361  *-----------------------------------------------------------------------------
362  */
363
364 void
365 refresh_atlantis(ModeInfo * mi)
366 {
367     MI_CLEARWINDOW(mi);
368     Reshape(mi, MI_WIDTH(mi), MI_HEIGHT(mi));
369 }
370
371 void
372 change_atlantis(ModeInfo * mi)
373 {
374         atlantisstruct *ap = &atlantis[MI_SCREEN(mi)];
375
376         if (!ap->glx_context)
377                 return;
378
379         glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(ap->glx_context));
380         Init(ap);
381 }
382
383 #endif  /* USE_GL */