blob: 100df8156514135b7a58dd57c79f1d63d50c279e [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
Brian Paule188b6e2000-10-21 04:29:02 +0000497idle(void)
498{
499 glutPostRedisplay();
500}
501
502
503static void
Brian Paul5b0a7f32000-06-27 16:52:38 +0000504special(int key, int x, int y)
505{
506 switch (key) {
507 case GLUT_KEY_LEFT:
508 alpha += 2.0;
509 break;
510 case GLUT_KEY_RIGHT:
511 alpha -= 2.0;
512 break;
513 case GLUT_KEY_DOWN:
514 beta -= 2.0;
515 break;
516 case GLUT_KEY_UP:
517 beta += 2.0;
518 break;
519 }
520}
521
522static void
523key(unsigned char key, int x, int y)
524{
525 switch (key) {
526 case 27:
527 exit(0);
528 break;
529
530 case 'a':
531 v += 0.01;
532 break;
533 case 'z':
534 v -= 0.01;
535 break;
536
537 case 'j':
538 joyactive = (!joyactive);
539 break;
540 case 'h':
541 help = (!help);
542 break;
543 case 'f':
544 fog = (!fog);
545 break;
546 case 's':
547 shadows = !shadows;
548 break;
549 case 'R':
550 eject_r -= 0.03;
551 break;
552 case 'r':
553 eject_r += 0.03;
554 break;
555 case 't':
556 ridtri += 0.005;
557 break;
558 case 'T':
559 ridtri -= 0.005;
560 break;
561#ifdef XMESA
562 case ' ':
563 XMesaSetFXmode(fullscreen ? XMESA_FX_FULLSCREEN : XMESA_FX_WINDOW);
564 fullscreen = (!fullscreen);
565 break;
566#endif
567 }
568}
569
570static void
571inittextures(void)
572{
573 GLenum gluerr;
574 GLubyte tex[128][128][4];
575
576 glGenTextures(1, &groundid);
577 glBindTexture(GL_TEXTURE_2D, groundid);
578
579 glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
580 if (!LoadRGBMipmaps("../images/s128.rgb", GL_RGB)) {
581 fprintf(stderr, "Error reading a texture.\n");
582 exit(-1);
583 }
584
585 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
586 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
587
588 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
589 GL_LINEAR_MIPMAP_LINEAR);
590 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
591
592 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
593
594 glGenTextures(1, &treeid);
595 glBindTexture(GL_TEXTURE_2D, treeid);
596
Brian Paulf7688172000-06-27 17:12:10 +0000597 if (1)
Brian Paul5b0a7f32000-06-27 16:52:38 +0000598 {
599 int w, h;
600 GLenum format;
601 int x, y;
Brian Paulf7688172000-06-27 17:12:10 +0000602 GLubyte *image = LoadRGBImage("../images/tree3.rgb", &w, &h, &format);
Brian Paul5b0a7f32000-06-27 16:52:38 +0000603
604 if (!image) {
605 fprintf(stderr, "Error reading a texture.\n");
606 exit(-1);
607 }
608
609 for (y = 0; y < 128; y++)
610 for (x = 0; x < 128; x++) {
611 tex[x][y][0] = image[(y + x * 128) * 3];
612 tex[x][y][1] = image[(y + x * 128) * 3 + 1];
613 tex[x][y][2] = image[(y + x * 128) * 3 + 2];
614 if ((tex[x][y][0] == tex[x][y][1]) &&
615 (tex[x][y][1] == tex[x][y][2]) && (tex[x][y][2] == 255))
616 tex[x][y][3] = 0;
617 else
618 tex[x][y][3] = 255;
619 }
620
621 if ((gluerr = gluBuild2DMipmaps(GL_TEXTURE_2D, 4, 128, 128, GL_RGBA,
622 GL_UNSIGNED_BYTE, (GLvoid *) (tex)))) {
623 fprintf(stderr, "GLULib%s\n", gluErrorString(gluerr));
624 exit(-1);
625 }
626 }
Brian Paulf7688172000-06-27 17:12:10 +0000627 else {
628 if (!LoadRGBMipmaps("../images/tree2.rgba", GL_RGBA)) {
629 fprintf(stderr, "Error reading a texture.\n");
630 exit(-1);
631 }
632 }
Brian Paul5b0a7f32000-06-27 16:52:38 +0000633
634 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
635 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
636
637 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
638 GL_LINEAR_MIPMAP_LINEAR);
639 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
640
641 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
642}
643
644static void
645inittree(void)
646{
647 int i;
648 float dist;
649
650 for (i = 0; i < NUMTREE; i++)
651 do {
652 treepos[i][0] = vrnd() * TREEOUTR * 2.0 - TREEOUTR;
653 treepos[i][1] = 0.0;
654 treepos[i][2] = vrnd() * TREEOUTR * 2.0 - TREEOUTR;
655 dist =
656 sqrt(treepos[i][0] * treepos[i][0] +
657 treepos[i][2] * treepos[i][2]);
658 } while ((dist < TREEINR) || (dist > TREEOUTR));
659}
660
661int
662main(int ac, char **av)
663{
664 int i;
665
666 fprintf(stderr,
667 "Fire V1.5\nWritten by David Bucciarelli (tech.hmw@plus.it)\n");
668
669 /* Default settings */
670
671 WIDTH = 640;
672 HEIGHT = 480;
673 np = 800;
674 eject_r = 0.1;
675 dt = 0.015;
676 eject_vy = 4;
677 eject_vl = 1;
678 shadows = 1;
679 ridtri = 0.1;
680
681 maxage = 1.0 / dt;
682
683 if (ac == 2)
684 np = atoi(av[1]);
685
686 if (ac == 4) {
687 WIDTH = atoi(av[2]);
688 HEIGHT = atoi(av[3]);
689 }
690
691 glutInitWindowPosition(0, 0);
692 glutInitWindowSize(WIDTH, HEIGHT);
693 glutInit(&ac, av);
694
695 glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE);
696
697 if (!(win = glutCreateWindow("Fire"))) {
698 fprintf(stderr, "Error opening a window.\n");
699 exit(-1);
700 }
701
702 reshape(WIDTH, HEIGHT);
703
704 inittextures();
705
706 glShadeModel(GL_FLAT);
707 glEnable(GL_DEPTH_TEST);
708
709 glEnable(GL_BLEND);
710 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
711
712 glEnable(GL_FOG);
713 glFogi(GL_FOG_MODE, GL_EXP);
714 glFogfv(GL_FOG_COLOR, fogcolor);
715 glFogf(GL_FOG_DENSITY, 0.1);
716#ifdef FX
717 glHint(GL_FOG_HINT, GL_NICEST);
718#endif
719
720 p = malloc(sizeof(part) * np);
721
722 for (i = 0; i < np; i++)
723 setnewpart(&p[i]);
724
725 inittree();
726
727 glutKeyboardFunc(key);
728 glutSpecialFunc(special);
729 glutDisplayFunc(drawfire);
Brian Paule188b6e2000-10-21 04:29:02 +0000730 glutIdleFunc(idle);
Brian Paul5b0a7f32000-06-27 16:52:38 +0000731 glutReshapeFunc(reshape);
732 glutMainLoop();
733
734 return (0);
735}