~ubuntu-branches/ubuntu/dapper/xscreensaver/dapper

« back to all changes in this revision

Viewing changes to hacks/glx/glforestfire.c

  • Committer: Bazaar Package Importer
  • Author(s): Oliver Grawert
  • Date: 2005-10-11 21:00:42 UTC
  • mfrom: (2.1.1 sarge)
  • Revision ID: james.westby@ubuntu.com-20051011210042-u7q6zslgevdxspr3
Tags: 4.21-4ubuntu17
updated pt_BR again, fixed to UTF-8 

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -*- Mode: C; tab-width: 4 -*- */
 
2
/* fire --- 3D fire or rain landscape */
 
3
 
 
4
#if 0
 
5
static const char sccsid[] = "@(#)fire.c        5.02 2001/09/26 xlockmore";
 
6
#endif
 
7
 
 
8
/* Copyright (c) E. Lassauge, 2001. */
 
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 David Bucciarelli 
 
24
 * (tech.hmw@plus.it) and could be found in the demo package 
 
25
 * of Mesa (Mesa-3.2/3Dfx/demos/). This mode is the result of the merge of
 
26
 * two of the David's demos (fire and rain).
 
27
 *
 
28
 * Eric Lassauge  (October-10-2000) <lassauge@users.sourceforge.net>
 
29
 *                                  http://lassauge.free.fr/linux.html
 
30
 *
 
31
 * REVISION HISTORY:
 
32
 *
 
33
 * E.Lassauge - 26-Sep-2001:
 
34
 *      - add wander option and code 
 
35
 *      - cleanups for xscreensaver
 
36
 *
 
37
 * E.Lassauge - 09-Mar-2001:
 
38
 *      - get rid of my framerate options to use showfps
 
39
 *
 
40
 * E.Lassauge - 12-Jan-2001:
 
41
 *      - add rain particules, selected if count=0 (no fire means rain !)
 
42
 *
 
43
 * E.Lassauge - 28-Nov-2000:
 
44
 *      - modified release part to add freeing of GL objects
 
45
 *
 
46
 * E.Lassauge - 14-Nov-2000:
 
47
 *      - use new common xpm_to_ximage function
 
48
 *
 
49
 * E.Lassauge - 25-Oct-2000:
 
50
 *      - add the trees (with a new resource '-trees')
 
51
 *      - corrected handling of color (textured vs untextured)
 
52
 *      - corrected handling of endiannes for the xpm files
 
53
 *      - inverted ground pixmap file
 
54
 *      - use malloc-ed tree array
 
55
 *
 
56
 * TSchmidt - 23-Oct-2000:
 
57
 *      - added size option like used in sproingies mode
 
58
 *
 
59
 * E.Lassauge - 13-Oct-2000:
 
60
 *      - when trackmouse and window is iconified (login screen): stop tracking
 
61
 *      - add pure GLX handling of framerate display (erased GLUT stuff)
 
62
 *      - made count a per screen variable and update it only if framemode
 
63
 *      - changes for no_texture an wireframe modes
 
64
 *      - change no_texture color for the ground
 
65
 *      - add freeing of texture image
 
66
 *      - misc comments and little tweakings
 
67
 *
 
68
 * TODO:
 
69
 *      - perhaps use a user supplied xpm for ground image (or a whatever image
 
70
 *        file using ImageMagick ?)
 
71
 *      - random number of trees ? change trees at change_fire ?
 
72
 *      - fix wireframe mode: it's too CPU intensive.
 
73
 *      - look how we can get the Wheel events (Button4&5).
 
74
 */
 
75
 
 
76
 
 
77
#ifdef STANDALONE       /* xscreensaver mode */
 
78
#define PROGCLASS       "Fire"
 
79
#define HACK_INIT       init_fire
 
80
#define HACK_DRAW       draw_fire
 
81
#define HACK_RESHAPE    reshape_fire
 
82
#define fire_opts       xlockmore_opts
 
83
#define DEFAULTS "*delay:     10000 \n" \
 
84
                "*count:        800 \n" \
 
85
                "*size:           0 \n" \
 
86
                "*showFPS:    False \n" \
 
87
                "*wireframe:  False \n" \
 
88
 
 
89
#define MODE_fire
 
90
#include "xlockmore.h"          /* from the xscreensaver distribution */
 
91
#else                           /* !STANDALONE */
 
92
#include "xlock.h"              /* from the xlockmore distribution */
 
93
#include "visgl.h"
 
94
#endif                          /* !STANDALONE */
 
95
 
 
96
#ifdef MODE_fire
 
97
 
 
98
#define MINSIZE 32
 
99
 
 
100
#include <GL/gl.h>
 
101
#include <GL/glx.h>
 
102
#include <GL/glu.h>
 
103
 
 
104
#if defined( USE_XPM ) || defined( USE_XPMINC ) || defined( HAVE_XPM )
 
105
/* USE_XPM & USE_XPMINC in xlock mode ; HAVE_XPM in xscreensaver mode */
 
106
#include "xpm-ximage.h"
 
107
#define I_HAVE_XPM
 
108
 
 
109
#ifdef STANDALONE
 
110
#include "../images/ground.xpm"
 
111
#include "../images/tree.xpm"
 
112
#else /* !STANDALONE */
 
113
#include "pixmaps/ground.xpm"
 
114
#include "pixmaps/tree.xpm"
 
115
#endif /* !STANDALONE */
 
116
#endif /* HAVE_XPM */
 
117
 
 
118
/* vector utility macros */
 
119
#define vinit(a,i,j,k) {\
 
120
  (a)[0]=i;\
 
121
  (a)[1]=j;\
 
122
  (a)[2]=k;\
 
123
}
 
124
 
 
125
#define vinit4(a,i,j,k,w) {\
 
126
  (a)[0]=i;\
 
127
  (a)[1]=j;\
 
128
  (a)[2]=k;\
 
129
  (a)[3]=w;\
 
130
}
 
131
 
 
132
#define vadds(a,dt,b) {\
 
133
  (a)[0]+=(dt)*(b)[0];\
 
134
  (a)[1]+=(dt)*(b)[1];\
 
135
  (a)[2]+=(dt)*(b)[2];\
 
136
}
 
137
 
 
138
#define vequ(a,b) {\
 
139
  (a)[0]=(b)[0];\
 
140
  (a)[1]=(b)[1];\
 
141
  (a)[2]=(b)[2];\
 
142
}
 
143
 
 
144
#define vinter(a,dt,b,c) {\
 
145
  (a)[0]=(dt)*(b)[0]+(1.0-dt)*(c)[0];\
 
