220 lines
3.4 KiB
C++
220 lines
3.4 KiB
C++
/*
|
|
* 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];
|
|
}
|