From http://www.jwz.org/xscreensaver/xscreensaver-5.38.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 release_sproingies 0
57 # define sproingies_handle_event 0
58 # include "xlockmore.h"                         /* from the xscreensaver distribution */
59 #else  /* !STANDALONE */
60 # include "xlock.h"                                     /* from the xlockmore distribution */
61 #endif /* !STANDALONE */
62
63 #ifdef USE_GL
64
65 #define DEF_SMART_SPROINGIES "True" /* Smart sproingies do not fall down the edge */
66
67 #include "sproingies.h"
68
69 #undef countof
70 #define countof(x) (sizeof((x))/sizeof((*x)))
71
72 static XrmOptionDescRec opts[] = {
73     {"-fall",     ".smartSproingies",  XrmoptionNoArg,  "False"},
74     {"-no-fall",  ".smartSproingies",  XrmoptionNoArg,  "True"},
75 };
76
77 static int smrt_spr;
78
79 static argtype vars[] = {
80     {&smrt_spr,  "smartSproingies",  "Boolean",  DEF_SMART_SPROINGIES,  t_Bool},
81 };
82
83 ENTRYPOINT ModeSpecOpt sproingies_opts =
84 {countof(opts), opts, countof(vars), vars, NULL};
85
86 #ifdef USE_MODULES
87 ModStruct   sproingies_description =
88 {"sproingies", "init_sproingies", "draw_sproingies", NULL,
89  "refresh_sproingies", "init_sproingies", "free_sproingies", &sproingies_opts,
90  1000, 5, 0, 400, 4, 1.0, "",
91  "Shows Sproingies!  Nontoxic.  Safe for pets and small children", 0, NULL};
92
93 #endif
94
95 #define MINSIZE 32
96
97 #include <time.h>
98
99 typedef struct {
100         GLfloat     view_rotx, view_roty, view_rotz;
101         GLint       gear1, gear2, gear3;
102         GLfloat     angle;
103         GLuint      limit;
104         GLuint      count;
105         GLXContext *glx_context;
106         int         mono;
107         Window      window;
108         sp_instance si;
109 } sproingiesstruct;
110
111 static sproingiesstruct *sproingies = NULL;
112
113
114 ENTRYPOINT void
115 init_sproingies (ModeInfo * mi)
116 {
117         Window      window = MI_WINDOW(mi);
118         int         screen = MI_SCREEN(mi);
119
120         int         count = MI_COUNT(mi);
121         int         size = MI_SIZE(mi);
122
123         sproingiesstruct *sp;
124         int         wfmode = 0, grnd = 0, mspr, w, h;
125
126         MI_INIT (mi, sproingies);
127         sp = &sproingies[screen];
128
129         sp->mono = (MI_IS_MONO(mi) ? 1 : 0);
130         sp->window = window;
131         if ((sp->glx_context = init_GL(mi)) != NULL) {
132
133                 if (MI_IS_WIREFRAME(mi))
134                         wfmode = 1;
135
136                 if (grnd > 2)
137                         grnd = 2;
138
139                 mspr = count;
140                 if (mspr > 100)
141                         mspr = 100;
142
143                 /* wireframe, ground, maxsproingies */
144                 InitSproingies(&sp->si, wfmode, grnd, mspr, smrt_spr, sp->mono);
145
146                 /* Viewport is specified size if size >= MINSIZE && size < screensize */
147                 if (size == 0) {
148                         w = MI_WIDTH(mi);
149                         h = MI_HEIGHT(mi);
150                 } else if (size < MINSIZE) {
151                         w = MINSIZE;
152                         h = MINSIZE;
153                 } else {
154                         w = (size > MI_WIDTH(mi)) ? MI_WIDTH(mi) : size;
155                         h = (size > MI_HEIGHT(mi)) ? MI_HEIGHT(mi) : size;
156                 }
157
158                 glViewport((MI_WIDTH(mi) - w) / 2, (MI_HEIGHT(mi) - h) / 2, w, h);
159                 glMatrixMode(GL_PROJECTION);
160                 glLoadIdentity();
161                 gluPerspective(65.0, (GLfloat) w / (GLfloat) h, 0.1, 2000.0);   /* was 200000.0 */
162                 glMatrixMode(GL_MODELVIEW);
163                 glLoadIdentity();
164
165                 DisplaySproingies(&sp->si);
166
167         } else {
168                 MI_CLEARWINDOW(mi);
169         }
170 }
171
172 /* ARGSUSED */
173 ENTRYPOINT void
174 draw_sproingies (ModeInfo * mi)
175 {
176         sproingiesstruct *sp = &sproingies[MI_SCREEN(mi)];
177         Display    *display = MI_DISPLAY(mi);
178         Window      window = MI_WINDOW(mi);
179
180         if (!sp->glx_context)
181                 return;
182
183         glDrawBuffer(GL_BACK);
184         glXMakeCurrent(display, window, *(sp->glx_context));
185
186     glPushMatrix();
187     glRotatef(current_device_rotation(), 0, 0, 1);
188         NextSproingieDisplay(&sp->si);  /* It will swap. */
189     glPopMatrix();
190
191     if (mi->fps_p) do_fps (mi);
192     glFinish();
193     glXSwapBuffers(MI_DISPLAY(mi), MI_WINDOW(mi));
194 }
195
196 #ifndef STANDALONE
197 ENTRYPOINT void
198 refresh_sproingies(ModeInfo * mi)
199 {
200         /* No need to do anything here... The whole screen is updated
201          * every frame anyway.  Otherwise this would be just like
202          * draw_sproingies, above, but replace NextSproingieDisplay(...)
203          * with DisplaySproingies(...).
204          */
205 }
206 #endif /* !STANDALONE */
207
208 ENTRYPOINT void
209 reshape_sproingies (ModeInfo *mi, int w, int h)
210 {
211   ReshapeSproingies(w, h);
212 }
213
214
215 ENTRYPOINT void
216 free_sproingies (ModeInfo * mi)
217 {
218         sproingiesstruct *sp = &sproingies[MI_SCREEN(mi)];
219
220         if (sp->glx_context) {
221
222                 glXMakeCurrent(MI_DISPLAY(mi), sp->window, *(sp->glx_context));
223                 CleanupSproingies(&sp->si);
224         }
225 }
226
227 XSCREENSAVER_MODULE ("Sproingies", sproingies)
228
229 #endif /* USE_GL */
230
231 /* End of sproingiewrap.c */