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