blob: 52ea8683021e9960933a1e83c25f93a030cb7515 [file] [log] [blame]
Brian Paul5b0a7f32000-06-27 16:52:38 +00001/*
2 * This program is under the GNU GPL.
3 * Use at your own risk.
4 *
5 * written by David Bucciarelli (tech.hmw@plus.it)
6 * Humanware s.r.l.
7 */
8
9#include <stdio.h>
10#include <stdlib.h>
11#include <math.h>
12#include <time.h>
13
14#ifdef WIN32
15#include <windows.h>
16#include <mmsystem.h>
17#endif
18
19#include <GL/glut.h>
20#include "../util/readtex.c"
21
22#ifdef XMESA
23#include "GL/xmesa.h"
24static int fullscreen = 1;
25#endif
26
27#ifndef M_PI
28#define M_PI 3.1415926535
29#endif
30
31#define vinit(a,i,j,k) {\
32 (a)[0]=i;\
33 (a)[1]=j;\
34 (a)[2]=k;\
35}
36
37#define vinit4(a,i,j,k,w) {\
38 (a)[0]=i;\
39 (a)[1]=j;\
40 (a)[2]=k;\
41 (a)[3]=w;\
42}
43
44
45#define vadds(a,dt,b) {\
46 (a)[0]+=(dt)*(b)[0];\
47 (a)[1]+=(dt)*(b)[1];\
48 (a)[2]+=(dt)*(b)[2];\
49}
50
51#define vequ(a,b) {\
52 (a)[0]=(b)[0];\
53 (a)[1]=(b)[1];\
54 (a)[2]=(b)[2];\
55}
56
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];\
61}
62
63#define clamp(a) ((a) < 0.0 ? 0.0 : ((a) < 1.0 ? (a) : 1.0))
64
65#define vclamp(v) {\
66 (v)[0]=clamp((v)[0]);\
67 (v)[1]=clamp((v)[1]);\
68 (v)[2]=clamp((v)[2]);\
69}
70
71static int WIDTH = 640;
72static int HEIGHT = 480;
73
Brian Pauld49b34a2000-09-12 18:44:45 +000074static GLint T0 = 0;
75static GLint Frames = 0;
76
Brian Paul5b0a7f32000-06-27 16:52:38 +000077#define DIMP 20.0
78#define DIMTP 16.0
79
80#define RIDCOL 0.4
81
82#define NUMTREE 50
83#define TREEINR 2.5
84#define TREEOUTR 8.0
85
86#define AGRAV -9.8
87
88typedef struct
89{
90 int age;
91 float p[3][3];
92 float v[3];
93 float c[3][4];
94}
95part;
96
97static float treepos[NUMTREE][3];
98
99static float black[3] = { 0.0, 0.0, 0.0 };
100static float blu[3] = { 0.0, 0.2, 1.0 };
101static float blu2[3] = { 0.0, 1.0, 1.0 };
102
103static float fogcolor[4] = { 1.0, 1.0, 1.0, 1.0 };
104
105static float q[4][3] = {
106 {-DIMP, 0.0, -DIMP},
107 {DIMP, 0.0, -DIMP},
108 {DIMP, 0.0, DIMP},
109 {-DIMP, 0.0, DIMP}
110};
111
112static float qt[4][2] = {
113 {-DIMTP, -DIMTP},
114 {DIMTP, -DIMTP},
115 {DIMTP, DIMTP},
116 {-DIMTP, DIMTP}
117};
118
119static int win = 0;
120
121static int np;
122static float eject_r, dt, maxage, eject_vy, eject_vl;
123static short shadows;
124static float ridtri;
125static int fog = 1;
126static int help = 1;
127static int joyavailable = 0;
128static int joyactive = 0;
129
130static part *p;
131
132static GLuint groundid;
133static GLuint treeid;
134
135static float obs[3] = { 2.0, 1.0, 0.0 };
136static float dir[3];
137static float v = 0.0;
138static float alpha = -90.0;
139static float beta = 90.0;
140
141static float
Brian Paul5b0a7f32000-06-27 16:52:38 +0000142vrnd(void)
143{
144 return (((float) rand()) / RAND_MAX);
145}
146
147static void
148setnewpart(part * p)
149{
150 float a, v[3], *c;
151
152 p->age = 0;
153
154 a = vrnd() * 3.14159265359 * 2.0;
155
156 vinit(v, sin(a) * eject_r * vrnd(), 0.15, cos(a) * eject_r * vrnd());
157 vinit(p->p[0], v[0] + vrnd() * ridtri, v[1] + vrnd() * ridtri,
158 v[2] + vrnd() * ridtri);
159 vinit(p->p[1], v[0] + vrnd() * ridtri, v[1] + vrnd() * ridtri,
160 v[2] + vrnd() * ridtri);
161 vinit(p->p[2], v[0] + vrnd() * ridtri, v[1] + vrnd() * ridtri,
162 v[2] + vrnd() * ridtri);
163
164 vinit(p->v, v[0] * eject_vl / (eject_r / 2),
165 vrnd() * eject_vy + eject_vy / 2, v[2] * eject_vl / (eject_r / 2));
166
167 c = blu;
168
169 vinit4(p->c[0], c[0] * ((1.0 - RIDCOL) + vrnd() * RIDCOL),
170 c[1] * ((1.0 - RIDCOL) + vrnd() * RIDCOL),
171 c[2] * ((1.0 - RIDCOL) + vrnd() * RIDCOL), 1.0);
172 vinit4(p->c[1], 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[2], 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}
179
180static void
181setpart(part * p)
182{
183 float fact;
184
185 if (p->p[0][1] < 0.1) {
186 setnewpart(p);
187 return;
188 }
189
190 p->v[1] += AGRAV * dt;
191
192 vadds(p->p[0], dt, p->v);
193 vadds(p->p[1], dt, p->v);
194 vadds(p->p[2], dt, p->v);
195
196 p->age++;
197
198 if ((p->age) > maxage) {
199 vequ(p->c[0], blu2);
200 vequ(p->c[1], blu2);
201 vequ(p->c[2], blu2);
202 }
203 else {
204 fact = 1.0 / maxage;
205 vadds(p->c[0], fact, blu2);
206 vclamp(p->c[0]);
207 p->c[0][3] = fact * (maxage - p->age);
208
209 vadds(p->c[1], fact, blu2);
210 vclamp(p->c[1]);
211 p->c[1][3] = fact * (maxage - p->age);
212
213 vadds(p->c[2], fact, blu2);
214 vclamp(p->c[2]);
215 p->c[2][3] = fact * (maxage - p->age);
216 }
217}
218
219static void
220drawtree(float x, float y, float z)
221{
222 glBegin(GL_QUADS);
223 glTexCoord2f(0.0, 0.0);
224 glVertex3f(x - 1.5, y + 0.0, z);
225
226 glTexCoord2f(1.0, 0.0);
227 glVertex3f(x + 1.5, y + 0.0, z);
228
229 glTexCoord2f(1.0, 1.0);
230 glVertex3f(x + 1.5, y + 3.0, z);
231
232 glTexCoord2f(0.0, 1.0);
233 glVertex3f(x - 1.5, y + 3.0, z);
234
235
236 glTexCoord2f(0.0, 0.0);
237 glVertex3f(x, y + 0.0, z - 1.5);
238
239 glTexCoord2f(1.0, 0.0);
240 glVertex3f(x, y + 0.0, z + 1.5);
241
242 glTexCoord2f(1.0, 1.0);
243 glVertex3f(x, y + 3.0, z + 1.5);
244
245 glTexCoord2f(0.0, 1.0);
246 glVertex3f(x, y + 3.0, z - 1.5);
247
248 glEnd();
249
250}
251
252static void
253calcposobs(void)
254{
255 dir[0] = sin(alpha * M_PI / 180.0);
256 dir[2] = cos(alpha * M_PI / 180.0) * sin(beta * M_PI / 180.0);
257 dir[1] = cos(beta * M_PI / 180.0);
258
259 obs[0] += v * dir[0];
260 obs[1] += v * dir[1];
261 obs[2] += v * dir[2];
262}
263
264static void
265printstring(void *font, char *string)
266{
267 int len, i;
268
269 len = (int) strlen(string);
270 for (i = 0; i < len; i++)
271 glutBitmapCharacter(font, string[i]);
272}
273
274static void
275reshape(int width, int height)
276{
277 WIDTH = width;
278 HEIGHT = height;
279 glViewport(0, 0, (GLint) width, (GLint) height);
280 glMatrixMode(GL_PROJECTION);
281 glLoadIdentity();
282 gluPerspective(70.0, width / (float) height, 0.1, 30.0);
283
284 glMatrixMode(GL_MODELVIEW);
285}
286
287static void
288printhelp(void)
289{
290 glColor4f(0.0, 0.0, 0.0, 0.5);
291 glRecti(40, 40, 600, 440);
292
293 glColor3f(1.0, 0.0, 0.0);
294 glRasterPos2i(300, 420);
295 printstring(GLUT_BITMAP_TIMES_ROMAN_24, "Help");
296
297 glRasterPos2i(60, 390);
298 printstring(GLUT_BITMAP_TIMES_ROMAN_24, "h - Togle Help");
299
300 glRasterPos2i(60, 360);
301 printstring(GLUT_BITMAP_TIMES_ROMAN_24, "t - Increase particle size");
302 glRasterPos2i(60, 330);
303 printstring(GLUT_BITMAP_TIMES_ROMAN_24, "T - Decrease particle size");
304
305 glRasterPos2i(60, 300);
306 printstring(GLUT_BITMAP_TIMES_ROMAN_24, "r - Increase emission radius");
307 glRasterPos2i(60, 270);
308 printstring(GLUT_BITMAP_TIMES_ROMAN_24, "R - Decrease emission radius");
309
310 glRasterPos2i(60, 240);
311 printstring(GLUT_BITMAP_TIMES_ROMAN_24, "f - Togle Fog");
312 glRasterPos2i(60, 210);
313 printstring(GLUT_BITMAP_TIMES_ROMAN_24, "s - Togle shadows");
314 glRasterPos2i(60, 180);
315 printstring(GLUT_BITMAP_TIMES_ROMAN_24, "Arrow Keys - Rotate");
316 glRasterPos2i(60, 150);
317 printstring(GLUT_BITMAP_TIMES_ROMAN_24, "a - Increase velocity");
318 glRasterPos2i(60, 120);
319 printstring(GLUT_BITMAP_TIMES_ROMAN_24, "z - Decrease velocity");
320
321 glRasterPos2i(60, 90);
322 if (joyavailable)
323 printstring(GLUT_BITMAP_TIMES_ROMAN_24,
324 "j - Togle jostick control (Joystick control available)");
325 else
326 printstring(GLUT_BITMAP_TIMES_ROMAN_24,
327 "(No Joystick control available)");
328}
329
330static void
331dojoy(void)
332{
333#ifdef WIN32
334 static UINT max[2] = { 0, 0 };
335 static UINT min[2] = { 0xffffffff, 0xffffffff }, center[2];
336 MMRESULT res;
337 JOYINFO joy;
338
339 res = joyGetPos(JOYSTICKID1, &joy);
340
341 if (res == JOYERR_NOERROR) {
342 joyavailable = 1;
343
344 if (max[0] < joy.wXpos)
345 max[0] = joy.wXpos;
346 if (min[0] > joy.wXpos)
347 min[0] = joy.wXpos;
348 center[0] = (max[0] + min[0]) / 2;
349
350 if (max[1] < joy.wYpos)
351 max[1] = joy.wYpos;
352 if (min[1] > joy.wYpos)
353 min[1] = joy.wYpos;
354 center[1] = (max[1] + min[1]) / 2;
355
356 if (joyactive) {
357 if (fabs(center[0] - (float) joy.wXpos) > 0.1 * (max[0] - min[0]))
358 alpha +=
359 2.5 * (center[0] - (float) joy.wXpos) / (max[0] - min[0]);
360 if (fabs(center[1] - (float) joy.wYpos) > 0.1 * (max[1] - min[1]))
361 beta += 2.5 * (center[1] - (float) joy.wYpos) / (max[1] - min[1]);
362
363 if (joy.wButtons & JOY_BUTTON1)
364 v += 0.01;
365 if (joy.wButtons & JOY_BUTTON2)
366 v -= 0.01;
367 }
368 }
369 else
370 joyavailable = 0;
371#endif
372}
373
374static void
375drawfire(void)
376{
Brian Pauld49b34a2000-09-12 18:44:45 +0000377 static char frbuf[80] = "";
Brian Paul5b0a7f32000-06-27 16:52:38 +0000378 int j;
Brian Paul5b0a7f32000-06-27 16:52:38 +0000379
380 dojoy();
381
382 glEnable(GL_DEPTH_TEST);
383
384 if (fog)
385 glEnable(GL_FOG);
386 else
387 glDisable(GL_FOG);
388
389 glDepthMask(GL_TRUE);
390 glClearColor(1.0, 1.0, 1.0, 1.0);
391 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
392
393 glPushMatrix();
394 calcposobs();
395 gluLookAt(obs[0], obs[1], obs[2],
396 obs[0] + dir[0], obs[1] + dir[1], obs[2] + dir[2],
397 0.0, 1.0, 0.0);
398
399 glColor4f(1.0, 1.0, 1.0, 1.0);
400
401 glEnable(GL_TEXTURE_2D);
402
403 glBindTexture(GL_TEXTURE_2D, groundid);
404 glBegin(GL_QUADS);
405 glTexCoord2fv(qt[0]);
406 glVertex3fv(q[0]);
407 glTexCoord2fv(qt[1]);
408 glVertex3fv(q[1]);
409 glTexCoord2fv(qt[2]);
410 glVertex3fv(q[2]);
411 glTexCoord2fv(qt[3]);
412 glVertex3fv(q[3]);
413 glEnd();
414
415 glEnable(GL_ALPHA_TEST);
416 glAlphaFunc(GL_GEQUAL, 0.9);
417
418 glBindTexture(GL_TEXTURE_2D, treeid);
419 for (j = 0; j < NUMTREE; j++)
420 drawtree(treepos[j][0], treepos[j][1], treepos[j][2]);
421
422 glDisable(GL_TEXTURE_2D);
423 glDepthMask(GL_FALSE);
424 glDisable(GL_ALPHA_TEST);
425
426 if (shadows) {
427 glBegin(GL_TRIANGLES);
428 for (j = 0; j < np; j++) {
429 glColor4f(black[0], black[1], black[2], p[j].c[0][3]);
430 glVertex3f(p[j].p[0][0], 0.1, p[j].p[0][2]);
431
432 glColor4f(black[0], black[1], black[2], p[j].c[1][3]);
433 glVertex3f(p[j].p[1][0], 0.1, p[j].p[1][2]);
434
435 glColor4f(black[0], black[1], black[2], p[j].c[2][3]);
436 glVertex3f(p[j].p[2][0], 0.1, p[j].p[2][2]);
437 }
438 glEnd();
439 }
440
441 glBegin(GL_TRIANGLES);
442 for (j = 0; j < np; j++) {
443 glColor4fv(p[j].c[0]);
444 glVertex3fv(p[j].p[0]);
445
446 glColor4fv(p[j].c[1]);
447 glVertex3fv(p[j].p[1]);
448
449 glColor4fv(p[j].c[2]);
450 glVertex3fv(p[j].p[2]);
451
452 setpart(&p[j]);
453 }
454 glEnd();
455
Brian Paul5b0a7f32000-06-27 16:52:38 +0000456 glDisable(GL_TEXTURE_2D);
457 glDisable(GL_ALPHA_TEST);
458 glDisable(GL_DEPTH_TEST);
459 glDisable(GL_FOG);
460
461 glMatrixMode(GL_PROJECTION);
462 glLoadIdentity();
463 glOrtho(-0.5, 639.5, -0.5, 479.5, -1.0, 1.0);
464 glMatrixMode(GL_MODELVIEW);
465 glLoadIdentity();
466
467 glColor3f(1.0, 0.0, 0.0);
468 glRasterPos2i(10, 10);
469 printstring(GLUT_BITMAP_HELVETICA_18, frbuf);
470 glRasterPos2i(370, 470);
471 printstring(GLUT_BITMAP_HELVETICA_10,
472 "Fire V1.5 Written by David Bucciarelli (tech.hmw@plus.it)");
473
474 if (help)
475 printhelp();
476
477 reshape(WIDTH, HEIGHT);
478 glPopMatrix();
479
480 glutSwapBuffers();
481
Brian Pauld49b34a2000-09-12 18:44:45 +0000482 Frames++;
483 {
484 GLint t = glutGet(GLUT_ELAPSED_TIME);
485 if (t - T0 >= 2000) {
486 GLfloat seconds = (t - T0) / 1000.0;
487 GLfloat fps = Frames / seconds;
488 sprintf(frbuf, "Frame rate: %f", fps);
489 T0 = t;
490 Frames = 0;
491 }
492 }
Brian Paul5b0a7f32000-06-27 16:52:38 +0000493}
494
495
496static void
497special(int key, int x, int y)
498{
499 switch (key) {
500 case GLUT_KEY_LEFT:
501 alpha += 2.0;
502 break;
503 case GLUT_KEY_RIGHT:
504 alpha -= 2.0;
505 break;
506 case GLUT_KEY_DOWN:
507 beta -= 2.0;
508 break;
509 case GLUT_KEY_UP:
510 beta += 2.0;
511 break;
512 }
513}
514
515static void
516key(unsigned char key, int x, int y)
517{
518 switch (key) {
519 case 27:
520 exit(0);
521 break;
522
523 case 'a':
524 v += 0.01;
525 break;
526 case 'z':
527 v -= 0.01;
528 break;
529
530 case 'j':
531 joyactive = (!joyactive);
532 break;
533 case 'h':
534 help = (!help);
535 break;
536 case 'f':
537 fog = (!fog);
538 break;
539 case 's':
540 shadows = !shadows;
541 break;
542 case 'R':
543 eject_r -= 0.03;
544 break;
545 case 'r':
546 eject_r += 0.03;
547 break;
548 case 't':
549 ridtri += 0.005;
550 break;
551 case 'T':
552 ridtri -= 0.005;
553 break;
554#ifdef XMESA
555 case ' ':
556 XMesaSetFXmode(fullscreen ? XMESA_FX_FULLSCREEN : XMESA_FX_WINDOW);
557 fullscreen = (!fullscreen);
558 break;
559#endif
560 }
561}
562
563static void
564inittextures(void)
565{
566 GLenum gluerr;
567 GLubyte tex[128][128][4];
568
569 glGenTextures(1, &groundid);
570 glBindTexture(GL_TEXTURE_2D, groundid);
571
572 glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
573 if (!LoadRGBMipmaps("../images/s128.rgb", GL_RGB)) {
574 fprintf(stderr, "Error reading a texture.\n");
575 exit(-1);
576 }
577
578 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
579 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
580
581 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
582 GL_LINEAR_MIPMAP_LINEAR);
583 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
584
585 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
586
587 glGenTextures(1, &treeid);
588 glBindTexture(GL_TEXTURE_2D, treeid);
589
Brian Paulf7688172000-06-27 17:12:10 +0000590 if (1)
Brian Paul5b0a7f32000-06-27 16:52:38 +0000591 {
592 int w, h;
593 GLenum format;
594 int x, y;
Brian Paulf7688172000-06-27 17:12:10 +0000595 GLubyte *image = LoadRGBImage("../images/tree3.rgb", &w, &h, &format);
Brian Paul5b0a7f32000-06-27 16:52:38 +0000596
597 if (!image) {
598 fprintf(stderr, "Error reading a texture.\n");
599 exit(-1);
600 }
601
602 for (y = 0; y < 128; y++)
603 for (x = 0; x < 128; x++) {
604 tex[x][y][0] = image[(y + x * 128) * 3];
605 tex[x][y][1] = image[(y + x * 128) * 3 + 1];
606 tex[x][y][2] = image[(y + x * 128) * 3 + 2];
607 if ((tex[x][y][0] == tex[x][y][1]) &&
608 (tex[x][y][1] == tex[x][y][2]) && (tex[x][y][2] == 255))
609 tex[x][y][3] = 0;
610 else
611 tex[x][y][3] = 255;
612 }
613
614 if ((gluerr = gluBuild2DMipmaps(GL_TEXTURE_2D, 4, 128, 128, GL_RGBA,
615 GL_UNSIGNED_BYTE, (GLvoid *) (tex)))) {
616 fprintf(stderr, "GLULib%s\n", gluErrorString(gluerr));
617 exit(-1);
618 }
619 }
Brian Paulf7688172000-06-27 17:12:10 +0000620 else {
621 if (!LoadRGBMipmaps("../images/tree2.rgba", GL_RGBA)) {
622 fprintf(stderr, "Error reading a texture.\n");
623 exit(-1);
624 }
625 }
Brian Paul5b0a7f32000-06-27 16:52:38 +0000626
627 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
628 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
629
630 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
631 GL_LINEAR_MIPMAP_LINEAR);
632 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
633
634 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
635}
636
637static void
638inittree(void)
639{
640 int i;
641 float dist;
642
643 for (i = 0; i < NUMTREE; i++)
644 do {
645 treepos[i][0] = vrnd() * TREEOUTR * 2.0 - TREEOUTR;
646 treepos[i][1] = 0.0;
647 treepos[i][2] = vrnd() * TREEOUTR * 2.0 - TREEOUTR;
648 dist =
649 sqrt(treepos[i][0] * treepos[i][0] +
650 treepos[i][2] * treepos[i][2]);
651 } while ((dist < TREEINR) || (dist > TREEOUTR));
652}
653
654int
655main(int ac, char **av)
656{
657 int i;
658
659 fprintf(stderr,
660 "Fire V1.5\nWritten by David Bucciarelli (tech.hmw@plus.it)\n");
661
662 /* Default settings */
663
664 WIDTH = 640;
665 HEIGHT = 480;
666 np = 800;
667 eject_r = 0.1;
668 dt = 0.015;
669 eject_vy = 4;
670 eject_vl = 1;
671 shadows = 1;
672 ridtri = 0.1;
673
674 maxage = 1.0 / dt;
675
676 if (ac == 2)
677 np = atoi(av[1]);
678
679 if (ac == 4) {
680 WIDTH = atoi(av[2]);
681 HEIGHT = atoi(av[3]);
682 }
683
684 glutInitWindowPosition(0, 0);
685 glutInitWindowSize(WIDTH, HEIGHT);
686 glutInit(&ac, av);
687
688 glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE);
689
690 if (!(win = glutCreateWindow("Fire"))) {
691 fprintf(stderr, "Error opening a window.\n");
692 exit(-1);
693 }
694
695 reshape(WIDTH, HEIGHT);
696
697 inittextures();
698
699 glShadeModel(GL_FLAT);
700 glEnable(GL_DEPTH_TEST);
701
702 glEnable(GL_BLEND);
703 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
704
705 glEnable(GL_FOG);
706 glFogi(GL_FOG_MODE, GL_EXP);
707 glFogfv(GL_FOG_COLOR, fogcolor);
708 glFogf(GL_FOG_DENSITY, 0.1);
709#ifdef FX
710 glHint(GL_FOG_HINT, GL_NICEST);
711#endif
712
713 p = malloc(sizeof(part) * np);
714
715 for (i = 0; i < np; i++)
716 setnewpart(&p[i]);
717
718 inittree();
719
720 glutKeyboardFunc(key);
721 glutSpecialFunc(special);
722 glutDisplayFunc(drawfire);
723 glutIdleFunc(drawfire);
724 glutReshapeFunc(reshape);
725 glutMainLoop();
726
727 return (0);
728}