146
  (a)[1]=(dt)*(b)[1]+(1.0-dt)*(c)[1];\
 
147
  (a)[2]=(dt)*(b)[2]+(1.0-dt)*(c)[2];\
 
148
}
 
149
 
 
150
#define clamp(a)        ((a) < 0.0 ? 0.0 : ((a) < 1.0 ? (a) : 1.0))
 
151
 
 
152
#define vclamp(v) {\
 
153
  (v)[0]=clamp((v)[0]);\
 
154
  (v)[1]=clamp((v)[1]);\
 
155
  (v)[2]=clamp((v)[2]);\
 
156
}
 
157
 
 
158
/* Manage option vars */
 
159
#define DEF_TEXTURE     "True"
 
160
#define DEF_FOG         "False"
 
161
#define DEF_SHADOWS     "True"
 
162
#define DEF_FRAMERATE   "False"
 
163
#define DEF_TRACKMOUSE  "False"
 
164
#define DEF_WANDER      "True"
 
165
#define DEF_TREES       "5"
 
166
#define MAX_TREES       20
 
167
static Bool do_texture;
 
168
static Bool do_fog;
 
169
static Bool do_shadows;
 
170
static Bool do_trackmouse;
 
171
static Bool do_wander;
 
172
static int num_trees;
 
173
static int frame = 0;
 
174
static XFontStruct *mode_font = None;
 
175
 
 
176
static XrmOptionDescRec opts[] = {
 
177
    {"-texture", ".fire.texture", XrmoptionNoArg, "on"},
 
178
    {"+texture", ".fire.texture", XrmoptionNoArg, "off"},
 
179
    {"-fog", ".fire.fog", XrmoptionNoArg, "on"},
 
180
    {"+fog", ".fire.fog", XrmoptionNoArg, "off"},
 
181
    {"-shadows", ".fire.shadows", XrmoptionNoArg, "on"},
 
182
    {"+shadows", ".fire.shadows", XrmoptionNoArg, "off"},
 
183
    {"-trackmouse", ".fire.trackmouse", XrmoptionNoArg, "on"},
 
184
    {"+trackmouse", ".fire.trackmouse", XrmoptionNoArg, "off"},
 
185
    {"-wander", ".fire.wander", XrmoptionNoArg, "on"},
 
186
    {"+wander", ".fire.wander", XrmoptionNoArg, "off"},
 
187
    {"-trees", ".fire.trees", XrmoptionSepArg, 0},
 
188
    {"-rain", ".fire.count", XrmoptionNoArg, "0"},
 
189
 
 
190
};
 
191
 
 
192
static argtype vars[] = {
 
193
    {&do_texture,    "texture",    "Texture",    DEF_TEXTURE,    t_Bool},
 
194
    {&do_fog,        "fog",        "Fog",        DEF_FOG,        t_Bool},
 
195
    {&do_shadows,    "shadows",    "Shadows",    DEF_SHADOWS,    t_Bool},
 
196
    {&do_trackmouse, "trackmouse", "TrackMouse", DEF_TRACKMOUSE, t_Bool},
 
197
    {&do_wander,     "wander",     "Wander",     DEF_WANDER,     t_Bool},
 
198
    {&num_trees,     "trees",      "Trees",      DEF_TREES,      t_Int},
 
199
};
 
200
 
 
201
static OptionStruct desc[] = {
 
202
    {"-/+texture", "turn on/off texturing"},
 
203
    {"-/+fog", "turn on/off fog"},
 
204
    {"-/+shadows", "turn on/off shadows"},
 
205
    {"-/+trackmouse", "turn on/off the tracking of the mouse"},
 
206
    {"-/+wander", "turn on/off wandering"},
 
207
    {"-trees num", "number of trees (0 disables)"},
 
208
};
 
209
 
 
210
ModeSpecOpt fire_opts =
 
211
 { sizeof opts / sizeof opts[0], opts, sizeof vars / sizeof vars[0], vars, desc };
 
212
 
 
213
#ifdef USE_MODULES
 
214
ModStruct fire_description =
 
215
    { "fire", "init_fire", "draw_fire", "release_fire",
 
216
    "draw_fire", "change_fire", (char *) NULL, &fire_opts,
 
217
    10000, 800, 1, 400, 64, 1.0, "",
 
218
    "Shows a 3D fire-like image", 0, NULL
 
219
};
 
220
#endif /* USE_MODULES */
 
221
 
 
222
/* misc defines */
 
223
#define TREEINR         2.5     /* tree min distance */
 
224
#define TREEOUTR        8.0     /* tree max distance */
 
225
#define FRAME           50      /* frame count interval */
 
226
#define DIMP            20.0    /* dimension of ground */
 
227
#define DIMTP           16.0    /* dimension of ground texture */
 
228
 
 
229
#define RIDCOL          0.4     /* factor for color blending */
 
230
 
 
231
#define AGRAV           -9.8    /* gravity */
 
232
 
 
233
#define NUMPART         7500    /* rain particles */
 
234
 
 
235
/* fire particle struct */
 
236
typedef struct {
 
237
    int age;
 
238
    float p[3][3];
 
239
    float v[3];
 
240
    float c[3][4];
 
241
} part;
 
242
 
 
243
/* rain particle struct */
 
244
typedef struct {
 
245
    float age;
 
246
    float acc[3];
 
247
    float vel[3];
 
248
    float pos[3];
 
249
    float partLength;
 
250
    float oldpos[3];
 
251
} rain;
 
252
 
 
253
/* colors */
 
254
static float black[3]    = { 0.0, 0.0, 0.0 }; /* shadow color */
 
255
static float partcol1[3] = { 1.0, 0.2, 0.0 }; /* initial color: red-ish */
 
256
static float partcol2[3] = { 1.0, 1.0, 0.0 }; /* blending color: yellow-ish */
 
257
static float fogcolor[4] = { 0.9, 0.9, 1.0, 1.0 };
 
258
 
 
259
/* ground */
 
260
static float q[4][3] = {
 
261
    {-DIMP, 0.0, -DIMP},
 
262
    {DIMP, 0.0, -DIMP},
 
263
    {DIMP, 0.0, DIMP},
 
264
    {-DIMP, 0.0, DIMP}
 
265
};
 
266
 
 
267
/* ground texture */
 
268
static float qt[4][2] = {
 
269
    {-DIMTP, -DIMTP},
 
270
    {DIMTP, -DIMTP},
 
271
    {DIMTP, DIMTP},
 
272
    {-DIMTP, DIMTP}
 
273
};
 
