Browse Source

Particles

Panagiotis Christopoulos Charitos 13 years ago
parent
commit
79ec7967c4

+ 11 - 13
include/anki/resource/ParticleEmitterResource.h

@@ -12,10 +12,8 @@ class XmlElement;
 /// ParticleEmitterResource so it can be inherited
 struct ParticleEmitterProperties
 {
-public:
 	ParticleEmitterProperties& operator=(const ParticleEmitterProperties& b);
 
-protected:
 	/// @name Particle specific properties
 	/// @{
 	struct
@@ -61,25 +59,27 @@ protected:
 	F32 emissionPeriod = 1.0;
 	/// How many particles are emitted every emission. Required
 	U32 particlesPerEmittion = 1;
+	/// Use bullet for the simulation
+	Bool usePhysicsEngine = true;
 	/// @}
+
+	// Optimization flags
+	Bool forceEnabled;
+	Bool wordGravityEnabled;
+
+	void updateFlags();
 };
 
 /// This is the properties of the particle emitter resource
-class ParticleEmitterResource: public ParticleEmitterProperties
+class ParticleEmitterResource: private ParticleEmitterProperties
 {
 public:
 	ParticleEmitterResource();
 	~ParticleEmitterResource();
 
-	Bool hasForce() const
+	const ParticleEmitterProperties& getProperties() const
 	{
-		return forceEnabled;
-	}
-
-	///< @return True if gravity is derived
-	Bool usingWorldGravity() const
-	{
-		return wordGravityEnabled;
+		return *this;
 	}
 
 	const Model& getModel() const
@@ -92,8 +92,6 @@ public:
 
 private:
 	ModelResourcePointer model;
-	Bool forceEnabled;
-	Bool wordGravityEnabled;
 
 	void loadInternal(const XmlElement& el);
 };

+ 52 - 7
include/anki/scene/ParticleEmitter.h

@@ -10,18 +10,18 @@
 
 namespace anki {
 
-/// Particle without rigid body properties
+/// Particle base
 /// XXX Remove SceneNode
-class ParticleSimple: public SceneNode, public Movable
+class ParticleBase: public SceneNode, public Movable
 {
 public:
-	ParticleSimple(
+	ParticleBase(
 		// SceneNode
 		const char* name, Scene* scene, 
 		// Movable
 		U32 movableFlags, Movable* movParent);
 
-	virtual ~ParticleSimple();
+	virtual ~ParticleBase();
 
 	/// @name Accessors
 	/// @{
@@ -67,13 +67,52 @@ public:
 		return timeOfDeath < 0.0;
 	}
 
+	/// Kill the particle
+	virtual void kill()
+	{
+		timeOfDeath = -1.0;
+	}
+
+	/// Revive the particle
+	virtual void revive(const ParticleEmitterProperties& props,
+		F32 prevUpdateTime, F32 crntTime)
+	{
+		(void)props;
+		(void)prevUpdateTime;
+		(void)crntTime;
+	}
+
 private:
 	F32 timeOfBirth; ///< Keep the time of birth for nice effects
 	F32 timeOfDeath = -1.0; ///< Time of death. If < 0.0 then dead. In seconds
 };
 
-/// Particle scene node
-class Particle: public ParticleSimple, public RigidBody
+/// Simple particle for simple simulation
+class ParticleSimple: public ParticleBase
+{
+public:
+	ParticleSimple(
+		// SceneNode
+		const char* name, Scene* scene, 
+		// Movable
+		U32 movableFlags, Movable* movParent)
+		: ParticleBase(name, scene, movableFlags, movParent)
+	{}
+
+	void revive(const ParticleEmitterProperties& props,
+		F32 prevUpdateTime, F32 crntTime)
+	{
+		ParticleBase::revive(props, prevUpdateTime, crntTime);
+		velocity = Vec3(0.0);
+	}
+
+private:
+	/// The velocity
+	Vec3 velocity = Vec3(0.0);
+};
+
+/// Particle for bullet simulations
+class Particle: public ParticleBase, public RigidBody
 {
 public:
 	Particle(
@@ -95,6 +134,12 @@ public:
 		return this;
 	}
 	/// @}
+
+	void kill()
+	{
+		ParticleBase::kill();
+		setActivationState(DISABLE_SIMULATION);
+	}
 };
 
 /// The particle emitter scene node. This scene node emitts
@@ -188,7 +233,7 @@ private:
 	static F32 getRandom(F32 initial, F32 deviation);
 	static Vec3 getRandom(const Vec3& initial, const Vec3& deviation);
 
-	void reanimateParticle(ParticleSimple& p, F32 crntTime);
+	void reanimateParticle(ParticleBase& p, F32 crntTime);
 };
 
 } // end namespace anki

