Browse Source

Particles

Panagiotis Christopoulos Charitos 13 years ago
parent
commit
b8be75d8d6
3 changed files with 134 additions and 113 deletions
  1. 24 12
      include/anki/scene/ParticleEmitter.h
  2. 109 100
      src/scene/ParticleEmitter.cpp
  3. 1 1
      testapp/Main.cpp

+ 24 - 12
include/anki/scene/ParticleEmitter.h

@@ -10,12 +10,21 @@
 
 
 namespace anki {
 namespace anki {
 
 
+class ParticleEmitter;
+
 /// Particle base
 /// Particle base
 /// XXX Remove SceneNode
 /// XXX Remove SceneNode
 class ParticleBase: public SceneNode, public Movable
 class ParticleBase: public SceneNode, public Movable
 {
 {
 public:
 public:
+	enum ParticleType
+	{
+		PT_SIMPLE,
+		PT_PHYSICS
+	};
+
 	ParticleBase(
 	ParticleBase(
+		ParticleType type,
 		// SceneNode
 		// SceneNode
 		const char* name, Scene* scene, 
 		const char* name, Scene* scene, 
 		// Movable
 		// Movable
@@ -74,17 +83,20 @@ public:
 	}
 	}
 
 
 	/// Revive the particle
 	/// Revive the particle
-	virtual void revive(const ParticleEmitterProperties& props,
+	virtual void revive(const ParticleEmitter& pe,
 		F32 prevUpdateTime, F32 crntTime)
 		F32 prevUpdateTime, F32 crntTime)
 	{
 	{
-		(void)props;
+		(void)pe;
 		(void)prevUpdateTime;
 		(void)prevUpdateTime;
 		(void)crntTime;
 		(void)crntTime;
 	}
 	}
 
 
-private:
+protected:
 	F32 timeOfBirth; ///< Keep the time of birth for nice effects
 	F32 timeOfBirth; ///< Keep the time of birth for nice effects
 	F32 timeOfDeath = -1.0; ///< Time of death. If < 0.0 then dead. In seconds
 	F32 timeOfDeath = -1.0; ///< Time of death. If < 0.0 then dead. In seconds
+
+private:
+	ParticleType type;
 };
 };
 
 
 /// Simple particle for simple simulation
 /// Simple particle for simple simulation
@@ -96,13 +108,13 @@ public:
 		const char* name, Scene* scene, 
 		const char* name, Scene* scene, 
 		// Movable
 		// Movable
 		U32 movableFlags, Movable* movParent)
 		U32 movableFlags, Movable* movParent)
-		: ParticleBase(name, scene, movableFlags, movParent)
+		: ParticleBase(PT_SIMPLE, name, scene, movableFlags, movParent)
 	{}
 	{}
 
 
-	void revive(const ParticleEmitterProperties& props,
+	void revive(const ParticleEmitter& pe,
 		F32 prevUpdateTime, F32 crntTime)
 		F32 prevUpdateTime, F32 crntTime)
 	{
 	{
-		ParticleBase::revive(props, prevUpdateTime, crntTime);
+		ParticleBase::revive(pe, prevUpdateTime, crntTime);
 		velocity = Vec3(0.0);
 		velocity = Vec3(0.0);
 	}
 	}
 
 
@@ -140,12 +152,17 @@ public:
 		ParticleBase::kill();
 		ParticleBase::kill();
 		setActivationState(DISABLE_SIMULATION);
 		setActivationState(DISABLE_SIMULATION);
 	}
 	}
