diff --git a/apps/openmw/mwrender/animation.cpp b/apps/openmw/mwrender/animation.cpp index c3ddbf297..c2cbb4627 100644 --- a/apps/openmw/mwrender/animation.cpp +++ b/apps/openmw/mwrender/animation.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include @@ -196,10 +197,18 @@ namespace traverse(node); } +#if OSG_VERSION_GREATER_OR_EQUAL(3,3,3) + virtual void apply(osg::Drawable& drw) + { + mToRemove.push_back(&drw); + } +#endif + void remove() { for (std::vector::iterator it = mToRemove.begin(); it != mToRemove.end(); ++it) { + // FIXME: a Drawable might have more than one parent osg::Node* node = *it; if (node->getNumParents()) node->getParent(0)->removeChild(node); @@ -219,6 +228,18 @@ namespace } virtual void apply(osg::Geode &node) + { + applyImpl(node); + } + +#if OSG_VERSION_GREATER_OR_EQUAL(3,3,3) + virtual void apply(osg::Drawable& drw) + { + applyImpl(drw); + } +#endif + + void applyImpl(osg::Node& node) { const std::string toFind = "tri bip"; if (Misc::StringUtils::ciCompareLen(node.getName(), toFind, toFind.size()) == 0) @@ -232,6 +253,7 @@ namespace { for (std::vector::iterator it = mToRemove.begin(); it != mToRemove.end(); ++it) { + // FIXME: a Drawable might have more than one parent osg::Node* node = *it; if (node->getNumParents()) node->getParent(0)->removeChild(node); diff --git a/apps/openmw/mwrender/objects.cpp b/apps/openmw/mwrender/objects.cpp index bdefdcafa..9f4fe2de2 100644 --- a/apps/openmw/mwrender/objects.cpp +++ b/apps/openmw/mwrender/objects.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include #include @@ -54,11 +55,19 @@ namespace for (std::vector::iterator it = partsysVector.begin(); it != partsysVector.end(); ++it) geode.removeDrawable(*it); } +#if OSG_VERSION_GREATER_OR_EQUAL(3,3,3) + virtual void apply(osg::Drawable& drw) + { + if (osgParticle::ParticleSystem* partsys = dynamic_cast(&drw)) + mToRemove.push_back(partsys); + } +#endif void remove() { for (std::vector >::iterator it = mToRemove.begin(); it != mToRemove.end(); ++it) { + // FIXME: a Drawable might have more than one parent osg::Node* node = *it; if (node->getNumParents()) node->getParent(0)->removeChild(node); diff --git a/apps/openmw/mwrender/sky.cpp b/apps/openmw/mwrender/sky.cpp index 5c38d79d4..7d38308b1 100644 --- a/apps/openmw/mwrender/sky.cpp +++ b/apps/openmw/mwrender/sky.cpp @@ -351,33 +351,36 @@ public: for (unsigned int i=0; iasGeometry(); - if (!geom) - continue; - - osg::ref_ptr colors = new osg::Vec4Array(geom->getVertexArray()->getNumElements()); - for (unsigned int i=0; isize(); ++i) + osg::ref_ptr colors = new osg::Vec4Array(geom->getVertexArray()->getNumElements()); + for (unsigned int i=0; isize(); ++i) + { + float alpha = 1.f; + if (mMeshType == 0) alpha = i%2 ? 0.f : 1.f; // this is a cylinder, so every second vertex belongs to the bottom-most row + else if (mMeshType == 1) { - float alpha = 1.f; - if (mMeshType == 0) alpha = i%2 ? 0.f : 1.f; // this is a cylinder, so every second vertex belongs to the bottom-most row - else if (mMeshType == 1) - { - if (i>= 49 && i <= 64) alpha = 0.f; // bottom-most row - else if (i>= 33 && i <= 48) alpha = 0.25098; // second row - else alpha = 1.f; - } - else if (mMeshType == 2) - { - osg::Vec4Array* origColors = static_cast(geom->getColorArray()); - alpha = ((*origColors)[i].x() == 1.f) ? 1.f : 0.f; - } - - (*colors)[i] = osg::Vec4f(0.f, 0.f, 0.f, alpha); + if (i>= 49 && i <= 64) alpha = 0.f; // bottom-most row + else if (i>= 33 && i <= 48) alpha = 0.25098; // second row + else alpha = 1.f; + } + else if (mMeshType == 2) + { + osg::Vec4Array* origColors = static_cast(geom->getColorArray()); + alpha = ((*origColors)[i].x() == 1.f) ? 1.f : 0.f; } - geom->setColorArray(colors, osg::Array::BIND_PER_VERTEX); + (*colors)[i] = osg::Vec4f(0.f, 0.f, 0.f, alpha); } + + geom->setColorArray(colors, osg::Array::BIND_PER_VERTEX); } private: diff --git a/components/nifosg/nifloader.cpp b/components/nifosg/nifloader.cpp index 49bc7b0fb..b926d7eea 100644 --- a/components/nifosg/nifloader.cpp +++ b/components/nifosg/nifloader.cpp @@ -5,6 +5,7 @@ #include #include #include +#include // resource #include @@ -885,9 +886,6 @@ namespace NifOsg // localToWorldMatrix for transforming to particle space handleParticlePrograms(partctrl->affectors, partctrl->colliders, parentNode, partsys.get(), rf); - osg::ref_ptr geode (new osg::Geode); - geode->addDrawable(partsys); - std::vector drawableProps; collectDrawableProperties(nifNode, drawableProps); applyDrawableProperties(parentNode, drawableProps, composite, true, animflags); @@ -907,13 +905,21 @@ namespace NifOsg updater->addParticleSystem(partsys); parentNode->addChild(updater); +#if not(OSG_MIN_VERSION_REQUIRED(3,3,3)) + osg::ref_ptr geode (new osg::Geode); + geode->addDrawable(partsys); + osg::Node* toAttach = geode.get(); +#else + osg::Node* toAttach = partsys.get(); +#endif + if (rf == osgParticle::ParticleProcessor::RELATIVE_RF) - parentNode->addChild(geode); + parentNode->addChild(toAttach); else { osg::MatrixTransform* trans = new osg::MatrixTransform; trans->setUpdateCallback(new InverseWorldMatrix); - trans->addChild(geode); + trans->addChild(toAttach); parentNode->addChild(trans); } } @@ -957,8 +963,6 @@ namespace NifOsg void handleTriShape(const Nif::NiTriShape* triShape, osg::Group* parentNode, SceneUtil::CompositeStateSetUpdater* composite, const std::vector& boundTextures, int animflags) { - osg::ref_ptr geode (new osg::Geode); - osg::ref_ptr geometry; for (Nif::ControllerPtr ctrl = triShape->controller; !ctrl.empty(); ctrl = ctrl->next) { @@ -981,21 +985,36 @@ namespace NifOsg triShapeToGeometry(triShape, geometry, parentNode, composite, boundTextures, animflags); +#if not(OSG_MIN_VERSION_REQUIRED(3,3,3)) + osg::ref_ptr geode (new osg::Geode); geode->addDrawable(geometry); +#endif if (geometry->getDataVariance() == osg::Object::DYNAMIC) { // Add a copy, we will alternate between the two copies every other frame using the FrameSwitch // This is so we can set the DataVariance as STATIC, giving a huge performance boost geometry->setDataVariance(osg::Object::STATIC); - osg::ref_ptr geode2 = static_cast(osg::clone(geode.get(), osg::CopyOp::DEEP_COPY_NODES|osg::CopyOp::DEEP_COPY_DRAWABLES)); osg::ref_ptr frameswitch = new FrameSwitch; + +#if not(OSG_MIN_VERSION_REQUIRED(3,3,3)) + osg::ref_ptr geode2 = static_cast(osg::clone(geode.get(), osg::CopyOp::DEEP_COPY_NODES|osg::CopyOp::DEEP_COPY_DRAWABLES)); frameswitch->addChild(geode); frameswitch->addChild(geode2); +#else + osg::ref_ptr geom2 = static_cast(osg::clone(geometry.get(), osg::CopyOp::DEEP_COPY_NODES|osg::CopyOp::DEEP_COPY_DRAWABLES)); + frameswitch->addChild(geometry); + frameswitch->addChild(geom2); +#endif + parentNode->addChild(frameswitch); } else +#if not(OSG_MIN_VERSION_REQUIRED(3,3,3)) parentNode->addChild(geode); +#else + parentNode->addChild(geometry); +#endif } osg::ref_ptr handleMorphGeometry(const Nif::NiGeomMorpherController* morpher) @@ -1056,8 +1075,6 @@ namespace NifOsg void handleSkinnedTriShape(const Nif::NiTriShape *triShape, osg::Group *parentNode, SceneUtil::CompositeStateSetUpdater* composite, const std::vector& boundTextures, int animflags) { - osg::ref_ptr geode (new osg::Geode); - osg::ref_ptr geometry (new osg::Geometry); triShapeToGeometry(triShape, geometry, parentNode, composite, boundTextures, animflags); @@ -1090,17 +1107,27 @@ namespace NifOsg } rig->setInfluenceMap(map); - geode->addDrawable(rig); - // Add a copy, we will alternate between the two copies every other frame using the FrameSwitch // This is so we can set the DataVariance as STATIC, giving a huge performance boost rig->setDataVariance(osg::Object::STATIC); + + osg::ref_ptr frameswitch = new FrameSwitch; + +#if not(OSG_MIN_VERSION_REQUIRED(3,3,3)) + osg::ref_ptr geode (new osg::Geode); + geode->addDrawable(rig); + osg::Geode* geode2 = static_cast(osg::clone(geode.get(), osg::CopyOp::DEEP_COPY_NODES| osg::CopyOp::DEEP_COPY_DRAWABLES)); - osg::ref_ptr frameswitch = new FrameSwitch; frameswitch->addChild(geode); frameswitch->addChild(geode2); +#else + SceneUtil::RigGeometry* rig2 = static_cast(osg::clone(rig.get(), osg::CopyOp::DEEP_COPY_NODES| + osg::CopyOp::DEEP_COPY_DRAWABLES)); + frameswitch->addChild(rig); + frameswitch->addChild(rig2); +#endif parentNode->addChild(frameswitch); } diff --git a/components/resource/scenemanager.cpp b/components/resource/scenemanager.cpp index f2840574b..20bee13d1 100644 --- a/components/resource/scenemanager.cpp +++ b/components/resource/scenemanager.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include @@ -32,30 +33,47 @@ namespace { } - void apply(osg::Node& node) + bool isWorldSpaceParticleSystem(osgParticle::ParticleSystem* partsys) { - if (osg::Geode* geode = node.asGeode()) + // HACK: ParticleSystem has no getReferenceFrame() + return (partsys->getUserDataContainer() + && partsys->getUserDataContainer()->getNumDescriptions() > 0 + && partsys->getUserDataContainer()->getDescriptions()[0] == "worldspace"); + } + + void apply(osg::Geode& geode) + { + for (unsigned int i=0;igetNumDrawables();++i) + if (osgParticle::ParticleSystem* partsys = dynamic_cast(geode.getDrawable(i))) { - if (osgParticle::ParticleSystem* partsys = dynamic_cast(geode->getDrawable(i))) + if (isWorldSpaceParticleSystem(partsys)) { - // HACK: ParticleSystem has no getReferenceFrame() - if (partsys->getUserDataContainer() - && partsys->getUserDataContainer()->getNumDescriptions() > 0 - && partsys->getUserDataContainer()->getDescriptions()[0] == "worldspace") - { - // HACK: Ignore the InverseWorldMatrix transform the geode is attached to - if (geode->getNumParents() && geode->getParent(0)->getNumParents()) - transformInitialParticles(partsys, geode->getParent(0)->getParent(0)); - } - geode->setNodeMask(mMask); + // HACK: Ignore the InverseWorldMatrix transform the geode is attached to + if (geode.getNumParents() && geode.getParent(0)->getNumParents()) + transformInitialParticles(partsys, geode.getParent(0)->getParent(0)); } + geode.setNodeMask(mMask); } } + } - traverse(node); +#if OSG_MIN_VERSION_REQUIRED(3,3,3) + // in OSG 3.3 and up Drawables can be directly in the scene graph without a Geode decorating them. + void apply(osg::Drawable& drw) + { + if (osgParticle::ParticleSystem* partsys = dynamic_cast(&drw)) + { + 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->setNodeMask(mMask); + } } +#endif void transformInitialParticles(osgParticle::ParticleSystem* partsys, osg::Node* node) { diff --git a/components/sceneutil/visitor.cpp b/components/sceneutil/visitor.cpp index 3738be08d..0a5ad2d00 100644 --- a/components/sceneutil/visitor.cpp +++ b/components/sceneutil/visitor.cpp @@ -22,11 +22,13 @@ namespace SceneUtil void DisableFreezeOnCullVisitor::apply(osg::Geode &geode) { for (unsigned int i=0; i(drw)) - partsys->setFreezeOnCull(false); - } + apply(*geode.getDrawable(i)); + } + + void DisableFreezeOnCullVisitor::apply(osg::Drawable& drw) + { + if (osgParticle::ParticleSystem* partsys = dynamic_cast(&drw)) + partsys->setFreezeOnCull(false); } } diff --git a/components/sceneutil/visitor.hpp b/components/sceneutil/visitor.hpp index 656084940..dcfefe9cd 100644 --- a/components/sceneutil/visitor.hpp +++ b/components/sceneutil/visitor.hpp @@ -35,6 +35,7 @@ namespace SceneUtil } virtual void apply(osg::Geode &geode); + virtual void apply(osg::Drawable& drw); }; }