274
 
 
275
/* default values for observer */
 
276
static const float DEF_OBS[3] = { 2.0f, 1.0f, 0.0f };
 
277
#define DEV_V           0.0
 
278
#define DEF_ALPHA       -90.0
 
279
#define DEF_BETA        90.0
 
280
 
 
281
/* tree struct */
 
282
typedef struct {
 
283
    float x,y,z;
 
284
} treestruct;
 
285
 
 
286
/* the mode struct, contains all per screen variables */
 
287
typedef struct {
 
288
    GLint WIDTH, HEIGHT;        /* display dimensions */
 
289
    GLXContext *glx_context;
 
290
 
 
291
    int np;                     /* number of fire particles : set it through 'count' resource */
 
292
    float eject_r;              /* emission radius */
 
293
    float dt, maxage, eject_vy, eject_vl;
 
294
    float ridtri;               /* fire particle size */
 
295
    Bool shadows;               /* misc booleans: set them through specific resources */
 
296
    Bool fog;
 
297
 
 
298
    part *p;                    /* fire particles array */
 
299
    rain *r;                    /* rain particles array */
 
300
 
 
301
    XImage *gtexture;           /* ground texture image bits */
 
302
    XImage *ttexture;           /* tree texture image bits */
 
303
    GLuint groundid;            /* ground texture id: GL world */
 
304
    GLuint treeid;              /* tree texture id: GL world */
 
305
    GLuint fontbase;            /* fontbase id: GL world */
 
306
 
 
307
    int   num_trees;            /* number of trees: set it through 'trees' resource */
 
308
    treestruct *treepos;        /* trees positions: float treepos[num_trees][3] */
 
309
 
 
310
    float min[3];               /* raining area */
 
311
    float max[3];
 
312
 
 
313
    float obs[3];               /* observer coordinates */
 
314
    float dir[3];               /* view direction */
 
315
    float v;                    /* observer velocity */
 
316
    float alpha;                /* observer angles */
 
317
    float beta;
 
318
} firestruct;
 
319
 
 
320
/* array of firestruct indexed by screen number */
 
321
static firestruct *fire = (firestruct *) NULL;
 
322
 
 
323
/*
 
324
 *-----------------------------------------------------------------------------
 
325
 *-----------------------------------------------------------------------------
 
326
 *    Misc funcs.
 
327
 *-----------------------------------------------------------------------------
 
328
 *-----------------------------------------------------------------------------
 
329
 */
 
330
 
 
331
/* utility function for the rain particles */
 
332
static float gettimerain(void)
 
333
{
 
334
#if 0
 
335
  /* Oh yeah, *that's* portable!  WTF. */
 
336
  /* 
 
337
   * I really thought clock() was standard ... EL
 
338
   * I found this on the net:
 
339
   * The clock() function conforms to ISO/IEC 9899:1990 (``ISO C89'') 
 
340
   * */
 
341
 
 
342
  static clock_t told= (clock_t)0;
 
343
  clock_t tnew,ris;
 
344
 
 
345
  tnew=clock();
 
346
 
 
347
  ris=tnew-told;
 
348
 
 
349
  told=tnew;
 
350
 
 
351
  return (0.0125 + ris/(float)CLOCKS_PER_SEC);
 
352
#else
 
353
  return 0.0150;
 
354
#endif
 
355
}
 
356
 
 
357
/* my RAND */
 
358
static float vrnd(void)
 
359
{
 
360
    return ((float) LRAND() / (float) MAXRAND);
 
361
}
 
362
 
 
363
/* initialise new fire particle */
 
364
static void setnewpart(firestruct * fs, part * p)
 
365
{
 
366
    float a, vi[3], *c;
 
367
 
 
368
    p->age = 0;
 
369
 
 
370
    a = vrnd() * M_PI * 2.0;
 
371
 
 
372
    vinit(vi, sin(a) * fs->eject_r * vrnd(), 0.15, cos(a) * fs->eject_r * vrnd());
 
373
    vinit(p->p[0], vi[0] + vrnd() * fs->ridtri, vi[1] + vrnd() * fs->ridtri, vi[2] + vrnd() * fs->ridtri);
 
374
    vinit(p->p[1], vi[0] + vrnd() * fs->ridtri, vi[1] + vrnd() * fs->ridtri, vi[2] + vrnd() * fs->ridtri);
 
375
    vinit(p->p[2], vi[0] + vrnd() * fs->ridtri, vi[1] + vrnd() * fs->ridtri, vi[2] + vrnd() * fs->ridtri);
 
376
 
 
377
    vinit(p->v, vi[0] * fs->eject_vl / (fs->eject_r / 2),
 
378
          vrnd() * fs->eject_vy + fs->eject_vy / 2,
 
379
          vi[2] * fs->eject_vl / (fs->eject_r / 2));
 
380
 
 
381
    c = partcol1;
 
382
 
 
383
    vinit4(p->c[0], c[0] * ((1.0 - RIDCOL) + vrnd() * RIDCOL),
 
384
           c[1] * ((1.0 - RIDCOL) + vrnd() * RIDCOL),
 
385
           c[2] * ((1.0 - RIDCOL) + vrnd() * RIDCOL), 1.0);
 
386
    vinit4(p->c[1], c[0] * ((1.0 - RIDCOL) + vrnd() * RIDCOL),
 
387
           c[1] * ((1.0 - RIDCOL) + vrnd() * RIDCOL),
 
388
           c[2] * ((1.0 - RIDCOL) + vrnd() * RIDCOL), 1.0);
 
389
    vinit4(p->c[2], c[0] * ((1.0 - RIDCOL) + vrnd() * RIDCOL),
 
390
           c[1] * ((1.0 - RIDCOL) + vrnd() * RIDCOL),
 
391
           c[2] * ((1.0 - RIDCOL) + vrnd() * RIDCOL), 1.0);
 
392
}
 
393
 
 
394
/* initialise new rain particle */
 
395
static void setnewrain(firestruct * fs, rain * r)
 
396
{
 
397
    r->age=0.0f;
 
398
 
 
399
    vinit(r->acc,0.0f,-0.98f,0.0f);
 
400
    vinit(r->vel,0.0f,0.0f,0.0f);
 
401
    
 
402
    r->partLength=0.2f;
 
403
 
 
404
    vinit(r->oldpos,fs->min[0]+(fs->max[0]-fs->min[0])*vrnd(),
 
405
                    fs->max[1]+0.2f*fs->max[1]*vrnd(),
 
406
                    fs->min[2]+(fs->max[2]-fs->min[2])*vrnd());
 
407
    vequ(r->pos,r->oldpos);
 
408
    vadds(r->oldpos,-(r->partLength),r->vel);
 
409
 
 
410
    r->pos[1]=(fs->max[1]-fs->min[1])*vrnd()+fs->min[1];
 
411
    r->oldpos[1]=r->pos[1]-r->partLength*r->vel[1];
 
412
}
 
