Merge branch 'no-lod-overlap' into 'master'
Some checks failed
Build and test / Ubuntu (push) Has been cancelled
Build and test / MacOS (push) Has been cancelled
Build and test / Read .env file and expose it as output (push) Has been cancelled
Build and test / Windows (2019) (push) Has been cancelled
Build and test / Windows (2022) (push) Has been cancelled

Draft: Remove LOD range overlap

Closes #8134

See merge request OpenMW/openmw!4343
This commit is contained in:
AnyOldName3 2025-04-26 13:45:50 +00:00
commit 85f3493c53

View file

@ -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<std::vector<Nif::NiLODNode::LODRange>> 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;