ソースを参照

Working on the particle emitter

Panagiotis Christopoulos Charitos 15 年 前
コミット
b91deacceb

ファイルの差分が大きいため隠しています
+ 425 - 435
build/debug/Makefile


+ 16 - 16
shaders/ms_mp_generic.glsl

@@ -154,24 +154,24 @@ void main()
 
 		vec2 superTexCoords = texCoords_v2f;
 		const float maxStepCount = 100.0;
-		float nSteps = maxStepCount * length(superTexCoords);
-
-		vec3 dir = vertPosEyeSpace_v2f;
-		dir.xy /= 8.0;
-		dir /= -nSteps * dir.z;
-
-		float diff0, diff1 = 1.0 - texture2D( heightMap, superTexCoords ).a;
+		float nSteps = maxStepCount * length(superTexCoords);
+
+		vec3 dir = vertPosEyeSpace_v2f;
+		dir.xy /= 8.0;
+		dir /= -nSteps * dir.z;
+
+		float diff0, diff1 = 1.0 - texture2D( heightMap, superTexCoords ).a;
 		if( diff1 > 0.0 )
-		{
+		{
 			do 
-			{
-				superTexCoords += dir.xy;
-
-				diff0 = diff1;
-				diff1 = texture2D(heightMap, superTexCoords ).w;
-			} while( diff1 > 0.0 );
-
-			superTexCoords.xy += (diff1 / (diff0 - diff1)) * dir.xy;
+			{
+				superTexCoords += dir.xy;
+
+				diff0 = diff1;
+				diff1 = texture2D(heightMap, superTexCoords ).w;
+			} while( diff1 > 0.0 );
+
+			superTexCoords.xy += (diff1 / (diff0 - diff1)) * dir.xy;
 		}
 	#else
 		#define superTexCoords texCoords_v2f

+ 1 - 1
src/Main.cpp

@@ -274,7 +274,7 @@ void init()
 
 	// particle emitter
 	partEmitter = new ParticleEmitter;
-	partEmitter->init(NULL);
+	partEmitter->init("asdf");
 	partEmitter->getLocalTransform().setOrigin(Vec3(3.0, 0.0, 0.0));
 
 	// crate

+ 13 - 13
src/Math/Vec3.inl.h

@@ -34,7 +34,7 @@ inline Vec3::Vec3(float f)
 	: x(f), y(f), z(f)
 {}
 
-// constructor [vec3]
+// constructor [Vec3]
 inline Vec3::Vec3(const Vec3& b)
 	: x(b.x), y(b.y), z(b.z)
 {}
@@ -132,76 +132,76 @@ inline bool Vec3::operator !=(const Vec3& b) const
 	return (isZero(x-b.x) && isZero(y-b.y) && isZero(z-b.z)) ? false : true;
 }
 
-// vec3 + float
+// Vec3 + float
 inline Vec3 Vec3::operator +(float f) const
 {
 	return ME + Vec3(f);
 }
 
-// float + vec3
+// float + Vec3
 inline Vec3 operator +(float f, const Vec3& v)
 {
 	return v+f;
 }
 
-// vec3 += float
+// Vec3 += float
 inline Vec3& Vec3::operator +=(float f)
 {
 	ME += Vec3(f);
 	return ME;
 }
 
-// vec3 - float
+// Vec3 - float
 inline Vec3 Vec3::operator -(float f) const
 {
 	return ME - Vec3(f);
 }
 
-// float - vec3
+// float - Vec3
 inline Vec3 operator -(float f, const Vec3& v)
 {
 	return Vec3(f-v.x, f-v.y, f-v.z);
 }
 
-// vec3 -= float
+// Vec3 -= float
 inline Vec3& Vec3::operator -=(float f)
 {
 	ME -= Vec3(f);
 	return ME;
 }
 
-// vec3 * float
+// Vec3 * float
 inline Vec3 Vec3::operator *(float f) const
 {
 	return ME * Vec3(f);
 }
 
-// float * vec3
+// float * Vec3
 inline Vec3 operator *(float f, const Vec3& v)
 {
 	return v*f;
 }
 
-// vec3 *= float
+// Vec3 *= float
 inline Vec3& Vec3::operator *=(float f)
 {
 	ME *= Vec3(f);
 	return ME;
 }
 
-// vec3 / float
+// Vec3 / float
 inline Vec3 Vec3::operator /(float f) const
 {
 	return ME / Vec3(f);
 }
 
-// float / vec3
+// float / Vec3
 inline Vec3 operator /(float f, const Vec3& v)
 {
 	return Vec3(f/v.x, f/v.y, f/v.z);
 }
 
