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 16KB

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