ftp://ftp.krokus.ru/pub/OpenBSD/distfiles/xscreensaver-5.01.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 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", "release_sproingies",
89  "refresh_sproingies", "init_sproingies", NULL, &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 void        NextSproingie(int screen);
100 void        NextSproingieDisplay(int screen,int pause);
101 void        DisplaySproingies(int screen,int pause);
102 void        ReshapeSproingies(int w, int h);
103 void        CleanupSproingies(int screen);
104 void        InitSproingies(int wfmode, int grnd, int mspr, int smrtspr,
105                                                    int screen, int numscreens, int mono);
106
107 typedef struct {
108         GLfloat     view_rotx, view_roty, view_rotz;
109         GLint       gear1, gear2, gear3;
110         GLfloat     angle;
111         GLuint      limit;
112         GLuint      count;
113         GLXContext *glx_context;
114         int         mono;
115         Window      window;
116 } sproingiesstruct;
117
118 static sproingiesstruct *sproingies = NULL;
119
120
121 ENTRYPOINT void
122 init_sproingies (ModeInfo * mi)
123 {
124         Window      window = MI_WINDOW(mi);
125         int         screen = MI_SCREEN(mi);
126
127         int         count = MI_COUNT(mi);
128         int         size = MI_SIZE(mi);
129
130         sproingiesstruct *sp;
131         int         wfmode = 0, grnd = 0, mspr, w, h;
132
133         if (sproingies == NULL) {
134                 if ((sproingies = (sproingiesstruct *) calloc(MI_NUM_SCREENS(mi),
135                                          sizeof (sproingiesstruct))) == NULL)
136                         return;
137         }
138         sp = &sproingies[screen];
139
140         sp->mono = (MI_IS_MONO(mi) ? 1 : 0);
141         sp->window = window;
142         if ((sp->glx_context = init_GL(mi)) != NULL) {
143
144                 if (MI_IS_WIREFRAME(mi))
145                         wfmode = 1;
146
147                 if (grnd > 2)
148                         grnd = 2;
149
150                 mspr = count;
151                 if (mspr > 100)
152                         mspr = 100;
153
154                 /* wireframe, ground, maxsproingies */
155                 InitSproingies(wfmode, grnd, mspr, smrt_spr, MI_SCREEN(mi), MI_NUM_SCREENS(mi), sp->mono);
156
157                 /* Viewport is specified size if size >= MINSIZE && size < screensize */
158                 if (size == 0) {
159                         w = MI_WIDTH(mi);
160                         h = MI_HEIGHT(mi);
161                 } else if (size < MINSIZE) {
162                         w = MINSIZE;
163                         h = MINSIZE;
164                 } else {
165                         w = (size > MI_WIDTH(mi)) ? MI_WIDTH(mi) : size;
166                         h = (size > MI_HEIGHT(mi)) ? MI_HEIGHT(mi) : size;
167                 }
168
169                 glViewport((MI_WIDTH(mi) - w) / 2, (MI_HEIGHT(mi) - h) / 2, w, h);
170                 glMatrixMode(GL_PROJECTION);
171                 glLoadIdentity();
172                 gluPerspective(65.0, (GLfloat) w / (GLfloat) h, 0.1, 2000.0);   /* was 200000.0 */
173                 glMatrixMode(GL_MODELVIEW);
174                 glLoadIdentity();
175
176                 DisplaySproingies(MI_SCREEN(mi),mi->pause);
177
178         } else {
179                 MI_CLEARWINDOW(mi);
180         }
181 }
182
183 /* ARGSUSED */
184 ENTRYPOINT void
185 draw_sproingies (ModeInfo * mi)
186 {
187         sproingiesstruct *sp = &sproingies[MI_SCREEN(mi)];
188         Display    *display = MI_DISPLAY(mi);
189         Window      window = MI_WINDOW(mi);
190
191         if (!sp->glx_context)
192                 return;
193
194         glDrawBuffer(GL_BACK);
195         glXMakeCurrent(display, window, *(sp->glx_context));
196
197         NextSproingieDisplay(MI_SCREEN(mi),mi->pause);  /* It will swap. */
198
199     if (mi->fps_p) do_fps (mi);
200     glFinish();
201     glXSwapBuffers(MI_DISPLAY(mi), MI_WINDOW(mi));
202 }
203
204 #ifndef STANDALONE
205 ENTRYPOINT void
206 refresh_sproingies(ModeInfo * mi)
207 {
208         /* No need to do anything here... The whole screen is updated
209          * every frame anyway.  Otherwise this would be just like
210          * draw_sproingies, above, but replace NextSproingieDisplay(...)
211          * with DisplaySproingies(...).
212          */
213 }
214 #endif /* !STANDALONE */
215
216 ENTRYPOINT void
217 reshape_sproingies (ModeInfo *mi, int w, int h)
218 {
219   ReshapeSproingies(w, h);
220 }
221
222
223 ENTRYPOINT void
224 release_sproingies (ModeInfo * mi)
225 {
226         if (sproingies != NULL) {
227                 int         screen;
228
229                 for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++) {
230                         sproingiesstruct *sp = &sproingies[screen];
231
232                         if (sp->glx_context) {
233
234                                 glXMakeCurrent(MI_DISPLAY(mi), sp->window, *(sp->glx_context));
235                                 CleanupSproingies(MI_SCREEN(mi));
236                         }
237                 }
238
239                 (void) free((void *) sproingies);
240                 sproingies = NULL;
241         }
242         FreeAllGL(mi);
243 }
244
245 XSCREENSAVER_MODULE ("Sproingies", sproingies)
246
247 #endif /* USE_GL */
248
249 /* End of sproingiewrap.c */