summaryrefslogtreecommitdiffstats
path: root/progs/demos/particles.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'progs/demos/particles.cxx')
-rw-r--r--progs/demos/particles.cxx219
1 files changed, 219 insertions, 0 deletions
diff --git a/progs/demos/particles.cxx b/progs/demos/particles.cxx
new file mode 100644
index 00000000000..b88c318e0bc
--- /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 ([email protected])
+ * 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];
+}