2 * This program is under the GNU GPL.
3 * Use at your own risk.
5 * written by David Bucciarelli (tech.hmw@plus.it)
20 #include "../util/readtex.c"
24 static int fullscreen
= 1;
28 #define M_PI 3.1415926535
31 #define vinit(a,i,j,k) {\
37 #define vinit4(a,i,j,k,w) {\
45 #define vadds(a,dt,b) {\
57 #define vinter(a,dt,b,c) {\
58 (a)[0]=(dt)*(b)[0]+(1.0-dt)*(c)[0];\
59 (a)[1]=(dt)*(b)[1]+(1.0-dt)*(c)[1];\
60 (a)[2]=(dt)*(b)[2]+(1.0-dt)*(c)[2];\
63 #define clamp(a) ((a) < 0.0 ? 0.0 : ((a) < 1.0 ? (a) : 1.0))
66 (v)[0]=clamp((v)[0]);\
67 (v)[1]=clamp((v)[1]);\
68 (v)[2]=clamp((v)[2]);\
71 static int WIDTH
= 640;
72 static int HEIGHT
= 480;
95 static float treepos
[NUMTREE
][3];
97 static float black
[3] = { 0.0, 0.0, 0.0 };
98 static float blu
[3] = { 0.0, 0.2, 1.0 };
99 static float blu2
[3] = { 0.0, 1.0, 1.0 };
101 static float fogcolor
[4] = { 1.0, 1.0, 1.0, 1.0 };
103 static float q
[4][3] = {
110 static float qt
[4][2] = {
120 static float eject_r
, dt
, maxage
, eject_vy
, eject_vl
;
121 static short shadows
;
125 static int joyavailable
= 0;
126 static int joyactive
= 0;
130 static GLuint groundid
;
131 static GLuint treeid
;
133 static float obs
[3] = { 2.0, 1.0, 0.0 };
135 static float v
= 0.0;
136 static float alpha
= -90.0;
137 static float beta
= 90.0;
142 static clock_t told
= 0;
151 return (ris
/ (float) CLOCKS_PER_SEC
);
157 return (((float) rand()) / RAND_MAX
);
167 a
= vrnd() * 3.14159265359 * 2.0;
169 vinit(v
, sin(a
) * eject_r
* vrnd(), 0.15, cos(a
) * eject_r
* vrnd());
170 vinit(p
->p
[0], v
[0] + vrnd() * ridtri
, v
[1] + vrnd() * ridtri
,
171 v
[2] + vrnd() * ridtri
);
172 vinit(p
->p
[1], v
[0] + vrnd() * ridtri
, v
[1] + vrnd() * ridtri
,
173 v
[2] + vrnd() * ridtri
);
174 vinit(p
->p
[2], v
[0] + vrnd() * ridtri
, v
[1] + vrnd() * ridtri
,
175 v
[2] + vrnd() * ridtri
);
177 vinit(p
->v
, v
[0] * eject_vl
/ (eject_r
/ 2),
178 vrnd() * eject_vy
+ eject_vy
/ 2, v
[2] * eject_vl
/ (eject_r
/ 2));
182 vinit4(p
->c
[0], c
[0] * ((1.0 - RIDCOL
) + vrnd() * RIDCOL
),
183 c
[1] * ((1.0 - RIDCOL
) + vrnd() * RIDCOL
),
184 c
[2] * ((1.0 - RIDCOL
) + vrnd() * RIDCOL
), 1.0);
185 vinit4(p
->c
[1], c
[0] * ((1.0 - RIDCOL
) + vrnd() * RIDCOL
),
186 c
[1] * ((1.0 - RIDCOL
) + vrnd() * RIDCOL
),
187 c
[2] * ((1.0 - RIDCOL
) + vrnd() * RIDCOL
), 1.0);
188 vinit4(p
->c
[2], c
[0] * ((1.0 - RIDCOL
) + vrnd() * RIDCOL
),
189 c
[1] * ((1.0 - RIDCOL
) + vrnd() * RIDCOL
),
190 c
[2] * ((1.0 - RIDCOL
) + vrnd() * RIDCOL
), 1.0);
198 if (p
->p
[0][1] < 0.1) {
203 p
->v
[1] += AGRAV
* dt
;
205 vadds(p
->p
[0], dt
, p
->v
);
206 vadds(p
->p
[1], dt
, p
->v
);
207 vadds(p
->p
[2], dt
, p
->v
);
211 if ((p
->age
) > maxage
) {
218 vadds(p
->c
[0], fact
, blu2
);
220 p
->c
[0][3] = fact
* (maxage
- p
->age
);
222 vadds(p
->c
[1], fact
, blu2
);
224 p
->c
[1][3] = fact
* (maxage
- p
->age
);
226 vadds(p
->c
[2], fact
, blu2
);
228 p
->c
[2][3] = fact
* (maxage
- p
->age
);
233 drawtree(float x
, float y
, float z
)
236 glTexCoord2f(0.0, 0.0);
237 glVertex3f(x
- 1.5, y
+ 0.0, z
);
239 glTexCoord2f(1.0, 0.0);
240 glVertex3f(x
+ 1.5, y
+ 0.0, z
);
242 glTexCoord2f(1.0, 1.0);
243 glVertex3f(x
+ 1.5, y
+ 3.0, z
);
245 glTexCoord2f(0.0, 1.0);
246 glVertex3f(x
- 1.5, y
+ 3.0, z
);
249 glTexCoord2f(0.0, 0.0);
250 glVertex3f(x
, y
+ 0.0, z
- 1.5);
252 glTexCoord2f(1.0, 0.0);
253 glVertex3f(x
, y
+ 0.0, z
+ 1.5);
255 glTexCoord2f(1.0, 1.0);
256 glVertex3f(x
, y
+ 3.0, z
+ 1.5);
258 glTexCoord2f(0.0, 1.0);
259 glVertex3f(x
, y
+ 3.0, z
- 1.5);
268 dir
[0] = sin(alpha
* M_PI
/ 180.0);
269 dir
[2] = cos(alpha
* M_PI
/ 180.0) * sin(beta
* M_PI
/ 180.0);
270 dir
[1] = cos(beta
* M_PI
/ 180.0);
272 obs
[0] += v
* dir
[0];
273 obs
[1] += v
* dir
[1];
274 obs
[2] += v
* dir
[2];
278 printstring(void *font
, char *string
)
282 len
= (int) strlen(string
);
283 for (i
= 0; i
< len
; i
++)
284 glutBitmapCharacter(font
, string
[i
]);
288 reshape(int width
, int height
)
292 glViewport(0, 0, (GLint
) width
, (GLint
) height
);
293 glMatrixMode(GL_PROJECTION
);
295 gluPerspective(70.0, width
/ (float) height
, 0.1, 30.0);
297 glMatrixMode(GL_MODELVIEW
);
303 glColor4f(0.0, 0.0, 0.0, 0.5);
304 glRecti(40, 40, 600, 440);
306 glColor3f(1.0, 0.0, 0.0);
307 glRasterPos2i(300, 420);
308 printstring(GLUT_BITMAP_TIMES_ROMAN_24
, "Help");
310 glRasterPos2i(60, 390);
311 printstring(GLUT_BITMAP_TIMES_ROMAN_24
, "h - Togle Help");
313 glRasterPos2i(60, 360);
314 printstring(GLUT_BITMAP_TIMES_ROMAN_24
, "t - Increase particle size");
315 glRasterPos2i(60, 330);
316 printstring(GLUT_BITMAP_TIMES_ROMAN_24
, "T - Decrease particle size");
318 glRasterPos2i(60, 300);
319 printstring(GLUT_BITMAP_TIMES_ROMAN_24
, "r - Increase emission radius");
320 glRasterPos2i(60, 270);
321 printstring(GLUT_BITMAP_TIMES_ROMAN_24
, "R - Decrease emission radius");
323 glRasterPos2i(60, 240);
324 printstring(GLUT_BITMAP_TIMES_ROMAN_24
, "f - Togle Fog");
325 glRasterPos2i(60, 210);
326 printstring(GLUT_BITMAP_TIMES_ROMAN_24
, "s - Togle shadows");
327 glRasterPos2i(60, 180);
328 printstring(GLUT_BITMAP_TIMES_ROMAN_24
, "Arrow Keys - Rotate");
329 glRasterPos2i(60, 150);
330 printstring(GLUT_BITMAP_TIMES_ROMAN_24
, "a - Increase velocity");
331 glRasterPos2i(60, 120);
332 printstring(GLUT_BITMAP_TIMES_ROMAN_24
, "z - Decrease velocity");
334 glRasterPos2i(60, 90);
336 printstring(GLUT_BITMAP_TIMES_ROMAN_24
,
337 "j - Togle jostick control (Joystick control available)");
339 printstring(GLUT_BITMAP_TIMES_ROMAN_24
,
340 "(No Joystick control available)");
347 static UINT max
[2] = { 0, 0 };
348 static UINT min
[2] = { 0xffffffff, 0xffffffff }, center
[2];
352 res
= joyGetPos(JOYSTICKID1
, &joy
);
354 if (res
== JOYERR_NOERROR
) {
357 if (max
[0] < joy
.wXpos
)
359 if (min
[0] > joy
.wXpos
)
361 center
[0] = (max
[0] + min
[0]) / 2;
363 if (max
[1] < joy
.wYpos
)
365 if (min
[1] > joy
.wYpos
)
367 center
[1] = (max
[1] + min
[1]) / 2;
370 if (fabs(center
[0] - (float) joy
.wXpos
) > 0.1 * (max
[0] - min
[0]))
372 2.5 * (center
[0] - (float) joy
.wXpos
) / (max
[0] - min
[0]);
373 if (fabs(center
[1] - (float) joy
.wYpos
) > 0.1 * (max
[1] - min
[1]))
374 beta
+= 2.5 * (center
[1] - (float) joy
.wYpos
) / (max
[1] - min
[1]);
376 if (joy
.wButtons
& JOY_BUTTON1
)
378 if (joy
.wButtons
& JOY_BUTTON2
)
390 static int count
= 0;
391 static char frbuf
[80];
397 glEnable(GL_DEPTH_TEST
);
404 glDepthMask(GL_TRUE
);
405 glClearColor(1.0, 1.0, 1.0, 1.0);
406 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
);
410 gluLookAt(obs
[0], obs
[1], obs
[2],
411 obs
[0] + dir
[0], obs
[1] + dir
[1], obs
[2] + dir
[2],
414 glColor4f(1.0, 1.0, 1.0, 1.0);
416 glEnable(GL_TEXTURE_2D
);
418 glBindTexture(GL_TEXTURE_2D
, groundid
);
420 glTexCoord2fv(qt
[0]);
422 glTexCoord2fv(qt
[1]);
424 glTexCoord2fv(qt
[2]);
426 glTexCoord2fv(qt
[3]);
430 glEnable(GL_ALPHA_TEST
);
431 glAlphaFunc(GL_GEQUAL
, 0.9);
433 glBindTexture(GL_TEXTURE_2D
, treeid
);
434 for (j
= 0; j
< NUMTREE
; j
++)
435 drawtree(treepos
[j
][0], treepos
[j
][1], treepos
[j
][2]);
437 glDisable(GL_TEXTURE_2D
);
438 glDepthMask(GL_FALSE
);
439 glDisable(GL_ALPHA_TEST
);
442 glBegin(GL_TRIANGLES
);
443 for (j
= 0; j
< np
; j
++) {
444 glColor4f(black
[0], black
[1], black
[2], p
[j
].c
[0][3]);
445 glVertex3f(p
[j
].p
[0][0], 0.1, p
[j
].p
[0][2]);
447 glColor4f(black
[0], black
[1], black
[2], p
[j
].c
[1][3]);
448 glVertex3f(p
[j
].p
[1][0], 0.1, p
[j
].p
[1][2]);
450 glColor4f(black
[0], black
[1], black
[2], p
[j
].c
[2][3]);
451 glVertex3f(p
[j
].p
[2][0], 0.1, p
[j
].p
[2][2]);
456 glBegin(GL_TRIANGLES
);
457 for (j
= 0; j
< np
; j
++) {
458 glColor4fv(p
[j
].c
[0]);
459 glVertex3fv(p
[j
].p
[0]);
461 glColor4fv(p
[j
].c
[1]);
462 glVertex3fv(p
[j
].p
[1]);
464 glColor4fv(p
[j
].c
[2]);
465 glVertex3fv(p
[j
].p
[2]);
471 if ((count
% FRAME
) == 0) {
473 sprintf(frbuf
, "Frame rate: %f", FRAME
/ fr
);
476 glDisable(GL_TEXTURE_2D
);
477 glDisable(GL_ALPHA_TEST
);
478 glDisable(GL_DEPTH_TEST
);
481 glMatrixMode(GL_PROJECTION
);
483 glOrtho(-0.5, 639.5, -0.5, 479.5, -1.0, 1.0);
484 glMatrixMode(GL_MODELVIEW
);
487 glColor3f(1.0, 0.0, 0.0);
488 glRasterPos2i(10, 10);
489 printstring(GLUT_BITMAP_HELVETICA_18
, frbuf
);
490 glRasterPos2i(370, 470);
491 printstring(GLUT_BITMAP_HELVETICA_10
,
492 "Fire V1.5 Written by David Bucciarelli (tech.hmw@plus.it)");
497 reshape(WIDTH
, HEIGHT
);
507 special(int key
, int x
, int y
)
526 key(unsigned char key
, int x
, int y
)
541 joyactive
= (!joyactive
);
566 XMesaSetFXmode(fullscreen
? XMESA_FX_FULLSCREEN
: XMESA_FX_WINDOW
);
567 fullscreen
= (!fullscreen
);
577 GLubyte tex
[128][128][4];
579 glGenTextures(1, &groundid
);
580 glBindTexture(GL_TEXTURE_2D
, groundid
);
582 glPixelStorei(GL_UNPACK_ALIGNMENT
, 4);
583 if (!LoadRGBMipmaps("../images/s128.rgb", GL_RGB
)) {
584 fprintf(stderr
, "Error reading a texture.\n");
588 glTexParameterf(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_REPEAT
);
589 glTexParameterf(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_REPEAT
);
591 glTexParameterf(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
,
592 GL_LINEAR_MIPMAP_LINEAR
);
593 glTexParameterf(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
);
595 glTexEnvf(GL_TEXTURE_ENV
, GL_TEXTURE_ENV_MODE
, GL_DECAL
);
597 glGenTextures(1, &treeid
);
598 glBindTexture(GL_TEXTURE_2D
, treeid
);
605 GLubyte
*image
= LoadRGBImage("../images/tree3.rgb", &w
, &h
, &format
);
608 fprintf(stderr
, "Error reading a texture.\n");
612 for (y
= 0; y
< 128; y
++)
613 for (x
= 0; x
< 128; x
++) {
614 tex
[x
][y
][0] = image
[(y
+ x
* 128) * 3];
615 tex
[x
][y
][1] = image
[(y
+ x
* 128) * 3 + 1];
616 tex
[x
][y
][2] = image
[(y
+ x
* 128) * 3 + 2];
617 if ((tex
[x
][y
][0] == tex
[x
][y
][1]) &&
618 (tex
[x
][y
][1] == tex
[x
][y
][2]) && (tex
[x
][y
][2] == 255))
624 if ((gluerr
= gluBuild2DMipmaps(GL_TEXTURE_2D
, 4, 128, 128, GL_RGBA
,
625 GL_UNSIGNED_BYTE
, (GLvoid
*) (tex
)))) {
626 fprintf(stderr
, "GLULib%s\n", gluErrorString(gluerr
));
631 if (!LoadRGBMipmaps("../images/tree2.rgba", GL_RGBA
)) {
632 fprintf(stderr
, "Error reading a texture.\n");
637 glTexParameterf(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_REPEAT
);
638 glTexParameterf(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_REPEAT
);
640 glTexParameterf(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
,
641 GL_LINEAR_MIPMAP_LINEAR
);
642 glTexParameterf(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
);
644 glTexEnvf(GL_TEXTURE_ENV
, GL_TEXTURE_ENV_MODE
, GL_MODULATE
);
653 for (i
= 0; i
< NUMTREE
; i
++)
655 treepos
[i
][0] = vrnd() * TREEOUTR
* 2.0 - TREEOUTR
;
657 treepos
[i
][2] = vrnd() * TREEOUTR
* 2.0 - TREEOUTR
;
659 sqrt(treepos
[i
][0] * treepos
[i
][0] +
660 treepos
[i
][2] * treepos
[i
][2]);
661 } while ((dist
< TREEINR
) || (dist
> TREEOUTR
));
665 main(int ac
, char **av
)
670 "Fire V1.5\nWritten by David Bucciarelli (tech.hmw@plus.it)\n");
672 /* Default settings */
691 HEIGHT
= atoi(av
[3]);
694 glutInitWindowPosition(0, 0);
695 glutInitWindowSize(WIDTH
, HEIGHT
);
698 glutInitDisplayMode(GLUT_RGB
| GLUT_DEPTH
| GLUT_DOUBLE
);
700 if (!(win
= glutCreateWindow("Fire"))) {
701 fprintf(stderr
, "Error opening a window.\n");
705 reshape(WIDTH
, HEIGHT
);
709 glShadeModel(GL_FLAT
);
710 glEnable(GL_DEPTH_TEST
);
713 glBlendFunc(GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
716 glFogi(GL_FOG_MODE
, GL_EXP
);
717 glFogfv(GL_FOG_COLOR
, fogcolor
);
718 glFogf(GL_FOG_DENSITY
, 0.1);
720 glHint(GL_FOG_HINT
, GL_NICEST
);
723 p
= malloc(sizeof(part
) * np
);
725 for (i
= 0; i
< np
; i
++)
730 glutKeyboardFunc(key
);
731 glutSpecialFunc(special
);
732 glutDisplayFunc(drawfire
);
733 glutIdleFunc(drawfire
);
734 glutReshapeFunc(reshape
);