+
+	void revive(const ParticleEmitter& pe,
+		F32 prevUpdateTime, F32 crntTime);
 };
 };
 
 
 /// The particle emitter scene node. This scene node emitts
 /// The particle emitter scene node. This scene node emitts
 class ParticleEmitter: public SceneNode, public Spatial, public Movable,
 class ParticleEmitter: public SceneNode, public Spatial, public Movable,
 	public Renderable, private ParticleEmitterProperties
 	public Renderable, private ParticleEmitterProperties
 {
 {
+	friend class Particle;
+
 public:
 public:
 	ParticleEmitter(
 	ParticleEmitter(
 		const char* filename,
 		const char* filename,
@@ -213,7 +230,7 @@ public:
 private:
 private:
 	ParticleEmitterResourcePointer particleEmitterResource;
 	ParticleEmitterResourcePointer particleEmitterResource;
 	std::unique_ptr<btCollisionShape> collShape;
 	std::unique_ptr<btCollisionShape> collShape;
-	PtrVector<Particle> particles;
+	PtrVector<ParticleBase> particles;
 	F32 timeLeftForNextEmission;
 	F32 timeLeftForNextEmission;
 	/// The resource
 	/// The resource
 	Aabb aabb;
 	Aabb aabb;
@@ -229,11 +246,6 @@ private:
 	RenderableVariable* alphaRenderableVar = nullptr;
 	RenderableVariable* alphaRenderableVar = nullptr;
 
 
 	void init(const char* filename, Scene* scene);
 	void init(const char* filename, Scene* scene);
-
-	static F32 getRandom(F32 initial, F32 deviation);
-	static Vec3 getRandom(const Vec3& initial, const Vec3& deviation);
-
-	void reanimateParticle(ParticleBase& p, F32 crntTime);
 };
 };
 
 
 } // end namespace anki
 } // end namespace anki

+ 109 - 100
src/scene/ParticleEmitter.cpp

