From a939cb669256b49efb3381edfdc9494a283f0b53 Mon Sep 17 00:00:00 2001 From: Andrei Kortunov Date: Sun, 9 May 2021 14:10:35 +0400 Subject: [PATCH 1/2] Skip hidden nodes for ObjectPaging --- apps/openmw/mwrender/objectpaging.cpp | 29 ++++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/apps/openmw/mwrender/objectpaging.cpp b/apps/openmw/mwrender/objectpaging.cpp index 064d3aa35..c36ceefe2 100644 --- a/apps/openmw/mwrender/objectpaging.cpp +++ b/apps/openmw/mwrender/objectpaging.cpp @@ -105,6 +105,7 @@ namespace MWRender bool mOptimizeBillboards = true; float mSqrDistance = 0.f; osg::Vec3f mViewVector; + osg::Node::NodeMask mCopyMask = ~0u; mutable std::vector mNodePath; void copy(const osg::Node* toCopy, osg::Group* attachTo) @@ -121,6 +122,9 @@ namespace MWRender osg::Node* operator() (const osg::Node* node) const override { + if (!(node->getNodeMask() & mCopyMask)) + return nullptr; + if (const osg::Drawable* d = node->asDrawable()) return operator()(d); @@ -224,6 +228,9 @@ namespace MWRender } osg::Drawable* operator() (const osg::Drawable* drawable) const override { + if (!(drawable->getNodeMask() & mCopyMask)) + return nullptr; + if (dynamic_cast(drawable)) return nullptr; @@ -261,9 +268,10 @@ namespace MWRender class AnalyzeVisitor : public osg::NodeVisitor { public: - AnalyzeVisitor() + AnalyzeVisitor(osg::Node::NodeMask analyzeMask) : osg::NodeVisitor(TRAVERSE_ALL_CHILDREN) - , mCurrentStateSet(nullptr) {} + , mCurrentStateSet(nullptr) + , mAnalyzeMask(analyzeMask) {} typedef std::unordered_map StateSetCounter; struct Result @@ -274,12 +282,18 @@ namespace MWRender void apply(osg::Node& node) override { + if (!(node.getNodeMask() & mAnalyzeMask)) + return; + if (node.getStateSet()) mCurrentStateSet = node.getStateSet(); traverse(node); } void apply(osg::Geometry& geom) override { + if (!(geom.getNodeMask() & mAnalyzeMask)) + return; + if (osg::Array* array = geom.getVertexArray()) mResult.mNumVerts += array->getNumElements(); @@ -313,6 +327,7 @@ namespace MWRender Result mResult; osg::StateSet* mCurrentStateSet; StateSetCounter mGlobalStateSetCounter; + osg::Node::NodeMask mAnalyzeMask; }; class DebugVisitor : public osg::NodeVisitor @@ -438,7 +453,14 @@ namespace MWRender typedef std::map, InstanceList> NodeMap; NodeMap nodes; osg::ref_ptr refnumSet = activeGrid ? new RefnumSet : nullptr; - AnalyzeVisitor analyzeVisitor; + + // Mask_UpdateVisitor is used in such cases in NIF loader: + // 1. For collision nodes, which is not supposed to be rendered. + // 2. For nodes masked via Flag_Hidden (VisController can change this flag value at runtime). + // Since ObjectPaging does not handle VisController, we can just ignore both types of nodes. + constexpr auto copyMask = ~Mask_UpdateVisitor; + + AnalyzeVisitor analyzeVisitor(copyMask); float minSize = mMinSize; if (mMinSizeMergeFactor) minSize *= mMinSizeMergeFactor; @@ -525,6 +547,7 @@ namespace MWRender osg::ref_ptr templateRefs = new Resource::TemplateMultiRef; osgUtil::StateToCompile stateToCompile(0, nullptr); CopyOp copyop; + copyop.mCopyMask = copyMask; for (const auto& pair : nodes) { const osg::Node* cnode = pair.first; From 132fedf2909a209afc04281b1a328d279e1ea58b Mon Sep 17 00:00:00 2001 From: Andrei Kortunov Date: Sun, 9 May 2021 15:43:13 +0400 Subject: [PATCH 2/2] Analyze only used LOD levels in ObjectPaging --- apps/openmw/mwrender/objectpaging.cpp | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/apps/openmw/mwrender/objectpaging.cpp b/apps/openmw/mwrender/objectpaging.cpp index c36ceefe2..4217c4714 100644 --- a/apps/openmw/mwrender/objectpaging.cpp +++ b/apps/openmw/mwrender/objectpaging.cpp @@ -271,6 +271,7 @@ namespace MWRender AnalyzeVisitor(osg::Node::NodeMask analyzeMask) : osg::NodeVisitor(TRAVERSE_ALL_CHILDREN) , mCurrentStateSet(nullptr) + , mCurrentDistance(0.f) , mAnalyzeMask(analyzeMask) {} typedef std::unordered_map StateSetCounter; @@ -287,6 +288,22 @@ namespace MWRender if (node.getStateSet()) mCurrentStateSet = node.getStateSet(); + + if (osg::Switch* sw = node.asSwitch()) + { + for (unsigned int i=0; igetNumChildren(); ++i) + if (sw->getValue(i)) + traverse(*sw->getChild(i)); + return; + } + if (osg::LOD* lod = dynamic_cast(&node)) + { + for (unsigned int i=0; igetNumChildren(); ++i) + if (lod->getMinRange(i) * lod->getMinRange(i) <= mCurrentDistance && mCurrentDistance < lod->getMaxRange(i) * lod->getMaxRange(i)) + traverse(*lod->getChild(i)); + return; + } + traverse(node); } void apply(osg::Geometry& geom) override @@ -327,6 +344,7 @@ namespace MWRender Result mResult; osg::StateSet* mCurrentStateSet; StateSetCounter mGlobalStateSetCounter; + float mCurrentDistance; osg::Node::NodeMask mAnalyzeMask; }; @@ -530,6 +548,7 @@ namespace MWRender continue; } + analyzeVisitor.mCurrentDistance = dSqr; auto emplaced = nodes.emplace(cnode, InstanceList()); if (emplaced.second) {