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