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