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