368 lines
10 KiB
C
368 lines
10 KiB
C
/* -*- Mode: C; tab-width: 4 -*- */
|
|
/* atunnels --- OpenGL Advanced Tunnel Screensaver */
|
|
|
|
#if !defined( lint ) && !defined( SABER )
|
|
static const char sccsid[] = "@(#)atunnels.c 5.13 2004/07/19 xlockmore";
|
|
#endif
|
|
|
|
/* Copyright (c) E. Lassauge, 2002-2004. */
|
|
|
|
/*
|
|
* Permission to use, copy, modify, and distribute this software and its
|
|
* documentation for any purpose and without fee is hereby granted,
|
|
* provided that the above copyright notice appear in all copies and that
|
|
* both that copyright notice and this permission notice appear in
|
|
* supporting documentation.
|
|
*
|
|
* This file is provided AS IS with no warranties of any kind. The author
|
|
* shall have no liability with respect to the infringement of copyrights,
|
|
* trade secrets or any patents by this file or any part thereof. In no
|
|
* event will the author be liable for any lost revenue or profits or
|
|
* other special, indirect and consequential damages.
|
|
*
|
|
* The original code for this mode was written by Roman Podobedov
|
|
* Email: romka@ut.ee
|
|
* WEB: http://romka.demonews.com
|
|
*
|
|
* Eric Lassauge (March-16-2002) <lassauge AT users DOT sourceforge DOT net>
|
|
* http://lassauge.free.fr/linux.html
|
|
*
|
|
* REVISION HISTORY:
|
|
*
|
|
* E.Lassauge - 25-May-2004:
|
|
* - added more texture !
|
|
* E.Lassauge - 16-Mar-2002:
|
|
* - created based on the Roman demo.
|
|
* - deleted all external file stuff to use xpm textures and
|
|
* hardcoded path point values.
|
|
*
|
|
*/
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
#include <config.h>
|
|
#endif
|
|
|
|
#ifdef STANDALONE /* xscreensaver mode */
|
|
# define PROGCLASS "Atunnels"
|
|
# define HACK_INIT init_atunnels
|
|
# define HACK_DRAW draw_atunnels
|
|
# define HACK_RESHAPE reshape_atunnels
|
|
# define atunnels_opts xlockmore_opts
|
|
#define DEFAULTS "*delay: 10000 \n" \
|
|
"*showFPS: False \n" \
|
|
"*light: True \n" \
|
|
"*wire: False \n" \
|
|
"*texture: True \n"
|
|
|
|
# include "xlockmore.h" /* from the xscreensaver distribution */
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <math.h>
|
|
#else /* !STANDALONE */
|
|
# include "xlock.h" /* from the xlockmore distribution */
|
|
# include "visgl.h"
|
|
#endif /* !STANDALONE */
|
|
|
|
#ifdef USE_GL /* whole file */
|
|
|
|
#include "tunnel_draw.h"
|
|
|
|
#ifdef HAVE_XPM
|
|
#include "xpm-ximage.h"
|
|
|
|
#ifdef STANDALONE
|
|
#include "../images/tunnel0.xpm"
|
|
#include "../images/tunnel1.xpm"
|
|
#include "../images/tunnel2.xpm"
|
|
#include "../images/tunnel3.xpm"
|
|
#include "../images/tunnel4.xpm"
|
|
#include "../images/tunnel5.xpm"
|
|
#else /* !STANDALONE */
|
|
#include "pixmaps/tunnel0.xpm"
|
|
#include "pixmaps/tunnel1.xpm"
|
|
#include "pixmaps/tunnel2.xpm"
|
|
#include "pixmaps/tunnel3.xpm"
|
|
#include "pixmaps/tunnel4.xpm"
|
|
#include "pixmaps/tunnel5.xpm"
|
|
#endif /* !STANDALONE */
|
|
#endif /* HAVE_XPM */
|
|
|
|
#undef countof
|
|
#define countof(x) (sizeof((x))/sizeof((*x)))
|
|
|
|
#define DEF_LIGHT "True"
|
|
#define DEF_WIRE "False"
|
|
#define DEF_TEXTURE "True"
|
|
#define MINSIZE 32 /* minimal viewport size */
|
|
|
|
static int do_light;
|
|
static int do_wire;
|
|
static int do_texture;
|
|
|
|
static XrmOptionDescRec opts[] = {
|
|
{(char *)"-light", (char *)".atunnels.light", XrmoptionNoArg, (caddr_t) "true" },
|
|
{(char *)"+light", (char *)".atunnels.light", XrmoptionNoArg, (caddr_t) "false" },
|
|
{(char *)"-wire", (char *)".atunnels.wire", XrmoptionNoArg, (caddr_t) "true" },
|
|
{(char *)"+wire", (char *)".atunnels.wire", XrmoptionNoArg, (caddr_t) "false" },
|
|
{(char *)"-texture", (char *)".atunnels.texture", XrmoptionNoArg, (caddr_t) "true" },
|
|
{(char *)"+texture", (char *)".atunnels.texture", XrmoptionNoArg, (caddr_t) "false" },
|
|
};
|
|
|
|
static argtype vars[] = {
|
|
{(void *) &do_light, (char *)"light", (char *)"Light", DEF_LIGHT, t_Bool},
|
|
{(void *) &do_wire, (char *)"wire", (char *)"Wire", DEF_WIRE, t_Bool},
|
|
{(void *) &do_texture, (char *)"texture",(char *)"Texture", DEF_TEXTURE, t_Bool},
|
|
};
|
|
|
|
static OptionStruct desc[] =
|
|
{
|
|
{(char *)"-/+ light", (char *)"whether to do enable lighting (slower)"},
|
|
{(char *)"-/+ wire", (char *)"whether to do use wireframe instead of filled (faster)"},
|
|
{(char *)"-/+ texture", (char *)"whether to apply a texture (slower)"},
|
|
};
|
|
|
|
ModeSpecOpt atunnels_opts = {countof(opts), opts, countof(vars), vars, desc};
|
|
|
|
#ifdef USE_MODULES
|
|
ModStruct atunnels_description =
|
|
{"atunnels", "init_atunnels", "draw_atunnels", "release_atunnels",
|
|
"draw_atunnels", "init_atunnels", NULL, &atunnels_opts,
|
|
25000, 1, 1, 1, 0, 1.0, "",
|
|
"Shows an OpenGL advanced tunnel screensaver", 0, NULL};
|
|
#endif
|
|
|
|
/* structure for holding the screensaver data */
|
|
typedef struct {
|
|
GLint WIDTH, HEIGHT;
|
|
GLXContext *glx_context;
|
|
} atunnelsstruct;
|
|
|
|
static atunnelsstruct *Atunnels = NULL;
|
|
|
|
/* convenient access to the screen width */
|
|
static GLuint texture[MAX_TEXTURE]; /* Textures */
|
|
|
|
/*=================== Load Texture =========================================*/
|
|
static Bool LoadTexture(ModeInfo * mi, char **fn, int t_num)
|
|
{
|
|
#ifdef HAVE_XPM
|
|
XImage *teximage; /* Texture data */
|
|
|
|
if ((teximage = xpm_to_ximage(MI_DISPLAY(mi), MI_VISUAL(mi),
|
|
MI_COLORMAP(mi), fn)) == None) {
|
|
(void) fprintf(stderr, "Error reading the texture.\n");
|
|
glDeleteTextures(1, &texture[t_num]);
|
|
return False;
|
|
}
|
|
|
|
#ifdef HAVE_GLBINDTEXTURE
|
|
glBindTexture(GL_TEXTURE_2D, texture[t_num]);
|
|
#endif /* HAVE_GLBINDTEXTURE */
|
|
glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
|
|
clear_gl_error();
|
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, teximage->width, teximage->height,
|
|
0, GL_RGBA, GL_UNSIGNED_BYTE, teximage->data);
|
|
if (check_gl_error("texture"))
|
|
return False;
|
|
|
|
/* Texture parameters, LINEAR scaling for better texture quality */
|
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
|
|
|
XDestroyImage(teximage);
|
|
return True;
|
|
#else /* !HAVE_XPM */
|
|
return False;
|
|
#endif /* !HAVE_XPM */
|
|
}
|
|
|
|
/*=================== Main Initialization ==================================*/
|
|
static Bool Init(ModeInfo * mi)
|
|
{
|
|
GLfloat light_ambient[] = {1.0, 1.0, 1.0, 1.0};
|
|
GLfloat light_diffuse[] = {1.0, 1.0, 1.0, 1.0};
|
|
GLfloat light_specular[] = {1.0, 1.0, 1.0, 1.0};
|
|
GLfloat light_position[] = {0.0, 0.0, 1.0, 0.0};
|
|
GLfloat fogColor[4] = {0.8, 0.8, 0.8, 1.0};
|
|
|
|
glClearColor(0, 0, 0, 0);
|
|
#ifdef HAVE_XPM
|
|
if (do_texture)
|
|
{
|
|
glGenTextures(MAX_TEXTURE, texture);
|
|
if (!LoadTexture(mi, texture0,0))
|
|
do_texture = False;
|
|
else if (!LoadTexture(mi, texture1,1))
|
|
do_texture = False;
|
|
else if (!LoadTexture(mi, texture2,2))
|
|
do_texture = False;
|
|
else if (!LoadTexture(mi, texture3,3))
|
|
do_texture = False;
|
|
else if (!LoadTexture(mi, texture4,4))
|
|
do_texture = False;
|
|
else if (!LoadTexture(mi, texture5,5))
|
|
do_texture = False;
|
|
else
|
|
glEnable(GL_TEXTURE_2D);
|
|
}
|
|
#endif
|
|
if (!InitTunnel())
|
|
return False;
|
|
|
|
/* Set lighting parameters */
|
|
if (do_light)
|
|
{
|
|
glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient);
|
|
glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse);
|
|
glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular);
|
|
glLightfv(GL_LIGHT0, GL_POSITION, light_position);
|
|
|
|
/* Enable light 0 */
|
|
glEnable(GL_LIGHT0);
|
|
glDepthFunc(GL_LESS);
|
|
|
|
glEnable(GL_LIGHTING);
|
|
}
|
|
if (do_wire) {
|
|
glDisable(GL_NORMALIZE);
|
|
glDisable(GL_CULL_FACE);
|
|
glDisable(GL_DEPTH_TEST);
|
|
glDisable(GL_TEXTURE_2D);
|
|
glPolygonMode(GL_FRONT,GL_LINE);
|
|
glPolygonMode(GL_BACK,GL_LINE);
|
|
} else {
|
|
glEnable(GL_DEPTH_TEST);
|
|
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
|
|
|
/* Enable fog */
|
|
glFogi(GL_FOG_MODE, GL_EXP);
|
|
glFogfv(GL_FOG_COLOR, fogColor);
|
|
glFogf(GL_FOG_DENSITY, 0.3);
|
|
glEnable(GL_FOG);
|
|
|
|
/* Cull face */
|
|
glCullFace(GL_FRONT);
|
|
glEnable(GL_CULL_FACE);
|
|
}
|
|
|
|
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
|
|
return True;
|
|
}
|
|
|
|
|
|
/* Standard reshape function */
|
|
void
|
|
reshape_atunnels(ModeInfo *mi, int width, int height)
|
|
{
|
|
float a;
|
|
|
|
glViewport((MI_WIDTH(mi) - width) / 2, (MI_HEIGHT(mi) - height) / 2, width, height);
|
|
glMatrixMode(GL_PROJECTION);
|
|
glLoadIdentity();
|
|
a = (float)width/(float)height;
|
|
glFrustum(-0.1*a, 0.1*a, -0.1, 0.1, 0.1, 10);
|
|
glMatrixMode(GL_MODELVIEW);
|
|
}
|
|
|
|
/* draw the screensaver once */
|
|
void draw_atunnels(ModeInfo * mi)
|
|
{
|
|
atunnelsstruct *gp;
|
|
Display *display = MI_DISPLAY(mi);
|
|
Window window = MI_WINDOW(mi);
|
|
|
|
if (Atunnels == NULL)
|
|
return;
|
|
gp = &Atunnels[MI_SCREEN(mi)];
|
|
if (!gp->glx_context)
|
|
return;
|
|
|
|
glXMakeCurrent(display, window, *(gp->glx_context));
|
|
|
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
|
|
|
glLoadIdentity();
|
|
|
|
DrawTunnel(do_texture, do_light, texture);
|
|
SplashScreen(do_wire, do_texture, do_light);
|
|
|
|
glFlush();
|
|
if (MI_IS_FPS(mi)) do_fps (mi);
|
|
glXSwapBuffers(display, window);
|
|
|
|
}
|
|
|
|
void
|
|
refresh_atunnels(ModeInfo * mi)
|
|
{
|
|
}
|
|
|
|
|
|
/* xscreensaver initialization routine */
|
|
void init_atunnels(ModeInfo * mi)
|
|
{
|
|
int screen = MI_SCREEN(mi);
|
|
int size = MI_SIZE(mi);
|
|
atunnelsstruct *gp;
|
|
|
|
if (Atunnels == NULL) {
|
|
if ((Atunnels = (atunnelsstruct *) calloc(MI_NUM_SCREENS(mi), sizeof (atunnelsstruct))) == NULL)
|
|
return;
|
|
}
|
|
gp = &Atunnels[screen];
|
|
|
|
/* Viewport is specified size if size >= MINSIZE && size < screensize */
|
|
if (size <= 1) {
|
|
gp->WIDTH = MI_WIDTH(mi);
|
|
gp->HEIGHT = MI_HEIGHT(mi);
|
|
} else if (size < MINSIZE) {
|
|
gp->WIDTH = MINSIZE;
|
|
gp->HEIGHT = MINSIZE;
|
|
} else {
|
|
gp->WIDTH = (size > MI_WIDTH(mi)) ? MI_WIDTH(mi) : size;
|
|
gp->HEIGHT = (size > MI_HEIGHT(mi)) ? MI_HEIGHT(mi) : size;
|
|
}
|
|
|
|
if ((gp->glx_context = init_GL(mi)) != NULL) {
|
|
reshape_atunnels(mi, gp->WIDTH, gp->HEIGHT);
|
|
glDrawBuffer(GL_BACK);
|
|
(void) Init(mi);
|
|
} else {
|
|
MI_CLEARWINDOW(mi);
|
|
}
|
|
|
|
}
|
|
|
|
/* all sorts of nice cleanup code should go here! */
|
|
void release_atunnels(ModeInfo * mi)
|
|
{
|
|
if (Atunnels != NULL) {
|
|
#if 0
|
|
int screen;
|
|
for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++) {
|
|
atunnelsstruct *gp = &Atunnels[screen];
|
|
FreeTunnel(gp->path);
|
|
}
|
|
#endif
|
|
free(Atunnels);
|
|
Atunnels = NULL;
|
|
}
|
|
FreeAllGL(mi);
|
|
}
|
|
#endif
|
|
|
|
void change_atunnels(ModeInfo * mi)
|
|
{
|
|
atunnelsstruct *gp;
|
|
|
|
if (Atunnels == NULL)
|
|
return;
|
|
gp = &Atunnels[MI_SCREEN(mi)];
|
|
if (!gp->glx_context)
|
|
return;
|
|
|
|
glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(gp->glx_context));
|
|
(void) Init(mi);
|
|
}
|
|
|