413
 
 
414
/* set fire particle values */
 
415
static void setpart(firestruct * fs, part * p)
 
416
{
 
417
    float fact;
 
418
 
 
419
    if (p->p[0][1] < 0.1) {
 
420
        setnewpart(fs, p);
 
421
        return;
 
422
    }
 
423
 
 
424
    p->v[1] += AGRAV * fs->dt;
 
425
 
 
426
    vadds(p->p[0], fs->dt, p->v);
 
427
    vadds(p->p[1], fs->dt, p->v);
 
428
    vadds(p->p[2], fs->dt, p->v);
 
429
 
 
430
    p->age++;
 
431
 
 
432
    if ((p->age) > fs->maxage) {
 
433
        vequ(p->c[0], partcol2);
 
434
        vequ(p->c[1], partcol2);
 
435
        vequ(p->c[2], partcol2);
 
436
    } else {
 
437
        fact = 1.0 / fs->maxage;
 
438
        vadds(p->c[0], fact, partcol2);
 
439
        vclamp(p->c[0]);
 
440
        p->c[0][3] = fact * (fs->maxage - p->age);
 
441
 
 
442
        vadds(p->c[1], fact, partcol2);
 
443
        vclamp(p->c[1]);
 
444
        p->c[1][3] = fact * (fs->maxage - p->age);
 
445
 
 
446
        vadds(p->c[2], fact, partcol2);
 
447
        vclamp(p->c[2]);
 
448
        p->c[2][3] = fact * (fs->maxage - p->age);
 
449
    }
 
450
}
 
451
 
 
452
/* set rain particle values */
 
453
static void setpartrain(firestruct * fs, rain * r, float dt)
 
454
{
 
455
    r->age += dt;
 
456
 
 
457
    vadds(r->vel,dt,r->acc);
 
458
    vadds(r->pos,dt,r->vel);
 
459
 
 
460
    if(r->pos[0]<fs->min[0])
 
461
        r->pos[0]=fs->max[0]-(fs->min[0]-r->pos[0]);
 
462
    if(r->pos[2]<fs->min[2])
 
463
        r->pos[2]=fs->max[2]-(fs->min[2]-r->pos[2]);
 
464
 
 
465
    if(r->pos[0]>fs->max[0])
 
466
        r->pos[0]=fs->min[0]+(r->pos[0]-fs->max[0]);
 
467
    if(r->pos[2]>fs->max[2])
 
468
        r->pos[2]=fs->min[2]+(r->pos[2]-fs->max[2]);
 
469
 
 
470
    vequ(r->oldpos,r->pos);
 
471
    vadds(r->oldpos,-(r->partLength),r->vel);
 
472
    if(r->pos[1]<fs->min[1])
 
473
        setnewrain(fs, r);
 
474
}
 
475
 
 
476
/* draw a tree */
 
477
static void drawtree(float x, float y, float z)
 
478
{
 
479
    glBegin(GL_QUADS);
 
480
    glTexCoord2f(0.0,0.0);
 
481
    glVertex3f(x-1.5,y+0.0,z);
 
482
 
 
483
    glTexCoord2f(1.0,0.0);
 
484
    glVertex3f(x+1.5,y+0.0,z);
 
485
 
 
486
    glTexCoord2f(1.0,1.0);
 
487
    glVertex3f(x+1.5,y+3.0,z);
 
488
 
 
489
    glTexCoord2f(0.0,1.0);
 
490
    glVertex3f(x-1.5,y+3.0,z);
 
491
 
 
492
 
 
493
    glTexCoord2f(0.0,0.0);
 
494
    glVertex3f(x,y+0.0,z-1.5);
 
495
 
 
496
    glTexCoord2f(1.0,0.0);
 
497
    glVertex3f(x,y+0.0,z+1.5);
 
498
 
 
499
    glTexCoord2f(1.0,1.0);
 
500
    glVertex3f(x,y+3.0,z+1.5);
 
501
 
 
502
    glTexCoord2f(0.0,1.0);
 
503
    glVertex3f(x,y+3.0,z-1.5);
 
504
 
 
505
    glEnd();
 
506
 
 
507
}
 
508
 
 
509
/* calculate observer position : modified only if trackmouse is used */
 
510
static void calcposobs(firestruct * fs)
 
511
{
 
512
    fs->dir[0] = sin(fs->alpha * M_PI / 180.0);
 
513
    fs->dir[2] =
 
514
        cos(fs->alpha * M_PI / 180.0) * sin(fs->beta * M_PI / 180.0);
 
515
    fs->dir[1] = cos(fs->beta * M_PI / 180.0);
 
516
 
 
517
    fs->obs[0] += fs->v * fs->dir[0];
 
518
    fs->obs[1] += fs->v * fs->dir[1];
 
519
    fs->obs[2] += fs->v * fs->dir[2];
 
520
 
 
521
    if (!fs->np)
 
522
    {
 
523
        vinit(fs->min,fs->obs[0]-7.0f,-0.2f,fs->obs[2]-7.0f);
 
524
        vinit(fs->max,fs->obs[0]+7.0f,8.0f,fs->obs[2]+7.0f);
 
525
    }
 
526
}
 
527
 
 
528
/* track the mouse in a joystick manner : not perfect but it works */
 
529
static void trackmouse(ModeInfo * mi)
 
