/* * 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 #include #include #include #include #ifdef _WIN32 #include #endif #include #include "image.h" #if defined(GL_VERSION_1_1) /* Routines called directly. */ #elif defined(GL_EXT_texture_object) && defined(GL_EXT_copy_texture) && defined(GL_EXT_subtexture) #define glBindTexture(A,B) glBindTextureEXT(A,B) #define glGenTextures(A,B) glGenTexturesEXT(A,B) #else #define glBindTexture(A,B) #define glGenTextures(A,B) #endif /* Some files do not define M_PI... */ #ifndef M_PI #define M_PI 3.14159265358979323846 #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; #define FRAME 50 #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 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 gettime(void) { static clock_t told=0; clock_t tnew,ris; tnew=clock(); ris=tnew-told; told=tnew; return(ris/(float)CLOCKS_PER_SEC); } 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;ijoy.wXpos) min[0]=joy.wXpos; center[0]=(max[0]+min[0])/2; if(max[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 int count=0; static char frbuf[80]; int j; float fr; dojoy(); 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); 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(); glEnable(GL_ALPHA_TEST); glAlphaFunc(GL_GEQUAL,0.9); glBindTexture(GL_TEXTURE_2D,treeid); for(j=0;jsizeX, img->sizeY, GL_RGB, GL_UNSIGNED_BYTE, (GLvoid *)(img->data)))) { fprintf(stderr,"GLULib%s\n",gluErrorString(gluerr)); 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_NEAREST_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(!(img=ImageLoad("tree2.rgb"))) { 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]=img->data[(y+x*128)*3]; tex[x][y][1]=img->data[(y+x*128)*3+1]; tex[x][y][2]=img->data[(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); } 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_NEAREST_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;iTREEOUTR)); } int main(int ac,char **av) { int i; fprintf(stderr,"Fire V1.5\nWritten by David Bucciarelli (tech.hmw@plus.it)\n"); /* Default settings */ WIDTH=640; HEIGHT=480; 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); glutCreateWindow("Fire"); 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); #ifdef FX glHint(GL_FOG_HINT,GL_NICEST); #endif p=malloc(sizeof(part)*np); for(i=0;i