* of Mesa (Mesa-3.2/3Dfx/demos/). This mode is the result of the merge of
* two of the David's demos (fire and rain).
*
- * Eric Lassauge (October-10-2000) <lassauge@mail.dotcom.fr>
+ * Eric Lassauge (October-10-2000) <lassauge@users.sourceforge.net>
* http://lassauge.free.fr/linux.html
*
* REVISION HISTORY:
#ifdef STANDALONE /* xscreensaver mode */
-#define PROGCLASS "Fire"
-#define HACK_INIT init_fire
-#define HACK_DRAW draw_fire
-#define HACK_RESHAPE reshape_fire
-#define fire_opts xlockmore_opts
#define DEFAULTS "*delay: 10000 \n" \
"*count: 800 \n" \
"*size: 0 \n" \
- "*trees: 5 \n" \
"*showFPS: False \n" \
- "*trackmouse: False \n" \
- "*wander: True \n" \
"*wireframe: False \n" \
- "*fog: False \n" \
- "*shadows: True \n" \
- "*texture: True \n"
+# define refresh_fire 0
#define MODE_fire
#include "xlockmore.h" /* from the xscreensaver distribution */
+#include "gltrackball.h"
#else /* !STANDALONE */
#include "xlock.h" /* from the xlockmore distribution */
#include "visgl.h"
#define MINSIZE 32
-#include <GL/gl.h>
-#include <GL/glx.h>
-#include <GL/glu.h>
-
-#if defined( USE_XPM ) || defined( USE_XPMINC ) || defined( HAVE_XPM )
+#if defined( USE_XPM ) || defined( USE_XPMINC ) || defined(STANDALONE)
/* USE_XPM & USE_XPMINC in xlock mode ; HAVE_XPM in xscreensaver mode */
#include "xpm-ximage.h"
#define I_HAVE_XPM
#define DEF_FOG "False"
#define DEF_SHADOWS "True"
#define DEF_FRAMERATE "False"
-#define DEF_TRACKMOUSE "False"
#define DEF_WANDER "True"
#define DEF_TREES "5"
#define MAX_TREES 20
static Bool do_texture;
static Bool do_fog;
static Bool do_shadows;
-static Bool do_trackmouse;
static Bool do_wander;
static int num_trees;
-static int frame = 0;
static XFontStruct *mode_font = None;
static XrmOptionDescRec opts[] = {
- {(char *) "-texture", (char *) ".fire.texture", XrmoptionNoArg, (caddr_t) "on"},
- {(char *) "+texture", (char *) ".fire.texture", XrmoptionNoArg, (caddr_t) "off"},
- {(char *) "-fog", (char *) ".fire.fog", XrmoptionNoArg, (caddr_t) "on"},
- {(char *) "+fog", (char *) ".fire.fog", XrmoptionNoArg, (caddr_t) "off"},
- {(char *) "-shadows", (char *) ".fire.shadows", XrmoptionNoArg, (caddr_t) "on"},
- {(char *) "+shadows", (char *) ".fire.shadows", XrmoptionNoArg, (caddr_t) "off"},
- {(char *) "-trackmouse", (char *) ".fire.trackmouse", XrmoptionNoArg, (caddr_t) "on"},
- {(char *) "+trackmouse", (char *) ".fire.trackmouse", XrmoptionNoArg, (caddr_t) "off"},
- {(char *) "-wander", (char *) ".fire.wander", XrmoptionNoArg, (caddr_t) "on"},
- {(char *) "+wander", (char *) ".fire.wander", XrmoptionNoArg, (caddr_t) "off"},
- {(char *) "-trees", (char *) ".fire.trees", XrmoptionSepArg, (caddr_t) NULL},
- {(char *) "-rain", (char *) ".fire.count", XrmoptionNoArg, (caddr_t) "0"},
+ {"-texture", ".fire.texture", XrmoptionNoArg, "on"},
+ {"+texture", ".fire.texture", XrmoptionNoArg, "off"},
+ {"-fog", ".fire.fog", XrmoptionNoArg, "on"},
+ {"+fog", ".fire.fog", XrmoptionNoArg, "off"},
+ {"-shadows", ".fire.shadows", XrmoptionNoArg, "on"},
+ {"+shadows", ".fire.shadows", XrmoptionNoArg, "off"},
+ {"-wander", ".fire.wander", XrmoptionNoArg, "on"},
+ {"+wander", ".fire.wander", XrmoptionNoArg, "off"},
+ {"-trees", ".fire.trees", XrmoptionSepArg, 0},
+ {"-rain", ".fire.count", XrmoptionNoArg, "0"},
};
{&do_texture, "texture", "Texture", DEF_TEXTURE, t_Bool},
{&do_fog, "fog", "Fog", DEF_FOG, t_Bool},
{&do_shadows, "shadows", "Shadows", DEF_SHADOWS, t_Bool},
- {&do_trackmouse, "trackmouse", "TrackMouse", DEF_TRACKMOUSE, t_Bool},
{&do_wander, "wander", "Wander", DEF_WANDER, t_Bool},
{&num_trees, "trees", "Trees", DEF_TREES, t_Int},
};
static OptionStruct desc[] = {
- {(char *) "-/+texture", (char *) "turn on/off texturing"},
- {(char *) "-/+fog", (char *) "turn on/off fog"},
- {(char *) "-/+shadows", (char *) "turn on/off shadows"},
- {(char *) "-/+trackmouse", (char *) "turn on/off the tracking of the mouse"},
- {(char *) "-/+wander", (char *) "turn on/off wandering"},
- {(char *) "-trees num", (char *) "number of trees (0 disables)"},
+ {"-/+texture", "turn on/off texturing"},
+ {"-/+fog", "turn on/off fog"},
+ {"-/+shadows", "turn on/off shadows"},
+ {"-/+wander", "turn on/off wandering"},
+ {"-trees num", "number of trees (0 disables)"},
};
-ModeSpecOpt fire_opts =
+ENTRYPOINT ModeSpecOpt fire_opts =
{ sizeof opts / sizeof opts[0], opts, sizeof vars / sizeof vars[0], vars, desc };
#ifdef USE_MODULES
} rain;
/* colors */
-static float black[3] = { 0.0, 0.0, 0.0 }; /* shadow color */
-static float partcol1[3] = { 1.0, 0.2, 0.0 }; /* initial color: red-ish */
-static float partcol2[3] = { 1.0, 1.0, 0.0 }; /* blending color: yellow-ish */
-static float fogcolor[4] = { 0.9, 0.9, 1.0, 1.0 };
+static const GLfloat black[3] = { 0.0, 0.0, 0.0 }; /* shadow color */
+static const GLfloat partcol1[3] = { 1.0, 0.2, 0.0 }; /* initial color: red-ish */
+static const GLfloat partcol2[3] = { 1.0, 1.0, 0.0 }; /* blending color: yellow-ish */
+static const GLfloat fogcolor[4] = { 0.9, 0.9, 1.0, 1.0 };
/* ground */
-static float q[4][3] = {
+static const float q[4][3] = {
{-DIMP, 0.0, -DIMP},
{DIMP, 0.0, -DIMP},
{DIMP, 0.0, DIMP},
};
/* ground texture */
-static float qt[4][2] = {
+static const float qt[4][2] = {
{-DIMTP, -DIMTP},
{DIMTP, -DIMTP},
{DIMTP, DIMTP},
float v; /* observer velocity */
float alpha; /* observer angles */
float beta;
+
+ trackball_state *trackball;
+ Bool button_down_p;
+ int frame;
+
} firestruct;
/* array of firestruct indexed by screen number */
/* initialise new fire particle */
static void setnewpart(firestruct * fs, part * p)
{
- float a, vi[3], *c;
+ float a, vi[3];
+ const float *c;
p->age = 0;
}
/* draw a tree */
-static void drawtree(float x, float y, float z)
+static int drawtree(float x, float y, float z)
{
+ int polys = 0;
glBegin(GL_QUADS);
glTexCoord2f(0.0,0.0);
glVertex3f(x-1.5,y+0.0,z);
glTexCoord2f(0.0,1.0);
glVertex3f(x-1.5,y+3.0,z);
+ polys++;
glTexCoord2f(0.0,0.0);
glTexCoord2f(0.0,1.0);
glVertex3f(x,y+3.0,z-1.5);
+ polys++;
glEnd();
+ return polys;
}
/* calculate observer position : modified only if trackmouse is used */
}
}
-/* track the mouse in a joystick manner : not perfect but it works */
-static void trackmouse(ModeInfo * mi)
-{
- firestruct *fs = &fire[MI_SCREEN(mi)];
- /* we keep static values (not per screen) for the mouse stuff: in general you have only one mouse :-> */
- static int max[2] = { 0, 0 };
- static int min[2] = { 0x7fffffff, 0x7fffffff }, center[2];
- Window r, c;
- int rx, ry, cx, cy;
- unsigned int m;
-
- (void) XQueryPointer(MI_DISPLAY(mi), MI_WINDOW(mi),
- &r, &c, &rx, &ry, &cx, &cy, &m);
-
- if (max[0] < cx)
- max[0] = cx;
- if (min[0] > cx)
- min[0] = cx;
- center[0] = (max[0] + min[0]) / 2;
-
- if (max[1] < cy)
- max[1] = cy;
- if (min[1] > cy)
- min[1] = cy;
- center[1] = (max[1] + min[1]) / 2;
-
- if (fabs(center[0] - (float) cx) > 0.1 * (max[0] - min[0]))
- fs->alpha += 2.5 * (center[0] - (float) cx) / (max[0] - min[0]);
- if (fabs(center[1] - (float) cy) > 0.1 * (max[1] - min[1]))
- fs->beta += 2.5 * (center[1] - (float) cy) / (max[1] - min[1]);
-
- /* oops: can't get those buttons */
- if (m & Button4Mask)
- fs->v += 0.01;
- if (m & Button5Mask)
- fs->v -= 0.01;
-
-}
/* initialise textures */
static void inittextures(ModeInfo * mi)
*-----------------------------------------------------------------------------
*/
-#ifndef STANDALONE
-static void Reshape(ModeInfo * mi)
-#else
-void reshape_fire(ModeInfo * mi, int width, int height)
-#endif
+ENTRYPOINT void reshape_fire(ModeInfo * mi, int width, int height)
{
firestruct *fs = &fire[MI_SCREEN(mi)];
firestruct *fs = &fire[MI_SCREEN(mi)];
Bool wire = MI_IS_WIREFRAME(mi);
- if (do_trackmouse && !MI_IS_ICONIC(mi))
- trackmouse(mi);
+ mi->polygon_count = 0;
- if (do_wander)
+ if (do_wander && !fs->button_down_p)
{
GLfloat x, y, z;
# define SINOID(SCALE,SIZE) \
- ((((1 + sin((frame * (SCALE)) / 2 * M_PI)) / 2.0) * (SIZE)) - (SIZE)/2)
+ ((((1 + sin((fs->frame * (SCALE)) / 2 * M_PI)) / 2.0) * (SIZE)) - (SIZE)/2)
x = SINOID(0.031, 0.85);
y = SINOID(0.017, 0.25);
z = SINOID(0.023, 0.85);
- frame++;
+ fs->frame++;
fs->obs[0] = x + DEF_OBS[0];
fs->obs[1] = y + DEF_OBS[1];
fs->obs[2] = z + DEF_OBS[2];
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glPushMatrix();
+
calcposobs(fs);
- gluLookAt(fs->obs[0], fs->obs[1], fs->obs[2],
- fs->obs[0] + fs->dir[0], fs->obs[1] + fs->dir[1],
- fs->obs[2] + fs->dir[2], 0.0, 1.0, 0.0);
+ gltrackball_rotate (fs->trackball);
+
+ gluLookAt(fs->obs[0], fs->obs[1], fs->obs[2],
+ fs->obs[0] + fs->dir[0],
+ fs->obs[1] + fs->dir[1],
+ fs->obs[2] + fs->dir[2],
+ 0.0, 1.0, 0.0);
glEnable(GL_TEXTURE_2D);
glVertex3fv(q[2]);
glTexCoord2fv(qt[3]);
glVertex3fv(q[3]);
+ mi->polygon_count++;
glEnd();
glAlphaFunc(GL_GEQUAL, 0.9);
glBindTexture(GL_TEXTURE_2D,fs->treeid);
#endif /* HAVE_GLBINDTEXTURE */
for(j=0;j<fs->num_trees;j++)
- drawtree(fs->treepos[j].x ,fs->treepos[j].y ,fs->treepos[j].z );
+ mi->polygon_count += drawtree(fs->treepos[j].x ,fs->treepos[j].y ,fs->treepos[j].z );
glDisable(GL_ALPHA_TEST);
}
glDisable(GL_TEXTURE_2D);
glColor4f(black[0], black[1], black[2], fs->p[j].c[2][3]);
glVertex3f(fs->p[j].p[2][0], 0.1, fs->p[j].p[2][2]);
+ mi->polygon_count++;
}
glEnd();
}
glColor4fv(fs->p[j].c[2]);
glVertex3fv(fs->p[j].p[2]);
+ mi->polygon_count++;
setpart(fs, &fs->p[j]);
}
glColor4f(0.3f,0.7f,1.0f,1.0f);
glVertex3fv(fs->r[j].pos);
setpartrain(fs, &fs->r[j],timeused);
+ mi->polygon_count++;
}
glEnd();
glShadeModel(GL_FLAT);
fs->eject_r, fs->ridtri);
}
- glShadeModel(GL_FLAT);
- glEnable(GL_DEPTH_TEST);
-
- /* makes particles blend with background */
- if (!MI_IS_WIREFRAME(mi)||(!fs->np))
- {
- glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- }
-
- /* fog stuff */
- glEnable(GL_FOG);
- glFogi(GL_FOG_MODE, GL_EXP);
- glFogfv(GL_FOG_COLOR, fogcolor);
- glFogf(GL_FOG_DENSITY, 0.03);
- glHint(GL_FOG_HINT, GL_NICEST);
-
/* initialise particles and trees */
for (i = 0; i < fs->np; i++) {
setnewpart(fs, &(fs->p[i]));
*-----------------------------------------------------------------------------
*/
-void
+ENTRYPOINT void
init_fire(ModeInfo * mi)
{
firestruct *fs;
else
fs->num_trees = 0;
- /* check wander/trackmouse */
- if (do_trackmouse && do_wander) do_wander = 0;
+ fs->trackball = gltrackball_init ();
/* xlock GL stuff */
if ((fs->glx_context = init_GL(mi)) != NULL) {
* Called by the mainline code periodically to update the display.
*-----------------------------------------------------------------------------
*/
-void draw_fire(ModeInfo * mi)
+ENTRYPOINT void draw_fire(ModeInfo * mi)
{
firestruct *fs = &fire[MI_SCREEN(mi)];
return;
glXMakeCurrent(display, window, *(fs->glx_context));
+
+ glShadeModel(GL_FLAT);
+ glEnable(GL_DEPTH_TEST);
+
+ /* makes particles blend with background */
+ if (!MI_IS_WIREFRAME(mi)||(!fs->np))
+ {
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ }
+
+ /* fog stuff */
+ glEnable(GL_FOG);
+ glFogi(GL_FOG_MODE, GL_EXP);
+ glFogfv(GL_FOG_COLOR, fogcolor);
+ glFogf(GL_FOG_DENSITY, 0.03);
+ glHint(GL_FOG_HINT, GL_NICEST);
+
+ glPushMatrix();
+ glRotatef(current_device_rotation(), 0, 0, 1);
DrawFire(mi);
+ glPopMatrix();
#ifndef STANDALONE
Reshape(mi); /* xlock mode */
#else
*-----------------------------------------------------------------------------
*/
-void release_fire(ModeInfo * mi)
+ENTRYPOINT void release_fire(ModeInfo * mi)
{
if (fire != NULL) {
int screen;
FreeAllGL(mi);
}
-void change_fire(ModeInfo * mi)
+ENTRYPOINT Bool
+fire_handle_event (ModeInfo *mi, XEvent *event)
+{
+ firestruct *fs = &fire[MI_SCREEN(mi)];
+
+ if (event->xany.type == ButtonPress &&
+ event->xbutton.button == Button1)
+ {
+ fs->button_down_p = True;
+ event->xbutton.x = MI_WIDTH(mi) - event->xbutton.x; /* kludge! */
+ event->xbutton.y = MI_HEIGHT(mi) - event->xbutton.y;
+ gltrackball_start (fs->trackball,
+ event->xbutton.x, event->xbutton.y,
+ MI_WIDTH (mi), MI_HEIGHT (mi));
+ return True;
+ }
+ else if (event->xany.type == ButtonRelease &&
+ event->xbutton.button == Button1)
+ {
+ fs->button_down_p = False;
+ return True;
+ }
+ else if (event->xany.type == ButtonPress &&
+ (event->xbutton.button == Button4 ||
+ event->xbutton.button == Button5 ||
+ event->xbutton.button == Button6 ||
+ event->xbutton.button == Button7))
+ {
+ gltrackball_mousewheel (fs->trackball, event->xbutton.button, 5,
+ !!event->xbutton.state);
+ return True;
+ }
+ else if (event->xany.type == MotionNotify &&
+ fs->button_down_p)
+ {
+ event->xmotion.x = MI_WIDTH(mi) - event->xmotion.x; /* kludge! */
+ event->xmotion.y = MI_HEIGHT(mi) - event->xmotion.y;
+ gltrackball_track (fs->trackball,
+ event->xmotion.x, event->xmotion.y,
+ MI_WIDTH (mi), MI_HEIGHT (mi));
+ return True;
+ }
+
+ return False;
+}
+
+
+#ifndef STANDALONE
+ENTRYPOINT void change_fire(ModeInfo * mi)
{
firestruct *fs = &fire[MI_SCREEN(mi)];
fs->eject_r, fs->ridtri);
}
}
+#endif /* !STANDALONE */
+
+XSCREENSAVER_MODULE_2 ("GLForestFire", glforestfire, fire)
+
#endif /* MODE_fire */