| /* |
| * This program is under the GNU GPL. |
| * Use at your own risk. |
| * |
| * written by David Bucciarelli (tech.hmw@plus.it) |
| * Humanware s.r.l. |
| */ |
| |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <math.h> |
| #include <time.h> |
| |
| #ifdef WIN32 |
| #include <windows.h> |
| #include <mmsystem.h> |
| #endif |
| |
| #include <GL/glut.h> |
| #include "readtex.c" |
| |
| #ifdef XMESA |
| #include "GL/xmesa.h" |
| static int fullscreen = 1; |
| #endif |
| |
| #ifndef M_PI |
| #define M_PI 3.1415926535 |
| #endif |
| |
| #define vinit(a,i,j,k) {\ |
| (a)[0]=i;\ |
| (a)[1]=j;\ |
| (a)[2]=k;\ |
| } |
| |
| #define vinit4(a,i,j,k,w) {\ |
| (a)[0]=i;\ |
| (a)[1]=j;\ |
| (a)[2]=k;\ |
| (a)[3]=w;\ |
| } |
| |
| |
| #define vadds(a,dt,b) {\ |
| (a)[0]+=(dt)*(b)[0];\ |
| (a)[1]+=(dt)*(b)[1];\ |
| (a)[2]+=(dt)*(b)[2];\ |
| } |
| |
| #define vequ(a,b) {\ |
| (a)[0]=(b)[0];\ |
| (a)[1]=(b)[1];\ |
| (a)[2]=(b)[2];\ |
| } |
| |
| #define vinter(a,dt,b,c) {\ |
| (a)[0]=(dt)*(b)[0]+(1.0-dt)*(c)[0];\ |
| (a)[1]=(dt)*(b)[1]+(1.0-dt)*(c)[1];\ |
| (a)[2]=(dt)*(b)[2]+(1.0-dt)*(c)[2];\ |
| } |
| |
| #define clamp(a) ((a) < 0.0 ? 0.0 : ((a) < 1.0 ? (a) : 1.0)) |
| |
| #define vclamp(v) {\ |
| (v)[0]=clamp((v)[0]);\ |
| (v)[1]=clamp((v)[1]);\ |
| (v)[2]=clamp((v)[2]);\ |
| } |
| |
| static int WIDTH = 640; |
| static int HEIGHT = 480; |
| |
| static GLint T0 = 0; |
| static GLint Frames = 0; |
| static GLint NiceFog = 1; |
| |
| #define DIMP 20.0 |
| #define DIMTP 16.0 |
| |
| #define RIDCOL 0.4 |
| |
| #define NUMTREE 50 |
| #define TREEINR 2.5 |
| #define TREEOUTR 8.0 |
| |
| #define AGRAV -9.8 |
| |
| typedef struct |
| { |
| int age; |
| float p[3][3]; |
| float v[3]; |
| float c[3][4]; |
| } |
| part; |
| |
| static float treepos[NUMTREE][3]; |
| |
| static float black[3] = { 0.0, 0.0, 0.0 }; |
| static float blu[3] = { 0.0, 0.2, 1.0 }; |
| static float blu2[3] = { 0.0, 1.0, 1.0 }; |
| |
| static float fogcolor[4] = { 1.0, 1.0, 1.0, 1.0 }; |
| |
| static float q[4][3] = { |
| {-DIMP, 0.0, -DIMP}, |
| {DIMP, 0.0, -DIMP}, |
| {DIMP, 0.0, DIMP}, |
| {-DIMP, 0.0, DIMP} |
| }; |
| |
| static float qt[4][2] = { |
| {-DIMTP, -DIMTP}, |
| {DIMTP, -DIMTP}, |
| {DIMTP, DIMTP}, |
| {-DIMTP, DIMTP} |
| }; |
| |
| static int win = 0; |
| |
| static int np; |
| static float eject_r, dt, maxage, eject_vy, eject_vl; |
| static short shadows; |
| static float ridtri; |
| static int fog = 1; |
| static int help = 1; |
| static int joyavailable = 0; |
| static int joyactive = 0; |
| |
| static part *p; |
| |
| static GLuint groundid; |
| static GLuint treeid; |
| |
| static float obs[3] = { 2.0, 1.0, 0.0 }; |
| static float dir[3]; |
| static float v = 0.0; |
| static float alpha = -90.0; |
| static float beta = 90.0; |
| |
| static float |
| vrnd(void) |
| { |
| return (((float) rand()) / RAND_MAX); |
| } |
| |
| static void |
| setnewpart(part * p) |
| { |
| float a, v[3], *c; |
| |
| p->age = 0; |
| |
| a = vrnd() * 3.14159265359 * 2.0; |
| |
| vinit(v, sin(a) * eject_r * vrnd(), 0.15, cos(a) * eject_r * vrnd()); |
| vinit(p->p[0], v[0] + vrnd() * ridtri, v[1] + vrnd() * ridtri, |
| v[2] + vrnd() * ridtri); |
| vinit(p->p[1], v[0] + vrnd() * ridtri, v[1] + vrnd() * ridtri, |
| v[2] + vrnd() * ridtri); |
| vinit(p->p[2], v[0] + vrnd() * ridtri, v[1] + vrnd() * ridtri, |
| v[2] + vrnd() * ridtri); |
| |
| vinit(p->v, v[0] * eject_vl / (eject_r / 2), |
| vrnd() * eject_vy + eject_vy / 2, v[2] * eject_vl / (eject_r / 2)); |
| |
| c = blu; |
| |
| vinit4(p->c[0], c[0] * ((1.0 - RIDCOL) + vrnd() * RIDCOL), |
| c[1] * ((1.0 - RIDCOL) + vrnd() * RIDCOL), |
| c[2] * ((1.0 - RIDCOL) + vrnd() * RIDCOL), 1.0); |
| vinit4(p->c[1], c[0] * ((1.0 - RIDCOL) + vrnd() * RIDCOL), |
| c[1] * ((1.0 - RIDCOL) + vrnd() * RIDCOL), |
| c[2] * ((1.0 - RIDCOL) + vrnd() * RIDCOL), 1.0); |
| vinit4(p->c[2], c[0] * ((1.0 - RIDCOL) + vrnd() * RIDCOL), |
| c[1] * ((1.0 - RIDCOL) + vrnd() * RIDCOL), |
| c[2] * ((1.0 - RIDCOL) + vrnd() * RIDCOL), 1.0); |
| } |
| |
| static void |
| setpart(part * p) |
| { |
| float fact; |
| |
| if (p->p[0][1] < 0.1) { |
| setnewpart(p); |
| return; |
| } |
| |
| p->v[1] += AGRAV * dt; |
| |
| vadds(p->p[0], dt, p->v); |
| vadds(p->p[1], dt, p->v); |
| vadds(p->p[2], dt, p->v); |
| |
| p->age++; |
| |
| if ((p->age) > maxage) { |
| vequ(p->c[0], blu2); |
| vequ(p->c[1], blu2); |
| vequ(p->c[2], blu2); |
| } |
| else { |
| fact = 1.0 / maxage; |
| vadds(p->c[0], fact, blu2); |
| vclamp(p->c[0]); |
| p->c[0][3] = fact * (maxage - p->age); |
| |
| vadds(p->c[1], fact, blu2); |
| vclamp(p->c[1]); |
| p->c[1][3] = fact * (maxage - p->age); |
| |
| vadds(p->c[2], fact, blu2); |
| vclamp(p->c[2]); |
| p->c[2][3] = fact * (maxage - p->age); |
| } |
| } |
| |
| static void |
| drawtree(float x, float y, float z) |
| { |
| glBegin(GL_QUADS); |
| glTexCoord2f(0.0, 0.0); |
| glVertex3f(x - 1.5, y + 0.0, z); |
| |
| glTexCoord2f(1.0, 0.0); |
| glVertex3f(x + 1.5, y + 0.0, z); |
| |
| glTexCoord2f(1.0, 1.0); |
| glVertex3f(x + 1.5, y + 3.0, z); |
| |
| glTexCoord2f(0.0, 1.0); |
| glVertex3f(x - 1.5, y + 3.0, z); |
| |
| |
| glTexCoord2f(0.0, 0.0); |
| glVertex3f(x, y + 0.0, z - 1.5); |
| |
| glTexCoord2f(1.0, 0.0); |
| glVertex3f(x, y + 0.0, z + 1.5); |
| |
| glTexCoord2f(1.0, 1.0); |
| glVertex3f(x, y + 3.0, z + 1.5); |
| |
| glTexCoord2f(0.0, 1.0); |
| glVertex3f(x, y + 3.0, z - 1.5); |
| |
| glEnd(); |
| |
| } |
| |
| static void |
| calcposobs(void) |
| { |
| dir[0] = sin(alpha * M_PI / 180.0); |
| dir[2] = cos(alpha * M_PI / 180.0) * sin(beta * M_PI / 180.0); |
| dir[1] = cos(beta * M_PI / 180.0); |
| |
| obs[0] += v * dir[0]; |
| obs[1] += v * dir[1]; |
| obs[2] += v * dir[2]; |
| } |
| |
| static void |
| printstring(void *font, char *string) |
| { |
| int len, i; |
| |
| len = (int) strlen(string); |
| for (i = 0; i < len; i++) |
| glutBitmapCharacter(font, string[i]); |
| } |
| |
| static void |
| reshape(int width, int height) |
| { |
| WIDTH = width; |
| HEIGHT = height; |
| glViewport(0, 0, (GLint) width, (GLint) height); |
| glMatrixMode(GL_PROJECTION); |
| glLoadIdentity(); |
| gluPerspective(70.0, width / (float) height, 0.1, 30.0); |
| |
| glMatrixMode(GL_MODELVIEW); |
| } |
| |
| static void |
| printhelp(void) |
| { |
| glColor4f(0.0, 0.0, 0.0, 0.5); |
| glRecti(40, 40, 600, 440); |
| |
| glColor3f(1.0, 0.0, 0.0); |
| glRasterPos2i(300, 420); |
| printstring(GLUT_BITMAP_TIMES_ROMAN_24, "Help"); |
| |
| glRasterPos2i(60, 390); |
| printstring(GLUT_BITMAP_TIMES_ROMAN_24, "h - Togle Help"); |
| |
| glRasterPos2i(60, 360); |
| printstring(GLUT_BITMAP_TIMES_ROMAN_24, "t - Increase particle size"); |
| glRasterPos2i(60, 330); |
| printstring(GLUT_BITMAP_TIMES_ROMAN_24, "T - Decrease particle size"); |
| |
| glRasterPos2i(60, 300); |
| printstring(GLUT_BITMAP_TIMES_ROMAN_24, "r - Increase emission radius"); |
| glRasterPos2i(60, 270); |
| printstring(GLUT_BITMAP_TIMES_ROMAN_24, "R - Decrease emission radius"); |
| |
| glRasterPos2i(60, 240); |
| printstring(GLUT_BITMAP_TIMES_ROMAN_24, "f - Togle Fog"); |
| glRasterPos2i(60, 210); |
| printstring(GLUT_BITMAP_TIMES_ROMAN_24, "s - Togle shadows"); |
| glRasterPos2i(60, 180); |
| printstring(GLUT_BITMAP_TIMES_ROMAN_24, "Arrow Keys - Rotate"); |
| glRasterPos2i(60, 150); |
| printstring(GLUT_BITMAP_TIMES_ROMAN_24, "a - Increase velocity"); |
| glRasterPos2i(60, 120); |
| printstring(GLUT_BITMAP_TIMES_ROMAN_24, "z - Decrease velocity"); |
| |
| glRasterPos2i(60, 90); |
| if (joyavailable) |
| printstring(GLUT_BITMAP_TIMES_ROMAN_24, |
| "j - Togle jostick control (Joystick control available)"); |
| else |
| printstring(GLUT_BITMAP_TIMES_ROMAN_24, |
| "(No Joystick control available)"); |
| } |
| |
| static void |
| dojoy(void) |
| { |
| #ifdef WIN32 |
| static UINT max[2] = { 0, 0 }; |
| static UINT min[2] = { 0xffffffff, 0xffffffff }, center[2]; |
| MMRESULT res; |
| JOYINFO joy; |
| |
| res = joyGetPos(JOYSTICKID1, &joy); |
| |
| if (res == JOYERR_NOERROR) { |
| joyavailable = 1; |
| |
| if (max[0] < joy.wXpos) |
| max[0] = joy.wXpos; |
| if (min[0] > joy.wXpos) |
| min[0] = joy.wXpos; |
| center[0] = (max[0] + min[0]) / 2; |
| |
| if (max[1] < joy.wYpos) |
| max[1] = joy.wYpos; |
| if (min[1] > joy.wYpos) |
| min[1] = joy.wYpos; |
| center[1] = (max[1] + min[1]) / 2; |
| |
| if (joyactive) { |
| if (fabs(center[0] - (float) joy.wXpos) > 0.1 * (max[0] - min[0])) |
| alpha += |
| 2.5 * (center[0] - (float) joy.wXpos) / (max[0] - min[0]); |
| if (fabs(center[1] - (float) joy.wYpos) > 0.1 * (max[1] - min[1])) |
| beta += 2.5 * (center[1] - (float) joy.wYpos) / (max[1] - min[1]); |
| |
| if (joy.wButtons & JOY_BUTTON1) |
| v += 0.01; |
| if (joy.wButtons & JOY_BUTTON2) |
| v -= 0.01; |
| } |
| } |
| else |
| joyavailable = 0; |
| #endif |
| } |
| |
| static void |
| drawfire(void) |
| { |
| static char frbuf[80] = ""; |
| int j; |
| |
| dojoy(); |
| |
| if (NiceFog) |
| glHint(GL_FOG_HINT, GL_NICEST); |
| else |
| glHint(GL_FOG_HINT, GL_DONT_CARE); |
| |
| glEnable(GL_DEPTH_TEST); |
| |
| if (fog) |
| glEnable(GL_FOG); |
| else |
| glDisable(GL_FOG); |
| |
| glDepthMask(GL_TRUE); |
| glClearColor(1.0, 1.0, 1.0, 1.0); |
| glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); |
| |
| glPushMatrix(); |
| calcposobs(); |
| gluLookAt(obs[0], obs[1], obs[2], |
| obs[0] + dir[0], obs[1] + dir[1], obs[2] + dir[2], |
| 0.0, 1.0, 0.0); |
| |
| glColor4f(1.0, 1.0, 1.0, 1.0); |
| |
| glEnable(GL_TEXTURE_2D); |
| |
| glBindTexture(GL_TEXTURE_2D, groundid); |
| #if 1 |
| glBegin(GL_QUADS); |
| glTexCoord2fv(qt[0]); |
| glVertex3fv(q[0]); |
| glTexCoord2fv(qt[1]); |
| glVertex3fv(q[1]); |
| glTexCoord2fv(qt[2]); |
| glVertex3fv(q[2]); |
| glTexCoord2fv(qt[3]); |
| glVertex3fv(q[3]); |
| glEnd(); |
| #else |
| /* Subdivide the ground into a bunch of quads. This improves fog |
| * if GL_FOG_HINT != GL_NICEST |
| */ |
| { |
| float x, y; |
| float dx = 1.0, dy = 1.0; |
| glBegin(GL_QUADS); |
| for (y = -DIMP; y < DIMP; y += 1.0) { |
| for (x = -DIMP; x < DIMP; x += 1.0) { |
| glTexCoord2f(0, 0); glVertex3f(x, 0, y); |
| glTexCoord2f(1, 0); glVertex3f(x+dx, 0, y); |
| glTexCoord2f(1, 1); glVertex3f(x+dx, 0, y+dy); |
| glTexCoord2f(0, 1); glVertex3f(x, 0, y+dy); |
| } |
| } |
| glEnd(); |
| } |
| #endif |
| |
| |
| glEnable(GL_ALPHA_TEST); |
| glAlphaFunc(GL_GEQUAL, 0.9); |
| |
| glBindTexture(GL_TEXTURE_2D, treeid); |
| for (j = 0; j < NUMTREE; j++) |
| drawtree(treepos[j][0], treepos[j][1], treepos[j][2]); |
| |
| glDisable(GL_TEXTURE_2D); |
| glDepthMask(GL_FALSE); |
| glDisable(GL_ALPHA_TEST); |
| |
| if (shadows) { |
| glBegin(GL_TRIANGLES); |
| for (j = 0; j < np; j++) { |
| glColor4f(black[0], black[1], black[2], p[j].c[0][3]); |
| glVertex3f(p[j].p[0][0], 0.1, p[j].p[0][2]); |
| |
| glColor4f(black[0], black[1], black[2], p[j].c[1][3]); |
| glVertex3f(p[j].p[1][0], 0.1, p[j].p[1][2]); |
| |
| glColor4f(black[0], black[1], black[2], p[j].c[2][3]); |
| glVertex3f(p[j].p[2][0], 0.1, p[j].p[2][2]); |
| } |
| glEnd(); |
| } |
| |
| glBegin(GL_TRIANGLES); |
| for (j = 0; j < np; j++) { |
| glColor4fv(p[j].c[0]); |
| glVertex3fv(p[j].p[0]); |
| |
| glColor4fv(p[j].c[1]); |
| glVertex3fv(p[j].p[1]); |
| |
| glColor4fv(p[j].c[2]); |
| glVertex3fv(p[j].p[2]); |
| |
| setpart(&p[j]); |
| } |
| glEnd(); |
| |
| glDisable(GL_TEXTURE_2D); |
| glDisable(GL_ALPHA_TEST); |
| glDisable(GL_DEPTH_TEST); |
| glDisable(GL_FOG); |
| |
| glMatrixMode(GL_PROJECTION); |
| glLoadIdentity(); |
| glOrtho(-0.5, 639.5, -0.5, 479.5, -1.0, 1.0); |
| glMatrixMode(GL_MODELVIEW); |
| glLoadIdentity(); |
| |
| glColor3f(1.0, 0.0, 0.0); |
| glRasterPos2i(10, 10); |
| printstring(GLUT_BITMAP_HELVETICA_18, frbuf); |
| glRasterPos2i(370, 470); |
| printstring(GLUT_BITMAP_HELVETICA_10, |
| "Fire V1.5 Written by David Bucciarelli (tech.hmw@plus.it)"); |
| |
| if (help) |
| printhelp(); |
| |
| reshape(WIDTH, HEIGHT); |
| glPopMatrix(); |
| |
| glutSwapBuffers(); |
| |
| Frames++; |
| { |
| GLint t = glutGet(GLUT_ELAPSED_TIME); |
| if (t - T0 >= 2000) { |
| GLfloat seconds = (t - T0) / 1000.0; |
| GLfloat fps = Frames / seconds; |
| sprintf(frbuf, "Frame rate: %f", fps); |
| T0 = t; |
| Frames = 0; |
| } |
| } |
| } |
| |
| |
| static void |
| idle(void) |
| { |
| glutPostRedisplay(); |
| } |
| |
| |
| static void |
| special(int key, int x, int y) |
| { |
| switch (key) { |
| case GLUT_KEY_LEFT: |
| alpha += 2.0; |
| break; |
| case GLUT_KEY_RIGHT: |
| alpha -= 2.0; |
| break; |
| case GLUT_KEY_DOWN: |
| beta -= 2.0; |
| break; |
| case GLUT_KEY_UP: |
| beta += 2.0; |
| break; |
| } |
| glutPostRedisplay(); |
| } |
| |
| static void |
| key(unsigned char key, int x, int y) |
| { |
| switch (key) { |
| case 27: |
| exit(0); |
| break; |
| |
| case 'a': |
| v += 0.01; |
| break; |
| case 'z': |
| v -= 0.01; |
| break; |
| |
| case 'j': |
| joyactive = (!joyactive); |
| break; |
| case 'h': |
| help = (!help); |
| break; |
| case 'f': |
| fog = (!fog); |
| break; |
| case 's': |
| shadows = !shadows; |
| break; |
| case 'R': |
| eject_r -= 0.03; |
| break; |
| case 'r': |
| eject_r += 0.03; |
| break; |
| case 't': |
| ridtri += 0.005; |
| break; |
| case 'T': |
| ridtri -= 0.005; |
| break; |
| #ifdef XMESA |
| case ' ': |
| XMesaSetFXmode(fullscreen ? XMESA_FX_FULLSCREEN : XMESA_FX_WINDOW); |
| fullscreen = (!fullscreen); |
| break; |
| #endif |
| case 'n': |
| NiceFog = !NiceFog; |
| printf("NiceFog %d\n", NiceFog); |
| break; |
| } |
| glutPostRedisplay(); |
| } |
| |
| static void |
| inittextures(void) |
| { |
| GLenum gluerr; |
| GLubyte tex[128][128][4]; |
| |
| glGenTextures(1, &groundid); |
| glBindTexture(GL_TEXTURE_2D, groundid); |
| |
| glPixelStorei(GL_UNPACK_ALIGNMENT, 4); |
| if (!LoadRGBMipmaps("../images/s128.rgb", GL_RGB)) { |
| fprintf(stderr, "Error reading a texture.\n"); |
| exit(-1); |
| } |
| |
| glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); |
| glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); |
| |
| glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, |
| GL_LINEAR_MIPMAP_LINEAR); |
| glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); |
| |
| glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL); |
| |
| glGenTextures(1, &treeid); |
| glBindTexture(GL_TEXTURE_2D, treeid); |
| |
| if (1) |
| { |
| int w, h; |
| GLenum format; |
| int x, y; |
| GLubyte *image = LoadRGBImage("../images/tree3.rgb", &w, &h, &format); |
| |
| if (!image) { |
| fprintf(stderr, "Error reading a texture.\n"); |
| exit(-1); |
| } |
| |
| for (y = 0; y < 128; y++) |
| for (x = 0; x < 128; x++) { |
| tex[x][y][0] = image[(y + x * 128) * 3]; |
| tex[x][y][1] = image[(y + x * 128) * 3 + 1]; |
| tex[x][y][2] = image[(y + x * 128) * 3 + 2]; |
| if ((tex[x][y][0] == tex[x][y][1]) && |
| (tex[x][y][1] == tex[x][y][2]) && (tex[x][y][2] == 255)) |
| tex[x][y][3] = 0; |
| else |
| tex[x][y][3] = 255; |
| } |
| |
| if ((gluerr = gluBuild2DMipmaps(GL_TEXTURE_2D, 4, 128, 128, GL_RGBA, |
| GL_UNSIGNED_BYTE, (GLvoid *) (tex)))) { |
| fprintf(stderr, "GLULib%s\n", gluErrorString(gluerr)); |
| exit(-1); |
| } |
| } |
| else { |
| if (!LoadRGBMipmaps("../images/tree2.rgba", GL_RGBA)) { |
| fprintf(stderr, "Error reading a texture.\n"); |
| exit(-1); |
| } |
| } |
| |
| glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); |
| glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); |
| |
| glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, |
| GL_LINEAR_MIPMAP_LINEAR); |
| glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); |
| |
| glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); |
| } |
| |
| static void |
| inittree(void) |
| { |
| int i; |
| float dist; |
| |
| for (i = 0; i < NUMTREE; i++) |
| do { |
| treepos[i][0] = vrnd() * TREEOUTR * 2.0 - TREEOUTR; |
| treepos[i][1] = 0.0; |
| treepos[i][2] = vrnd() * TREEOUTR * 2.0 - TREEOUTR; |
| dist = |
| sqrt(treepos[i][0] * treepos[i][0] + |
| treepos[i][2] * treepos[i][2]); |
| } while ((dist < TREEINR) || (dist > TREEOUTR)); |
| } |
| |
| int |
| main(int ac, char **av) |
| { |
| int i; |
| |
| fprintf(stderr, |
| "Fire V1.5\nWritten by David Bucciarelli (tech.hmw@plus.it)\n"); |
| |
| /* Default settings */ |
| |
| np = 800; |
| eject_r = 0.1; |
| dt = 0.015; |
| eject_vy = 4; |
| eject_vl = 1; |
| shadows = 1; |
| ridtri = 0.1; |
| |
| maxage = 1.0 / dt; |
| |
| if (ac == 2) |
| np = atoi(av[1]); |
| |
| if (ac == 4) { |
| WIDTH = atoi(av[2]); |
| HEIGHT = atoi(av[3]); |
| } |
| |
| glutInitWindowPosition(0, 0); |
| glutInitWindowSize(WIDTH, HEIGHT); |
| glutInit(&ac, av); |
| |
| glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE); |
| |
| if (!(win = glutCreateWindow("Fire"))) { |
| fprintf(stderr, "Error opening a window.\n"); |
| exit(-1); |
| } |
| |
| reshape(WIDTH, HEIGHT); |
| |
| inittextures(); |
| |
| glShadeModel(GL_FLAT); |
| glEnable(GL_DEPTH_TEST); |
| |
| glEnable(GL_BLEND); |
| glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); |
| |
| glEnable(GL_FOG); |
| glFogi(GL_FOG_MODE, GL_EXP); |
| glFogfv(GL_FOG_COLOR, fogcolor); |
| glFogf(GL_FOG_DENSITY, 0.1); |
| |
| p = malloc(sizeof(part) * np); |
| |
| for (i = 0; i < np; i++) |
| setnewpart(&p[i]); |
| |
| inittree(); |
| |
| glutKeyboardFunc(key); |
| glutSpecialFunc(special); |
| glutDisplayFunc(drawfire); |
| glutIdleFunc(idle); |
| glutReshapeFunc(reshape); |
| glutMainLoop(); |
| |
| return (0); |
| } |