diff options
Diffstat (limited to 'progs/demos/particles.cxx')
-rw-r--r-- | progs/demos/particles.cxx | 219 |
1 files changed, 219 insertions, 0 deletions
diff --git a/progs/demos/particles.cxx b/progs/demos/particles.cxx new file mode 100644 index 0000000000..b88c318e0b --- /dev/null +++ b/progs/demos/particles.cxx @@ -0,0 +1,219 @@ +/* + * This program is under the GNU GPL. + * Use at your own risk. + * + * written by David Bucciarelli (humanware@plus.it) + * Humanware s.r.l. + */ + +#include <stdlib.h> + +#include "particles.h" + +#define vinit(a,i,j,k) {\ + (a)[0]=i;\ + (a)[1]=j;\ + (a)[2]=k;\ +} + +#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]);\ +} + + +float rainParticle::min[3]; +float rainParticle::max[3]; +float rainParticle::partLength=0.2f; + + +static float vrnd(void) +{ + return(((float)rand())/RAND_MAX); +} + + +particle::particle() +{ + age=0.0f; + + vinit(acc,0.0f,0.0f,0.0f); + vinit(vel,0.0f,0.0f,0.0f); + vinit(pos,0.0f,0.0f,0.0f); +} + +void particle::elapsedTime(float dt) +{ + age+=dt; + + vadds(vel,dt,acc); + + vadds(pos,dt,vel); +} + +///////////////////////////////////////// +// Particle System +///////////////////////////////////////// + +particleSystem::particleSystem() +{ + t=0.0f; + + part=NULL; + + particleNum=0; +} + +particleSystem::~particleSystem() +{ + if(part) + free(part); +} + +void particleSystem::addParticle(particle *p) +{ + if(!part) { + part=(particle **)calloc(1,sizeof(particle *)); + part[0]=p; + particleNum=1; + } else { + particleNum++; + part=(particle **)realloc(part,sizeof(particle *)*particleNum); + part[particleNum-1]=p; + } +} + +void particleSystem::reset(void) +{ + if(part) + free(part); + + t=0.0f; + + part=NULL; + + particleNum=0; +} + +void particleSystem::draw(void) +{ + if(!part) + return; + + part[0]->beginDraw(); + for(unsigned int i=0;i<particleNum;i++) + part[i]->draw(); + part[0]->endDraw(); +} + +void particleSystem::addTime(float dt) +{ + if(!part) + return; + + for(unsigned int i=0;i<particleNum;i++) { + part[i]->elapsedTime(dt); + part[i]->checkAge(); + } +} + +///////////////////////////////////////// +// Rain +///////////////////////////////////////// + +void rainParticle::init(void) +{ + age=0.0f; + + acc[0]=0.0f; + acc[1]=-0.98f; + acc[2]=0.0f; + + vel[0]=0.0f; + vel[1]=0.0f; + vel[2]=0.0f; + + oldpos[0]=pos[0]=min[0]+(max[0]-min[0])*vrnd(); + oldpos[1]=pos[1]=max[1]+0.2f*max[1]*vrnd(); + oldpos[2]=pos[2]=min[2]+(max[2]-min[2])*vrnd(); + + vadds(oldpos,-partLength,vel); +} + +rainParticle::rainParticle() +{ + init(); +} + +void rainParticle::setRainingArea(float minx, float miny, float minz, + float maxx, float maxy, float maxz) +{ + vinit(min,minx,miny,minz); + vinit(max,maxx,maxy,maxz); +} + +void rainParticle::setLength(float l) +{ + partLength=l; +} + +void rainParticle::draw(void) +{ + glColor4f(0.7f,0.95f,1.0f,0.0f); + glVertex3fv(oldpos); + + glColor4f(0.3f,0.7f,1.0f,1.0f); + glVertex3fv(pos); +} + +void rainParticle::checkAge(void) +{ + if(pos[1]<min[1]) + init(); +} + +void rainParticle::elapsedTime(float dt) +{ + particle::elapsedTime(dt); + + if(pos[0]<min[0]) + pos[0]=max[0]-(min[0]-pos[0]); + if(pos[2]<min[2]) + pos[2]=max[2]-(min[2]-pos[2]); + + if(pos[0]>max[0]) + pos[0]=min[0]+(pos[0]-max[0]); + if(pos[2]>max[2]) + pos[2]=min[2]+(pos[2]-max[2]); + + vequ(oldpos,pos); + vadds(oldpos,-partLength,vel); +} + +void rainParticle::randomHeight(void) +{ + pos[1]=(max[1]-min[1])*vrnd()+min[1]; + + oldpos[1]=pos[1]-partLength*vel[1]; +} |