@@ -7,17 +7,48 @@
 
 
 namespace anki {
 namespace anki {
 
 
+//==============================================================================
+// Misc                                                                        =
+//==============================================================================
+
+//==============================================================================
+F32 getRandom(F32 initial, F32 deviation)
+{
+	return (deviation == 0.0) ? initial
+		: initial + randFloat(deviation) * 2.0 - deviation;
+}
+
+//==============================================================================
+Vec3 getRandom(const Vec3& initial, const Vec3& deviation)
+{
+	if(deviation == Vec3(0.0))
+	{
+		return initial;
+	}
+	else
+	{
+		Vec3 out;
+		for(U i = 0; i < 3; i++)
+		{
+			out[i] = getRandom(initial[i], deviation[i]);
+		}
+		return out;
+	}
+}
+
 //==============================================================================
 //==============================================================================
 // ParticleBase                                                                =
 // ParticleBase                                                                =
 //==============================================================================
 //==============================================================================
 
 
 //==============================================================================
 //==============================================================================
 ParticleBase::ParticleBase(
 ParticleBase::ParticleBase(
+	ParticleType type_,
 	// SceneNode
 	// SceneNode
 	const char* name, Scene* scene, 
 	const char* name, Scene* scene, 
 	// Movable
 	// Movable
 	U32 movableFlags, Movable* movParent)
 	U32 movableFlags, Movable* movParent)
-	: SceneNode(name, scene), Movable(movableFlags, movParent, *this)
+	: SceneNode(name, scene), Movable(movableFlags, movParent, *this),
+		type(type_)
 {}
 {}
 
 
 //==============================================================================
 //==============================================================================
@@ -36,7 +67,7 @@ Particle::Particle(
 	U32 movableFlags, Movable* movParent, 
 	U32 movableFlags, Movable* movParent, 
 	// RigidBody
 	// RigidBody
 	PhysWorld* masterContainer, const Initializer& init)
 	PhysWorld* masterContainer, const Initializer& init)
-	: ParticleBase(name, scene, movableFlags, movParent),
+	: ParticleBase(PT_PHYSICS, name, scene, movableFlags, movParent),
 		RigidBody(masterContainer, init, this)
 		RigidBody(masterContainer, init, this)
 {}
 {}
 
 
@@ -44,6 +75,77 @@ Particle::Particle(
 Particle::~Particle()
 Particle::~Particle()
 {}
 {}
 
 
+//==============================================================================
+void Particle::revive(const ParticleEmitter& pe,
+	F32 prevUpdateTime, F32 crntTime)
+{
+	ParticleBase::revive(pe, prevUpdateTime, crntTime);
+	ANKI_ASSERT(isDead());
+
+	const ParticleEmitterProperties& props = pe;
+
+	RigidBody& body = *this;
+
+	// pre calculate
+	Bool forceFlag = props.forceEnabled;
+	Bool worldGravFlag = props.wordGravityEnabled;
+
+	// life
+	timeOfDeath = getRandom(crntTime + props.particle.life,
+		props.particle.lifeDeviation);
+	timeOfBirth = crntTime;
+
+	// activate it (Bullet stuff)
+	body.forceActivationState(ACTIVE_TAG);
+	body.activate();
+	body.clearForces();
+	body.setLinearVelocity(btVector3(0.0, 0.0, 0.0));
+	body.setAngularVelocity(btVector3(0.0, 0.0, 0.0));
+
+	// force
+	if(forceFlag)
+	{
+		Vec3 forceDir = getRandom(props.particle.forceDirection,
+			props.particle.forceDirectionDeviation);
+		forceDir.normalize();
+
+		if(!pe.identityRotation)
+		{
+			// the forceDir depends on the particle emitter rotation
+			forceDir = pe.getWorldTransform().getRotation() * forceDir;
+		}
+
+		F32 forceMag = getRandom(props.particle.forceMagnitude,
+			props.particle.forceMagnitudeDeviation);
+
+		body.applyCentralForce(toBt(forceDir * forceMag));
+	}
+
+	// gravity
+	if(!worldGravFlag)
+	{
+		body.setGravity(toBt(getRandom(props.particle.gravity,
+			props.particle.gravityDeviation)));
+	}
+
+	// Starting pos. In local space
+	Vec3 pos = getRandom(props.particle.startingPos,
+		props.particle.startingPosDeviation);
+
+	if(pe.identityRotation)
+	{
+		pos += pe.getWorldTransform().getOrigin();
+	}
+	else
+	{
+		pos.transform(pe.getWorldTransform());
+	}
+
+	btTransform trf(
+		toBt(Transform(pos, pe.getWorldTransform().getRotation(), 1.0)));
+	body.setWorldTransform(trf);
+}
+
 //==============================================================================
 //==============================================================================
 // ParticleEmitter                                                             =
 // ParticleEmitter                                                             =
 //==============================================================================
 //==============================================================================
@@ -78,31 +180,6 @@ ParticleEmitter::ParticleEmitter(
 ParticleEmitter::~ParticleEmitter()
 ParticleEmitter::~ParticleEmitter()
 {}
 {}
 
 
-//==============================================================================
-F32 ParticleEmitter::getRandom(F32 initial, F32 deviation)
-{
-	return (deviation == 0.0) ? initial
-		: initial + randFloat(deviation) * 2.0 - deviation;
-}
-
-//==============================================================================
-Vec3 ParticleEmitter::getRandom(const Vec3& initial, const Vec3& deviation)
-{
-	if(deviation == Vec3(0.0))
-	{
-		return initial;
-	}
-	else
-	{
-		Vec3 out;
-		for(U i = 0; i < 3; i++)
-		{
-			out[i] = getRandom(initial[i], deviation[i]);
-		}
-		return out;
-	}
-}
-
 //==============================================================================
 //==============================================================================
 const ModelPatchBase& ParticleEmitter::getRenderableModelPatchBase() const
 const ModelPatchBase& ParticleEmitter::getRenderableModelPatchBase() const
 {
 {
@@ -172,7 +249,7 @@ void ParticleEmitter::frameUpdate(F32 prevUpdateTime, F32 crntTime, I frame)
 	Vec3 aabbmax(std::numeric_limits<F32>::min());
 	Vec3 aabbmax(std::numeric_limits<F32>::min());
 	instancingTransformations.clear();
 	instancingTransformations.clear();
 	Vector<F32> alpha;
 	Vector<F32> alpha;
-	for(Particle* p : particles)
+	for(ParticleBase* p : particles)
 	{
 	{
 		if(p->isDead())
 		if(p->isDead())
 		{
 		{
@@ -183,8 +260,7 @@ void ParticleEmitter::frameUpdate(F32 prevUpdateTime, F32 crntTime, I frame)
 		if(p->getTimeOfDeath() < crntTime)
 		if(p->getTimeOfDeath() < crntTime)
 		{
 		{
 			// Just died
 			// Just died
-			p->setActivationState(DISABLE_SIMULATION);
-			p->setTimeOfDeath(-1.0);
+			p->kill();
 		}
 		}
 		else
 		else
 		{
 		{
@@ -237,16 +313,16 @@ void ParticleEmitter::frameUpdate(F32 prevUpdateTime, F32 crntTime, I frame)
 	if(timeLeftForNextEmission <= 0.0)
 	if(timeLeftForNextEmission <= 0.0)
 	{
 	{
 		U particlesCount = 0; // How many particles I am allowed to emmit
 		U particlesCount = 0; // How many particles I am allowed to emmit
-		for(Particle* pp : particles)
+		for(ParticleBase* pp : particles)
 		{
 		{
-			Particle& p = *pp;
+			ParticleBase& p = *pp;
 			if(!p.isDead())
 			if(!p.isDead())
 			{
 			{
 				// its alive so skip it
 				// its alive so skip it
 				continue;
 				continue;
 			}
 			}
 
 
-			reanimateParticle(p, crntTime);
+			p.revive(*this, prevUpdateTime, crntTime);
 
 
 			// do the rest
 			// do the rest
 			++particlesCount;
 			++particlesCount;
@@ -264,71 +340,4 @@ void ParticleEmitter::frameUpdate(F32 prevUpdateTime, F32 crntTime, I frame)
 	}
 	}
 }
 }
 
 
-//==============================================================================
-void ParticleEmitter::reanimateParticle(ParticleBase& p, F32 crntTime)
-{
-	ANKI_ASSERT(p.isDead());
-
-	ANKI_ASSERT(p.getRigidBody() != nullptr);
-	RigidBody& body = *p.getRigidBody();
-
-	// pre calculate
-	Bool forceFlag = forceEnabled;
-	Bool worldGravFlag = wordGravityEnabled;
-
-	// life
-	p.setTimeOfDeath(
-		getRandom(crntTime + particle.life, particle.lifeDeviation));
-	p.setTimeOfBirth(crntTime);
-
-	// activate it (Bullet stuff)
-	body.forceActivationState(ACTIVE_TAG);
-	body.activate();
-	body.clearForces();
-	body.setLinearVelocity(btVector3(0.0, 0.0, 0.0));
-	body.setAngularVelocity(btVector3(0.0, 0.0, 0.0));
-
-	// force
-	if(forceFlag)
-	{
-		Vec3 forceDir = getRandom(particle.forceDirection,
-			particle.forceDirectionDeviation);
-		forceDir.normalize();
-
-		if(!identityRotation)
-		{
-			// the forceDir depends on the particle emitter rotation
-			forceDir = getWorldTransform().getRotation() * forceDir;
-		}
-
-		F32 forceMag = getRandom(particle.forceMagnitude,
-			particle.forceMagnitudeDeviation);
-
-		body.applyCentralForce(toBt(forceDir * forceMag));
-	}
-
-	// gravity
-	if(!worldGravFlag)
-	{
-		body.setGravity(
-			toBt(getRandom(particle.gravity, particle.gravityDeviation)));
-	}
-
-	// Starting pos. In local space
-	Vec3 pos = getRandom(particle.startingPos, particle.startingPosDeviation);
-
-	if(identityRotation)
-	{
-		pos += getWorldTransform().getOrigin();
-	}
-	else
-	{
-		pos.transform(getWorldTransform());
-	}
-
-	btTransform trf(
-		toBt(Transform(pos, getWorldTransform().getRotation(), 1.0)));
-	body.setWorldTransform(trf);
-}
-
 } // end namespace anki
 } // end namespace anki

+ 1 - 1
testapp/Main.cpp

@@ -483,7 +483,7 @@ void initSubsystems(int argc, char* argv[])
 	initializer.ms.ez.enabled = true;
 	initializer.ms.ez.enabled = true;
 	initializer.dbg.enabled = false;
 	initializer.dbg.enabled = false;
 	initializer.is.sm.bilinearEnabled = true;
 	initializer.is.sm.bilinearEnabled = true;
-	initializer.is.groundLightEnabled = true;
+	initializer.is.groundLightEnabled = false;
 	initializer.is.sm.enabled = true;
 	initializer.is.sm.enabled = true;
 	initializer.is.sm.pcfEnabled = false;
 	initializer.is.sm.pcfEnabled = false;
 	initializer.is.sm.resolution = 512;
 	initializer.is.sm.resolution = 512;