-// vec3 /= float
+// Vec3 /= float
 inline Vec3& Vec3::operator /=(float f)
 {
 	ME /= Vec3(f);

+ 2 - 1
src/Physics/Physics.h

@@ -29,7 +29,8 @@ class Physics
 		{
 			CG_NOTHING = 0,
 			CG_MAP = 1,
-			CG_PARTICLE = 2
+			CG_PARTICLE = 2,
+			CG_ALL = CG_MAP | CG_PARTICLE
 		};
 
 		Physics();

+ 1 - 0
src/Resources/Core/RsrcContainer.inl.h

@@ -72,6 +72,7 @@ typename RsrcContainer<Type>::Iterator RsrcContainer<Type>::findByPtr(Type* ptr)
 template<typename Type>
 Type* RsrcContainer<Type>::load(const char* fname)
 {
+	DEBUG_ERR(fname == NULL);
 	filesystem::path fpathname = filesystem::path(fname);
 	string name = fpathname.filename();
 	string path = fpathname.parent_path().string();

+ 2 - 0
src/Resources/Core/RsrcContainers.cpp

@@ -6,6 +6,7 @@
 #include "Skeleton.h"
 #include "SkelAnim.h"
 #include "LightProps.h"
+#include "ParticleEmitterProps.h"
 
 
 namespace RsrcContainers {
@@ -17,5 +18,6 @@ RsrcContainer<Mesh>       meshes;
 RsrcContainer<Skeleton>   skeletons;
 RsrcContainer<SkelAnim>   skelAnims;
 RsrcContainer<LightProps> lightProps;
+RsrcContainer<ParticleEmitterProps> particleEmitterProps;
 
 }

+ 22 - 0
src/Resources/Core/RsrcPtr.cpp

@@ -7,6 +7,7 @@
 #include "Skeleton.h"
 #include "SkelAnim.h"
 #include "LightProps.h"
+#include "ParticleEmitterProps.h"
 
 
 namespace RsrcContainers {
@@ -18,6 +19,7 @@ extern RsrcContainer<Mesh>       meshes;
 extern RsrcContainer<Skeleton>   skeletons;
 extern RsrcContainer<SkelAnim>   skelAnims;
 extern RsrcContainer<LightProps> lightProps;
+extern RsrcContainer<ParticleEmitterProps> particleEmitterProps;
 
 }
 
@@ -105,6 +107,16 @@ bool RsrcPtr<LightProps>::loadRsrc(const char* filename)
 }
 
 
+//======================================================================================================================
+// loadRsrc <ParticleEmitterProps>                                                                                     =
+//======================================================================================================================
+template<>
+bool RsrcPtr<ParticleEmitterProps>::loadRsrc(const char* filename)
+{
+	LOAD_RSRC(particleEmitterProps);
+}
+
+
 //======================================================================================================================
 // unload <Texture>                                                                                                    =
 //======================================================================================================================
@@ -174,3 +186,13 @@ void RsrcPtr<LightProps>::unload()
 {
 	UNLOAD_RSRC(lightProps);
 }
+
+
+//======================================================================================================================
+// unload <ParticleEmitterProps>                                                                                       =
+//======================================================================================================================
+template<>
+void RsrcPtr<ParticleEmitterProps>::unload()
+{
+	UNLOAD_RSRC(particleEmitterProps);
+}

+ 67 - 1
src/Resources/ParticleEmitterProps.cpp

@@ -2,18 +2,27 @@
 #include "ParticleEmitterProps.h"
 
 
+static const char* errMsg = "Incorrect value ";
+
+
 //======================================================================================================================
 // Constructor                                                                                                         =
 //======================================================================================================================
 ParticleEmitterPropsStruct::ParticleEmitterPropsStruct():
+	particleLife(0.0),
 	particleLifeMargin(0.0),
+	forceDirection(0.0),
 	forceDirectionMargin(0.0),
+	forceMagnitude(0.0),
 	forceMagnitudeMargin(0.0),
+	particleMass(0.0),
 	particleMassMargin(0.0),
+	gravity(0.0),
 	gravityMargin(0.0),
 	startingPos(0.0),
 	startingPosMargin(0.0),
-	usingWorldGrav(true)
+	usingWorldGrav(true),
+	hasForce(false)
 {}
 
 
@@ -21,6 +30,15 @@ ParticleEmitterPropsStruct::ParticleEmitterPropsStruct():
 // Constructor [copy]                                                                                                  =
 //======================================================================================================================
 ParticleEmitterPropsStruct::ParticleEmitterPropsStruct(const ParticleEmitterPropsStruct& a)
+{
+	(*this) = a;
+}
+
+
+//======================================================================================================================
+//                                                                                                                     =
+//======================================================================================================================
+ParticleEmitterPropsStruct& ParticleEmitterPropsStruct::operator=(const ParticleEmitterPropsStruct& a)
 {
 	memcpy(this, &(const_cast<ParticleEmitterPropsStruct&>(a)), sizeof(ParticleEmitterPropsStruct));
 }
@@ -32,4 +50,52 @@ ParticleEmitterPropsStruct::ParticleEmitterPropsStruct(const ParticleEmitterProp
 bool ParticleEmitterProps::load(const char* filename)
 {
 	// dummy load
+	particleLife = 7.0;
+	particleLifeMargin = 2.0;
+
+	forceDirection = Vec3(0.0, 0.000001, 0.0);
+	forceDirectionMargin = Vec3(1.0, 0.0, 1.0);
+	forceMagnitude = 200.0;
+	forceMagnitudeMargin = 100.0;
+
+	particleMass = 1.0;
+	particleMassMargin = 0.0;
+
+	usingWorldGrav = false;
+	gravity = Vec3(0.0, 10.0, 0.0);
+	gravityMargin = Vec3(0.0, 0.0, 0.0);
+
+	startingPos = Vec3(0.0, 1.0, 0.0);
+	startingPosMargin = Vec3(0.0, 0.0, 0.0);
+	maxNumOfParticles = 50;
+	emittionPeriod = 0.05;
+	particlesPerEmittion = 2;
+
+	// set some values
+	if((M::isZero(forceDirection.getLength()) && M::isZero(forceDirectionMargin.getLength())) ||
+	   (forceMagnitude == 0.0 && forceMagnitudeMargin == 0.0))
+	{
+		hasForce = false;
+	}
+	else
+		hasForce = true;
+
+	usingWorldGrav = M::isZero(gravity.getLength()) ? true : false;
+
+
+	// sanity checks
+	if(particleLife <= 0.0)
+	{
+		ERROR(errMsg << "particleLife");
+		return false;
+	}
+
+	if(particleLife - particleLifeMargin <= 0.0)
+	{
+		ERROR(errMsg << "particleLifeMargin");
+		return false;
+	}
+
+
+	return true;
 }

+ 9 - 8
src/Resources/ParticleEmitterProps.h

@@ -17,15 +17,15 @@ class ParticleEmitterPropsStruct
 		 * @name Particle properties
 		 */
 		/**@{*/
-		float particleLife; ///< Required
+		float particleLife; ///< Required and > 0.0
 		float particleLifeMargin;
 
-		Vec3 forceDirection; ///< Required
+		Vec3 forceDirection;
 		Vec3 forceDirectionMargin;
-		float forceMagnitude; ///< Required
+		float forceMagnitude; ///< Default 0.0
 		float forceMagnitudeMargin;
 
-		float particleMass; ///< Required
+		float particleMass; ///< Required and > 0.0
 		float particleMassMargin;
 
 		Vec3 gravity; ///< If not set then it uses the world's default
@@ -46,9 +46,12 @@ class ParticleEmitterPropsStruct
 
 		ParticleEmitterPropsStruct();
 		ParticleEmitterPropsStruct(const ParticleEmitterPropsStruct& a);
+		ParticleEmitterPropsStruct& operator=(const ParticleEmitterPropsStruct& a);
+		~ParticleEmitterPropsStruct() {}
 
 	protected:
 		bool usingWorldGrav; ///< This flag indicates if we should use the default world gravity or to override it
+		bool hasForce; ///< False if all force stuff are zero
 };
 
 
@@ -60,9 +63,10 @@ class ParticleEmitterProps: public ParticleEmitterPropsStruct, public Resource
 {
 	public:
 		ParticleEmitterProps();
+		~ParticleEmitterProps() {}
 
 		bool load(const char* filename);
-		void unload();
+		void unload() {} ///< Do nothing
 };
 
 
@@ -71,7 +75,4 @@ inline ParticleEmitterProps::ParticleEmitterProps():
 {}
 
 
-inline void ParticleEmitterProps::unload()
-{}
-
 #endif

+ 121 - 4
src/Scene/ParticleEmitter.cpp

@@ -3,6 +3,7 @@
 #include "PhyCommon.h"
 #include "App.h"
 #include "Scene.h"
+#include "Util.h"
 
 
 //======================================================================================================================
@@ -28,10 +29,12 @@ void ParticleEmitter::Particle::render()
 //======================================================================================================================
 void ParticleEmitter::init(const char* filename)
 {
-	ParticleEmitterProps props;
-	//ParticleEmitterProps* me = this;
-	//(*this) = props;
+	particleEmitterProps.loadRsrc(filename);
 
+	// copy the resource to me
+	ParticleEmitterPropsStruct& me = *this;
+	ParticleEmitterPropsStruct& other = *particleEmitterProps.get();
+	me = other;
 }
 
 
@@ -40,7 +43,122 @@ void ParticleEmitter::init(const char* filename)
 //======================================================================================================================
 void ParticleEmitter::update()
 {
+	float crntTime = SDL_GetTicks() / 1000.0;
 
+	// deactivate the dead particles
+	for(uint i=0; i<particles.size(); i++)
+	{
+		Particle& p = particles[i];
+		if(p.timeOfDeath < 0.0) continue; // its already dead so dont deactivate it again
+
+		if(p.timeOfDeath < crntTime)
+		{
+			//cout << "Killing " << i << " " << p.timeOfDeath << endl;
+			p.body->setActivationState(DISABLE_SIMULATION);
+			p.timeOfDeath = -1.0;
+		}
+	}
+
+
+	if((crntTime - timeOfPrevEmittion) > emittionPeriod)
+	{
+		uint partNum = 0;
+		for(uint i=0; i<particles.size(); i++)
+		{
+			Particle& p = particles[i];
+			if(p.timeOfDeath > 0.0) continue; // its alive so skip it
+
+			// life
+			if(particleLifeMargin != 0.0)
+				p.timeOfDeath = crntTime + particleLife + Util::randFloat(particleLifeMargin) * 2.0 - particleLifeMargin;
+			else
+				p.timeOfDeath = crntTime + particleLife;
+
+			//cout << "Time of death " << p.timeOfDeath << endl;
+			//cout << "Particle life " << p.timeOfDeath - crntTime << endl;
+
+			// activate it (Bullet stuff)
+			p.body->forceActivationState(ACTIVE_TAG);
+			p.body->activate();
+			p.body->clearForces();
+			p.body->setLinearVelocity(btVector3(0.0, 0.0, 0.0));
+			p.body->setAngularVelocity(btVector3(0.0, 0.0, 0.0));
+
+			//cout << p.body->internalGetDeltaAngularVelocity() << endl;
+
+			// force
+			if(hasForce)
+			{
+				Vec3 forceDir;
+				if(forceDirectionMargin != Vec3(0.0))
+				{
+					for(int i=0; i<3; i++)
+					{
+						forceDir[i] = forceDirection[i] + Util::randFloat(forceDirectionMargin[i]) * 2.0 - forceDirectionMargin[i];
+					}
+				}
+				else
+				{
+					forceDir = forceDirection;
+				}
+				forceDir.normalize();
+				forceDir = worldTransform.getRotation() * forceDir; // the forceDir depends on the particle emitter rotation
+				Vec3 force;
+
+				if(forceMagnitudeMargin != 0.0)
+					force = forceDir * (forceMagnitude + Util::randFloat(forceMagnitudeMargin) * 2.0 - forceMagnitudeMargin);
+				else
+					force = forceDir * forceMagnitude;
+
+				p.body->applyCentralForce(toBt(force));
+			}
+
+			// gravity
+			if(!usingWorldGrav)
+			{
+				Vec3 grav;
+				if(gravityMargin != Vec3(0.0, 0.0, 0.0))
+				{
+					for(int i=0; i<3; i++)
+					{
+						grav[i] = gravity[i] + Util::randFloat(gravityMargin[i]) * 2.0 - gravityMargin[i];
+					}
+				}
+				else
+				{
+					grav = gravity;
+				}
+				p.body->setGravity(toBt(grav));
+			}
+
+			// starting pos
+			Vec3 pos; // in local space
+			if(startingPosMargin != Vec3(0.0))
+			{
+				for(int i=0; i<3; i++)
+				{
+					pos[i] = startingPos[i] + Util::randFloat(startingPosMargin[i]) * 2.0 - startingPosMargin[i];
+				}
+			}
+			else
+			{
+				pos = startingPos;
+			}
+			pos.transform(worldTransform);
+			btTransform trf;
+			trf.setIdentity();
+			trf.setOrigin(toBt(pos));
+			p.body->setWorldTransform(trf);
+
+			// do the rest
+			++partNum;
+			if(partNum >= particlesPerEmittion) break;
+		} // end for all particles
+
+		timeOfPrevEmittion = crntTime;
+	} // end if can emit
+
+	timeOfPrevUpdate = crntTime;
 }
 
 
@@ -54,5 +172,4 @@ void ParticleEmitter::render()
 	Renderer::Dbg::setModelMat(Mat4(getWorldTransform()));
 	Renderer::Dbg::renderCube();
 	glPolygonMode(GL_FRONT, GL_FILL);
-
 }

+ 11 - 6
src/Scene/ParticleEmitter.h

@@ -1,5 +1,5 @@
-#ifndef _PARTICLEEMITTER_H_
-#define _PARTICLEEMITTER_H_
+#ifndef PARTICLEEMITTER_H
+#define PARTICLEEMITTER_H
 
 #include <boost/ptr_container/ptr_vector.hpp>
 #include "Common.h"
@@ -16,25 +16,24 @@
 class ParticleEmitter: public SceneNode, public ParticleEmitterPropsStruct
 {
 	public:
-
 		/**
 		 * The scene node particle class
 		 */
 		class Particle: public GhostNode
 		{
 			public:
-				float timeOfDeath; ///< Life till death. If < 0 then dead. In seconds
+				float timeOfDeath; ///< Life of death. If < 0.0 then dead. In seconds
 				btRigidBody* body;
 
-				Particle(): timeOfDeath(-1.0) {}
+				Particle();
 				void render();
-				void renderDepth() {};
 		};
 
 		// the changeable vars
 		ptr_vector<Particle> particles;
 		float timeOfPrevUpdate;
 		float timeOfPrevEmittion;
+		RsrcPtr<ParticleEmitterProps> particleEmitterProps;
 
 		// funcs
 		ParticleEmitter();
@@ -45,8 +44,14 @@ class ParticleEmitter: public SceneNode, public ParticleEmitterPropsStruct
 };
 
 
