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/07/19 xlockmore";
6 #endif
7 
8 /* Copyright (c) E. Lassauge, 2002-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  (March-16-2002) <lassauge AT users DOT sourceforge DOT 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 HAVE_CONFIG_H
42 #include <config.h>
43 #endif
44 
45 #ifdef STANDALONE		/* xscreensaver mode */
46 # define MODE_atunnels
47 #define	DEFAULTS                "*delay:	10000	\n" \
48 				"*showFPS:     	False	\n"
49 
50 # include "xlockmore.h"		/* from the xscreensaver distribution */
51 #include <stdio.h>
52 #include <stdlib.h>
53 #include <math.h>
54 #define free_atunnels 0
55 #define atunnels_handle_event 0
56 #else /* !STANDALONE */
57 # include "xlock.h"		/* from the xlockmore distribution */
58 # include "visgl.h"
59 #endif /* !STANDALONE */
60 
61 #ifdef MODE_atunnels
62 #include "tunnel_draw.h"
63 
64 #ifdef HAVE_XPM
65 #include "xpm-ximage.h"
66 
67 #if 0
68 #include "../images/tunnel0.xpm"
69 #include "../images/tunnel1.xpm"
70 #include "../images/tunnel2.xpm"
71 #include "../images/tunnel3.xpm"
72 #include "../images/tunnel4.xpm"
73 #include "../images/tunnel5.xpm"
74 #endif
75 #include "pixmaps/tunnel0.xpm"
76 #include "pixmaps/tunnel1.xpm"
77 #include "pixmaps/tunnel2.xpm"
78 #include "pixmaps/tunnel3.xpm"
79 #include "pixmaps/tunnel4.xpm"
80 #include "pixmaps/tunnel5.xpm"
81 #endif /* HAVE_XPM */
82 
83 #undef countof
84 #define countof(x) (sizeof((x))/sizeof((*x)))
85 
86 #define DEF_LIGHT	"True"
87 #define DEF_WIRE   	"False"
88 #define DEF_TEXTURE	"True"
89 #define MINSIZE         32      /* minimal viewport size */
90 
91 static int do_light;
92 static int do_wire;
93 static int do_texture;
94 
95 static XrmOptionDescRec opts[] = {
96   {(char *)"-light",   (char *)".atunnels.light",      XrmoptionNoArg, (caddr_t) "true" },
97   {(char *)"+light",   (char *)".atunnels.light",      XrmoptionNoArg, (caddr_t) "false" },
98   {(char *)"-wire",    (char *)".atunnels.wire",       XrmoptionNoArg, (caddr_t) "true" },
99   {(char *)"+wire",    (char *)".atunnels.wire",       XrmoptionNoArg, (caddr_t) "false" },
100   {(char *)"-texture", (char *)".atunnels.texture",    XrmoptionNoArg, (caddr_t) "true" },
101   {(char *)"+texture", (char *)".atunnels.texture",    XrmoptionNoArg, (caddr_t) "false" },
102 };
103 
104 static argtype vars[] = {
105   {(void *) &do_light,   (char *)"light",  (char *)"Light",   (char *)DEF_LIGHT,   t_Bool},
106   {(void *) &do_wire,    (char *)"wire",   (char *)"Wire",    (char *)DEF_WIRE,    t_Bool},
107   {(void *) &do_texture, (char *)"texture",(char *)"Texture", (char *)DEF_TEXTURE, t_Bool},
108 };
109 
110 static OptionStruct desc[] =
111 {
112   {(char *)"-/+ light",   (char *)"whether to do enable lighting (slower)"},
113   {(char *)"-/+ wire",    (char *)"whether to do use wireframe instead of filled (faster)"},
114   {(char *)"-/+ texture", (char *)"whether to apply a texture (slower)"},
115 };
116 
117 ENTRYPOINT ModeSpecOpt atunnels_opts =
118 {countof(opts), opts, countof(vars), vars, desc};
119 
120 #ifdef USE_MODULES
121 ModStruct   atunnels_description =
122 {"atunnels", "init_atunnels", "draw_atunnels", "release_atunnels",
123  "draw_atunnels", "init_atunnels", NULL, &atunnels_opts,
124  25000, 1, 1, 1, 0, 1.0, "",
125  "Shows an OpenGL advanced tunnel screensaver", 0, NULL};
126 #endif
127 
128 /* structure for holding the screensaver data */
129 typedef struct {
130 #ifdef WIN32
131   HGLRC       glx_context;
132 #else
133   GLXContext *glx_context;
134 #endif
135   GLint WIDTH, HEIGHT;
136 } atunnelsstruct;
137 
138 static atunnelsstruct *Atunnels = NULL;
139 
140 /* convenient access to the screen width */
141 static GLuint texture[MAX_TEXTURE];     /* Textures */
142 
143 /*=================== Load Texture =========================================*/
144 #ifdef HAVE_XPM
LoadTexture(ModeInfo * mi,char ** fn,int t_num)145 static Bool LoadTexture(ModeInfo * mi, char **fn, int t_num)
146 {
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 	    return False;
154 	}
155 
156 #ifdef HAVE_GLBINDTEXTURE
157 	glBindTexture(GL_TEXTURE_2D, texture[t_num]);
158 #endif /* HAVE_GLBINDTEXTURE */
159 	glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
160 	clear_gl_error();
161 	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, teximage->width, teximage->height,
162 			0, GL_RGBA, GL_UNSIGNED_BYTE, teximage->data);
163 #ifdef STANDALONE
164 	check_gl_error("texture");
165 #else
166 	if (check_gl_error("texture"))
167 		return False;
168 #endif
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 	return True;
176 }
177 #endif /* !HAVE_XPM */
178 
179 /*=================== Main Initialization ==================================*/
Init(ModeInfo * mi)180 static Bool Init(ModeInfo * mi)
181 {
182 	GLfloat light_ambient[] = {1.0, 1.0, 1.0, 1.0};
183 	GLfloat light_diffuse[] = {1.0, 1.0, 1.0, 1.0};
184 	GLfloat light_specular[] = {1.0, 1.0, 1.0, 1.0};
185 	GLfloat light_position[] = {0.0, 0.0, 1.0, 0.0};
186 	GLfloat fogColor[4] = {0.8, 0.8, 0.8, 1.0};
187 
188   	glClearColor(0, 0, 0, 0);
189 #ifdef HAVE_XPM
190 	if (do_texture)
191 	{
192 		glGenTextures(MAX_TEXTURE, texture);
193 		if (!LoadTexture(mi, texture0,0))
194 			do_texture = False;
195 		else if (!LoadTexture(mi, texture1,1))
196 			do_texture = False;
197 		else if (!LoadTexture(mi, texture2,2))
198 			do_texture = False;
199 		else if (!LoadTexture(mi, texture3,3))
200 			do_texture = False;
201 		else if (!LoadTexture(mi, texture4,4))
202 			do_texture = False;
203 		else if (!LoadTexture(mi, texture5,5))
204 			do_texture = False;
205 		else
206 			glEnable(GL_TEXTURE_2D);
207 	}
208 #endif
209 	if (!InitTunnel())
210 		return False;
211 
212 	/* Set lighting parameters */
213 	if (do_light)
214 	{
215 		glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient);
216 		glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse);
217 		glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular);
218 		glLightfv(GL_LIGHT0, GL_POSITION, light_position);
219 
220 		/* Enable light 0 */
221 		glEnable(GL_LIGHT0);
222 		glDepthFunc(GL_LESS);
223 
224 		glEnable(GL_LIGHTING);
225 	}
226   	if (do_wire) {
227 		glDisable(GL_NORMALIZE);
228 		glDisable(GL_CULL_FACE);
229 		glDisable(GL_DEPTH_TEST);
230 		glDisable(GL_TEXTURE_2D);
231 		glPolygonMode(GL_FRONT,GL_LINE);
232   		glPolygonMode(GL_BACK,GL_LINE);
233   	} else {
234 		glEnable(GL_DEPTH_TEST);
235 		glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
236 
237 		/* Enable fog */
238 		glFogi(GL_FOG_MODE, GL_EXP);
239 		glFogfv(GL_FOG_COLOR, fogColor);
240 		glFogf(GL_FOG_DENSITY, 0.3);
241 		glEnable(GL_FOG);
242 
243 		/* Cull face */
244 		glCullFace(GL_FRONT);
245 		glEnable(GL_CULL_FACE);
246 	}
247 
248 	glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
249 	return True;
250 }
251 
252 
253 /* Standard reshape function */
254 static void
reshape_atunnels(ModeInfo * mi,int width,int height)255 reshape_atunnels(ModeInfo *mi, int width, int height)
256 {
257 	float a;
258 
259 	glViewport((MI_WIDTH(mi) - width) / 2, (MI_HEIGHT(mi) - height) / 2, width, height);
260 	glMatrixMode(GL_PROJECTION);
261 	glLoadIdentity();
262 	a = (float)width/(float)height;
263 	glFrustum(-0.1*a, 0.1*a, -0.1, 0.1, 0.1, 10);
264 	glMatrixMode(GL_MODELVIEW);
265 }
266 
267 /* draw the screensaver once */
268 ENTRYPOINT void
draw_atunnels(ModeInfo * mi)269 draw_atunnels(ModeInfo * mi)
270 {
271   	atunnelsstruct *gp;
272   	Display    *display = MI_DISPLAY(mi);
273   	Window      window = MI_WINDOW(mi);
274 
275 	if (Atunnels == NULL)
276 		return;
277   	gp = &Atunnels[MI_SCREEN(mi)];
278   	if (!gp->glx_context)
279 		return;
280 #ifdef WIN32
281 	wglMakeCurrent(hdc, gp->glx_context);
282 #else
283 	glXMakeCurrent(display, window, *(gp->glx_context));
284 #endif
285 	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
286 
287 	glLoadIdentity();
288 
289 	DrawTunnel(do_texture, do_light, texture);
290 	SplashScreen(do_wire, do_texture, do_light);
291 
292 	glFlush();
293   	if (MI_IS_FPS(mi)) do_fps (mi);
294   	glXSwapBuffers(display, window);
295 
296 }
297 
298 /* xscreensaver initialization routine */
299 ENTRYPOINT void
init_atunnels(ModeInfo * mi)300 init_atunnels(ModeInfo * mi)
301 {
302   int screen = MI_SCREEN(mi);
303   int size = MI_SIZE(mi);
304   atunnelsstruct *gp;
305 
306   MI_INIT(mi, Atunnels);
307   gp = &Atunnels[screen];
308 
309   /* Viewport is specified size if size >= MINSIZE && size < screensize */
310   if (size <= 1) {
311       gp->WIDTH = MI_WIDTH(mi);
312       gp->HEIGHT = MI_HEIGHT(mi);
313   } else if (size < MINSIZE) {
314       gp->WIDTH = MINSIZE;
315       gp->HEIGHT = MINSIZE;
316   } else {
317       gp->WIDTH = (size > MI_WIDTH(mi)) ? MI_WIDTH(mi) : size;
318       gp->HEIGHT = (size > MI_HEIGHT(mi)) ? MI_HEIGHT(mi) : size;
319   }
320 
321   if ((gp->glx_context = init_GL(mi)) != NULL) {
322 	reshape_atunnels(mi, gp->WIDTH, gp->HEIGHT);
323 	glDrawBuffer(GL_BACK);
324 	(void) Init(mi);
325   } else {
326 	MI_CLEARWINDOW(mi);
327   }
328 
329 }
330 
331 /* all sorts of nice cleanup code should go here! */
332 ENTRYPOINT void
release_atunnels(ModeInfo * mi)333 release_atunnels(ModeInfo * mi)
334 {
335   if (Atunnels != NULL) {
336 #if 0
337   	int screen;
338 	for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++) {
339 	  atunnelsstruct *gp = &Atunnels[screen];
340 	   FreeTunnel(gp->path);
341 	}
342 #endif
343 	free(Atunnels);
344 	Atunnels = NULL;
345   }
346   FreeAllGL(mi);
347 }
348 
349 #ifndef STANDALONE
350 ENTRYPOINT void
change_atunnels(ModeInfo * mi)351 change_atunnels(ModeInfo * mi)
352 {
353   	atunnelsstruct *gp;
354 
355 	if (Atunnels == NULL)
356 		return;
357   	gp = &Atunnels[MI_SCREEN(mi)];
358 	if (!gp->glx_context)
359 		return;
360 #ifdef WIN32
361 	wglMakeCurrent(hdc, gp->glx_context);
362 #else
363 	glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(gp->glx_context));
364 #endif
365 	(void) Init(mi);
366 }
367 #endif
368 
369 XSCREENSAVER_MODULE ("Atunnels", atunnels)
370 
371 #endif /* MODE_atunnels */
372