diff --git a/components/nifosg/nifloader.cpp b/components/nifosg/nifloader.cpp index 07eb342221..5c151beca2 100644 --- a/components/nifosg/nifloader.cpp +++ b/components/nifosg/nifloader.cpp @@ -475,10 +475,45 @@ namespace NifOsg lod->setName(niLodNode->mName); lod->setCenterMode(osg::LOD::USER_DEFINED_CENTER); lod->setCenter(niLodNode->mLODCenter); + // NiLODNode only uses the last child with a compatible range, osg::LOD uses all of them + // We must remove overlaps + std::vector> ranges; for (unsigned int i = 0; i < niLodNode->mLODLevels.size(); ++i) { const Nif::NiLODNode::LODRange& range = niLodNode->mLODLevels[i]; - lod->setRange(i, range.mMinRange, range.mMaxRange); + for (auto& rangeVec : ranges) + { + for (auto itr = rangeVec.begin(); itr != rangeVec.end();) + { + if (itr->mMinRange >= range.mMinRange && itr->mMaxRange <= range.mMaxRange) + { + itr = rangeVec.erase(itr); + continue; + } + else if (itr->mMinRange >= range.mMinRange && itr->mMaxRange > range.mMaxRange) + itr->mMinRange = range.mMaxRange; + else if (itr->mMinRange < range.mMinRange && itr->mMaxRange <= range.mMaxRange) + itr->mMaxRange = range.mMinRange; + else if (itr->mMinRange < range.mMinRange && itr->mMaxRange > range.mMaxRange) + { + auto max = itr->mMaxRange; + itr->mMaxRange = range.mMinRange; + itr = rangeVec.emplace(itr + 1, range.mMaxRange, max); + } + ++itr; + } + } + ranges.emplace_back(std::initializer_list{ range }); + } + size_t childIndex = 0; + for (auto rangeVec : ranges) + { + if (rangeVec.empty()) + lod->removeChild(childIndex); + for (size_t i = 1; i < rangeVec.size(); ++i) + lod->insertChild(childIndex + i, lod->getChild(childIndex)); + for (const auto range : rangeVec) + lod->setRange(childIndex++, range.mMinRange, range.mMaxRange); } lod->setRangeMode(osg::LOD::DISTANCE_FROM_EYE_POINT); return lod;