Skip to content

Instantly share code, notes, and snippets.

@lukaspj
Created February 9, 2015 20:54
Show Gist options
  • Save lukaspj/448c8910951ad6f4c232 to your computer and use it in GitHub Desktop.
Save lukaspj/448c8910951ad6f4c232 to your computer and use it in GitHub Desktop.
//-----------------------------------------------------------------------------
// Update particles
//-----------------------------------------------------------------------------
void ParticleSystem::simulate(U32 ms)
{
// TODO: Prefetch
if (Con::getBoolVariable("$ParticleSystem::ParticleLOD"))
{
if (mSkipUpdateCount < 1000)
{
if (mSkippedUpdates == 0)
mSkippedUpdates = 1;
if (mSkippedUpdates < mSkipUpdateCount)
{
mSkippedUpdates++;
mTSU += ms;
return;
}
if (mSkippedUpdates >= mSkipUpdateCount)
{
mSkippedUpdates = 1;
ms += mTSU;
mTSU = 0;
}
}
else return;
}
IParticleBehaviour **BHVs = getDataBlock()->ParticleBHVs;
// TODO: WHAT SO MANY SORTS PER SECOND? WTF DO A DIRTY FLAG!
dQsort(BHVs, ParticleBehaviourCount, sizeof(IParticleBehaviour*), &IParticleBehaviour::compare);
ParticleQueue* queue = new ParticleQueue(mParticlePool->GetParticleHead()->next);
ThreadPool* pool = &ThreadPool::GLOBAL();
F32 t = F32(ms) / 1000.0;
for (U32 i = 0; i < 4; ++i)
{
ThreadSafeRef< ParticleUpdateItem > item(new ParticleUpdateItem(queue, t, this, BHVs));
pool->queueWorkItem(item);
}
pool->flushWorkItems();
delete queue;
}
#include "particleThreading.h"
Particle* ParticleQueue::mGetNextParticle()
{
Mutex::lockMutex(mMutex, true);
Particle* retPart = mCurrentParticle;
if (retPart != NULL)
mCurrentParticle = mCurrentParticle->next;
Mutex::unlockMutex(mMutex);
return retPart;
}
void ParticleUpdateItem::execute()
{
Particle* part = mPartQueue->mGetNextParticle();
while (part != NULL)
{
// TODO: Don't overwrite acceleration
part->acc.zero();
// First calculate the acceleration of the particle.
for (int i = 0; i < ParticleBehaviourCount; i++)
{
IParticleBehaviour* bhv = mBHVs[i];
if (!bhv)
continue;
if (bhv->getType() == behaviourType::Acceleration)
bhv->updateParticle(mSystem, part, mT);
}
// Apply physics constants to the acceleration
Point3F a = part->acc;
a -= part->vel * mSystem->getDataBlock()->mDragCoefficient;
a -= ParticleSystem::mWindVelocity * mSystem->getDataBlock()->mWindCoefficient;
a += Point3F(0.0f, 0.0f, -9.81f) * mSystem->getDataBlock()->mGravityCoefficient;
// Acceleration multiplied by time gives the amount of increased velocity
part->vel += a * mT;
for (int i = 0; i < ParticleBehaviourCount; i++)
{
IParticleBehaviour* bhv = mBHVs[i];
if (!bhv)
continue;
if (bhv->getType() == behaviourType::Velocity)
bhv->updateParticle(mSystem, part, mT);
}
// Velocity multiplied by time gives the distance the particle has travelled
part->relPos += part->vel * mT;
part->pos += part->vel * mT;
for (int i = 0; i < ParticleBehaviourCount; i++)
{
IParticleBehaviour* bhv = mBHVs[i];
if (!bhv)
continue;
if (bhv->getType() == behaviourType::Position)
bhv->updateParticle(mSystem, part, mT);
}
part = mPartQueue->mGetNextParticle();
}
}
#ifndef PARTICLE_THREADING_H_
#define PARTICLE_THREADING_H_
#include "platform/threads/threadPool.h"
#include "platform/threads/mutex.h"
#include "../particle.h"
#include "../particleSystem.h"
class ParticleQueue{
Particle* mCurrentParticle;
void *mMutex;
public:
Particle* mGetNextParticle();
ParticleQueue(Particle* pFirstParticle)
: mCurrentParticle(pFirstParticle)
{
mMutex = Mutex::createMutex();
};
~ParticleQueue()
{
Mutex::destroyMutex(mMutex);
}
};
class ParticleUpdateItem : public ThreadPool::WorkItem
{
public:
typedef ThreadPool::WorkItem Parent;
private:
ParticleQueue* mPartQueue;
F32 mT;
ParticleSystem* mSystem;
IParticleBehaviour **mBHVs;
public:
ParticleUpdateItem(ParticleQueue* pQueue, F32 pT, ParticleSystem* pSystem, IParticleBehaviour **pBHVs)
: mPartQueue(pQueue), mT(pT), mSystem(pSystem), mBHVs(pBHVs){}
protected:
virtual void execute();
};
#endif // PARTICLE_THREADING_H_
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment