Skip to content

Instantly share code, notes, and snippets.

@fenbf
Created June 5, 2014 18:37
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save fenbf/30e3ca85659624380392 to your computer and use it in GitHub Desktop.
Save fenbf/30e3ca85659624380392 to your computer and use it in GitHub Desktop.
Particle Updaters
namespace updaters
{
void EulerUpdater::update(double dt, ParticleData *p)
{
const glm::vec4 globalA{ dt * m_globalAcceleration.x, dt * m_globalAcceleration.y, dt * m_globalAcceleration.z, 0.0 };
const float localDT = (float)dt;
const unsigned int endId = p->m_countAlive;
for (size_t i = 0; i < endId; ++i)
p->m_acc[i] += globalA;
for (size_t i = 0; i < endId; ++i)
p->m_vel[i] += localDT * p->m_acc[i];
for (size_t i = 0; i < endId; ++i)
p->m_pos[i] += localDT * p->m_vel[i];
}
void FloorUpdater::update(double dt, ParticleData *p)
{
const float localDT = (float)dt;
const size_t endId = p->m_countAlive;
for (size_t i = 0; i < endId; ++i)
{
if (p->m_pos[i].y < m_floorY)
{
glm::vec4 force = p->m_acc[i];
float normalFactor = glm::dot(force, glm::vec4(0.0f, 1.0f, 0.0f, 0.0f));
if (normalFactor < 0.0f)
force -= glm::vec4(0.0f, 1.0f, 0.0f, 0.0f) * normalFactor;
float velFactor = glm::dot(p->m_vel[i], glm::vec4(0.0f, 1.0f, 0.0f, 0.0f));
//if (velFactor < 0.0)
p->m_vel[i] -= glm::vec4(0.0f, 1.0f, 0.0f, 0.0f) * (1.0f + m_bounceFactor) * velFactor;
p->m_acc[i] = force;
}
}
}
void AttractorUpdater::update(double dt, ParticleData *p)
{
const float localDT = (float)dt;
const size_t endId = p->m_countAlive;
const size_t countAttractors = m_attractors.size();
glm::vec4 off;
float dist;
size_t a;
for (size_t i = 0; i < endId; ++i)
{
for (a = 0; a < countAttractors; ++a)
{
off.x = m_attractors[a].x - p->m_pos[i].x;
off.y = m_attractors[a].y - p->m_pos[i].y;
off.z = m_attractors[a].z - p->m_pos[i].z;
dist = glm::dot(off, off);
//if (fabs(dist) > 0.00001)
dist = m_attractors[a].w / dist;
p->m_acc[i] += off * dist;
}
}
}
void BasicColorUpdater::update(double dt, ParticleData *p)
{
const size_t endId = p->m_countAlive;
for (size_t i = 0; i < endId; ++i)
p->m_col[i] = glm::mix(p->m_startCol[i], p->m_endCol[i], p->m_time[i].z);
}
void PosColorUpdater::update(double dt, ParticleData *p)
{
const size_t endId = p->m_countAlive;
float scaler, scaleg, scaleb;
float diffr = m_maxPos.x - m_minPos.x;
float diffg = m_maxPos.y - m_minPos.y;
float diffb = m_maxPos.z - m_minPos.z;
for (size_t i = 0; i < endId; ++i)
{
scaler = (p->m_pos[i].x - m_minPos.x) / diffr;
scaleg = (p->m_pos[i].y - m_minPos.y) / diffg;
scaleb = (p->m_pos[i].z - m_minPos.z) / diffb;
p->m_col[i].r = scaler;// glm::mix(p->m_startCol[i].r, p->m_endCol[i].r, scaler);
p->m_col[i].g = scaleg;// glm::mix(p->m_startCol[i].g, p->m_endCol[i].g, scaleg);
p->m_col[i].b = scaleb;// glm::mix(p->m_startCol[i].b, p->m_endCol[i].b, scaleb);
p->m_col[i].a = glm::mix(p->m_startCol[i].a, p->m_endCol[i].a, p->m_time[i].z);
}
}
void VelColorUpdater::update(double dt, ParticleData *p)
{
const size_t endId = p->m_countAlive;
float scaler, scaleg, scaleb;
float diffr = m_maxVel.x - m_minVel.x;
float diffg = m_maxVel.y - m_minVel.y;
float diffb = m_maxVel.z - m_minVel.z;
for (size_t i = 0; i < endId; ++i)
{
scaler = (p->m_vel[i].x - m_minVel.x) / diffr;
scaleg = (p->m_vel[i].y - m_minVel.y) / diffg;
scaleb = (p->m_vel[i].z - m_minVel.z) / diffb;
p->m_col[i].r = scaler;// glm::mix(p->m_startCol[i].r, p->m_endCol[i].r, scaler);
p->m_col[i].g = scaleg;// glm::mix(p->m_startCol[i].g, p->m_endCol[i].g, scaleg);
p->m_col[i].b = scaleb;// glm::mix(p->m_startCol[i].b, p->m_endCol[i].b, scaleb);
p->m_col[i].a = glm::mix(p->m_startCol[i].a, p->m_endCol[i].a, p->m_time[i].z);
}
}
void BasicTimeUpdater::update(double dt, ParticleData *p)
{
unsigned int endId = p->m_countAlive;
const float localDT = (float)dt;
if (endId == 0) return;
for (size_t i = 0; i < endId; ++i)
{
p->m_time[i].x -= localDT;
// interpolation: from 0 (start of life) till 1 (end of life)
p->m_time[i].z = (float)1.0 - (p->m_time[i].x*p->m_time[i].w); // .w is 1.0/max life time
if (p->m_time[i].x < (float)0.0)
{
p->kill(i);
endId = p->m_countAlive < p->m_count ? p->m_countAlive : p->m_count;
}
}
}
}
class ParticleUpdater
{
public:
ParticleUpdater() { }
virtual ~ParticleUpdater() { }
virtual void update(double dt, ParticleData *p) = 0;
};
namespace updaters
{
class EulerUpdater : public ParticleUpdater
{
public:
glm::vec4 m_globalAcceleration{ 0.0f };
public:
virtual void update(double dt, ParticleData *p) override;
};
// collision with the floor :) todo: implement a collision model
class FloorUpdater : public particles::ParticleUpdater
{
public:
float m_floorY{ 0.0f };
float m_bounceFactor{ 0.5f };
public:
virtual void update(double dt, ParticleData *p) override;
};
class AttractorUpdater : public particles::ParticleUpdater
{
protected:
std::vector<glm::vec4> m_attractors; // .w is force
public:
virtual void update(double dt, ParticleData *p) override;
size_t collectionSize() const { return m_attractors.size(); }
void add(const glm::vec4 &attr) { m_attractors.push_back(attr); }
glm::vec4 &get(size_t id) { return m_attractors[id]; }
};
class BasicColorUpdater : public ParticleUpdater
{
public:
virtual void update(double dt, ParticleData *p) override;
};
class PosColorUpdater : public ParticleUpdater
{
public:
glm::vec4 m_minPos{ 0.0 };
glm::vec4 m_maxPos{ 1.0 };
public:
virtual void update(double dt, ParticleData *p) override;
};
class VelColorUpdater : public ParticleUpdater
{
public:
glm::vec4 m_minVel{ 0.0 };
glm::vec4 m_maxVel{ 1.0 };
public:
virtual void update(double dt, ParticleData *p) override;
};
class BasicTimeUpdater : public ParticleUpdater
{
public:
virtual void update(double dt, ParticleData *p) override;
};
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment