diff --git a/components/nifosg/nifloader.cpp b/components/nifosg/nifloader.cpp index 15c461bf2b..f89720dd4c 100644 --- a/components/nifosg/nifloader.cpp +++ b/components/nifosg/nifloader.cpp @@ -1056,6 +1056,8 @@ namespace NifOsg emitter->setReferenceFrame(osgParticle::ParticleProcessor::RELATIVE_RF); // The emitter node may not actually be handled yet, so let's delay attaching the emitter to a later moment. + // If the emitter node is placed later than the particle node, it'll have a single frame delay in particle processing. + // But that shouldn't be a game-breaking issue. mEmitterQueue.emplace_back(partctrl->emitter->recIndex, emitter); osg::ref_ptr callback(new ParticleSystemController(partctrl)); @@ -1073,7 +1075,7 @@ namespace NifOsg partsys->update(0.0, nv); } - // affectors must be attached *after* the emitter in the scene graph for correct update order + // affectors should be attached *after* the emitter in the scene graph for correct update order // attach to same node as the ParticleSystem, we need osgParticle Operators to get the correct // localToWorldMatrix for transforming to particle space handleParticlePrograms(partctrl->affectors, partctrl->colliders, parentNode, partsys.get(), rf); diff --git a/components/sceneutil/clone.cpp b/components/sceneutil/clone.cpp index 04fd5d78db..0423d61171 100644 --- a/components/sceneutil/clone.cpp +++ b/components/sceneutil/clone.cpp @@ -69,6 +69,15 @@ namespace SceneUtil osgParticle::ParticleProcessor* CopyOp::operator() (const osgParticle::ParticleProcessor* processor) const { osgParticle::ParticleProcessor* cloned = osg::clone(processor, osg::CopyOp::DEEP_COPY_CALLBACKS); + for (std::map::const_iterator it = mMap3.begin(); it != mMap3.end(); ++it) + { + if (processor->getParticleSystem() == it->first) + { + cloned->setParticleSystem(it->second); + return cloned; + } + } + mMap[cloned] = processor->getParticleSystem(); return cloned; } @@ -93,6 +102,9 @@ namespace SceneUtil updater->addParticleSystem(cloned); } } + // In rare situations a particle processor may be placed after the particle system in the scene graph. + mMap3[partsys] = cloned; + return cloned; } diff --git a/components/sceneutil/clone.hpp b/components/sceneutil/clone.hpp index 8a18eeb20b..b0a9d56c3e 100644 --- a/components/sceneutil/clone.hpp +++ b/components/sceneutil/clone.hpp @@ -35,10 +35,11 @@ namespace SceneUtil virtual osg::Object* operator ()(const osg::Object* node) const; private: - // maps new ParticleProcessor to their old ParticleSystem pointer + // maps new pointers to their old pointers // a little messy, but I think this should be the most efficient way mutable std::map mMap; mutable std::map mMap2; + mutable std::map mMap3; }; }