+inline ParticleEmitter::Particle::Particle():
+	timeOfDeath(-1.0)
+{}
+
+
 inline ParticleEmitter::ParticleEmitter():
 	SceneNode(NT_PARTICLE_EMITTER)
 {}
 
+
 #endif

+ 3 - 1
src/Util/Tokenizer/Scanner.cpp

@@ -152,6 +152,8 @@ void Scanner::initAsciiMap()
 
 	asciiLookupTable['\t'] = asciiLookupTable[' '] = asciiLookupTable['\0'] = AC_WHITESPACE;
 	asciiLookupTable['\n'] = AC_ERROR; // newline is unacceptable char
+
+	asciiLookupTable['@'] = asciiLookupTable['`'] = asciiLookupTable['$'] = AC_ACCEPTABLE_IN_COMMENTS;
 	                   
 	asciiLookupTable['\"']         = AC_DOUBLEQUOTE;
 	asciiLookupTable['\'']         = AC_QUOTE;
@@ -207,7 +209,7 @@ char Scanner::getNextChar()
 	}
 	else if(lookupAscii(*pchar) == AC_ERROR)
 	{
-		ERROR("Unacceptable char 0x" << int(*pchar));
+		SERROR("Unacceptable char '" << *pchar << "' 0x" << int(*pchar));
 	}
 
 	return *pchar;

