Transform world-space particle systems in update callback so that animations are accounted for

pull/164/head
scrawl 8 years ago
parent 0fbd29ccb8
commit 3693f05ef5

@ -31,12 +31,47 @@
namespace
{
/// @todo Do this in updateCallback so that animations are accounted for.
class InitWorldSpaceParticlesVisitor : public osg::NodeVisitor
class InitWorldSpaceParticlesCallback : public osg::NodeCallback
{
public:
virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
{
osgParticle::ParticleSystem* partsys = static_cast<osgParticle::ParticleSystem*>(node);
// HACK: Ignore the InverseWorldMatrix transform the particle system is attached to
if (partsys->getNumParents() && partsys->getParent(0)->getNumParents())
transformInitialParticles(partsys, partsys->getParent(0)->getParent(0));
node->removeUpdateCallback(this);
}
void transformInitialParticles(osgParticle::ParticleSystem* partsys, osg::Node* node)
{
osg::NodePathList nodepaths = node->getParentalNodePaths();
if (nodepaths.empty())
return;
osg::Matrixf worldMat = osg::computeLocalToWorld(nodepaths[0]);
worldMat.orthoNormalize(worldMat); // scale is already applied on the particle node
for (int i=0; i<partsys->numParticles(); ++i)
{
partsys->getParticle(i)->transformPositionVelocity(worldMat);
}
// transform initial bounds to worldspace
osg::BoundingSphere sphere(partsys->getInitialBound());
SceneUtil::transformBoundingSphere(worldMat, sphere);
osg::BoundingBox box;
box.expandBy(sphere);
partsys->setInitialBound(box);
}
};
class InitParticlesVisitor : public osg::NodeVisitor
{
public:
/// @param mask The node mask to set on ParticleSystem nodes.
InitWorldSpaceParticlesVisitor(unsigned int mask)
InitParticlesVisitor(unsigned int mask)
: osg::NodeVisitor(TRAVERSE_ALL_CHILDREN)
, mMask(mask)
{
@ -56,33 +91,12 @@ namespace
{
if (isWorldSpaceParticleSystem(partsys))
{
// HACK: Ignore the InverseWorldMatrix transform the particle system is attached to
if (partsys->getNumParents() && partsys->getParent(0)->getNumParents())
transformInitialParticles(partsys, partsys->getParent(0)->getParent(0));
partsys->addUpdateCallback(new InitWorldSpaceParticlesCallback);
}
partsys->setNodeMask(mMask);
}
}
void transformInitialParticles(osgParticle::ParticleSystem* partsys, osg::Node* node)
{
osg::NodePathList nodepaths = node->getParentalNodePaths();
if (nodepaths.empty())
return;
osg::Matrixf worldMat = osg::computeLocalToWorld(nodepaths[0]);
worldMat.orthoNormalize(worldMat); // scale is already applied on the particle node
for (int i=0; i<partsys->numParticles(); ++i)
{
partsys->getParticle(i)->transformPositionVelocity(worldMat);
}
// transform initial bounds to worldspace
osg::BoundingSphere sphere(partsys->getInitialBound());
SceneUtil::transformBoundingSphere(worldMat, sphere);
osg::BoundingBox box;
box.expandBy(sphere);
partsys->setInitialBound(box);
}
private:
unsigned int mMask;
};
@ -489,7 +503,7 @@ namespace Resource
// we can skip any scene graphs without update callbacks since we know that particle emitters will have an update callback set
if (node->getNumChildrenRequiringUpdateTraversal() > 0)
{
InitWorldSpaceParticlesVisitor visitor (mParticleSystemMask);
InitParticlesVisitor visitor (mParticleSystemMask);
node->accept(visitor);
}
}

Loading…
Cancel
Save