Skip to content

Commit

Permalink
osgParticle: dynamically allocate _particles
Browse files Browse the repository at this point in the history
Makes the std::sort much faster (only need to exchange pointers, not complete Particle objects).

The render_vertex_array has been temporarily removed because it relied on the particles stored contiguously in memory.
  • Loading branch information
scrawl authored and psi29a committed Jun 10, 2021
1 parent b57089f commit 05e712f
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 26 deletions.
4 changes: 2 additions & 2 deletions include/osgParticle/ConnectedParticleSystem
Expand Up @@ -44,13 +44,13 @@ namespace osgParticle
///Get the (const) particle from where the line or quadstrip starts to be drawn
const osgParticle::Particle* getStartParticle() const
{
return (_startParticle != Particle::INVALID_INDEX) ? &_particles[_startParticle] : 0;
return (_startParticle != Particle::INVALID_INDEX) ? _particles[_startParticle] : 0;
}

///Get the particle from where the line or quadstrip starts to be drawn
osgParticle::Particle* getStartParticle()
{
return (_startParticle != Particle::INVALID_INDEX) ? &_particles[_startParticle] : 0;
return (_startParticle != Particle::INVALID_INDEX) ? _particles[_startParticle] : 0;
}

///Set the maximum numbers of particles to be skipped during the predraw filtering
Expand Down
15 changes: 10 additions & 5 deletions include/osgParticle/ParticleSystem
Expand Up @@ -173,7 +173,7 @@ namespace osgParticle
inline virtual void destroyParticle(int i);

/// Reuse the i-th particle.
inline virtual void reuseParticle(int i) { _deadparts.push(&(_particles[i])); }
inline virtual void reuseParticle(int i) { _deadparts.push((_particles[i])); }

/// Get the last frame number.
inline unsigned int getLastFrameNumber() const;
Expand Down Expand Up @@ -280,7 +280,12 @@ namespace osgParticle

inline void update_bounds(const osg::Vec3& p, float r);

typedef std::vector<Particle> Particle_vector;
void single_pass_render(osg::RenderInfo& renderInfo, const osg::Matrix& modelview) const;

void new_drawImplementation(osg::RenderInfo& renderInfo) const;

typedef std::vector<Particle*> Particle_vector;

typedef std::stack<Particle*> Death_stack;

Particle_vector _particles;
Expand Down Expand Up @@ -436,17 +441,17 @@ namespace osgParticle

inline Particle* ParticleSystem::getParticle(int i)
{
return &_particles[i];
return _particles[i];
}

inline const Particle* ParticleSystem::getParticle(int i) const
{
return &_particles[i];
return _particles[i];
}

inline void ParticleSystem::destroyParticle(int i)
{
_particles[i].kill();
_particles[i]->kill();
}

inline unsigned int ParticleSystem::getLastFrameNumber() const
Expand Down
22 changes: 12 additions & 10 deletions src/osgParticle/ConnectedParticleSystem.cpp
Expand Up @@ -42,7 +42,8 @@ Particle* ConnectedParticleSystem::createParticle(const Particle* ptemplate)
// OSG_NOTICE<<this<< " Creating particle "<<std::endl;

Particle* particle = ParticleSystem::createParticle(ptemplate);
int particleIndex = (int)(particle - &_particles[0]);
// FIXME: This is broken by the change to dynamic allocated particles
int particleIndex = (int)(particle - _particles[0]);

if (particle)
{
Expand All @@ -58,7 +59,7 @@ Particle* ConnectedParticleSystem::createParticle(const Particle* ptemplate)
// OSG_NOTICE<<this<< " Connecting "<<_lastParticleCreated<<" to "<<particleIndex<<std::endl;

// write up the last created particle to this new particle
_particles[_lastParticleCreated].setNextParticle(particleIndex);
_particles[_lastParticleCreated]->setNextParticle(particleIndex);
particle->setPreviousParticle(_lastParticleCreated);
}

Expand All @@ -76,7 +77,7 @@ void ConnectedParticleSystem::reuseParticle(int particleIndex)

