Browse Source

Added ParticleSystem:setRelativeRotation. If enabled, particle rotations and angles will be relative to their current velocities.

Alex Szpakowski 11 years ago
parent
commit
615492540d

+ 36 - 15
src/modules/graphics/opengl/ParticleSystem.cpp

@@ -94,6 +94,7 @@ ParticleSystem::ParticleSystem(Texture *texture, uint32 size)
 	, spinVariation(0)
 	, spinVariation(0)
 	, offsetX(float(texture->getWidth())*0.5f)
 	, offsetX(float(texture->getWidth())*0.5f)
 	, offsetY(float(texture->getHeight())*0.5f)
 	, offsetY(float(texture->getHeight())*0.5f)
+	, relativeRotation(false)
 {
 {
 	if (size == 0 || size > MAX_PARTICLES)
 	if (size == 0 || size > MAX_PARTICLES)
 		throw love::Exception("Invalid ParticleSystem size.");
 		throw love::Exception("Invalid ParticleSystem size.");
@@ -145,6 +146,7 @@ ParticleSystem::ParticleSystem(const ParticleSystem &p)
 	, offsetX(p.offsetX)
 	, offsetX(p.offsetX)
 	, offsetY(p.offsetY)
 	, offsetY(p.offsetY)
 	, colors(p.colors)
 	, colors(p.colors)
+	, relativeRotation(p.relativeRotation)
 {
 {
 	setBufferSize(maxParticles);
 	setBufferSize(maxParticles);
 
 
@@ -169,7 +171,7 @@ void ParticleSystem::createBuffers(size_t size)
 {
 {
 	try
 	try
 	{
 	{
-		pFree = pMem = new particle[size];
+		pFree = pMem = new Particle[size];
 		particleVerts = new love::Vertex[size * 4];
 		particleVerts = new love::Vertex[size * 4];
 		maxParticles = (uint32) size;
 		maxParticles = (uint32) size;
 	}
 	}
@@ -212,7 +214,7 @@ void ParticleSystem::addParticle(float t)
 		return;
 		return;
 
 
 	// Gets a free particle and updates the allocation pointer.
 	// Gets a free particle and updates the allocation pointer.
-	particle *p = pFree++;
+	Particle *p = pFree++;
 	initParticle(p, t);
 	initParticle(p, t);
 
 
 	switch (insertMode)
 	switch (insertMode)
@@ -232,7 +234,7 @@ void ParticleSystem::addParticle(float t)
 	activeParticles++;
 	activeParticles++;
 }
 }
 
 
-void ParticleSystem::initParticle(particle *p, float t)
+void ParticleSystem::initParticle(Particle *p, float t)
 {
 {
 	float min,max;
 	float min,max;
 
 
@@ -298,10 +300,14 @@ void ParticleSystem::initParticle(particle *p, float t)
 	p->spinEnd = calculate_variation(spinEnd, spinStart, spinVariation);
 	p->spinEnd = calculate_variation(spinEnd, spinStart, spinVariation);
 	p->rotation = (float) rng.random(min, max);
 	p->rotation = (float) rng.random(min, max);
 
 
+	p->angle = p->rotation;
+	if (relativeRotation)
+		p->angle += atan2f(p->speed.y, p->speed.x);
+
 	p->color = colors[0];
 	p->color = colors[0];
 }
 }
 
 
-void ParticleSystem::insertTop(particle *p)
+void ParticleSystem::insertTop(Particle *p)
 {
 {
 	if (pHead == nullptr)
 	if (pHead == nullptr)
 	{
 	{
@@ -317,7 +323,7 @@ void ParticleSystem::insertTop(particle *p)
 	pTail = p;
 	pTail = p;
 }
 }
 
 
-void ParticleSystem::insertBottom(particle *p)
+void ParticleSystem::insertBottom(Particle *p)
 {
 {
 	if (pTail == nullptr)
 	if (pTail == nullptr)
 	{
 	{
@@ -333,7 +339,7 @@ void ParticleSystem::insertBottom(particle *p)
 	pHead = p;
 	pHead = p;
 }
 }
 
 
-void ParticleSystem::insertRandom(particle *p)
+void ParticleSystem::insertRandom(Particle *p)
 {
 {
 	// Nonuniform, but 64-bit is so large nobody will notice. Hopefully.
 	// Nonuniform, but 64-bit is so large nobody will notice. Hopefully.
 	uint64 pos = rng.rand() % ((int64) activeParticles + 1);
 	uint64 pos = rng.rand() % ((int64) activeParticles + 1);
@@ -341,7 +347,7 @@ void ParticleSystem::insertRandom(particle *p)
 	// Special case where the particle gets inserted before the head.
 	// Special case where the particle gets inserted before the head.
 	if (pos == activeParticles)
 	if (pos == activeParticles)
 	{
 	{
-		particle *pA = pHead;
+		Particle *pA = pHead;
 		if (pA)
 		if (pA)
 			pA->prev = p;
 			pA->prev = p;
 		p->prev = nullptr;
 		p->prev = nullptr;
@@ -351,8 +357,8 @@ void ParticleSystem::insertRandom(particle *p)
 	}
 	}
 
 
 	// Inserts the particle after the randomly selected particle.
 	// Inserts the particle after the randomly selected particle.
-	particle *pA = pMem + pos;
-	particle *pB = pA->next;
+	Particle *pA = pMem + pos;
+	Particle *pB = pA->next;
 	pA->next = p;
 	pA->next = p;
 	if (pB)
 	if (pB)
 		pB->prev = p;
 		pB->prev = p;
@@ -362,12 +368,12 @@ void ParticleSystem::insertRandom(particle *p)
 	p->next = pB;
 	p->next = pB;
 }
 }
 
 
-ParticleSystem::particle *ParticleSystem::removeParticle(particle *p)
+ParticleSystem::Particle *ParticleSystem::removeParticle(Particle *p)
 {
 {
 	// The linked list is updated in this function and old pointers may be
 	// The linked list is updated in this function and old pointers may be
 	// invalidated. The returned pointer will inform the caller of the new
 	// invalidated. The returned pointer will inform the caller of the new
 	// pointer to the next particle.
 	// pointer to the next particle.
-	particle *pNext = nullptr;
+	Particle *pNext = nullptr;
 
 
 	// Removes the particle from the linked list.
 	// Removes the particle from the linked list.
 	if (p->prev)
 	if (p->prev)
@@ -715,6 +721,16 @@ std::vector<Color> ParticleSystem::getColor() const
 	return ncolors;
 	return ncolors;
 }
 }
 
 
+void ParticleSystem::setRelativeRotation(bool enable)
+{
+	relativeRotation = enable;
+}
+
+bool ParticleSystem::hasRelativeRotation() const
+{
+	return relativeRotation;
+}
+
 uint32 ParticleSystem::getCount() const
 uint32 ParticleSystem::getCount() const
 {
 {
 	return activeParticles;
 	return activeParticles;
@@ -802,13 +818,13 @@ void ParticleSystem::draw(float x, float y, float angle, float sx, float sy, flo
 
 
 	const Vertex *textureVerts = texture->getVertices();
 	const Vertex *textureVerts = texture->getVertices();
 	Vertex *pVerts = particleVerts;
 	Vertex *pVerts = particleVerts;
-	particle *p = pHead;
+	Particle *p = pHead;
 
 
 	// set the vertex data for each particle (transformation, texcoords, color)
 	// set the vertex data for each particle (transformation, texcoords, color)
 	while (p)
 	while (p)
 	{
 	{
 		// particle vertices are image vertices transformed by particle information
 		// particle vertices are image vertices transformed by particle information
-		t.setTransformation(p->position[0], p->position[1], p->rotation, p->size, p->size, offsetX, offsetY, 0.0f, 0.0f);
+		t.setTransformation(p->position[0], p->position[1], p->angle, p->size, p->size, offsetX, offsetY, 0.0f, 0.0f);
 		t.transform(pVerts, textureVerts, 4);
 		t.transform(pVerts, textureVerts, 4);
 
 
 		// set the texture coordinate and color data for particle vertices
 		// set the texture coordinate and color data for particle vertices
@@ -858,7 +874,7 @@ void ParticleSystem::update(float dt)
 		return;
 		return;
 
 
 	// Traverse all particles and update.
 	// Traverse all particles and update.
-	particle *p = pHead;
+	Particle *p = pHead;
 
 
 	while (p)
 	while (p)
 	{
 	{
@@ -903,7 +919,12 @@ void ParticleSystem::update(float dt)
 			const float t = 1.0f - p->life / p->lifetime;
 			const float t = 1.0f - p->life / p->lifetime;
 
 
 			// Rotate.
 			// Rotate.
-			p->rotation += (p->spinStart * (1.0f - t) + p->spinEnd * t)*dt;
+			p->rotation += (p->spinStart * (1.0f - t) + p->spinEnd * t) * dt;
+
+			p->angle = p->rotation;
+
+			if (relativeRotation)
+				p->angle += atan2f(p->speed.y, p->speed.x);
 
 
 			// Change size according to given intervals:
 			// Change size according to given intervals:
 			// i = 0       1       2      3          n-1
 			// i = 0       1       2      3          n-1

+ 23 - 13
src/modules/graphics/opengl/ParticleSystem.h

@@ -421,6 +421,12 @@ public:
 	 **/
 	 **/
 	std::vector<Color> getColor() const;
 	std::vector<Color> getColor() const;
 
 
+	/**
+	 * sets whether particle angles & rotations are relative to their velocities.
+	 **/
+	void setRelativeRotation(bool enable);
+	bool hasRelativeRotation() const;
+
 	/**
 	/**
 	 * Returns the amount of particles that are currently active in the system.
 	 * Returns the amount of particles that are currently active in the system.
 	 **/
 	 **/
@@ -494,11 +500,12 @@ public:
 	static bool getConstant(InsertMode in, const char *&out);
 	static bool getConstant(InsertMode in, const char *&out);
 
 
 protected:
 protected:
+
 	// Represents a single particle.
 	// Represents a single particle.
-	struct particle
+	struct Particle
 	{
 	{
-		particle *prev;
-		particle *next;
+		Particle *prev;
+		Particle *next;
 
 
 		float lifetime;
 		float lifetime;
 		float life;
 		float life;
@@ -518,7 +525,8 @@ protected:
 		float sizeOffset;
 		float sizeOffset;
 		float sizeIntervalSize;
 		float sizeIntervalSize;
 
 
-		float rotation;
+		float rotation; // Amount of rotation applied to the final angle.
+		float angle;
 		float spinStart;
 		float spinStart;
 		float spinEnd;
 		float spinEnd;
 
 
@@ -526,16 +534,16 @@ protected:
 	};
 	};
 
 
 	// Pointer to the beginning of the allocated memory.
 	// Pointer to the beginning of the allocated memory.
-	particle *pMem;
+	Particle *pMem;
 
 
 	// Pointer to a free particle.
 	// Pointer to a free particle.
-	particle *pFree;
+	Particle *pFree;
 
 
 	// Pointer to the start of the linked list.
 	// Pointer to the start of the linked list.
-	particle *pHead;
+	Particle *pHead;
 
 
 	// Pointer to the end of the linked list.
 	// Pointer to the end of the linked list.
-	particle *pTail;
+	Particle *pTail;
 
 
 	// array of transformed vertex data for all particles, for drawing
 	// array of transformed vertex data for all particles, for drawing
 	Vertex *particleVerts;
 	Vertex *particleVerts;
@@ -617,17 +625,19 @@ protected:
 	// Color.
 	// Color.
 	std::vector<Colorf> colors;
 	std::vector<Colorf> colors;
 
 
+	bool relativeRotation;
+
 	void createBuffers(size_t size);
 	void createBuffers(size_t size);
 	void deleteBuffers();
 	void deleteBuffers();
 
 
 	void addParticle(float t);
 	void addParticle(float t);
-	particle *removeParticle(particle *p);
+	Particle *removeParticle(Particle *p);
 
 
 	// Called by addParticle.
 	// Called by addParticle.
-	void initParticle(particle *p, float t);
-	void insertTop(particle *p);
-	void insertBottom(particle *p);
-	void insertRandom(particle *p);
+	void initParticle(Particle *p, float t);
+	void insertTop(Particle *p);
+	void insertBottom(Particle *p);
+	void insertRandom(Particle *p);
 
 
 	static StringMap<AreaSpreadDistribution, DISTRIBUTION_MAX_ENUM>::Entry distributionsEntries[];
 	static StringMap<AreaSpreadDistribution, DISTRIBUTION_MAX_ENUM>::Entry distributionsEntries[];
 	static StringMap<AreaSpreadDistribution, DISTRIBUTION_MAX_ENUM> distributions;
 	static StringMap<AreaSpreadDistribution, DISTRIBUTION_MAX_ENUM> distributions;

+ 16 - 0
src/modules/graphics/opengl/wrap_ParticleSystem.cpp

@@ -569,6 +569,20 @@ int w_ParticleSystem_getColors(lua_State *L)
 	return colors.size();
 	return colors.size();
 }
 }
 
 
+int w_ParticleSystem_setRelativeRotation(lua_State *L)
+{
+	ParticleSystem *t = luax_checkparticlesystem(L, 1);
+	t->setRelativeRotation(luax_toboolean(L, 2));
+	return 0;
+}
+
+int w_ParticleSystem_hasRelativeRotation(lua_State *L)
+{
+	ParticleSystem *t = luax_checkparticlesystem(L, 1);
+	luax_pushboolean(L, t->hasRelativeRotation());
+	return 1;
+}
+
 int w_ParticleSystem_getCount(lua_State *L)
 int w_ParticleSystem_getCount(lua_State *L)
 {
 {
 	ParticleSystem *t = luax_checkparticlesystem(L, 1);
 	ParticleSystem *t = luax_checkparticlesystem(L, 1);
@@ -687,6 +701,8 @@ static const luaL_Reg functions[] =
 	{ "getColors", w_ParticleSystem_getColors },
 	{ "getColors", w_ParticleSystem_getColors },
 	{ "setOffset", w_ParticleSystem_setOffset },
 	{ "setOffset", w_ParticleSystem_setOffset },
 	{ "getOffset", w_ParticleSystem_getOffset },
 	{ "getOffset", w_ParticleSystem_getOffset },
+	{ "setRelativeRotation", w_ParticleSystem_setRelativeRotation },
+	{ "hasRelativeRotation", w_ParticleSystem_hasRelativeRotation },
 	{ "getCount", w_ParticleSystem_getCount },
 	{ "getCount", w_ParticleSystem_getCount },
 	{ "start", w_ParticleSystem_start },
 	{ "start", w_ParticleSystem_start },
 	{ "stop", w_ParticleSystem_stop },
 	{ "stop", w_ParticleSystem_stop },

+ 2 - 0
src/modules/graphics/opengl/wrap_ParticleSystem.h

@@ -77,6 +77,8 @@ int w_ParticleSystem_setColors(lua_State *L);
 int w_ParticleSystem_getColors(lua_State *L);
 int w_ParticleSystem_getColors(lua_State *L);
 int w_ParticleSystem_setOffset(lua_State *L);
 int w_ParticleSystem_setOffset(lua_State *L);
 int w_ParticleSystem_getOffset(lua_State *L);
 int w_ParticleSystem_getOffset(lua_State *L);
+int w_ParticleSystem_setRelativeRotation(lua_State *L);
+int w_ParticleSystem_hasRelativeRotation(lua_State *L);
 int w_ParticleSystem_getCount(lua_State *L);
 int w_ParticleSystem_getCount(lua_State *L);
 int w_ParticleSystem_start(lua_State *L);
 int w_ParticleSystem_start(lua_State *L);
 int w_ParticleSystem_stop(lua_State *L);
 int w_ParticleSystem_stop(lua_State *L);