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