2 * This program is under the GNU GPL.
3 * Use at your own risk.
5 * written by David Bucciarelli (tech.hmw@plus.it)
25 static int fullscreen
= 1;
29 #define M_PI 3.1415926535
32 #define vinit(a,i,j,k) {\
38 #define vinit4(a,i,j,k,w) {\
46 #define vadds(a,dt,b) {\
58 #define vinter(a,dt,b,c) {\
59 (a)[0]=(dt)*(b)[0]+(1.0-dt)*(c)[0];\
60 (a)[1]=(dt)*(b)[1]+(1.0-dt)*(c)[1];\
61 (a)[2]=(dt)*(b)[2]+(1.0-dt)*(c)[2];\
64 #define clamp(a) ((a) < 0.0 ? 0.0 : ((a) < 1.0 ? (a) : 1.0))
67 (v)[0]=clamp((v)[0]);\
68 (v)[1]=clamp((v)[1]);\
69 (v)[2]=clamp((v)[2]);\
72 static int WIDTH
= 640;
73 static int HEIGHT
= 480;
76 static GLint Frames
= 0;
77 static GLint NiceFog
= 1;
99 static float treepos
[NUMTREE
][3];
101 static float black
[3] = { 0.0, 0.0, 0.0 };
102 static float blu
[3] = { 1.0, 0.2, 0.0 };
103 static float blu2
[3] = { 1.0, 1.0, 0.0 };
105 static float fogcolor
[4] = { 1.0, 1.0, 1.0, 1.0 };
107 static float q
[4][3] = {
114 static float qt
[4][2] = {
124 static float eject_r
, dt
, maxage
, eject_vy
, eject_vl
;
125 static short shadows
;
129 static int joyavailable
= 0;
130 static int joyactive
= 0;
134 static GLuint groundid
;
135 static GLuint treeid
;
137 static float obs
[3] = { 2.0, 1.0, 0.0 };
139 static float v
= 0.0;
140 static float alpha
= -84.0;
141 static float beta
= 90.0;
146 return (((float) rand()) / RAND_MAX
);
156 a
= vrnd() * 3.14159265359 * 2.0;
158 vinit(v
, sin(a
) * eject_r
* vrnd(), 0.15, cos(a
) * eject_r
* vrnd());
159 vinit(p
->p
[0], v
[0] + vrnd() * ridtri
, v
[1] + vrnd() * ridtri
,
160 v
[2] + vrnd() * ridtri
);
161 vinit(p
->p
[1], v
[0] + vrnd() * ridtri
, v
[1] + vrnd() * ridtri
,
162 v
[2] + vrnd() * ridtri
);
163 vinit(p
->p
[2], v
[0] + vrnd() * ridtri
, v
[1] + vrnd() * ridtri
,
164 v
[2] + vrnd() * ridtri
);
166 vinit(p
->v
, v
[0] * eject_vl
/ (eject_r
/ 2),
167 vrnd() * eject_vy
+ eject_vy
/ 2, v
[2] * eject_vl
/ (eject_r
/ 2));
171 vinit4(p
->c
[0], c
[0] * ((1.0 - RIDCOL
) + vrnd() * RIDCOL
),
172 c
[1] * ((1.0 - RIDCOL
) + vrnd() * RIDCOL
),
173 c
[2] * ((1.0 - RIDCOL
) + vrnd() * RIDCOL
), 1.0);
174 vinit4(p
->c
[1], c
[0] * ((1.0 - RIDCOL
) + vrnd() * RIDCOL
),
175 c
[1] * ((1.0 - RIDCOL
) + vrnd() * RIDCOL
),
176 c
[2] * ((1.0 - RIDCOL
) + vrnd() * RIDCOL
), 1.0);
177 vinit4(p
->c
[2], c
[0] * ((1.0 - RIDCOL
) + vrnd() * RIDCOL
),
178 c
[1] * ((1.0 - RIDCOL
) + vrnd() * RIDCOL
),
179 c
[2] * ((1.0 - RIDCOL
) + vrnd() * RIDCOL
), 1.0);
187 if (p
->p
[0][1] < 0.1) {
192 p
->v
[1] += AGRAV
* dt
;
194 vadds(p
->p
[0], dt
, p
->v
);
195 vadds(p
->p
[1], dt
, p
->v
);
196 vadds(p
->p
[2], dt
, p
->v
);
200 if ((p
->age
) > maxage
) {
207 vadds(p
->c
[0], fact
, blu2
);
209 p
->c
[0][3] = fact
* (maxage
- p
->age
);
211 vadds(p
->c
[1], fact
, blu2
);
213 p
->c
[1][3] = fact
* (maxage
- p
->age
);
215 vadds(p
->c
[2], fact
, blu2
);
217 p
->c
[2][3] = fact
* (maxage
- p
->age
);
222 drawtree(float x
, float y
, float z
)
225 glTexCoord2f(0.0, 0.0);
226 glVertex3f(x
- 1.5, y
+ 0.0, z
);
228 glTexCoord2f(1.0, 0.0);
229 glVertex3f(x
+ 1.5, y
+ 0.0, z
);
231 glTexCoord2f(1.0, 1.0);
232 glVertex3f(x
+ 1.5, y
+ 3.0, z
);
234 glTexCoord2f(0.0, 1.0);
235 glVertex3f(x
- 1.5, y
+ 3.0, z
);
238 glTexCoord2f(0.0, 0.0);
239 glVertex3f(x
, y
+ 0.0, z
- 1.5);
241 glTexCoord2f(1.0, 0.0);
242 glVertex3f(x
, y
+ 0.0, z
+ 1.5);
244 glTexCoord2f(1.0, 1.0);
245 glVertex3f(x
, y
+ 3.0, z
+ 1.5);
247 glTexCoord2f(0.0, 1.0);
248 glVertex3f(x
, y
+ 3.0, z
- 1.5);
257 dir
[0] = sin(alpha
* M_PI
/ 180.0);
258 dir
[2] = cos(alpha
* M_PI
/ 180.0) * sin(beta
* M_PI
/ 180.0);
259 dir
[1] = cos(beta
* M_PI
/ 180.0);
261 if (dir
[0] < 1.0e-5 && dir
[0] > -1.0e-5)
263 if (dir
[1] < 1.0e-5 && dir
[1] > -1.0e-5)
265 if (dir
[2] < 1.0e-5 && dir
[2] > -1.0e-5)
268 obs
[0] += v
* dir
[0];
269 obs
[1] += v
* dir
[1];
270 obs
[2] += v
* dir
[2];
274 printstring(void *font
, char *string
)
278 len
= (int) strlen(string
);
279 for (i
= 0; i
< len
; i
++)
280 glutBitmapCharacter(font
, string
[i
]);
284 reshape(int width
, int height
)
288 glViewport(0, 0, (GLint
) width
, (GLint
) height
);
289 glMatrixMode(GL_PROJECTION
);
291 gluPerspective(70.0, width
/ (float) height
, 0.1, 30.0);
293 glMatrixMode(GL_MODELVIEW
);
299 glColor4f(0.0, 0.0, 0.0, 0.5);
300 glRecti(40, 40, 600, 440);
302 glColor3f(1.0, 0.0, 0.0);
303 glRasterPos2i(300, 420);
304 printstring(GLUT_BITMAP_TIMES_ROMAN_24
, "Help");
306 glRasterPos2i(60, 390);
307 printstring(GLUT_BITMAP_TIMES_ROMAN_24
, "h - Toggle Help");
309 glRasterPos2i(60, 360);
310 printstring(GLUT_BITMAP_TIMES_ROMAN_24
, "t - Increase particle size");
311 glRasterPos2i(60, 330);
312 printstring(GLUT_BITMAP_TIMES_ROMAN_24
, "T - Decrease particle size");
314 glRasterPos2i(60, 300);
315 printstring(GLUT_BITMAP_TIMES_ROMAN_24
, "r - Increase emission radius");
316 glRasterPos2i(60, 270);
317 printstring(GLUT_BITMAP_TIMES_ROMAN_24
, "R - Decrease emission radius");
319 glRasterPos2i(60, 240);
320 printstring(GLUT_BITMAP_TIMES_ROMAN_24
, "f - Toggle Fog");
321 glRasterPos2i(60, 210);
322 printstring(GLUT_BITMAP_TIMES_ROMAN_24
, "s - Toggle shadows");
323 glRasterPos2i(60, 180);
324 printstring(GLUT_BITMAP_TIMES_ROMAN_24
, "Arrow Keys - Rotate");
325 glRasterPos2i(60, 150);
326 printstring(GLUT_BITMAP_TIMES_ROMAN_24
, "a - Increase velocity");
327 glRasterPos2i(60, 120);
328 printstring(GLUT_BITMAP_TIMES_ROMAN_24
, "z - Decrease velocity");
330 glRasterPos2i(60, 90);
332 printstring(GLUT_BITMAP_TIMES_ROMAN_24
,
333 "j - Toggle jostick control (Joystick control available)");
335 printstring(GLUT_BITMAP_TIMES_ROMAN_24
,
336 "(No Joystick control available)");
343 static UINT max
[2] = { 0, 0 };
344 static UINT min
[2] = { 0xffffffff, 0xffffffff }, center
[2];
348 res
= joyGetPos(JOYSTICKID1
, &joy
);
350 if (res
== JOYERR_NOERROR
) {
353 if (max
[0] < joy
.wXpos
)
355 if (min
[0] > joy
.wXpos
)
357 center
[0] = (max
[0] + min
[0]) / 2;
359 if (max
[1] < joy
.wYpos
)
361 if (min
[1] > joy
.wYpos
)
363 center
[1] = (max
[1] + min
[1]) / 2;
366 if (fabs(center
[0] - (float) joy
.wXpos
) > 0.1 * (max
[0] - min
[0]))
368 2.5 * (center
[0] - (float) joy
.wXpos
) / (max
[0] - min
[0]);
369 if (fabs(center
[1] - (float) joy
.wYpos
) > 0.1 * (max
[1] - min
[1]))
370 beta
+= 2.5 * (center
[1] - (float) joy
.wYpos
) / (max
[1] - min
[1]);
372 if (joy
.wButtons
& JOY_BUTTON1
)
374 if (joy
.wButtons
& JOY_BUTTON2
)
386 static char frbuf
[80] = "";
388 static double t0
= -1.;
389 double t
= glutGet(GLUT_ELAPSED_TIME
) / 1000.0;
398 glHint(GL_FOG_HINT
, GL_NICEST
);
400 glHint(GL_FOG_HINT
, GL_DONT_CARE
);
402 glEnable(GL_DEPTH_TEST
);
409 glDepthMask(GL_TRUE
);
410 glClearColor(1.0, 1.0, 1.0, 1.0);
411 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
);
415 gluLookAt(obs
[0], obs
[1], obs
[2],
416 obs
[0] + dir
[0], obs
[1] + dir
[1], obs
[2] + dir
[2],
419 glColor4f(1.0, 1.0, 1.0, 1.0);
421 glEnable(GL_TEXTURE_2D
);
423 glBindTexture(GL_TEXTURE_2D
, groundid
);
426 glTexCoord2fv(qt
[0]);
428 glTexCoord2fv(qt
[1]);
430 glTexCoord2fv(qt
[2]);
432 glTexCoord2fv(qt
[3]);
436 /* Subdivide the ground into a bunch of quads. This improves fog
437 * if GL_FOG_HINT != GL_NICEST
441 float dx
= 1.0, dy
= 1.0;
443 for (y
= -DIMP
; y
< DIMP
; y
+= 1.0) {
444 for (x
= -DIMP
; x
< DIMP
; x
+= 1.0) {
445 glTexCoord2f(0, 0); glVertex3f(x
, 0, y
);
446 glTexCoord2f(1, 0); glVertex3f(x
+dx
, 0, y
);
447 glTexCoord2f(1, 1); glVertex3f(x
+dx
, 0, y
+dy
);
448 glTexCoord2f(0, 1); glVertex3f(x
, 0, y
+dy
);
456 glEnable(GL_ALPHA_TEST
);
457 glAlphaFunc(GL_GEQUAL
, 0.9);
459 glBindTexture(GL_TEXTURE_2D
, treeid
);
460 for (j
= 0; j
< NUMTREE
; j
++)
461 drawtree(treepos
[j
][0], treepos
[j
][1], treepos
[j
][2]);
463 glDisable(GL_TEXTURE_2D
);
464 glDepthMask(GL_FALSE
);
465 glDisable(GL_ALPHA_TEST
);
468 glBegin(GL_TRIANGLES
);
469 for (j
= 0; j
< np
; j
++) {
470 glColor4f(black
[0], black
[1], black
[2], p
[j
].c
[0][3]);
471 glVertex3f(p
[j
].p
[0][0], 0.1, p
[j
].p
[0][2]);
473 glColor4f(black
[0], black
[1], black
[2], p
[j
].c
[1][3]);
474 glVertex3f(p
[j
].p
[1][0], 0.1, p
[j
].p
[1][2]);
476 glColor4f(black
[0], black
[1], black
[2], p
[j
].c
[2][3]);
477 glVertex3f(p
[j
].p
[2][0], 0.1, p
[j
].p
[2][2]);
482 glBegin(GL_TRIANGLES
);
483 for (j
= 0; j
< np
; j
++) {
484 glColor4fv(p
[j
].c
[0]);
485 glVertex3fv(p
[j
].p
[0]);
487 glColor4fv(p
[j
].c
[1]);
488 glVertex3fv(p
[j
].p
[1]);
490 glColor4fv(p
[j
].c
[2]);
491 glVertex3fv(p
[j
].p
[2]);
497 glDisable(GL_TEXTURE_2D
);
498 glDisable(GL_ALPHA_TEST
);
499 glDisable(GL_DEPTH_TEST
);
502 glMatrixMode(GL_PROJECTION
);
504 glOrtho(-0.5, 639.5, -0.5, 479.5, -1.0, 1.0);
505 glMatrixMode(GL_MODELVIEW
);
508 glColor3f(1.0, 0.0, 0.0);
509 glRasterPos2i(10, 10);
510 printstring(GLUT_BITMAP_HELVETICA_18
, frbuf
);
511 glRasterPos2i(370, 470);
512 printstring(GLUT_BITMAP_HELVETICA_10
,
513 "Fire V1.5 Written by David Bucciarelli (tech.hmw@plus.it)");
518 reshape(WIDTH
, HEIGHT
);
525 GLint t
= glutGet(GLUT_ELAPSED_TIME
);
526 if (t
- T0
>= 2000) {
527 GLfloat seconds
= (t
- T0
) / 1000.0;
528 GLfloat fps
= Frames
/ seconds
;
529 sprintf(frbuf
, "Frame rate: %f", fps
);
545 special(int key
, int x
, int y
)
565 key(unsigned char key
, int x
, int y
)
580 joyactive
= (!joyactive
);
605 XMesaSetFXmode(fullscreen
? XMESA_FX_FULLSCREEN
: XMESA_FX_WINDOW
);
606 fullscreen
= (!fullscreen
);
611 printf("NiceFog %d\n", NiceFog
);
621 GLubyte tex
[128][128][4];
623 glGenTextures(1, &groundid
);
624 glBindTexture(GL_TEXTURE_2D
, groundid
);
626 glPixelStorei(GL_UNPACK_ALIGNMENT
, 4);
627 if (!LoadRGBMipmaps("../images/s128.rgb", GL_RGB
)) {
628 fprintf(stderr
, "Error reading a texture.\n");
632 glTexParameterf(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_REPEAT
);
633 glTexParameterf(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_REPEAT
);
635 glTexParameterf(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
,
636 GL_LINEAR_MIPMAP_LINEAR
);
637 glTexParameterf(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
);
639 glTexEnvf(GL_TEXTURE_ENV
, GL_TEXTURE_ENV_MODE
, GL_DECAL
);
641 glGenTextures(1, &treeid
);
642 glBindTexture(GL_TEXTURE_2D
, treeid
);
649 GLubyte
*image
= LoadRGBImage("../images/tree3.rgb", &w
, &h
, &format
);
652 fprintf(stderr
, "Error reading a texture.\n");
656 for (y
= 0; y
< 128; y
++)
657 for (x
= 0; x
< 128; x
++) {
658 tex
[x
][y
][0] = image
[(y
+ x
* 128) * 3];
659 tex
[x
][y
][1] = image
[(y
+ x
* 128) * 3 + 1];
660 tex
[x
][y
][2] = image
[(y
+ x
* 128) * 3 + 2];
661 if ((tex
[x
][y
][0] == tex
[x
][y
][1]) &&
662 (tex
[x
][y
][1] == tex
[x
][y
][2]) && (tex
[x
][y
][2] == 255))
668 if ((gluerr
= gluBuild2DMipmaps(GL_TEXTURE_2D
, 4, 128, 128, GL_RGBA
,
669 GL_UNSIGNED_BYTE
, (GLvoid
*) (tex
)))) {
670 fprintf(stderr
, "GLULib%s\n", (char *) gluErrorString(gluerr
));
675 if (!LoadRGBMipmaps("../images/tree2.rgba", GL_RGBA
)) {
676 fprintf(stderr
, "Error reading a texture.\n");
681 glTexParameterf(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_REPEAT
);
682 glTexParameterf(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_REPEAT
);
684 glTexParameterf(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
,
685 GL_LINEAR_MIPMAP_LINEAR
);
686 glTexParameterf(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
);
688 glTexEnvf(GL_TEXTURE_ENV
, GL_TEXTURE_ENV_MODE
, GL_MODULATE
);
697 for (i
= 0; i
< NUMTREE
; i
++)
699 treepos
[i
][0] = vrnd() * TREEOUTR
* 2.0 - TREEOUTR
;
701 treepos
[i
][2] = vrnd() * TREEOUTR
* 2.0 - TREEOUTR
;
703 sqrt(treepos
[i
][0] * treepos
[i
][0] +
704 treepos
[i
][2] * treepos
[i
][2]);
705 } while ((dist
< TREEINR
) || (dist
> TREEOUTR
));
709 main(int ac
, char **av
)
714 "Fire V1.5\nWritten by David Bucciarelli (tech.hmw@plus.it)\n");
716 /* Default settings */
733 HEIGHT
= atoi(av
[3]);
736 glutInitWindowPosition(0, 0);
737 glutInitWindowSize(WIDTH
, HEIGHT
);
740 glutInitDisplayMode(GLUT_RGB
| GLUT_DEPTH
| GLUT_DOUBLE
);
742 if (!(win
= glutCreateWindow("Fire"))) {
743 fprintf(stderr
, "Error opening a window.\n");
747 reshape(WIDTH
, HEIGHT
);
751 glShadeModel(GL_FLAT
);
752 glEnable(GL_DEPTH_TEST
);
755 glBlendFunc(GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
758 glFogi(GL_FOG_MODE
, GL_EXP
);
759 glFogfv(GL_FOG_COLOR
, fogcolor
);
760 glFogf(GL_FOG_DENSITY
, 0.1);
762 p
= (part
*) malloc(sizeof(part
) * np
);
764 for (i
= 0; i
< np
; i
++)
769 glutKeyboardFunc(key
);
770 glutSpecialFunc(special
);
771 glutDisplayFunc(drawfire
);
773 glutReshapeFunc(reshape
);