ftp://netsw.org/x11/tools/desktop/xscreensaver-4.07.tar.gz
[xscreensaver] / hacks / glx / sproingiewrap.c
1 /* -*- Mode: C; tab-width: 4 -*- */
2 /* sproingiewrap.c - sproingies wrapper */
3
4 #if !defined( lint ) && !defined( SABER )
5 static const char sccsid[] = "@(#)sproingiewrap.c       4.07 97/11/24 xlockmore";
6
7 #endif
8
9 /*-
10  * sproingiewrap.c - Copyright 1996 Sproingie Technologies Incorporated.
11  *
12  * Permission to use, copy, modify, and distribute this software and its
13  * documentation for any purpose and without fee is hereby granted,
14  * provided that the above copyright notice appear in all copies and that
15  * both that copyright notice and this permission notice appear in
16  * supporting documentation.
17  *
18  * This file is provided AS IS with no warranties of any kind.  The author
19  * shall have no liability with respect to the infringement of copyrights,
20  * trade secrets or any patents by this file or any part thereof.  In no
21  * event will the author be liable for any lost revenue or profits or
22  * other special, indirect and consequential damages.
23  *
24  *    Programming:  Ed Mackey, http://www.netaxs.com/~emackey/
25  *                  Gordon Wrigley, gdw33@student.canterbury.ac.nz
26  *    Sproingie 3D objects modeled by:  Al Mackey, al@iam.com
27  *       (using MetaNURBS in NewTek's Lightwave 3D v5).
28  *
29  * Revision History:
30  * 13-Dec-02: Changed triangle normals into vertex normals to give a smooth
31                 apperance and moved the sproingies from Display Lists to 
32                                 Vertex Arrays, still need to do this for the TopsSides.
33                 (gordon)
34  * 26-Apr-97: Added glPointSize() calls around explosions, plus other fixes.
35  * 28-Mar-97: Added size support.
36  * 22-Mar-97: Updated to use glX interface instead of xmesa one.
37  *              Also, support for multiscreens added.
38  * 20-Mar-97: Updated for xlockmore v4.02alpha7 and higher, using
39  *              xlockmore's built-in Mesa/OpenGL support instead of
40  *              my own.  Submitted for inclusion in xlockmore.
41  * 09-Dec-96: Written.
42  */
43
44 /*-
45  * The sproingies have six "real" frames, (s1_1 to s1_6) that show a
46  * sproingie jumping off a block, headed down and to the right.  But
47  * the program thinks of sproingies as having twelve "virtual" frames,
48  * with the latter six being copies of the first, only lowered and
49  * rotated by 90 degrees (jumping to the left).  So after going
50  * through 12 frames, a sproingie has gone down two rows but not
51  * moved horizontally. 
52  *
53  * To have the sproingies randomly choose left/right jumps at each
54  * block, the program should go back to thinking of only 6 frames,
55  * and jumping down only one row when it is done.  Then it can pick a
56  * direction for the next row.
57  *
58  * (Falling off the end might not be so bad either.  :) )  
59  */
60
61 #ifdef STANDALONE
62 # define PROGCLASS                                      "Sproingies"
63 # define HACK_INIT                                      init_sproingies
64 # define HACK_DRAW                                      draw_sproingies
65 # define HACK_RESHAPE                           reshape_sproingies
66 # define sproingies_opts                        xlockmore_opts
67 # define DEFAULTS       "*delay:                25000   \n"                     \
68                                         "*count:                5       \n"                     \
69                                         "*cycles:               0       \n"                     \
70                                         "*size:                 0       \n"                     \
71                                         "*showFPS:      False   \n"                     \
72                                         "*fpsTop:       True    \n"                     \
73                                         "*wireframe:    False   \n"
74 # include "xlockmore.h"                         /* from the xscreensaver distribution */
75 #else  /* !STANDALONE */
76 # include "xlock.h"                                     /* from the xlockmore distribution */
77 #endif /* !STANDALONE */
78
79 #ifdef USE_GL
80
81 ModeSpecOpt sproingies_opts =
82 {0, NULL, 0, NULL, NULL};
83
84 #ifdef USE_MODULES
85 ModStruct   sproingies_description =
86 {"sproingies", "init_sproingies", "draw_sproingies", "release_sproingies",
87  "refresh_sproingies", "init_sproingies", NULL, &sproingies_opts,
88  1000, 5, 0, 400, 4, 1.0, "",
89  "Shows Sproingies!  Nontoxic.  Safe for pets and small children", 0, NULL};
90
91 #endif
92
93 #define MINSIZE 32
94
95 #include <GL/glu.h>
96 #include <time.h>
97
98 void        NextSproingie(int screen);
99 void        NextSproingieDisplay(int screen,int pause);
100 void        DisplaySproingies(int screen,int pause);
101 void        ReshapeSproingies(int w, int h);
102 void        CleanupSproingies(int screen);
103 void        InitSproingies(int wfmode, int grnd, int mspr, int screen, int numscreens, int mono);
104
105 typedef struct {
106         GLfloat     view_rotx, view_roty, view_rotz;
107         GLint       gear1, gear2, gear3;
108         GLfloat     angle;
109         GLuint      limit;
110         GLuint      count;
111         GLXContext *glx_context;
112         int         mono;
113         Window      window;
114 } sproingiesstruct;
115
116 static sproingiesstruct *sproingies = NULL;
117
118 static Display *swap_display;
119 static Window swap_window;
120
121 static ModeInfo *global_mi_kludge;
122
123 void
124 SproingieSwap(void)
125 {
126     ModeInfo *mi = global_mi_kludge;
127     if (mi->fps_p) do_fps (mi);
128         glFinish();
129         glXSwapBuffers(swap_display, swap_window);
130 }
131
132
133 void
134 init_sproingies(ModeInfo * mi)
135 {
136         Display    *display = MI_DISPLAY(mi);
137         Window      window = MI_WINDOW(mi);
138         int         screen = MI_SCREEN(mi);
139
140         int         cycles = MI_CYCLES(mi);
141         int         count = MI_COUNT(mi);
142         int         size = MI_SIZE(mi);
143
144         sproingiesstruct *sp;
145         int         wfmode = 0, grnd, mspr, w, h;
146
147     global_mi_kludge = mi;
148
149         if (sproingies == NULL) {
150                 if ((sproingies = (sproingiesstruct *) calloc(MI_NUM_SCREENS(mi),
151                                          sizeof (sproingiesstruct))) == NULL)
152                         return;
153         }
154         sp = &sproingies[screen];
155
156         sp->mono = (MI_IS_MONO(mi) ? 1 : 0);
157         sp->window = window;
158         if ((sp->glx_context = init_GL(mi)) != NULL) {
159
160                 if ((cycles & 1) || MI_IS_WIREFRAME(mi))
161                         wfmode = 1;
162                 grnd = (cycles >> 1);
163                 if (grnd > 2)
164                         grnd = 2;
165
166                 mspr = count;
167                 if (mspr > 100)
168                         mspr = 100;
169
170                 /* wireframe, ground, maxsproingies */
171                 InitSproingies(wfmode, grnd, mspr, MI_SCREEN(mi), MI_NUM_SCREENS(mi), sp->mono);
172
173                 /* Viewport is specified size if size >= MINSIZE && size < screensize */
174                 if (size == 0) {
175                         w = MI_WIDTH(mi);
176                         h = MI_HEIGHT(mi);
177                 } else if (size < MINSIZE) {
178                         w = MINSIZE;
179                         h = MINSIZE;
180                 } else {
181                         w = (size > MI_WIDTH(mi)) ? MI_WIDTH(mi) : size;
182                         h = (size > MI_HEIGHT(mi)) ? MI_HEIGHT(mi) : size;
183                 }
184
185                 glViewport((MI_WIDTH(mi) - w) / 2, (MI_HEIGHT(mi) - h) / 2, w, h);
186                 glMatrixMode(GL_PROJECTION);
187                 glLoadIdentity();
188                 gluPerspective(65.0, (GLfloat) w / (GLfloat) h, 0.1, 2000.0);   /* was 200000.0 */
189                 glMatrixMode(GL_MODELVIEW);
190                 glLoadIdentity();
191
192                 swap_display = display;
193                 swap_window = window;
194                 DisplaySproingies(MI_SCREEN(mi),mi->pause);
195         } else {
196                 MI_CLEARWINDOW(mi);
197         }
198 }
199
200 /* ARGSUSED */
201 void
202 draw_sproingies(ModeInfo * mi)
203 {
204         sproingiesstruct *sp = &sproingies[MI_SCREEN(mi)];
205         Display    *display = MI_DISPLAY(mi);
206         Window      window = MI_WINDOW(mi);
207
208         if (!sp->glx_context)
209                 return;
210
211         glDrawBuffer(GL_BACK);
212         glXMakeCurrent(display, window, *(sp->glx_context));
213
214         swap_display = display;
215         swap_window = window;
216
217         NextSproingieDisplay(MI_SCREEN(mi),mi->pause);  /* It will swap. */
218 }
219
220 void
221 refresh_sproingies(ModeInfo * mi)
222 {
223         /* No need to do anything here... The whole screen is updated
224          * every frame anyway.  Otherwise this would be just like
225          * draw_sproingies, above, but replace NextSproingieDisplay(...)
226          * with DisplaySproingies(...).
227          */
228 }
229
230 void
231 reshape_sproingies (ModeInfo *mi, int w, int h)
232 {
233   ReshapeSproingies(w, h);
234 }
235
236
237 void
238 release_sproingies(ModeInfo * mi)
239 {
240         if (sproingies != NULL) {
241                 int         screen;
242
243                 for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++) {
244                         sproingiesstruct *sp = &sproingies[screen];
245
246                         if (sp->glx_context) {
247
248                                 glXMakeCurrent(MI_DISPLAY(mi), sp->window, *(sp->glx_context));
249                                 CleanupSproingies(MI_SCREEN(mi));
250                         }
251                 }
252
253                 (void) free((void *) sproingies);
254                 sproingies = NULL;
255         }
256         FreeAllGL(mi);
257 }
258
259 #endif
260
261 /* End of sproingiewrap.c */