Clone of mesa.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

fire.c 15KB

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