From 29f47d9a1023086a84b69b9a0082327c2152c4e9 Mon Sep 17 00:00:00 2001 From: Alex Szpakowski Date: Thu, 16 Jan 2014 16:20:30 -0400 Subject: [PATCH] Changed particle spawning behaviour in ParticleSystems to spawn at an interpolated position between the location at the previous update and the current one. This results in much smoother behaviour when moving a ParticleSystem constantly via ParticleSystem:setPosition. Also fixed particle spawning to better fill up the buffer. --- .../graphics/opengl/ParticleSystem.cpp | 59 +++++++++++-------- src/modules/graphics/opengl/ParticleSystem.h | 5 +- 2 files changed, 36 insertions(+), 28 deletions(-) diff --git a/src/modules/graphics/opengl/ParticleSystem.cpp b/src/modules/graphics/opengl/ParticleSystem.cpp index dbc26eb2e..3f176a00b 100644 --- a/src/modules/graphics/opengl/ParticleSystem.cpp +++ b/src/modules/graphics/opengl/ParticleSystem.cpp @@ -118,6 +118,7 @@ ParticleSystem::ParticleSystem(const ParticleSystem &p) , emissionRate(p.emissionRate) , emitCounter(0.0f) , position(p.position) + , prevPosition(p.prevPosition) , areaSpreadDistribution(p.areaSpreadDistribution) , areaSpread(p.areaSpread) , lifetime(p.lifetime) @@ -205,14 +206,14 @@ uint32 ParticleSystem::getBufferSize() const return maxParticles; } -void ParticleSystem::addParticle() +void ParticleSystem::addParticle(float t) { if (isFull()) return; // Gets a free particle and updates the allocation pointer. particle *p = pFree++; - initParticle(p); + initParticle(p, t); switch (insertMode) { @@ -231,10 +232,13 @@ void ParticleSystem::addParticle() activeParticles++; } -void ParticleSystem::initParticle(particle *p) +void ParticleSystem::initParticle(particle *p, float t) { float min,max; + // Linearly interpolate between the previous and current emitter position. + love::Vector pos = prevPosition + (position - prevPosition) * t; + min = particleLifeMin; max = particleLifeMax; if (min == max) @@ -243,8 +247,8 @@ void ParticleSystem::initParticle(particle *p) p->life = (float) rng.random(min, max); p->lifetime = p->life; - p->position[0] = position.getX(); - p->position[1] = position.getY(); + p->position[0] = pos.x; + p->position[1] = pos.y; switch (areaSpreadDistribution) { @@ -265,7 +269,7 @@ void ParticleSystem::initParticle(particle *p) max = direction + spread/2.0f; p->direction = (float) rng.random(min, max); - p->origin = position; + p->origin = pos; min = speedMin; max = speedMax; @@ -748,7 +752,7 @@ void ParticleSystem::emit(uint32 num) num = std::min(num, maxParticles - activeParticles); while(num--) - addParticle(); + addParticle(1.0f); } bool ParticleSystem::isActive() const @@ -847,25 +851,6 @@ void ParticleSystem::update(float dt) if (pMem == nullptr || dt == 0.0f) return; - // Make some more particles. - if (active) - { - float rate = 1.0f / emissionRate; // the amount of time between each particle emit - emitCounter += dt; - while (emitCounter > rate) - { - addParticle(); - emitCounter -= rate; - } - /*int particles = (int)(emissionRate * dt); - for (int i = 0; i != particles; i++) - add();*/ - - life -= dt; - if (lifetime != -1 && life < 0) - stop(); - } - // Traverse all particles and update. particle *p = pHead; @@ -940,6 +925,28 @@ void ParticleSystem::update(float dt) p = p->next; } } + + // Make some more particles. + if (active) + { + float rate = 1.0f / emissionRate; // the amount of time between each particle emit + emitCounter += dt; + float total = emitCounter - rate; + while (emitCounter > rate) + { + addParticle(1.0f - (emitCounter - rate) / total); + emitCounter -= rate; + } + /*int particles = (int)(emissionRate * dt); + for (int i = 0; i != particles; i++) + add();*/ + + life -= dt; + if (lifetime != -1 && life < 0) + stop(); + } + + prevPosition = position; } bool ParticleSystem::getConstant(const char *in, AreaSpreadDistribution &out) diff --git a/src/modules/graphics/opengl/ParticleSystem.h b/src/modules/graphics/opengl/ParticleSystem.h index 08f692cb5..14b37a1c4 100644 --- a/src/modules/graphics/opengl/ParticleSystem.h +++ b/src/modules/graphics/opengl/ParticleSystem.h @@ -554,6 +554,7 @@ protected: // The relative position of the particle emitter. love::Vector position; + love::Vector prevPosition; // Emission area spread. AreaSpreadDistribution areaSpreadDistribution; @@ -610,11 +611,11 @@ protected: void createBuffers(size_t size); void deleteBuffers(); - void addParticle(); + void addParticle(float t); particle *removeParticle(particle *p); // Called by addParticle. - void initParticle(particle *p); + void initParticle(particle *p, float t); void insertTop(particle *p); void insertBottom(particle *p); void insertRandom(particle *p);