Do not load terrain beyond the viewing distance

pull/541/head
bzzt 6 years ago committed by Andrei Kortunov
parent a6fd077537
commit e0cf460ba3

@ -1198,6 +1198,10 @@ namespace MWRender
mUniformNear->set(mNearClip);
mUniformFar->set(mViewDistance);
// Since our fog is not radial yet, we should take FOV in account, otherwise terrain near viewing distance may disappear.
float distanceMult = std::cos(osg::DegreesToRadians(mFieldOfView)/2.f);
mTerrain->setViewDistance(mViewDistance * (distanceMult ? 1.f/distanceMult : 1.f));
}
void RenderingManager::updateTextureFiltering()

@ -76,6 +76,30 @@ QuadTreeNode *QuadTreeNode::getNeighbour(Direction dir)
return mNeighbours[dir];
}
float QuadTreeNode::distance(const osg::Vec3f& v) const
{
const osg::BoundingBox& box = getBoundingBox();
if (box.contains(v))
return 0;
else
{
osg::Vec3f maxDist(0,0,0);
if (v.x() < box.xMin())
maxDist.x() = box.xMin() - v.x();
else if (v.x() > box.xMax())
maxDist.x() = v.x() - box.xMax();
if (v.y() < box.yMin())
maxDist.y() = box.yMin() - v.y();
else if (v.y() > box.yMax())
maxDist.y() = v.y() - box.yMax();
if (v.z() < box.zMin())
maxDist.z() = box.zMin() - v.z();
else if (v.z() > box.zMax())
maxDist.z() = v.z() - box.zMax();
return maxDist.length();
}
}
void QuadTreeNode::initNeighbours()
{
for (int i=0; i<4; ++i)
@ -92,7 +116,7 @@ void QuadTreeNode::traverse(osg::NodeVisitor &nv)
ViewData* vd = getView(nv);
if ((mLodCallback && mLodCallback->isSufficientDetail(this, vd->getEyePoint())) || !getNumChildren())
if ((mLodCallback && mLodCallback->isSufficientDetail(this, distance(vd->getEyePoint()))) || !getNumChildren())
vd->add(this, true);
else
osg::Group::traverse(nv);

@ -23,7 +23,7 @@ namespace Terrain
public:
virtual ~LodCallback() {}
virtual bool isSufficientDetail(QuadTreeNode *node, const osg::Vec3f& eyePoint) = 0;
virtual bool isSufficientDetail(QuadTreeNode *node, float dist) = 0;
};
class ViewDataMap;
@ -49,6 +49,8 @@ namespace Terrain
child->addParent(this);
};
float distance(const osg::Vec3f& v) const;
/// Returns our direction relative to the parent node, or Root if we are the root node.
ChildDirection getDirection() { return mDirection; }

