http://packetstormsecurity.org/UNIX/admin/xscreensaver-4.14.tar.gz
[xscreensaver] / hacks / glx / atunnel.c
1 /* -*- Mode: C; tab-width: 4 -*- */
2 /* atunnels --- OpenGL Advanced Tunnel Screensaver */
3
4 #if 0
5 static const char sccsid[] = "@(#)atunnels.c    5.07 2003/02/12 xlockmore";
6 #endif
7
8 /* Copyright (c) E. Lassauge, 2003. */
9
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  * The original code for this mode was written by Roman Podobedov
24  * Email: romka@ut.ee
25  * WEB: http://romka.demonews.com
26  *
27  * Eric Lassauge  (March-16-2002) <lassauge@mail.dotcom.fr>
28  *                                  http://lassauge.free.fr/linux.html
29  *
30  * REVISION HISTORY:
31  *
32  * E.Lassauge - 16-Mar-2002:
33  *      - created based on the Roman demo.
34  *      - deleted all external file stuff to use xpm textures and
35  *        hardcoded path point values.
36  *
37  */
38
39 #ifdef STANDALONE               /* xscreensaver mode */
40 # define PROGCLASS              "Atunnels"
41 # define HACK_INIT              init_atunnels
42 # define HACK_DRAW              draw_atunnels
43 # define HACK_RESHAPE           reshape_atunnels
44 # define atunnels_opts          xlockmore_opts
45 #define DEFAULTS                "*delay:        10000   \n" \
46                                 "*showFPS:      False   \n" \
47                                 "*light:        True    \n" \
48                                 "*wire:         False   \n" \
49                                 "*texture:      True    \n"
50
51 #define MODE_atunnels
52 # include "xlockmore.h"         /* from the xscreensaver distribution */
53 #else                           /* !STANDALONE */
54 # include "xlock.h"             /* from the xlockmore distribution */
55 #endif                          /* !STANDALONE */
56
57 #ifdef MODE_atunnels /* whole file */
58
59 #include <stdio.h>
60 #include <stdlib.h>
61 #include <math.h>
62 #include "tunnel_draw.h"
63
64 #if defined( USE_XPM ) || defined( USE_XPMINC ) || defined(STANDALONE)
65 /* USE_XPM & USE_XPMINC in xlock mode ; STANDALONE in xscreensaver mode */
66 #include "xpm-ximage.h"
67 #define I_HAVE_XPM
68
69 #ifdef STANDALONE
70 #include "../images/tunnel0.xpm"
71 #include "../images/tunnel1.xpm"
72 #include "../images/tunnel2.xpm"
73 #else /* !STANDALONE */
74 #include "pixmaps/tunnel0.xpm"
75 #include "pixmaps/tunnel1.xpm"
76 #include "pixmaps/tunnel2.xpm"
77 #endif /* !STANDALONE */
78 #endif /* HAVE_XPM */
79
80 #undef countof
81 #define countof(x) (sizeof((x))/sizeof((*x)))
82
83 #define DEF_LIGHT       "True"
84 #define DEF_WIRE        "False"
85 #define DEF_TEXTURE     "True"
86
87 static Bool do_light;
88 static Bool do_wire;
89 static Bool do_texture;
90
91 static XrmOptionDescRec opts[] = {
92   {(char *)"-light",   (char *)".atunnels.light",      XrmoptionNoArg, (caddr_t) "true" },
93   {(char *)"+light",   (char *)".atunnels.light",      XrmoptionNoArg, (caddr_t) "false" },
94   {(char *)"-wire",    (char *)".atunnels.wire",       XrmoptionNoArg, (caddr_t) "true" },
95   {(char *)"+wire",    (char *)".atunnels.wire",       XrmoptionNoArg, (caddr_t) "false" },
96   {(char *)"-texture", (char *)".atunnels.texture",    XrmoptionNoArg, (caddr_t) "true" },
97   {(char *)"+texture", (char *)".atunnels.texture",    XrmoptionNoArg, (caddr_t) "false" },
98 };
99
100 static argtype vars[] = {
101   {(caddr_t *) &do_light,   (char *)"light",  (char *)"Light",   DEF_LIGHT,   t_Bool},
102   {(caddr_t *) &do_wire,    (char *)"wire",   (char *)"Wire",    DEF_WIRE,    t_Bool},
103   {(caddr_t *) &do_texture, (char *)"texture",(char *)"Texture", DEF_TEXTURE, t_Bool},
104 };
105
106 static OptionStruct desc[] =
107 {
108   {(char *)"-/+ light",   (char *)"whether to do enable lighting (slower)"},
109   {(char *)"-/+ wire",    (char *)"whether to do use wireframe instead of filled (faster)"},
110   {(char *)"-/+ texture", (char *)"whether to apply a texture (slower)"},
111 };
112
113 ModeSpecOpt atunnels_opts = {countof(opts), opts, countof(vars), vars, desc};
114
115 #ifdef USE_MODULES
116 ModStruct   atunnels_description =
117 {"atunnels", "init_atunnels", "draw_atunnels", "release_atunnels",
118  "draw_atunnels", "init_atunnels", NULL, &atunnels_opts,
119  1000, 1, 2, 1, 4, 1.0, "",
120  "OpenGL advanced tunnel screensaver", 0, NULL};
121 #endif
122
123 /* structure for holding the screensaver data */
124 typedef struct {
125   int screen_width, screen_height;
126   GLXContext *glx_context;
127   Window window;
128 } atunnelsstruct;
129
130 static atunnelsstruct *Atunnels = NULL;
131 static GLuint texture[3]; /* texture id: GL world */
132
133 /*=================== Load Texture =========================================*/
134 static void LoadTexture(ModeInfo * mi, char **fn, int t_num)
135 {
136 #if defined( I_HAVE_XPM )
137         XImage *teximage;    /* Texture data */
138  
139         if ((teximage = xpm_to_ximage(MI_DISPLAY(mi), MI_VISUAL(mi),
140                          MI_COLORMAP(mi), fn)) == None) {
141             (void) fprintf(stderr, "Error reading the texture.\n");
142             glDeleteTextures(1, &texture[t_num]);
143             do_texture = False;
144 #ifdef STANDALONE
145             exit(0);
146 #else
147             return;
148 #endif
149         }
150
151 #ifdef HAVE_GLBINDTEXTURE
152         glBindTexture(GL_TEXTURE_2D, texture[t_num]);
153 #endif /* HAVE_GLBINDTEXTURE */
154         glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
155         clear_gl_error();
156         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, teximage->width, teximage->height, 
157                         0, GL_RGBA, GL_UNSIGNED_BYTE, teximage->data);
158         check_gl_error("texture");
159
160         /* Texture parameters, LINEAR scaling for better texture quality */
161         glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 
162         glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 
163
164         XDestroyImage(teximage);
165 #else /* !I_HAVE_XPM */
166         do_texture = False;
167 #endif /* !I_HAVE_XPM */
168
169
170 /*=================== Main Initialization ==================================*/
171 static void Init(ModeInfo * mi)
172 {
173         GLfloat light_ambient[] = {1.0, 1.0, 1.0, 1.0};
174         GLfloat light_diffuse[] = {1.0, 1.0, 1.0, 1.0};
175         GLfloat light_specular[] = {1.0, 1.0, 1.0, 1.0};
176         GLfloat light_position[] = {0.0, 0.0, 1.0, 0.0};
177         GLfloat fogColor[4] = {0.8, 0.8, 0.8, 1.0};
178
179         glClearColor(0, 0, 0, 0);
180         if (do_texture)
181         {
182                 glGenTextures(3, texture);
183                 LoadTexture(mi, texture0,0);
184                 LoadTexture(mi, texture1,1);
185                 LoadTexture(mi, texture2,2);
186                 glEnable(GL_TEXTURE_2D);
187         }
188         InitTunnel();
189         
190         /* Set lighting parameters */
191         if (do_light)
192         {
193                 glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient);
194                 glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse);
195                 glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular);
196                 glLightfv(GL_LIGHT0, GL_POSITION, light_position);
197
198                 /* Enable light 0 */
199                 glEnable(GL_LIGHT0);
200                 glDepthFunc(GL_LESS);
201         
202                 glEnable(GL_LIGHTING);
203         }
204         if (do_wire) {
205                 glDisable(GL_NORMALIZE);
206                 glDisable(GL_CULL_FACE);
207                 glDisable(GL_DEPTH_TEST);
208                 glDisable(GL_TEXTURE_2D);
209                 glPolygonMode(GL_FRONT,GL_LINE);
210                 glPolygonMode(GL_BACK,GL_LINE);
211         }
212         else
213         {
214                 glEnable(GL_DEPTH_TEST);
215                 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
216
217                 /* Enable fog */
218                 glFogi(GL_FOG_MODE, GL_EXP);
219                 glFogfv(GL_FOG_COLOR, fogColor);
220                 glFogf(GL_FOG_DENSITY, 0.3);
221                 glEnable(GL_FOG);
222         
223                 /* Cull face */
224                 glCullFace(GL_FRONT);
225                 glEnable(GL_CULL_FACE);
226         }
227         
228         glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
229 }
230
231
232 /* Standard reshape function */
233 void
234 reshape_atunnels(ModeInfo *mi, int width, int height)
235 {
236         float a;
237
238         glViewport(0, 0, width, height);
239         glMatrixMode(GL_PROJECTION);
240         glLoadIdentity();
241         a = (float)width/(float)height;
242         glFrustum(-0.1*a, 0.1*a, -0.1, 0.1, 0.1, 10);
243         glMatrixMode(GL_MODELVIEW);
244 }
245
246 /* draw the screensaver once */
247 void draw_atunnels(ModeInfo * mi)
248 {
249         atunnelsstruct *sa = &Atunnels[MI_SCREEN(mi)];
250         Display    *display = MI_DISPLAY(mi);
251         Window      window = MI_WINDOW(mi);
252
253         if (!sa->glx_context)
254                 return;
255
256         glXMakeCurrent(display, window, *(sa->glx_context));
257
258         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
259
260         glLoadIdentity();
261
262         DrawTunnel(do_texture, do_light, texture);
263         SplashScreen(do_wire, do_texture, do_light);
264
265         glFlush();  
266         /* manage framerate display */
267         if (MI_IS_FPS(mi)) do_fps (mi);
268         glXSwapBuffers(display, window);
269
270 }
271
272
273 /* xscreensaver initialization routine */
274 void init_atunnels(ModeInfo * mi)
275 {
276   int screen = MI_SCREEN(mi);
277   atunnelsstruct *sa;
278
279   if (Atunnels == NULL) {
280         if ((Atunnels = (atunnelsstruct *) calloc(MI_NUM_SCREENS(mi), sizeof (atunnelsstruct))) == NULL)
281           return;
282   }
283   sa = &Atunnels[screen];
284
285   sa->window = MI_WINDOW(mi);
286   if ((sa->glx_context = init_GL(mi)) != NULL) {
287         reshape_atunnels(mi, MI_WIDTH(mi), MI_HEIGHT(mi));
288         Init(mi);
289   } else {
290         MI_CLEARWINDOW(mi);
291   }
292
293 }
294
295 /* all sorts of nice cleanup code should go here! */
296 void release_atunnels(ModeInfo * mi)
297 {
298   int screen;
299   if (Atunnels != NULL) {
300         for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++) {
301           /*      atunnelsstruct *sa = &Atunnels[screen];*/
302         }
303         (void) free((void *) Atunnels);
304         Atunnels = NULL;
305   }
306   FreeAllGL(mi);
307 }
308 #endif