if (particleIndex<0 || particleIndex>=(int)_particles.size()) return;

Particle* particle = &_particles[particleIndex];
Particle* particle = _particles[particleIndex];
int previous = particle->getPreviousParticle();
int next = particle->getNextParticle();

Expand All @@ -95,12 +96,12 @@ void ConnectedParticleSystem::reuseParticle(int particleIndex)
// the deletion of the this particle
if (previous != Particle::INVALID_INDEX)
{
_particles[previous].setNextParticle(next);
_particles[previous]->setNextParticle(next);
}

if (next != Particle::INVALID_INDEX)
{
_particles[next].setPreviousParticle(previous);
_particles[next]->setPreviousParticle(previous);
}

// reset the next and previous particle entries of this particle
Expand All @@ -118,7 +119,7 @@ void ConnectedParticleSystem::drawImplementation(osg::RenderInfo& renderInfo) co

osg::State& state = *renderInfo.getState();

const Particle* particle = (_startParticle != Particle::INVALID_INDEX) ? &_particles[_startParticle] : 0;
const Particle* particle = (_startParticle != Particle::INVALID_INDEX) ? _particles[_startParticle] : 0;
if (!particle) return;

ArrayData& ad = _bufferedArrayData[state.getContextID()];
Expand Down Expand Up @@ -158,7 +159,7 @@ void ConnectedParticleSystem::drawImplementation(osg::RenderInfo& renderInfo) co
texcoords.push_back(osg::Vec2( particle->getSTexCoord(), 0.5f ));
vertices.push_back(pos);

const Particle* nextParticle = (particle->getNextParticle() != Particle::INVALID_INDEX) ? &_particles[particle->getNextParticle()] : 0;
const Particle* nextParticle = (particle->getNextParticle() != Particle::INVALID_INDEX) ? _particles[particle->getNextParticle()] : 0;
if (nextParticle)
{
osg::Vec3 startDelta = nextParticle->getPosition()-pos;
Expand All @@ -170,8 +171,9 @@ void ConnectedParticleSystem::drawImplementation(osg::RenderInfo& renderInfo) co
i<_maxNumberOfParticlesToSkip && ((distance2<maxPixelError2) && (nextParticle->getNextParticle()!=Particle::INVALID_INDEX));
++i)
{
nextParticle = &_particles[nextParticle->getNextParticle()];
nextParticle = _particles[nextParticle->getNextParticle()];
osg::Vec3 delta = nextParticle->getPosition()-pos;

distance2 = (delta^startDelta).length2();
}
}
Expand All @@ -194,7 +196,7 @@ void ConnectedParticleSystem::drawImplementation(osg::RenderInfo& renderInfo) co
const osg::Vec4& color = particle->getCurrentColor();
const osg::Vec3& pos = particle->getPosition();

const Particle* nextParticle = (particle->getNextParticle() != Particle::INVALID_INDEX) ? &_particles[particle->getNextParticle()] : 0;
const Particle* nextParticle = (particle->getNextParticle() != Particle::INVALID_INDEX) ? _particles[particle->getNextParticle()] : 0;