@ -40,33 +40,6 @@ namespace
return targetlevel;
}
float distanceToBox(const osg::BoundingBox& box, const osg::Vec3f& v)
{
if (box.contains(v))
return 0;
else
{
osg::Vec3f maxDist(0,0,0);
if (v.x() < box.xMin())
maxDist.x() = box.xMin() - v.x();
else if (v.x() > box.xMax())
maxDist.x() = v.x() - box.xMax();
if (v.y() < box.yMin())
maxDist.y() = box.yMin() - v.y();
else if (v.y() > box.yMax())
maxDist.y() = v.y() - box.yMax();
if (v.z() < box.zMin())
maxDist.z() = box.zMin() - v.z();
else if (v.z() > box.zMax())
maxDist.z() = v.z() - box.zMax();
return maxDist.length();
}
}
}
namespace Terrain
@ -81,9 +54,8 @@ public:
{
}
virtual bool isSufficientDetail(QuadTreeNode* node, const osg::Vec3f& eyePoint)
virtual bool isSufficientDetail(QuadTreeNode* node, float dist)
{
float dist = distanceToBox(node->getBoundingBox(), eyePoint);
int nativeLodLevel = Log2(static_cast<unsigned int>(node->getSize()/mMinSize));
int lodLevel = Log2(static_cast<unsigned int>(dist/(Constants::CellSizeInUnits*mMinSize*mFactor)));
@ -254,6 +226,7 @@ QuadTreeWorld::QuadTreeWorld(osg::Group *parent, osg::Group *compileRoot, Resour
, mQuadTreeBuilt(false)
, mLodFactor(lodFactor)
, mVertexLodMod(vertexLodMod)
, mViewDistance(std::numeric_limits<float>::max())
{
// No need for culling on the Drawable / Transform level as the quad tree performs the culling already.
mChunkManager->setCullingActive(false);
@ -269,7 +242,7 @@ QuadTreeWorld::~QuadTreeWorld()
}
void traverse(QuadTreeNode* node, ViewData* vd, osg::NodeVisitor* nv, LodCallback* lodCallback, const osg::Vec3f& eyePoint, bool visible)
void traverse(QuadTreeNode* node, ViewData* vd, osg::NodeVisitor* nv, LodCallback* lodCallback, const osg::Vec3f& eyePoint, bool visible, float maxDist)
{
if (!node->hasValidBounds())
return;
@ -277,14 +250,18 @@ void traverse(QuadTreeNode* node, ViewData* vd, osg::NodeVisitor* nv, LodCallbac
if (nv && nv->getVisitorType() == osg::NodeVisitor::CULL_VISITOR)
visible = visible && !static_cast<osgUtil::CullVisitor*>(nv)->isCulled(node->getBoundingBox());
bool stopTraversal = (lodCallback && lodCallback->isSufficientDetail(node, eyePoint)) || !node->getNumChildren();
float dist = node->distance(eyePoint);
if (dist > maxDist)
return;
bool stopTraversal = (lodCallback && lodCallback->isSufficientDetail(node, dist)) || !node->getNumChildren();
if (stopTraversal)
vd->add(node, visible);
else
{
for (unsigned int i=0; i<node->getNumChildren(); ++i)
traverse(node->getChild(i), vd, nv, lodCallback, eyePoint, visible);
traverse(node->getChild(i), vd, nv, lodCallback, eyePoint, visible, maxDist);
}
}
@ -416,7 +393,7 @@ void QuadTreeWorld::accept(osg::NodeVisitor &nv)
traverseToCell(mRootNode.get(), vd, x,y);
}
else
traverse(mRootNode.get(), vd, cv, mRootNode->getLodCallback(), cv->getViewPoint(), true);
traverse(mRootNode.get(), vd, cv, mRootNode->getLodCallback(), cv->getViewPoint(), true, mViewDistance);
}
else
mRootNode->traverse(nv);
@ -496,7 +473,7 @@ void QuadTreeWorld::preload(View *view, const osg::Vec3f &eyePoint)
ensureQuadTreeBuilt();
ViewData* vd = static_cast<ViewData*>(view);
traverse(mRootNode.get(), vd, nullptr, mRootNode->getLodCallback(), eyePoint, false);
traverse(mRootNode.get(), vd, nullptr, mRootNode->getLodCallback(), eyePoint, false, mViewDistance);
for (unsigned int i=0; i<vd->getNumEntries(); ++i)
{

@ -28,6 +28,8 @@ namespace Terrain
virtual void enable(bool enabled);
virtual void setViewDistance(float distance) { mViewDistance = distance; }
void cacheCell(View *view, int x, int y);
/// @note Not thread safe.
virtual void loadCell(int x, int y);
@ -52,6 +54,7 @@ namespace Terrain
bool mQuadTreeBuilt;
float mLodFactor;
int mVertexLodMod;
float mViewDistance;
};
}

@ -100,6 +100,8 @@ namespace Terrain
/// Set the default viewer (usually a Camera), used as viewpoint for any viewers that don't use their own viewpoint.
virtual void setDefaultViewer(osg::Object* obj) {}
virtual void setViewDistance(float distance) {}
Storage* getStorage() { return mStorage; }
protected:

Loading…
Cancel
Save