530
{
 
531
    firestruct *fs = &fire[MI_SCREEN(mi)];
 
532
    /* we keep static values (not per screen) for the mouse stuff: in general you have only one mouse :-> */
 
533
    static int max[2] = { 0, 0 };
 
534
    static int min[2] = { 0x7fffffff, 0x7fffffff }, center[2];
 
535
    Window r, c;
 
536
    int rx, ry, cx, cy;
 
537
    unsigned int m;
 
538
 
 
539
    (void) XQueryPointer(MI_DISPLAY(mi), MI_WINDOW(mi),
 
540
                         &r, &c, &rx, &ry, &cx, &cy, &m);
 
541
 
 
542
    if (max[0] < cx)
 
543
        max[0] = cx;
 
544
    if (min[0] > cx)
 
545
        min[0] = cx;
 
546
    center[0] = (max[0] + min[0]) / 2;
 
547
 
 
548
    if (max[1] < cy)
 
549
        max[1] = cy;
 
550
    if (min[1] > cy)
 
551
        min[1] = cy;
 
552
    center[1] = (max[1] + min[1]) / 2;
 
553
 
 
554
    if (fabs(center[0] - (float) cx) > 0.1 * (max[0] - min[0]))
 
555
        fs->alpha += 2.5 * (center[0] - (float) cx) / (max[0] - min[0]);
 
556
    if (fabs(center[1] - (float) cy) > 0.1 * (max[1] - min[1]))
 
557
        fs->beta += 2.5 * (center[1] - (float) cy) / (max[1] - min[1]);
 
558
 
 
559
    /* oops: can't get those buttons */
 
560
    if (m & Button4Mask)
 
561
        fs->v += 0.01;
 
562
    if (m & Button5Mask)
 
563
        fs->v -= 0.01;
 
564
 
 
565
}
 
566
 
 
567
/* initialise textures */
 
568
static void inittextures(ModeInfo * mi)
 
569
{
 
570
    firestruct *fs = &fire[MI_SCREEN(mi)];
 
571
 
 
572
#if defined( I_HAVE_XPM )
 
573
    if (do_texture) {
 
574
 
 
575
        glGenTextures(1, &fs->groundid);
 
576
#ifdef HAVE_GLBINDTEXTURE
 
577
        glBindTexture(GL_TEXTURE_2D, fs->groundid);
 
578
#endif /* HAVE_GLBINDTEXTURE */
 
579
 
 
580
        if ((fs->gtexture = xpm_to_ximage(MI_DISPLAY(mi), MI_VISUAL(mi),
 
581
                         MI_COLORMAP(mi), ground)) == None) {
 
582
            (void) fprintf(stderr, "Error reading the ground texture.\n");
 
583
            glDeleteTextures(1, &fs->groundid);
 
584
            do_texture = False;
 
585
            fs->groundid = 0;
 
586
            fs->treeid   = 0;
 
587
            return;
 
588
        }
 
589
 
 
590
        glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
 
591
    clear_gl_error();
 
592
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
 
593
                 fs->gtexture->width, fs->gtexture->height, 0,
 
594
                 GL_RGBA,
 
595
                 /* GL_UNSIGNED_BYTE, */
 
596
                 GL_UNSIGNED_INT_8_8_8_8_REV,
 
597
                 fs->gtexture->data);
 
598
    check_gl_error("texture");
 
599
 
 
600
        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
 
601
        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
 
602
 
 
603
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
 
604
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
 
605
 
 
606
        glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
 
607
 
 
608
        if (fs->num_trees)
 
609
        {
 
610
            glGenTextures(1, &fs->treeid);
 
611
#ifdef HAVE_GLBINDTEXTURE
 
612
            glBindTexture(GL_TEXTURE_2D,fs->treeid);
 
613
#endif /* HAVE_GLBINDTEXTURE */
 
614
            if ((fs->ttexture = xpm_to_ximage(MI_DISPLAY(mi), MI_VISUAL(mi),
 
615
                         MI_COLORMAP(mi), tree)) == None) {
 
616
              (void)fprintf(stderr,"Error reading tree texture.\n");
 
617
              glDeleteTextures(1, &fs->treeid);
 
618
              fs->treeid    = 0;
 
619
              fs->num_trees = 0; 
 
620
              return;
 
621
            }
 
622
 
 
623
        clear_gl_error();
 
624
            glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
 
625
                     fs->ttexture->width, fs->ttexture->height, 0,
 
626
                     GL_RGBA,
 
627
                     /* GL_UNSIGNED_BYTE, */
 
628
                     GL_UNSIGNED_INT_8_8_8_8_REV,
 
629
                     fs->ttexture->data);
 
630
        check_gl_error("texture");
 
631
 
 
632
            glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
 
633
            glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
 
634
 
 
635
            glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
 
636
            glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
 
637
 
 
638
            glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MODULATE);
 
639
        }
 
640
    }
 
641
    else
 
642
    {
 
643
        fs->groundid = 0;       /* default textures */
 
644
        fs->treeid   = 0;
 
645
    }
 
646
#else /* !I_HAVE_XPM */
 
647
  do_texture = False;
 
648
  fs->groundid = 0;       /* default textures */
 
649
  fs->treeid = 0;
 
650
#endif /* !I_HAVE_XPM */
 
651
}
 
652
 
 
653
/* init tree array and positions */
 
654
static Bool inittree(ModeInfo * mi)
 
655
{
 
656
    firestruct *fs = &fire[MI_SCREEN(mi)];
 
657
    int i;
 
658
    float dist;
 
659
 
 
660
    /* allocate treepos array */
 
661
    if ((fs->treepos = (treestruct *) malloc(fs->num_trees *
 
662
                                        sizeof(treestruct))) == NULL) {
 
663
                return False;
 
664
    }
 
665
    /* initialise positions */
 
666
    for(i=0;i<fs->num_trees;i++)
 
667
        do {
 
668
            fs->treepos[i].x =vrnd()*TREEOUTR*2.0-TREEOUTR;
 
669
            fs->treepos[i].y =0.0;
 
670
            fs->treepos[i].z =vrnd()*TREEOUTR*2.0-TREEOUTR;
 
671
            dist=sqrt(fs->treepos[i].x *fs->treepos[i].x +fs->treepos[i].z *fs->treepos[i].z );
 
672
        } while((dist<TREEINR) || (dist>TREEOUTR));
 
673
        return True;
 
674
}
 
675
 
 
676
/*
 
677
 *-----------------------------------------------------------------------------
 
678
 *-----------------------------------------------------------------------------
 
679
 *    GL funcs.
 
680
 *-----------------------------------------------------------------------------
 
681
 *-----------------------------------------------------------------------------
 
682
 */
 
683
 
 
684
#ifndef STANDALONE
 
685
static void Reshape(ModeInfo * mi)
 
686
#else
 
687
void reshape_fire(ModeInfo * mi, int width, int height)
 
688
#endif
 