+ 17 - 9
src/resource/ParticleEmitterResource.cpp

@@ -78,6 +78,19 @@ ParticleEmitterProperties& ParticleEmitterProperties::operator=(
 	return *this;
 }
 
+//==============================================================================
+void ParticleEmitterProperties::updateFlags()
+{
+	forceEnabled = !isZero(particle.forceDirection.getLengthSquared());
+	forceEnabled = forceEnabled
+		|| !isZero(particle.forceDirectionDeviation.getLengthSquared());
+	forceEnabled = forceEnabled
+		&& (particle.forceMagnitude != 0.0
+		|| particle.forceMagnitudeDeviation != 0.0);
+
+	wordGravityEnabled = isZero(particle.gravity.getLengthSquared());
+}
+
 //==============================================================================
 // ParticleEmitterResource                                                     =
 //==============================================================================
@@ -138,6 +151,9 @@ void ParticleEmitterResource::loadInternal(const XmlElement& rootel)
 	xmlReadU(rootel, "maxNumberOfParticles", maxNumOfParticles);
 	xmlReadFloat(rootel, "emissionPeriod", emissionPeriod);
 	xmlReadU(rootel, "particlesPerEmittion", particlesPerEmittion);
+	U32 u = usePhysicsEngine;
+	xmlReadU(rootel, "usePhysicsEngine", u);
+	usePhysicsEngine = u;
 
 	XmlElement el = rootel.getChildElement("model");
 	model.load(el.getText());
@@ -177,15 +193,7 @@ void ParticleEmitterResource::loadInternal(const XmlElement& rootel)
 
 	// Calc some stuff
 	//
-
-	forceEnabled = !isZero(particle.forceDirection.getLengthSquared());
-	forceEnabled = forceEnabled
-		|| !isZero(particle.forceDirectionDeviation.getLengthSquared());
-	forceEnabled = forceEnabled
-		&& (particle.forceMagnitude != 0.0
-		|| particle.forceMagnitudeDeviation != 0.0);
-
-	wordGravityEnabled = isZero(particle.gravity.getLengthSquared());
+	updateFlags();
 }
 
 } // end namespace anki

+ 9 - 8
src/scene/ParticleEmitter.cpp

@@ -8,11 +8,11 @@
 namespace anki {
 
 //==============================================================================
-// ParticleSimple                                                              =
+// ParticleBase                                                                =
 //==============================================================================
 
 //==============================================================================
-ParticleSimple::ParticleSimple(
+ParticleBase::ParticleBase(
 	// SceneNode
 	const char* name, Scene* scene, 
 	// Movable
@@ -21,7 +21,7 @@ ParticleSimple::ParticleSimple(
 {}
 
 //==============================================================================
-ParticleSimple::~ParticleSimple()
+ParticleBase::~ParticleBase()
 {}
 
 //==============================================================================
@@ -36,7 +36,7 @@ Particle::Particle(
 	U32 movableFlags, Movable* movParent, 
 	// RigidBody
 	PhysWorld* masterContainer, const Initializer& init)
-	: ParticleSimple(name, scene, movableFlags, movParent),
+	: ParticleBase(name, scene, movableFlags, movParent),
 		RigidBody(masterContainer, init, this)
 {}
 
@@ -130,7 +130,8 @@ void ParticleEmitter::init(const char* filename, Scene* scene)
 
 	// copy the resource to me
 	ParticleEmitterProperties& me = *this;
-	const ParticleEmitterProperties& other = *particleEmitterResource;
+	const ParticleEmitterProperties& other = 
+		particleEmitterResource->getProperties();
 	me = other;
 
 	// create the particles
@@ -264,7 +265,7 @@ void ParticleEmitter::frameUpdate(F32 prevUpdateTime, F32 crntTime, I frame)
 }
 
 //==============================================================================
-void ParticleEmitter::reanimateParticle(ParticleSimple& p, F32 crntTime)
+void ParticleEmitter::reanimateParticle(ParticleBase& p, F32 crntTime)
 {
 	ANKI_ASSERT(p.isDead());
 
@@ -272,8 +273,8 @@ void ParticleEmitter::reanimateParticle(ParticleSimple& p, F32 crntTime)
 	RigidBody& body = *p.getRigidBody();
 
 	// pre calculate
-	Bool forceFlag = particleEmitterResource->hasForce();
-	Bool worldGravFlag = particleEmitterResource->usingWorldGravity();
+	Bool forceFlag = forceEnabled;
+	Bool worldGravFlag = wordGravityEnabled;
 
 	// life
 	p.setTimeOfDeath(

+ 1 - 1
testapp/Main.cpp

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