From http://www.jwz.org/xscreensaver/xscreensaver-5.37.tar.gz
[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  *                  Sergio GutiĆ©rrez "Sergut", sergut@gmail.com
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  * 01-Sep-06: Make the sproingies select a new direction after each hop
31  *              (6 frames); if they fall towards the edge, they explode.
32  *              (TODO: let them fall for a time before they explode or
33  *               disappear) [sergut]
34  * 13-Dec-02: Changed triangle normals into vertex normals to give a smooth
35  *              apperance and moved the sproingies from Display Lists to
36  *              Vertex Arrays, still need to do this for the TopsSides.
37  *              [gordon]
38  * 26-Apr-97: Added glPointSize() calls around explosions, plus other fixes.
39  * 28-Mar-97: Added size support.
40  * 22-Mar-97: Updated to use glX interface instead of xmesa one.
41  *              Also, support for multiscreens added.
42  * 20-Mar-97: Updated for xlockmore v4.02alpha7 and higher, using
43  *              xlockmore's built-in Mesa/OpenGL support instead of
44  *              my own.  Submitted for inclusion in xlockmore.
45  * 09-Dec-96: Written.
46  */
47
48 #ifdef STANDALONE
49 # define DEFAULTS       "*delay:                30000   \n"                     \
50                                         "*count:                8       \n"                     \
51                                         "*size:                 0       \n"                     \
52                                         "*showFPS:      False   \n"                     \
53                                         "*fpsTop:       True    \n"                     \
54                                         "*wireframe:    False   \n"
55
56 # define refresh_sproingies 0
57 # define release_sproingies 0
58 # define sproingies_handle_event 0
59 # include "xlockmore.h"                         /* from the xscreensaver distribution */
60 #else  /* !STANDALONE */
61 # include "xlock.h"                                     /* from the xlockmore distribution */
62 #endif /* !STANDALONE */
63
64 #ifdef USE_GL
65
66 #define DEF_SMART_SPROINGIES "True" /* Smart sproingies do not fall down the edge */
67
68 #include "sproingies.h"
69
70 #undef countof
71 #define countof(x) (sizeof((x))/sizeof((*x)))
72
73 static XrmOptionDescRec opts[] = {
74     {"-fall",     ".smartSproingies",  XrmoptionNoArg,  "False"},
75     {"-no-fall",  ".smartSproingies",  XrmoptionNoArg,  "True"},
76 };
77
78 static int smrt_spr;
79
80 static argtype vars[] = {
81     {&smrt_spr,  "smartSproingies",  "Boolean",  DEF_SMART_SPROINGIES,  t_Bool},
82 };
83
84 ENTRYPOINT ModeSpecOpt sproingies_opts =
85 {countof(opts), opts, countof(vars), vars, NULL};
86
87 #ifdef USE_MODULES
88 ModStruct   sproingies_description =
89 {"sproingies", "init_sproingies", "draw_sproingies", NULL,
90  "refresh_sproingies", "init_sproingies", NULL, &sproingies_opts,
91  1000, 5, 0, 400, 4, 1.0, "",
92  "Shows Sproingies!  Nontoxic.  Safe for pets and small children", 0, NULL};
93
94 #endif
95
96 #define MINSIZE 32
97
98 #include <time.h>
99
100 typedef struct {
101         GLfloat     view_rotx, view_roty, view_rotz;
102         GLint       gear1, gear2, gear3;
103         GLfloat     angle;
104         GLuint      limit;
105         GLuint      count;
106         GLXContext *glx_context;
107         int         mono;
108         Window      window;
109         sp_instance si;
110 } sproingiesstruct;
111
112 static sproingiesstruct *sproingies = NULL;
113
114
115 static void free_sproingies (ModeInfo * mi);
116
117
118 ENTRYPOINT void
119 init_sproingies (ModeInfo * mi)
120 {
121         Window      window = MI_WINDOW(mi);
122         int         screen = MI_SCREEN(mi);
123
124         int         count = MI_COUNT(mi);
125         int         size = MI_SIZE(mi);
126
127         sproingiesstruct *sp;
128         int         wfmode = 0, grnd = 0, mspr, w, h;
129
130         MI_INIT (mi, sproingies, free_sproingies);
131         sp = &sproingies[screen];
132
133         sp->mono = (MI_IS_MONO(mi) ? 1 : 0);
134         sp->window = window;
135         if ((sp->glx_context = init_GL(mi)) != NULL) {
136
137                 if (MI_IS_WIREFRAME(mi))
138                         wfmode = 1;
139
140                 if (grnd > 2)
141                         grnd = 2;
142
143                 mspr = count;
144                 if (mspr > 100)
145                         mspr = 100;
146
147                 /* wireframe, ground, maxsproingies */
148                 InitSproingies(&sp->si, wfmode, grnd, mspr, smrt_spr, sp->mono);
149
150                 /* Viewport is specified size if size >= MINSIZE && size < screensize */
151                 if (size == 0) {
152                         w = MI_WIDTH(mi);
153                         h = MI_HEIGHT(mi);
154                 } else if (size < MINSIZE) {
155                         w = MINSIZE;
156                         h = MINSIZE;
157                 } else {
158                         w = (size > MI_WIDTH(mi)) ? MI_WIDTH(mi) : size;
159                         h = (size > MI_HEIGHT(mi)) ? MI_HEIGHT(mi) : size;
160                 }
161
162                 glViewport((MI_WIDTH(mi) - w) / 2, (MI_HEIGHT(mi) - h) / 2, w, h);
163                 glMatrixMode(GL_PROJECTION);
164                 glLoadIdentity();
165                 gluPerspective(65.0, (GLfloat) w / (GLfloat) h, 0.1, 2000.0);   /* was 200000.0 */
166                 glMatrixMode(GL_MODELVIEW);
167                 glLoadIdentity();
168
169                 DisplaySproingies(&sp->si);
170
171         } else {
172                 MI_CLEARWINDOW(mi);
173         }
174 }
175
176 /* ARGSUSED */
177 ENTRYPOINT void
178 draw_sproingies (ModeInfo * mi)
179 {
180         sproingiesstruct *sp = &sproingies[MI_SCREEN(mi)];
181         Display    *display = MI_DISPLAY(mi);
182         Window      window = MI_WINDOW(mi);
183
184         if (!sp->glx_context)
185                 return;
186
187         glDrawBuffer(GL_BACK);
188         glXMakeCurrent(display, window, *(sp->glx_context));
189
190     glPushMatrix();
191     glRotatef(current_device_rotation(), 0, 0, 1);
192         NextSproingieDisplay(&sp->si);  /* It will swap. */
193     glPopMatrix();
194
195     if (mi->fps_p) do_fps (mi);
196     glFinish();
197     glXSwapBuffers(MI_DISPLAY(mi), MI_WINDOW(mi));
198 }
199
200 #ifndef STANDALONE
201 ENTRYPOINT void
202 refresh_sproingies(ModeInfo * mi)
203 {
204         /* No need to do anything here... The whole screen is updated
205          * every frame anyway.  Otherwise this would be just like
206          * draw_sproingies, above, but replace NextSproingieDisplay(...)
207          * with DisplaySproingies(...).
208          */
209 }
210 #endif /* !STANDALONE */
211
212 ENTRYPOINT void
213 reshape_sproingies (ModeInfo *mi, int w, int h)
214 {
215   ReshapeSproingies(w, h);
216 }
217
218
219 static void
220 free_sproingies (ModeInfo * mi)
221 {
222         sproingiesstruct *sp = &sproingies[MI_SCREEN(mi)];
223
224         if (sp->glx_context) {
225
226                 glXMakeCurrent(MI_DISPLAY(mi), sp->window, *(sp->glx_context));
227                 CleanupSproingies(&sp->si);
228         }
229 }
230
231 XSCREENSAVER_MODULE ("Sproingies", sproingies)
232
233 #endif /* USE_GL */
234
235 /* End of sproingiewrap.c */