Created
April 27, 2014 05:47
-
-
Save fenbf/11338457 to your computer and use it in GitHub Desktop.
Basic Particle classes design. Used as a starting point for my particle system. More details http://www.bfilipek.com
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "particles.h" | |
#include <assert.h> | |
#include <algorithm> | |
namespace particles | |
{ | |
void ParticleData::generate(size_t maxSize) | |
{ | |
m_count = maxSize; | |
m_countAlive = 0; | |
m_pos.reset(new glm::vec4[maxSize]); | |
m_col.reset(new glm::vec4[maxSize]); | |
m_startCol.reset(new glm::vec4[maxSize]); | |
m_endCol.reset(new glm::vec4[maxSize]); | |
m_vel.reset(new glm::vec4[maxSize]); | |
m_acc.reset(new glm::vec4[maxSize]); | |
m_time.reset(new glm::vec4[maxSize]); | |
m_alive.reset(new bool[maxSize]); | |
} | |
void ParticleData::kill(size_t id) | |
{ | |
if (m_countAlive > 0) // maybe this if can be removed? | |
{ | |
m_alive[id] = false; | |
swapData(id, m_countAlive - 1); | |
m_countAlive--; | |
} | |
} | |
void ParticleData::wake(size_t id) | |
{ | |
if (m_countAlive < m_count) // maybe this if can be removed? | |
{ | |
m_alive[id] = true; | |
swapData(id, m_countAlive); | |
m_countAlive++; | |
} | |
} | |
void ParticleData::swapData(size_t a, size_t b) | |
{ | |
std::swap(m_pos[a], m_pos[b]); | |
std::swap(m_col[a], m_col[b]); | |
std::swap(m_startCol[a], m_startCol[b]); | |
std::swap(m_endCol[a], m_endCol[b]); | |
std::swap(m_vel[a], m_vel[b]); | |
std::swap(m_acc[a], m_acc[b]); | |
std::swap(m_time[a], m_time[b]); | |
std::swap(m_alive[a], m_alive[b]); | |
} | |
//////////////////////////////////////////////////////////////////////////////// | |
// ParticleEmitter class | |
void ParticleEmitter::emit(double dt, ParticleData *p) | |
{ | |
const size_t maxNewParticles = static_cast<size_t>(dt*m_emitRate); | |
const size_t startId = p->m_countAlive; | |
const size_t endId = std::min(startId + maxNewParticles, p->m_count-1); | |
for (auto &gen : m_generators) | |
gen->generate(dt, p, startId, endId); | |
for (size_t i = startId; i < endId; ++i) | |
{ | |
p->wake(i); | |
} | |
} | |
//////////////////////////////////////////////////////////////////////////////// | |
// ParticleSystem class | |
//////////////////////////////////////////////////////////////////////////////// | |
ParticleSystem::ParticleSystem(size_t maxCount) | |
{ | |
m_count = maxCount; | |
m_particles.generate(maxCount); | |
m_aliveParticles.generate(maxCount); | |
for (size_t i = 0; i < maxCount; ++i) | |
m_particles.m_alive[i] = false; | |
} | |
void ParticleSystem::update(double dt) | |
{ | |
for (auto & em : m_emitters) | |
{ | |
em->emit(dt, &m_particles); | |
} | |
for (size_t i = 0; i < m_count; ++i) | |
{ | |
m_particles.m_acc[i] = glm::vec4(0.0f); | |
} | |
for (auto & up : m_updaters) | |
{ | |
up->update(dt, &m_particles); | |
} | |
//ParticleData::copyOnlyAlive(&m_particles, &m_aliveParticles); | |
} | |
void ParticleSystem::reset() | |
{ | |
m_particles.m_countAlive = 0; | |
} | |
size_t ParticleSystem::computeMemoryUsage(const ParticleSystem &p) | |
{ | |
return 2 * ParticleData::computeMemoryUsage(p.m_particles); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#pragma once | |
#include <vector> | |
#include <memory> | |
#include <glm/vec4.hpp> | |
namespace particles | |
{ | |
class ParticleData | |
{ | |
public: | |
std::unique_ptr<glm::vec4[]> m_pos; | |
std::unique_ptr<glm::vec4[]> m_col; | |
std::unique_ptr<glm::vec4[]> m_startCol; | |
std::unique_ptr<glm::vec4[]> m_endCol; | |
std::unique_ptr<glm::vec4[]> m_vel; | |
std::unique_ptr<glm::vec4[]> m_acc; | |
std::unique_ptr<glm::vec4[]> m_time; | |
std::unique_ptr<bool[]> m_alive; | |
size_t m_count{ 0 }; | |
size_t m_countAlive{ 0 }; | |
public: | |
ParticleData() { } | |
explicit ParticleData(size_t maxCount) { generate(maxCount); } | |
~ParticleData() { } | |
ParticleData(const ParticleData &) = delete; | |
ParticleData &operator=(const ParticleData &) = delete; | |
void generate(size_t maxSize); | |
void kill(size_t id); | |
void wake(size_t id); | |
void swapData(size_t a, size_t b); | |
}; | |
class ParticleGenerator | |
{ | |
public: | |
ParticleGenerator() { } | |
virtual ~ParticleGenerator() { } | |
virtual void generate(double dt, ParticleData *p, size_t startId, size_t endId) = 0; | |
}; | |
class ParticleEmitter | |
{ | |
protected: | |
std::vector<std::shared_ptr<ParticleGenerator>> m_generators; | |
public: | |
float m_emitRate{ 0.0 }; | |
public: | |
ParticleEmitter() { } | |
virtual ~ParticleEmitter() { } | |
// calls all the generators and at the end it activates (wakes) particle | |
virtual void emit(double dt, ParticleData *p); | |
void addGenerator(std::shared_ptr<ParticleGenerator> gen) { m_generators.push_back(gen); } | |
}; | |
class ParticleUpdater | |
{ | |
public: | |
ParticleUpdater() { } | |
virtual ~ParticleUpdater() { } | |
virtual void update(double dt, ParticleData *p) = 0; | |
}; | |
class ParticleSystem | |
{ | |
protected: | |
ParticleData m_particles; | |
ParticleData m_aliveParticles; | |
size_t m_count; | |
std::vector<std::shared_ptr<ParticleEmitter>> m_emitters; | |
std::vector<std::shared_ptr<ParticleUpdater>> m_updaters; | |
public: | |
explicit ParticleSystem(size_t maxCount); | |
virtual ~ParticleSystem() { } | |
ParticleSystem(const ParticleSystem &) = delete; | |
ParticleSystem &operator=(const ParticleSystem &) = delete; | |
virtual void update(double dt); | |
virtual void reset(); | |
virtual size_t numAllParticles() const { return m_particles.m_count; } | |
virtual size_t numAliveParticles() const { return m_particles.m_countAlive; } | |
void addEmitter(std::shared_ptr<ParticleEmitter> em) { m_emitters.push_back(em); } | |
void addUpdater(std::shared_ptr<ParticleUpdater> up) { m_updaters.push_back(up); } | |
ParticleData *finalData() { return &m_particles; } | |
static size_t computeMemoryUsage(const ParticleSystem &p); | |
}; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment