2
* This program is under the GNU GPL.
3
* Use at your own risk.
5
* written by David Bucciarelli (tech.hmw@plus.it)
26
static int fullscreen = 1;
30
#define M_PI 3.1415926535
33
#define vinit(a,i,j,k) {\
39
#define vinit4(a,i,j,k,w) {\
47
#define vadds(a,dt,b) {\
59
#define vinter(a,dt,b,c) {\
60
(a)[0]=(dt)*(b)[0]+(1.0-dt)*(c)[0];\
61
(a)[1]=(dt)*(b)[1]+(1.0-dt)*(c)[1];\
62
(a)[2]=(dt)*(b)[2]+(1.0-dt)*(c)[2];\
65
#define clamp(a) ((a) < 0.0 ? 0.0 : ((a) < 1.0 ? (a) : 1.0))
68
(v)[0]=clamp((v)[0]);\
69
(v)[1]=clamp((v)[1]);\
70
(v)[2]=clamp((v)[2]);\
73
static int WIDTH = 640;
74
static int HEIGHT = 480;
77
static GLint Frames = 0;
78
static GLint NiceFog = 1;
100
static float treepos[NUMTREE][3];
102
static float black[3] = { 0.0, 0.0, 0.0 };
103
static float blu[3] = { 1.0, 0.2, 0.0 };
104
static float blu2[3] = { 1.0, 1.0, 0.0 };
106
static float fogcolor[4] = { 1.0, 1.0, 1.0, 1.0 };
108
static float q[4][3] = {
115
static float qt[4][2] = {
125
static float eject_r, dt, maxage, eject_vy, eject_vl;
126
static short shadows;
130
static int joyavailable = 0;
131
static int joyactive = 0;
135
static GLuint groundid;
136
static GLuint treeid;
138
static float obs[3] = { 2.0, 1.0, 0.0 };
140
static float v = 0.0;
141
static float alpha = -84.0;
142
static float beta = 90.0;
147
return (((float) rand()) / RAND_MAX);
157
a = vrnd() * 3.14159265359 * 2.0;
159
vinit(v, sin(a) * eject_r * vrnd(), 0.15, cos(a) * eject_r * vrnd());
160
vinit(p->p[0], v[0] + vrnd() * ridtri, v[1] + vrnd() * ridtri,
161
v[2] + vrnd() * ridtri);
162
vinit(p->p[1], v[0] + vrnd() * ridtri, v[1] + vrnd() * ridtri,
163
v[2] + vrnd() * ridtri);
164
vinit(p->p[2], v[0] + vrnd() * ridtri, v[1] + vrnd() * ridtri,
165
v[2] + vrnd() * ridtri);
167
vinit(p->v, v[0] * eject_vl / (eject_r / 2),
168
vrnd() * eject_vy + eject_vy / 2, v[2] * eject_vl / (eject_r / 2));
172
vinit4(p->c[0], c[0] * ((1.0 - RIDCOL) + vrnd() * RIDCOL),
173
c[1] * ((1.0 - RIDCOL) + vrnd() * RIDCOL),
174
c[2] * ((1.0 - RIDCOL) + vrnd() * RIDCOL), 1.0);
175
vinit4(p->c[1], c[0] * ((1.0 - RIDCOL) + vrnd() * RIDCOL),
176
c[1] * ((1.0 - RIDCOL) + vrnd() * RIDCOL),
177
c[2] * ((1.0 - RIDCOL) + vrnd() * RIDCOL), 1.0);
178
vinit4(p->c[2], c[0] * ((1.0 - RIDCOL) + vrnd() * RIDCOL),
179
c[1] * ((1.0 - RIDCOL) + vrnd() * RIDCOL),
180
c[2] * ((1.0 - RIDCOL) + vrnd() * RIDCOL), 1.0);
188
if (p->p[0][1] < 0.1) {
193
p->v[1] += AGRAV * dt;
195
vadds(p->p[0], dt, p->v);
196
vadds(p->p[1], dt, p->v);
197
vadds(p->p[2], dt, p->v);
201
if ((p->age) > maxage) {
208
vadds(p->c[0], fact, blu2);
210
p->c[0][3] = fact * (maxage - p->age);
212
vadds(p->c[1], fact, blu2);
214
p->c[1][3] = fact * (maxage - p->age);
216
vadds(p->c[2], fact, blu2);
218
p->c[2][3] = fact * (maxage - p->age);
223
drawtree(float x, float y, float z)
226
glTexCoord2f(0.0, 0.0);
227
glVertex3f(x - 1.5, y + 0.0, z);
229
glTexCoord2f(1.0, 0.0);
230
glVertex3f(x + 1.5, y + 0.0, z);
232
glTexCoord2f(1.0, 1.0);
233
glVertex3f(x + 1.5, y + 3.0, z);
235
glTexCoord2f(0.0, 1.0);
236
glVertex3f(x - 1.5, y + 3.0, z);
239
glTexCoord2f(0.0, 0.0);
240
glVertex3f(x, y + 0.0, z - 1.5);
242
glTexCoord2f(1.0, 0.0);
243
glVertex3f(x, y + 0.0, z + 1.5);
245
glTexCoord2f(1.0, 1.0);
246
glVertex3f(x, y + 3.0, z + 1.5);
248
glTexCoord2f(0.0, 1.0);
249
glVertex3f(x, y + 3.0, z - 1.5);
258
dir[0] = sin(alpha * M_PI / 180.0);
259
dir[2] = cos(alpha * M_PI / 180.0) * sin(beta * M_PI / 180.0);
260
dir[1] = cos(beta * M_PI / 180.0);
262
if (dir[0] < 1.0e-5 && dir[0] > -1.0e-5)
264
if (dir[1] < 1.0e-5 && dir[1] > -1.0e-5)
266
if (dir[2] < 1.0e-5 && dir[2] > -1.0e-5)
269
obs[0] += v * dir[0];
270
obs[1] += v * dir[1];
271
obs[2] += v * dir[2];
275
printstring(void *font, char *string)
279
len = (int) strlen(string);
280
for (i = 0; i < len; i++)
281
glutBitmapCharacter(font, string[i]);
285
reshape(int width, int height)
289
glViewport(0, 0, (GLint) width, (GLint) height);
290
glMatrixMode(GL_PROJECTION);
292
gluPerspective(70.0, width / (float) height, 0.1, 30.0);
294
glMatrixMode(GL_MODELVIEW);
300
glColor4f(0.0, 0.0, 0.0, 0.5);
301
glRecti(40, 40, 600, 440);
303
glColor3f(1.0, 0.0, 0.0);
304
glRasterPos2i(300, 420);
305
printstring(GLUT_BITMAP_TIMES_ROMAN_24, "Help");
307
glRasterPos2i(60, 390);
308
printstring(GLUT_BITMAP_TIMES_ROMAN_24, "h - Toggle Help");
310
glRasterPos2i(60, 360);
311
printstring(GLUT_BITMAP_TIMES_ROMAN_24, "t - Increase particle size");
312
glRasterPos2i(60, 330);
313
printstring(GLUT_BITMAP_TIMES_ROMAN_24, "T - Decrease particle size");
315
glRasterPos2i(60, 300);
316
printstring(GLUT_BITMAP_TIMES_ROMAN_24, "r - Increase emission radius");
317
glRasterPos2i(60, 270);
318
printstring(GLUT_BITMAP_TIMES_ROMAN_24, "R - Decrease emission radius");
320
glRasterPos2i(60, 240);
321
printstring(GLUT_BITMAP_TIMES_ROMAN_24, "f - Toggle Fog");
322
glRasterPos2i(60, 210);
323
printstring(GLUT_BITMAP_TIMES_ROMAN_24, "s - Toggle shadows");
324
glRasterPos2i(60, 180);
325
printstring(GLUT_BITMAP_TIMES_ROMAN_24, "Arrow Keys - Rotate");
326
glRasterPos2i(60, 150);
327
printstring(GLUT_BITMAP_TIMES_ROMAN_24, "a - Increase velocity");
328
glRasterPos2i(60, 120);
329
printstring(GLUT_BITMAP_TIMES_ROMAN_24, "z - Decrease velocity");
331
glRasterPos2i(60, 90);
333
printstring(GLUT_BITMAP_TIMES_ROMAN_24,
334
"j - Toggle jostick control (Joystick control available)");
336
printstring(GLUT_BITMAP_TIMES_ROMAN_24,
337
"(No Joystick control available)");
344
static UINT max[2] = { 0, 0 };
345
static UINT min[2] = { 0xffffffff, 0xffffffff }, center[2];
349
res = joyGetPos(JOYSTICKID1, &joy);
351
if (res == JOYERR_NOERROR) {
354
if (max[0] < joy.wXpos)
356
if (min[0] > joy.wXpos)
358
center[0] = (max[0] + min[0]) / 2;
360
if (max[1] < joy.wYpos)
362
if (min[1] > joy.wYpos)
364
center[1] = (max[1] + min[1]) / 2;
367
if (fabs(center[0] - (float) joy.wXpos) > 0.1 * (max[0] - min[0]))
369
2.5 * (center[0] - (float) joy.wXpos) / (max[0] - min[0]);
370
if (fabs(center[1] - (float) joy.wYpos) > 0.1 * (max[1] - min[1]))
371
beta += 2.5 * (center[1] - (float) joy.wYpos) / (max[1] - min[1]);
373
if (joy.wButtons & JOY_BUTTON1)
375
if (joy.wButtons & JOY_BUTTON2)
387
static char frbuf[80] = "";
389
static double t0 = -1.;
390
double t = glutGet(GLUT_ELAPSED_TIME) / 1000.0;
399
glHint(GL_FOG_HINT, GL_NICEST);
401
glHint(GL_FOG_HINT, GL_DONT_CARE);
403
glEnable(GL_DEPTH_TEST);
410
glDepthMask(GL_TRUE);
411
glClearColor(1.0, 1.0, 1.0, 1.0);
412
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
416
gluLookAt(obs[0], obs[1], obs[2],
417
obs[0] + dir[0], obs[1] + dir[1], obs[2] + dir[2],
420
glColor4f(1.0, 1.0, 1.0, 1.0);
422
glEnable(GL_TEXTURE_2D);
424
glBindTexture(GL_TEXTURE_2D, groundid);
427
glTexCoord2fv(qt[0]);
429
glTexCoord2fv(qt[1]);
431
glTexCoord2fv(qt[2]);
433
glTexCoord2fv(qt[3]);
437
/* Subdivide the ground into a bunch of quads. This improves fog
438
* if GL_FOG_HINT != GL_NICEST
442
float dx = 1.0, dy = 1.0;
444
for (y = -DIMP; y < DIMP; y += 1.0) {
445
for (x = -DIMP; x < DIMP; x += 1.0) {
446
glTexCoord2f(0, 0); glVertex3f(x, 0, y);
447
glTexCoord2f(1, 0); glVertex3f(x+dx, 0, y);
448
glTexCoord2f(1, 1); glVertex3f(x+dx, 0, y+dy);
449
glTexCoord2f(0, 1); glVertex3f(x, 0, y+dy);
457
glEnable(GL_ALPHA_TEST);
458
glAlphaFunc(GL_GEQUAL, 0.9);
460
glBindTexture(GL_TEXTURE_2D, treeid);
461
for (j = 0; j < NUMTREE; j++)
462
drawtree(treepos[j][0], treepos[j][1], treepos[j][2]);
464
glDisable(GL_TEXTURE_2D);
465
glDepthMask(GL_FALSE);
466
glDisable(GL_ALPHA_TEST);
469
glBegin(GL_TRIANGLES);
470
for (j = 0; j < np; j++) {
471
glColor4f(black[0], black[1], black[2], p[j].c[0][3]);
472
glVertex3f(p[j].p[0][0], 0.1, p[j].p[0][2]);
474
glColor4f(black[0], black[1], black[2], p[j].c[1][3]);
475
glVertex3f(p[j].p[1][0], 0.1, p[j].p[1][2]);
477
glColor4f(black[0], black[1], black[2], p[j].c[2][3]);
478
glVertex3f(p[j].p[2][0], 0.1, p[j].p[2][2]);
483
glBegin(GL_TRIANGLES);
484
for (j = 0; j < np; j++) {
485
glColor4fv(p[j].c[0]);
486
glVertex3fv(p[j].p[0]);
488
glColor4fv(p[j].c[1]);
489
glVertex3fv(p[j].p[1]);
491
glColor4fv(p[j].c[2]);
492
glVertex3fv(p[j].p[2]);
498
glDisable(GL_TEXTURE_2D);
499
glDisable(GL_ALPHA_TEST);
500
glDisable(GL_DEPTH_TEST);
503
glMatrixMode(GL_PROJECTION);
505
glOrtho(-0.5, 639.5, -0.5, 479.5, -1.0, 1.0);
506
glMatrixMode(GL_MODELVIEW);
509
glColor3f(1.0, 0.0, 0.0);
510
glRasterPos2i(10, 10);
511
printstring(GLUT_BITMAP_HELVETICA_18, frbuf);
512
glRasterPos2i(370, 470);
513
printstring(GLUT_BITMAP_HELVETICA_10,
514
"Fire V1.5 Written by David Bucciarelli (tech.hmw@plus.it)");
519
reshape(WIDTH, HEIGHT);
526
GLint t = glutGet(GLUT_ELAPSED_TIME);
527
if (t - T0 >= 2000) {
528
GLfloat seconds = (t - T0) / 1000.0;
529
GLfloat fps = Frames / seconds;
530
sprintf(frbuf, "Frame rate: %f", fps);
546
special(int key, int x, int y)
566
key(unsigned char key, int x, int y)
581
joyactive = (!joyactive);
606
XMesaSetFXmode(fullscreen ? XMESA_FX_FULLSCREEN : XMESA_FX_WINDOW);
607
fullscreen = (!fullscreen);
612
printf("NiceFog %d\n", NiceFog);
622
GLubyte tex[128][128][4];
624
glGenTextures(1, &groundid);
625
glBindTexture(GL_TEXTURE_2D, groundid);
627
glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
628
if (!LoadRGBMipmaps("../images/s128.rgb", GL_RGB)) {
629
fprintf(stderr, "Error reading a texture.\n");
633
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
634
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
636
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
637
GL_LINEAR_MIPMAP_LINEAR);
638
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
640
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
642
glGenTextures(1, &treeid);
643
glBindTexture(GL_TEXTURE_2D, treeid);
650
GLubyte *image = LoadRGBImage("../images/tree3.rgb", &w, &h, &format);
653
fprintf(stderr, "Error reading a texture.\n");
657
for (y = 0; y < 128; y++)
658
for (x = 0; x < 128; x++) {
659
tex[x][y][0] = image[(y + x * 128) * 3];
660
tex[x][y][1] = image[(y + x * 128) * 3 + 1];
661
tex[x][y][2] = image[(y + x * 128) * 3 + 2];
662
if ((tex[x][y][0] == tex[x][y][1]) &&
663
(tex[x][y][1] == tex[x][y][2]) && (tex[x][y][2] == 255))
669
if ((gluerr = gluBuild2DMipmaps(GL_TEXTURE_2D, 4, 128, 128, GL_RGBA,
670
GL_UNSIGNED_BYTE, (GLvoid *) (tex)))) {
671
fprintf(stderr, "GLULib%s\n", (char *) gluErrorString(gluerr));
676
if (!LoadRGBMipmaps("../images/tree2.rgba", GL_RGBA)) {
677
fprintf(stderr, "Error reading a texture.\n");
682
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
683
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
685
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
686
GL_LINEAR_MIPMAP_LINEAR);
687
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
689
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
698
for (i = 0; i < NUMTREE; i++)
700
treepos[i][0] = vrnd() * TREEOUTR * 2.0 - TREEOUTR;
702
treepos[i][2] = vrnd() * TREEOUTR * 2.0 - TREEOUTR;
704
sqrt(treepos[i][0] * treepos[i][0] +
705
treepos[i][2] * treepos[i][2]);
706
} while ((dist < TREEINR) || (dist > TREEOUTR));
710
main(int ac, char **av)
715
"Fire V1.5\nWritten by David Bucciarelli (tech.hmw@plus.it)\n");
717
/* Default settings */
731
if (np <= 0 || np > 1000000) {
732
fprintf(stderr, "Invalid input.\n");
739
HEIGHT = atoi(av[3]);
742
glutInitWindowSize(WIDTH, HEIGHT);
745
glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE);
747
if (!(win = glutCreateWindow("Fire"))) {
748
fprintf(stderr, "Error opening a window.\n");
752
reshape(WIDTH, HEIGHT);
756
glShadeModel(GL_FLAT);
757
glEnable(GL_DEPTH_TEST);
760
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
763
glFogi(GL_FOG_MODE, GL_EXP);
764
glFogfv(GL_FOG_COLOR, fogcolor);
765
glFogf(GL_FOG_DENSITY, 0.1);
768
p = (part *) malloc(sizeof(part) * np);
771
for (i = 0; i < np; i++)
776
glutKeyboardFunc(key);
777
glutSpecialFunc(special);
778
glutDisplayFunc(drawfire);
780
glutReshapeFunc(reshape);