689
{
 
690
 
 
691
    firestruct *fs = &fire[MI_SCREEN(mi)];
 
692
    int size = MI_SIZE(mi);
 
693
 
 
694
    /* Viewport is specified size if size >= MINSIZE && size < screensize */
 
695
    if (size <= 1) {
 
696
        fs->WIDTH = MI_WIDTH(mi);
 
697
        fs->HEIGHT = MI_HEIGHT(mi);
 
698
    } else if (size < MINSIZE) {
 
699
        fs->WIDTH = MINSIZE;
 
700
        fs->HEIGHT = MINSIZE;
 
701
    } else {
 
702
        fs->WIDTH = (size > MI_WIDTH(mi)) ? MI_WIDTH(mi) : size;
 
703
        fs->HEIGHT = (size > MI_HEIGHT(mi)) ? MI_HEIGHT(mi) : size;
 
704
    }
 
705
    glViewport((MI_WIDTH(mi) - fs->WIDTH) / 2, (MI_HEIGHT(mi) - fs->HEIGHT) / 2, fs->WIDTH, fs->HEIGHT);
 
706
    glMatrixMode(GL_PROJECTION);
 
707
    glLoadIdentity();
 
708
    gluPerspective(70.0, fs->WIDTH / (float) fs->HEIGHT, 0.1, 30.0);
 
709
 
 
710
    glMatrixMode(GL_MODELVIEW);
 
711
 
 
712
}
 
713
 
 
714
static void DrawFire(ModeInfo * mi)
 
715
{
 
716
    int j;
 
717
    firestruct *fs = &fire[MI_SCREEN(mi)];
 
718
    Bool wire = MI_IS_WIREFRAME(mi);
 
719
 
 
720
    if (do_trackmouse && !MI_IS_ICONIC(mi))
 
721
        trackmouse(mi);
 
722
 
 
723
    if (do_wander)
 
724
    {
 
725
        GLfloat x, y, z;
 
726
 
 
727
#       define SINOID(SCALE,SIZE) \
 
728
        ((((1 + sin((frame * (SCALE)) / 2 * M_PI)) / 2.0) * (SIZE)) - (SIZE)/2)
 
729
 
 
730
        x = SINOID(0.031, 0.85);
 
731
        y = SINOID(0.017, 0.25);
 
732
        z = SINOID(0.023, 0.85);
 
733
        frame++;
 
734
        fs->obs[0] = x + DEF_OBS[0];
 
735
        fs->obs[1] = y + DEF_OBS[1];
 
736
        fs->obs[2] = z + DEF_OBS[2];
 
737
        fs->dir[1] = y;
 
738
        fs->dir[2] = z;
 
739
    }
 
740
 
 
741
    glEnable(GL_DEPTH_TEST);
 
742
 
 
743
    if (fs->fog)
 
744
        glEnable(GL_FOG);
 
745
    else
 
746
        glDisable(GL_FOG);
 
747
 
 
748
    glDepthMask(GL_TRUE);
 
749
    glClearColor(0.5, 0.5, 0.8, 1.0);   /* sky in the distance */
 
750
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 
751
 
 
752
    glPushMatrix();
 
753
    calcposobs(fs);
 
754
    gluLookAt(fs->obs[0], fs->obs[1], fs->obs[2],
 
755
              fs->obs[0] + fs->dir[0], fs->obs[1] + fs->dir[1],
 
756
              fs->obs[2] + fs->dir[2], 0.0, 1.0, 0.0);
 
757
 
 
758
 
 
759
    glEnable(GL_TEXTURE_2D);
 
760
 
 
761
    /* draw ground using the computed texture */
 
762
    if (do_texture) {
 
763
        glColor4f(1.0,1.0,1.0,1.0);     /* white to get texture in it's true color */
 
764
#ifdef HAVE_GLBINDTEXTURE
 
765
        glBindTexture(GL_TEXTURE_2D, fs->groundid);
 
766
#endif /* HAVE_GLBINDTEXTURE */
 
767
    }
 
768
    else
 
769
        glColor4f(0.54, 0.27, 0.07, 1.0);       /* untextured ground color */
 
770
    glBegin(GL_QUADS);
 
771
    glTexCoord2fv(qt[0]);
 
772
    glVertex3fv(q[0]);
 
773
    glTexCoord2fv(qt[1]);
 
774
    glVertex3fv(q[1]);
 
775
    glTexCoord2fv(qt[2]);
 
776
    glVertex3fv(q[2]);
 
777
    glTexCoord2fv(qt[3]);
 
778
    glVertex3fv(q[3]);
 
779
    glEnd();
 
780
 
 
781
    glAlphaFunc(GL_GEQUAL, 0.9);
 
782
    if (fs->num_trees)
 
783
    {
 
784
        /* here do_texture IS True - and color used is white */
 
785
        glEnable(GL_ALPHA_TEST);
 
786
#ifdef HAVE_GLBINDTEXTURE
 
787
        glBindTexture(GL_TEXTURE_2D,fs->treeid);
 
788
#endif /* HAVE_GLBINDTEXTURE */
 
789
        for(j=0;j<fs->num_trees;j++)
 
790
            drawtree(fs->treepos[j].x ,fs->treepos[j].y ,fs->treepos[j].z );
 
791
        glDisable(GL_ALPHA_TEST);
 
792
    }
 
793
    glDisable(GL_TEXTURE_2D);
 
794
    glDepthMask(GL_FALSE);
 
795
 
 
796
    if (fs->shadows) {
 
797
        /* draw shadows with black color */
 
798
        glBegin(wire ? GL_LINE_STRIP : GL_TRIANGLES);
 
799
        for (j = 0; j < fs->np; j++) {
 
800
            glColor4f(black[0], black[1], black[2], fs->p[j].c[0][3]);
 
801
            glVertex3f(fs->p[j].p[0][0], 0.1, fs->p[j].p[0][2]);
 
802
 
 
803
            glColor4f(black[0], black[1], black[2], fs->p[j].c[1][3]);
 
804
            glVertex3f(fs->p[j].p[1][0], 0.1, fs->p[j].p[1][2]);
 
805
 
 
806
            glColor4f(black[0], black[1], black[2], fs->p[j].c[2][3]);
 
807
            glVertex3f(fs->p[j].p[2][0], 0.1, fs->p[j].p[2][2]);
 
808
        }
 
809
        glEnd();
 
810
    }
 
811
 
 
812
    glBegin(wire ? GL_LINE_STRIP : GL_TRIANGLES);
 
813
    for (j = 0; j < fs->np; j++) {
 
814
        /* draw particles: colors are computed in setpart */
 
815
        glColor4fv(fs->p[j].c[0]);
 
816
        glVertex3fv(fs->p[j].p[0]);
 
817
 
 
818
        glColor4fv(fs->p[j].c[1]);
 
819
        glVertex3fv(fs->p[j].p[1]);
 
820
 
 
821
        glColor4fv(fs->p[j].c[2]);
 
822
        glVertex3fv(fs->p[j].p[2]);
 
823
 
 
824
        setpart(fs, &fs->p[j]);
 
825
    }
 
826
    glEnd();
 
827
 
 
828
    /* draw rain particles if no fire particles */
 
829
    if (!fs->np)
 
830
    {
 
831
        float timeused = gettimerain();
 
832
        glDisable(GL_TEXTURE_2D);
 
833
        glShadeModel(GL_SMOOTH);
 
834
        glBegin(GL_LINES);
 
835
        for (j = 0; j < NUMPART; j++) {
 
836
            glColor4f(0.7f,0.95f,1.0f,0.0f);
 
837
            glVertex3fv(fs->r[j].oldpos);
 
838
            glColor4f(0.3f,0.7f,1.0f,1.0f);
 
839
            glVertex3fv(fs->r[j].pos);
 
840
            setpartrain(fs, &fs->r[j],timeused);
 
841
        }
 
842
        glEnd();
 
843
        glShadeModel(GL_FLAT);
 
844
    }
 
845
 
 
846
    glDisable(GL_TEXTURE_2D);
 
847
    glDisable(GL_ALPHA_TEST);
 
848
    glDisable(GL_DEPTH_TEST);
 
849
    glDisable(GL_FOG);
 
850
 
 
851
    /* manage framerate display */
 
852
    if (MI_IS_FPS(mi)) do_fps (mi);
 
853
    glPopMatrix();
 
854
}
 