+ 2 - 1
src/Util/Tokenizer/Scanner.h

@@ -134,7 +134,8 @@ class Scanner
 			AC_SPECIAL = 8,
 			AC_WHITESPACE = 16,
 			AC_QUOTE = 32,
-			AC_DOUBLEQUOTE = 64
+			AC_DOUBLEQUOTE = 64,
+			AC_ACCEPTABLE_IN_COMMENTS = 128 ///< Only accepted in comments
 		};
 
 		/**

+ 10 - 0
src/Util/Util.cpp

@@ -71,4 +71,14 @@ Vec<string> getFileLines(const char* filename)
 }
 
 
+//======================================================================================================================
+// randFloat                                                                                                           =
+//======================================================================================================================
+float randFloat(float max)
+{
+	float r = float(rand()) / float(RAND_MAX);
+	return r * max;
+}
+
+
 } // end namesapce

+ 1 - 0
src/Util/Util.h

@@ -13,6 +13,7 @@ extern int    randRange(int min, int max); ///< Pick a random number from min to
 extern uint   randRange(uint min, uint max); ///< Pick a random number from min to max
 extern float  randRange(float min, float max); ///< Pick a random number from min to max
 extern double randRange(double min, double max); ///< Pick a random number from min to max
+extern float randFloat(float max);
 
 extern string      readFile(const char* filename); ///< Open a text file and return its contents into a string
 extern Vec<string> getFileLines(const char* filename); ///< Open a text file and return its lines into a string vector

この差分においてかなりの量のファイルが変更されているため、一部のファイルを表示していません