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

This commit is contained in:
scrawl 2017-02-21 18:59:38 +01:00
parent 0fbd29ccb8
commit 3693f05ef5

View file

@ -31,37 +31,18 @@
namespace namespace
{ {
/// @todo Do this in updateCallback so that animations are accounted for. class InitWorldSpaceParticlesCallback : public osg::NodeCallback
class InitWorldSpaceParticlesVisitor : public osg::NodeVisitor
{ {
public: public:
/// @param mask The node mask to set on ParticleSystem nodes. virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
InitWorldSpaceParticlesVisitor(unsigned int mask)
: osg::NodeVisitor(TRAVERSE_ALL_CHILDREN)
, mMask(mask)
{ {
} osgParticle::ParticleSystem* partsys = static_cast<osgParticle::ParticleSystem*>(node);
bool isWorldSpaceParticleSystem(osgParticle::ParticleSystem* partsys)
{
// HACK: ParticleSystem has no getReferenceFrame()
return (partsys->getUserDataContainer()
&& partsys->getUserDataContainer()->getNumDescriptions() > 0
&& partsys->getUserDataContainer()->getDescriptions()[0] == "worldspace");
}
void apply(osg::Drawable& drw)
{
if (osgParticle::ParticleSystem* partsys = dynamic_cast<osgParticle::ParticleSystem*>(&drw))
{
if (isWorldSpaceParticleSystem(partsys))
{
// HACK: Ignore the InverseWorldMatrix transform the particle system is attached to // HACK: Ignore the InverseWorldMatrix transform the particle system is attached to
if (partsys->getNumParents() && partsys->getParent(0)->getNumParents()) if (partsys->getNumParents() && partsys->getParent(0)->getNumParents())
transformInitialParticles(partsys, partsys->getParent(0)->getParent(0)); transformInitialParticles(partsys, partsys->getParent(0)->getParent(0));
}
partsys->setNodeMask(mMask); node->removeUpdateCallback(this);
}
} }
void transformInitialParticles(osgParticle::ParticleSystem* partsys, osg::Node* node) void transformInitialParticles(osgParticle::ParticleSystem* partsys, osg::Node* node)
@ -83,6 +64,39 @@ namespace
box.expandBy(sphere); box.expandBy(sphere);
partsys->setInitialBound(box); partsys->setInitialBound(box);
} }
};
class InitParticlesVisitor : public osg::NodeVisitor
{
public:
/// @param mask The node mask to set on ParticleSystem nodes.
InitParticlesVisitor(unsigned int mask)
: osg::NodeVisitor(TRAVERSE_ALL_CHILDREN)
, mMask(mask)
{
}
bool isWorldSpaceParticleSystem(osgParticle::ParticleSystem* partsys)
{
// HACK: ParticleSystem has no getReferenceFrame()
return (partsys->getUserDataContainer()
&& partsys->getUserDataContainer()->getNumDescriptions() > 0
&& partsys->getUserDataContainer()->getDescriptions()[0] == "worldspace");
}
void apply(osg::Drawable& drw)
{
if (osgParticle::ParticleSystem* partsys = dynamic_cast<osgParticle::ParticleSystem*>(&drw))
{
if (isWorldSpaceParticleSystem(partsys))
{
partsys->addUpdateCallback(new InitWorldSpaceParticlesCallback);
}
partsys->setNodeMask(mMask);
}
}
private: private:
unsigned int mMask; 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 // 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) if (node->getNumChildrenRequiringUpdateTraversal() > 0)
{ {
InitWorldSpaceParticlesVisitor visitor (mParticleSystemMask); InitParticlesVisitor visitor (mParticleSystemMask);
node->accept(visitor); node->accept(visitor);
} }
} }