855
 
 
856
 
 
857
static Bool Init(ModeInfo * mi)
 
858
{
 
859
    int i;
 
860
    firestruct *fs = &fire[MI_SCREEN(mi)];
 
861
 
 
862
    /* default settings */
 
863
    fs->eject_r = 0.1 + NRAND(10) * 0.03;
 
864
    fs->dt = 0.015;
 
865
    fs->eject_vy = 4;
 
866
    fs->eject_vl = 1;
 
867
    fs->ridtri = 0.1 + NRAND(10) * 0.005;
 
868
    fs->maxage = 1.0 / fs->dt;
 
869
    vinit(fs->obs, DEF_OBS[0], DEF_OBS[1], DEF_OBS[2]);
 
870
    fs->v = 0.0;
 
871
    fs->alpha = DEF_ALPHA;
 
872
    fs->beta = DEF_BETA;
 
873
 
 
874
    /* initialise texture stuff */
 
875
    if (do_texture)
 
876
        inittextures(mi);
 
877
    else
 
878
    {
 
879
        fs->ttexture = (XImage*) NULL;
 
880
        fs->gtexture = (XImage*) NULL;
 
881
    }
 
882
 
 
883
    if (MI_IS_DEBUG(mi)) {
 
884
        (void) fprintf(stderr,
 
885
                       "%s:\n\tnum_part=%d\n\ttrees=%d\n\tfog=%s\n\tshadows=%s\n\teject_r=%.3f\n\tridtri=%.3f\n",
 
886
                       MI_NAME(mi),
 
887
                       fs->np,
 
888
                       fs->num_trees,
 
889
                       fs->fog ? "on" : "off",
 
890
                       fs->shadows ? "on" : "off",
 
891
                       fs->eject_r, fs->ridtri);
 
892
    }
 
893
 
 
894
    glShadeModel(GL_FLAT);
 
895
    glEnable(GL_DEPTH_TEST);
 
896
 
 
897
    /* makes particles blend with background */
 
898
    if (!MI_IS_WIREFRAME(mi)||(!fs->np))
 
899
    {
 
900
        glEnable(GL_BLEND);
 
901
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
 
902
    }
 
903
 
 
904
    /* fog stuff */
 
905
    glEnable(GL_FOG);
 
906
    glFogi(GL_FOG_MODE, GL_EXP);
 
907
    glFogfv(GL_FOG_COLOR, fogcolor);
 
908
    glFogf(GL_FOG_DENSITY, 0.03);
 
909
    glHint(GL_FOG_HINT, GL_NICEST);
 
910
 
 
911
    /* initialise particles and trees */
 
912
    for (i = 0; i < fs->np; i++) {
 
913
        setnewpart(fs, &(fs->p[i]));
 
914
    }
 
915
 
 
916
    if (fs->num_trees)
 
917
        if (!inittree(mi)) {
 
918
                return False;
 
919
        }
 
920
 
 
921
    /* if no fire particles then initialise rain particles */
 
922
    if (!fs->np)
 
923
    {
 
924
        vinit(fs->min,-7.0f,-0.2f,-7.0f);
 
925
        vinit(fs->max,7.0f,8.0f,7.0f);
 
926
        for (i = 0; i < NUMPART; i++) {
 
927
            setnewrain(fs, &(fs->r[i]));
 
928
        }
 
929
    }
 
930
    
 
931
    return True;
 
932
}
 
933
 
 
934
/*
 
935
 *-----------------------------------------------------------------------------
 
936
 *-----------------------------------------------------------------------------
 
937
 *    Xlock hooks.
 
938
 *-----------------------------------------------------------------------------
 
939
 *-----------------------------------------------------------------------------
 
940
 */
 
941
 
 
942
 
 
943
static void
 
944
free_fire(firestruct *fs)
 
945
{
 
946
        if (mode_font != None && fs->fontbase != None) {
 
947
                glDeleteLists(fs->fontbase, mode_font->max_char_or_byte2 -
 
948
                        mode_font->min_char_or_byte2 + 1);
 
949
                fs->fontbase = None;
 
950
        }
 
951
 
 
952
        if (fs->p != NULL) {
 
953
                (void) free((void *) fs->p);
 
954
                fs->p = (part *) NULL;
 
955
        }
 
956
        if (fs->r != NULL) {
 
957
                (void) free((void *) fs->r);
 
958
                fs->r = (rain *) NULL;
 
959
        }
 
960
        if (fs->treepos != NULL) {
 
961
                (void) free((void *) fs->treepos);
 
962
                fs->treepos = (treestruct *) NULL;
 
963
        }
 
964
        if (fs->ttexture != None) {
 
965
                glDeleteTextures(1, &fs->treeid);
 
966
                XDestroyImage(fs->ttexture);
 
967
                fs->ttexture = None;
 
968
        }
 
969
        if (fs->gtexture != None) {
 
970
                glDeleteTextures(1, &fs->groundid);
 
971
                XDestroyImage(fs->gtexture);
 
972
                fs->gtexture = None;
 
973
        }
 
974
}
 
975
 
 
976
/*
 
977
 *-----------------------------------------------------------------------------
 
978
 *    Initialize fire.  Called each time the window changes.
 
979
 *-----------------------------------------------------------------------------
 
980
 */
 