if (nextParticle)
{
Expand All @@ -208,7 +210,7 @@ void ConnectedParticleSystem::drawImplementation(osg::RenderInfo& renderInfo) co
i<_maxNumberOfParticlesToSkip && ((distance2<maxPixelError2) && (nextParticle->getNextParticle()!=Particle::INVALID_INDEX));
++i)
{
nextParticle = &_particles[nextParticle->getNextParticle()];
nextParticle = _particles[nextParticle->getNextParticle()];
delta = nextParticle->getPosition()-pos;
distance2 = (delta^startDelta).length2();
}
Expand Down
28 changes: 19 additions & 9 deletions src/osgParticle/ParticleSystem.cpp
Expand Up @@ -94,6 +94,9 @@ osgParticle::ParticleSystem::ParticleSystem(const ParticleSystem& copy, const os
osgParticle::ParticleSystem::~ParticleSystem()
{
// OSG_NOTICE<<"ParticleSystem::~ParticleSystem() "<<std::dec<<this<<std::dec<<" _particles.size()="<<_particles.size()<<", _particles.capacity()="<<_particles.capacity()<<" _estimatedMaxNumOfParticles="<<_estimatedMaxNumOfParticles<<std::endl;
for (unsigned int i=0; i<_particles.size(); ++i)
delete _particles[i];
_particles.clear();
}

osgParticle::Particle* osgParticle::ParticleSystem::createParticle(const osgParticle::Particle* ptemplate)
Expand Down Expand Up @@ -125,11 +128,16 @@ osgParticle::Particle* osgParticle::ParticleSystem::createParticle(const osgPart
}

// add a new particle to the vector
_particles.push_back(ptemplate? *ptemplate: _def_ptemp);
return &_particles.back();
_particles.push_back(new Particle(ptemplate?*ptemplate:_def_ptemp));
return _particles.back();
}
}

bool cmp_particles(const osgParticle::Particle* left, const osgParticle::Particle* right)
{
return *left < *right;
}

void osgParticle::ParticleSystem::update(double dt, osg::NodeVisitor& nv)
{
// reset bounds
Expand All @@ -154,7 +162,7 @@ void osgParticle::ParticleSystem::update(double dt, osg::NodeVisitor& nv)

for(unsigned int i=0; i<_particles.size(); ++i)
{
Particle& particle = _particles[i];
Particle& particle = *_particles[i];
if (particle.isAlive())
{
if (particle.update(dt, _useShaders))
Expand All @@ -179,29 +187,31 @@ void osgParticle::ParticleSystem::update(double dt, osg::NodeVisitor& nv)
double deadDistance = DBL_MAX;
for (unsigned int i=0; i<_particles.size(); ++i)
{
Particle& particle = _particles[i];
Particle& particle = *_particles[i];
if (particle.isAlive())
particle.setDepth(distance(particle.getPosition(), modelview) * scale);
else
particle.setDepth(deadDistance);
}
std::sort<Particle_vector::iterator>(_particles.begin(), _particles.end());
std::sort<Particle_vector::iterator>(_particles.begin(), _particles.end(), cmp_particles);

// Repopulate the death stack as it will have been invalidated by the sort.
/*
unsigned int numDead = _deadparts.size();
if (numDead>0)
{
// clear the death stack
_deadparts = Death_stack();
// copy the tail of the _particles vector as this will contain all the dead Particle thanks to the depth sort against DBL_MAX
Particle* first_dead_ptr = &_particles[_particles.size()-numDead];
Particle* last_dead_ptr = &_particles[_particles.size()-1];
Particle* first_dead_ptr = _particles[_particles.size()-numDead];
Particle* last_dead_ptr = _particles[_particles.size()-1];
for(Particle* dead_ptr = first_dead_ptr; dead_ptr<=last_dead_ptr; ++dead_ptr)
{
_deadparts.push(dead_ptr);
}
}
*/
}
}

Expand Down Expand Up @@ -252,7 +262,7 @@ void osgParticle::ParticleSystem::drawImplementation(osg::RenderInfo& renderInfo

for(unsigned int i=0; i<_particles.size(); i+=_detail)
{
const Particle* particle = &_particles[i];
const Particle* particle = _particles[i];
const osg::Vec4& color = particle->getCurrentColor();
const osg::Vec3& pos = particle->getPosition();
const osg::Vec3& vel = particle->getVelocity();
Expand Down Expand Up @@ -321,7 +331,7 @@ void osgParticle::ParticleSystem::drawImplementation(osg::RenderInfo& renderInfo

for(unsigned int i=0; i<_particles.size(); i+=_detail)
{
const Particle* currentParticle = &_particles[i];
const Particle* currentParticle = _particles[i];

bool insideDistance = true;
if (_sortMode != NO_SORT && _visibilityDistance>0.0)
Expand Down

0 comments on commit 05e712f

Please sign in to comment.