981
 
 
982
void
 
983
init_fire(ModeInfo * mi)
 
984
{
 
985
    firestruct *fs;
 
986
 
 
987
    /* allocate the main fire table if needed */
 
988
    if (fire == NULL) {
 
989
        if ((fire = (firestruct *) calloc(MI_NUM_SCREENS(mi),
 
990
                                          sizeof(firestruct))) == NULL)
 
991
            return;
 
992
    }
 
993
 
 
994
    /* initialise the per screen fire structure */
 
995
    fs = &fire[MI_SCREEN(mi)];
 
996
    fs->np = MI_COUNT(mi);
 
997
    fs->fog = do_fog;
 
998
    fs->shadows = do_shadows;
 
999
    /* initialise fire particles if any */
 
1000
    if ((fs->np)&&(fs->p == NULL)) {
 
1001
        if ((fs->p = (part *) calloc(fs->np, sizeof(part))) == NULL) {
 
1002
            free_fire(fs);
 
1003
            return;
 
1004
        }
 
1005
    }
 
1006
    else if (fs->r == NULL) {
 
1007
        /* initialise rain particles if no fire particles */
 
1008
        if ((fs->r = (rain *) calloc(NUMPART, sizeof(part))) == NULL) {
 
1009
            free_fire(fs);
 
1010
            return;
 
1011
        }
 
1012
    }
 
1013
 
 
1014
    /* check tree number */
 
1015
    if (do_texture)
 
1016
        fs->num_trees = (num_trees<MAX_TREES)?num_trees:MAX_TREES;
 
1017
    else
 
1018
        fs->num_trees = 0;
 
1019
 
 
1020
    /* check wander/trackmouse */
 
1021
    if (do_trackmouse && do_wander) do_wander = 0;
 
1022
 
 
1023
    /* xlock GL stuff */
 
1024
    if ((fs->glx_context = init_GL(mi)) != NULL) {
 
1025
 
 
1026
#ifndef STANDALONE
 
1027
        Reshape(mi); /* xlock mode */
 
1028
#else
 
1029
        reshape_fire(mi,MI_WIDTH(mi),MI_HEIGHT(mi)); /* xscreensaver mode */
 
1030
#endif
 
1031
        glDrawBuffer(GL_BACK);
 
1032
        if (!Init(mi)) {
 
1033
                free_fire(fs);
 
1034
                return;
 
1035
        }
 
1036
    } else {
 
1037
        MI_CLEARWINDOW(mi);
 
1038
    }
 
1039
}
 
1040
 
 
1041
/*
 
1042
 *-----------------------------------------------------------------------------
 
1043
 *    Called by the mainline code periodically to update the display.
 
1044
 *-----------------------------------------------------------------------------
 
1045
 */
 
1046
void draw_fire(ModeInfo * mi)
 
1047
{
 
1048
    firestruct *fs = &fire[MI_SCREEN(mi)];
 
1049
 
 
1050
    Display *display = MI_DISPLAY(mi);
 
1051
    Window window = MI_WINDOW(mi);
 
1052
 
 
1053
    MI_IS_DRAWN(mi) = True;
 
1054
 
 
1055
    if (!fs->glx_context)
 
1056
        return;
 
1057
 
 
1058
    glXMakeCurrent(display, window, *(fs->glx_context));
 
1059
    DrawFire(mi);
 
1060
#ifndef STANDALONE
 
1061
    Reshape(mi); /* xlock mode */
 
1062
#else
 
1063
    reshape_fire(mi,MI_WIDTH(mi),MI_HEIGHT(mi)); /* xscreensaver mode */
 
1064
#endif
 
1065
 
 
1066
    glFinish();
 
1067
    glXSwapBuffers(display, window);
 
1068
}
 
1069
 
 
1070
 
 
1071
/*
 
1072
 *-----------------------------------------------------------------------------
 
1073
 *    The display is being taken away from us.  Free up malloc'ed
 
1074
 *      memory and X resources that we've alloc'ed.  Only called
 
1075
 *      once, we must zap everything for every screen.
 
1076
 *-----------------------------------------------------------------------------
 
1077
 */
 
1078
 
 
1079
void release_fire(ModeInfo * mi)
 
1080
{
 
1081
    if (fire != NULL) {
 
1082
    int screen;
 
1083
        for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++)
 
1084
                free_fire(&fire[screen]);
 
1085
        (void) free((void *) fire);
 
1086
        fire = (firestruct *) NULL;
 
1087
    }
 
1088
    if (mode_font != None)
 
1089
    {
 
1090
        /* only free-ed when there are no more screens used */
 
1091
        XFreeFont(MI_DISPLAY(mi), mode_font);
 
1092
        mode_font = None;
 
1093
    }
 
1094
    FreeAllGL(mi);
 
1095
}
 
1096
 
 
1097
void change_fire(ModeInfo * mi)
 
1098
{
 
1099
    firestruct *fs = &fire[MI_SCREEN(mi)];
 
1100
 
 
1101
    if (!fs->glx_context)
 
1102
        return;
 
1103
 
 
1104
    glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(fs->glx_context));
 
1105
 
 
1106
    /* if available, randomly change some values */
 
1107
    if (do_fog)
 
1108
        fs->fog = LRAND() & 1;
 
1109
    if (do_shadows)
 
1110
        fs->shadows = LRAND() & 1;
 
1111
    /* reset observer position */
 
1112
    frame = 0;
 
1113
    vinit(fs->obs, DEF_OBS[0], DEF_OBS[1], DEF_OBS[2]);
 
1114
    fs->v = 0.0;
 
1115
    /* particle randomisation */
 
1116
    fs->eject_r = 0.1 + NRAND(10) * 0.03;
 
1117
    fs->ridtri = 0.1 + NRAND(10) * 0.005;
 
1118
 
 
1119
    if (MI_IS_DEBUG(mi)) {
 
1120
        (void) fprintf(stderr,
 
1121
                       "%s:\n\tnum_part=%d\n\ttrees=%d\n\tfog=%s\n\tshadows=%s\n\teject_r=%.3f\n\tridtri=%.3f\n",
 
1122
                       MI_NAME(mi),
 
1123
                       fs->np,
 
1124
                       fs->num_trees,
 
1125
                       fs->fog ? "on" : "off",
 
1126
                       fs->shadows ? "on" : "off",
 
1127
                       fs->eject_r, fs->ridtri);
 
1128
    }
 
1129
}
 
1130
#endif /* MODE_fire */