1
0
Fork 0
mirror of https://github.com/OpenMW/openmw.git synced 2025-06-26 12:41:34 +00:00

Creanup Distant Terrain code

- Cull terrain in the stock osg::CullVisitor
- Do not compile composite maps for shadow camera
- Do not abuse userdata for composite maps
This commit is contained in:
bzzt 2019-02-20 13:37:00 +00:00 committed by Andrei Kortunov
parent e4ba6ecf15
commit a730365ea1
8 changed files with 39 additions and 63 deletions

View file

@ -30,7 +30,6 @@ ChunkManager::ChunkManager(Storage *storage, Resource::SceneManager *sceneMgr, T
, mCompositeMapSize(512) , mCompositeMapSize(512)
, mCompositeMapLevel(1.f) , mCompositeMapLevel(1.f)
, mMaxCompGeometrySize(1.f) , mMaxCompGeometrySize(1.f)
, mCullingActive(true)
{ {
} }
@ -208,7 +207,8 @@ osg::ref_ptr<osg::Node> ChunkManager::createChunk(float chunkSize, const osg::Ve
mCompositeMapRenderer->addCompositeMap(compositeMap.get(), false); mCompositeMapRenderer->addCompositeMap(compositeMap.get(), false);
transform->getOrCreateUserDataContainer()->setUserData(compositeMap); geometry->setCompositeMap(compositeMap);
geometry->setCompositeMapRenderer(mCompositeMapRenderer);
TextureLayer layer; TextureLayer layer;
layer.mDiffuseMap = compositeMap->mTexture; layer.mDiffuseMap = compositeMap->mTexture;
@ -222,14 +222,7 @@ osg::ref_ptr<osg::Node> ChunkManager::createChunk(float chunkSize, const osg::Ve
} }
transform->addChild(geometry); transform->addChild(geometry);
transform->getBound();
if (!mCullingActive)
{
transform->setCullingActive(false);
geometry->setCullingActive(false);
}
else
transform->getBound();
if (mSceneManager->getIncrementalCompileOperation()) if (mSceneManager->getIncrementalCompileOperation())
{ {

View file

@ -120,7 +120,7 @@ void QuadTreeNode::traverse(ViewData* vd, const osg::Vec3f& viewPoint, LodCallba
bool stopTraversal = (lodCallback->isSufficientDetail(this, dist)) || !getNumChildren(); bool stopTraversal = (lodCallback->isSufficientDetail(this, dist)) || !getNumChildren();
if (stopTraversal) if (stopTraversal)
vd->add(this, true); vd->add(this);
else else
{ {
for (unsigned int i=0; i<getNumChildren(); ++i) for (unsigned int i=0; i<getNumChildren(); ++i)
@ -142,7 +142,7 @@ void QuadTreeNode::traverseTo(ViewData* vd, float size, const osg::Vec2f& center
bool stopTraversal = (getSize() == size); bool stopTraversal = (getSize() == size);
if (stopTraversal) if (stopTraversal)
vd->add(this, true); vd->add(this);
else else
{ {
for (unsigned int i=0; i<getNumChildren(); ++i) for (unsigned int i=0; i<getNumChildren(); ++i)
@ -159,7 +159,7 @@ void QuadTreeNode::intersect(ViewData* vd, TerrainLineIntersector* intersector)
return; return;
if (getNumChildren() == 0) if (getNumChildren() == 0)
vd->add(this, true); vd->add(this);
else else
{ {
for (unsigned int i=0; i<getNumChildren(); ++i) for (unsigned int i=0; i<getNumChildren(); ++i)

View file

@ -186,7 +186,7 @@ public:
if (node->getSize() <= mMinSize) if (node->getSize() <= mMinSize)
{ {
// We arrived at a leaf. // We arrived at a leaf.
// Since the tree is used for LOD level selection instead of culling, we do not need to load an actual height data here. // Since the tree is used for LOD level selection instead of culling, we do not need to load the actual height data here.
float minZ = -std::numeric_limits<float>::max(); float minZ = -std::numeric_limits<float>::max();
float maxZ = std::numeric_limits<float>::max(); float maxZ = std::numeric_limits<float>::max();
float cellWorldSize = mStorage->getCellWorldSize(); float cellWorldSize = mStorage->getCellWorldSize();
@ -226,9 +226,6 @@ QuadTreeWorld::QuadTreeWorld(osg::Group *parent, osg::Group *compileRoot, Resour
, mVertexLodMod(vertexLodMod) , mVertexLodMod(vertexLodMod)
, mViewDistance(std::numeric_limits<float>::max()) , 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);
mChunkManager->setCompositeMapSize(compMapResolution); mChunkManager->setCompositeMapSize(compMapResolution);
mChunkManager->setCompositeMapLevel(compMapLevel); mChunkManager->setCompositeMapLevel(compMapLevel);
mChunkManager->setMaxCompositeGeometrySize(maxCompGeometrySize); mChunkManager->setMaxCompositeGeometrySize(maxCompGeometrySize);
@ -362,44 +359,25 @@ void QuadTreeWorld::accept(osg::NodeVisitor &nv)
else else
{ {
osgUtil::IntersectionVisitor* iv = static_cast<osgUtil::IntersectionVisitor*>(&nv); osgUtil::IntersectionVisitor* iv = static_cast<osgUtil::IntersectionVisitor*>(&nv);
osgUtil::LineSegmentIntersector* lineIntsersector = dynamic_cast<osgUtil::LineSegmentIntersector*>(iv->getIntersector()); osgUtil::LineSegmentIntersector* lineIntersector = dynamic_cast<osgUtil::LineSegmentIntersector*>(iv->getIntersector());
if (!lineIntsersector) if (!lineIntersector)
throw std::runtime_error("Can not update QuadTreeWorld - the LineSegmentIntersector expected"); throw std::runtime_error("Cannot update QuadTreeWorld: node visitor is not LineSegmentIntersector");
osg::Matrix matrix = osg::Matrix::identity(); osg::Matrix matrix = osg::Matrix::identity();
if (lineIntsersector->getCoordinateFrame() == osgUtil::Intersector::CoordinateFrame::MODEL && iv->getModelMatrix() == 0) if (lineIntersector->getCoordinateFrame() == osgUtil::Intersector::CoordinateFrame::MODEL && iv->getModelMatrix() == 0)
matrix = lineIntsersector->getTransformation(*iv, osgUtil::Intersector::CoordinateFrame::MODEL); matrix = lineIntersector->getTransformation(*iv, osgUtil::Intersector::CoordinateFrame::MODEL);
osg::ref_ptr<TerrainLineIntersector> terrainIntersector (new TerrainLineIntersector(lineIntsersector, matrix)); osg::ref_ptr<TerrainLineIntersector> terrainIntersector (new TerrainLineIntersector(lineIntersector, matrix));
mRootNode->intersect(vd, terrainIntersector); mRootNode->intersect(vd, terrainIntersector);
} }
} }
if (isCullVisitor)
{
for (unsigned int i=0; i<vd->getNumEntries(); ++i)
{
ViewData::Entry& entry = vd->getEntry(i);
entry.set(entry.mNode, !static_cast<osgUtil::CullVisitor*>(&nv)->isCulled(entry.mNode->getBoundingBox()));
}
}
for (unsigned int i=0; i<vd->getNumEntries(); ++i) for (unsigned int i=0; i<vd->getNumEntries(); ++i)
{ {
ViewData::Entry& entry = vd->getEntry(i); ViewData::Entry& entry = vd->getEntry(i);
loadRenderingNode(entry, vd, mVertexLodMod, mChunkManager.get()); loadRenderingNode(entry, vd, mVertexLodMod, mChunkManager.get());
if (entry.mVisible) entry.mRenderingNode->accept(nv);
{
osg::UserDataContainer* udc = entry.mRenderingNode->getUserDataContainer();
if (udc && udc->getUserData())
{
mCompositeMapRenderer->setImmediate(static_cast<CompositeMap*>(udc->getUserData()));
udc->setUserData(nullptr);
}
entry.mRenderingNode->accept(nv);
}
} }
if (!isCullVisitor) if (!isCullVisitor)

View file

@ -4,13 +4,11 @@
#include <components/sceneutil/lightmanager.hpp> #include <components/sceneutil/lightmanager.hpp>
#include "compositemaprenderer.hpp"
namespace Terrain namespace Terrain
{ {
TerrainDrawable::TerrainDrawable()
{
}
TerrainDrawable::TerrainDrawable(const TerrainDrawable &copy, const osg::CopyOp &copyop) TerrainDrawable::TerrainDrawable(const TerrainDrawable &copy, const osg::CopyOp &copyop)
: osg::Geometry(copy, copyop) : osg::Geometry(copy, copyop)
, mPasses(copy.mPasses) , mPasses(copy.mPasses)
@ -63,6 +61,12 @@ void TerrainDrawable::cull(osgUtil::CullVisitor *cv)
return; return;
} }
if (mCompositeMap)
{
mCompositeMapRenderer->setImmediate(mCompositeMap);
mCompositeMap = nullptr;
}
bool pushedLight = mLightListCallback && mLightListCallback->pushLightState(this, cv); bool pushedLight = mLightListCallback && mLightListCallback->pushLightState(this, cv);
for (PassVector::const_iterator it = mPasses.begin(); it != mPasses.end(); ++it) for (PassVector::const_iterator it = mPasses.begin(); it != mPasses.end(); ++it)

View file

@ -16,6 +16,9 @@ namespace SceneUtil
namespace Terrain namespace Terrain
{ {
class CompositeMap;
class CompositeMapRenderer;
/** /**
* Subclass of Geometry that supports built in multi-pass rendering and built in LightListCallback. * Subclass of Geometry that supports built in multi-pass rendering and built in LightListCallback.
*/ */
@ -28,7 +31,8 @@ namespace Terrain
virtual const char* className() const { return "TerrainDrawable"; } virtual const char* className() const { return "TerrainDrawable"; }
virtual const char* libraryName() const { return "Terrain"; } virtual const char* libraryName() const { return "Terrain"; }
TerrainDrawable(); TerrainDrawable() = default;
~TerrainDrawable() = default;
TerrainDrawable(const TerrainDrawable& copy, const osg::CopyOp& copyop); TerrainDrawable(const TerrainDrawable& copy, const osg::CopyOp& copyop);
virtual void accept(osg::NodeVisitor &nv); virtual void accept(osg::NodeVisitor &nv);
@ -41,10 +45,15 @@ namespace Terrain
virtual void compileGLObjects(osg::RenderInfo& renderInfo) const; virtual void compileGLObjects(osg::RenderInfo& renderInfo) const;
void setCompositeMap(CompositeMap* map) { mCompositeMap = map; }
void setCompositeMapRenderer(CompositeMapRenderer* renderer) { mCompositeMapRenderer = renderer; }
private: private:
PassVector mPasses; PassVector mPasses;
osg::ref_ptr<SceneUtil::LightListCallback> mLightListCallback; osg::ref_ptr<SceneUtil::LightListCallback> mLightListCallback;
osg::ref_ptr<CompositeMap> mCompositeMap;
osg::ref_ptr<CompositeMapRenderer> mCompositeMapRenderer;
}; };
} }

View file

@ -61,11 +61,6 @@ osg::ref_ptr<osg::Node> TerrainGrid::buildTerrain (osg::Group* parent, float chu
return nullptr; return nullptr;
if (parent) if (parent)
parent->addChild(node); parent->addChild(node);
osg::UserDataContainer* udc = node->getUserDataContainer();
if (udc && udc->getUserData())
mCompositeMapRenderer->setImmediate(static_cast<CompositeMap*>(udc->getUserData()));
return node; return node;
} }
} }

View file

@ -26,7 +26,7 @@ void ViewData::copyFrom(const ViewData& other)
mViewPoint = other.mViewPoint; mViewPoint = other.mViewPoint;
} }
void ViewData::add(QuadTreeNode *node, bool visible) void ViewData::add(QuadTreeNode *node)
{ {
unsigned int index = mNumEntries++; unsigned int index = mNumEntries++;
@ -34,7 +34,7 @@ void ViewData::add(QuadTreeNode *node, bool visible)
mEntries.resize(index+1); mEntries.resize(index+1);
Entry& entry = mEntries[index]; Entry& entry = mEntries[index];
if (entry.set(node, visible)) if (entry.set(node))
mChanged = true; mChanged = true;
} }
@ -73,7 +73,7 @@ void ViewData::reset()
{ {
// clear any unused entries // clear any unused entries
for (unsigned int i=mNumEntries; i<mEntries.size(); ++i) for (unsigned int i=mNumEntries; i<mEntries.size(); ++i)
mEntries[i].set(nullptr, false); mEntries[i].set(nullptr);
// reset index for next frame // reset index for next frame
mNumEntries = 0; mNumEntries = 0;
@ -83,7 +83,7 @@ void ViewData::reset()
void ViewData::clear() void ViewData::clear()
{ {
for (unsigned int i=0; i<mEntries.size(); ++i) for (unsigned int i=0; i<mEntries.size(); ++i)
mEntries[i].set(nullptr, false); mEntries[i].set(nullptr);
mNumEntries = 0; mNumEntries = 0;
mLastUsageTimeStamp = 0; mLastUsageTimeStamp = 0;
mChanged = false; mChanged = false;
@ -100,15 +100,13 @@ bool ViewData::contains(QuadTreeNode *node)
ViewData::Entry::Entry() ViewData::Entry::Entry()
: mNode(nullptr) : mNode(nullptr)
, mVisible(true)
, mLodFlags(0) , mLodFlags(0)
{ {
} }
bool ViewData::Entry::set(QuadTreeNode *node, bool visible) bool ViewData::Entry::set(QuadTreeNode *node)
{ {
mVisible = visible;
if (node == mNode) if (node == mNode)
return false; return false;
else else

View file

@ -19,7 +19,7 @@ namespace Terrain
ViewData(); ViewData();
~ViewData(); ~ViewData();
void add(QuadTreeNode* node, bool visible); void add(QuadTreeNode* node);
void reset(); void reset();
@ -33,10 +33,9 @@ namespace Terrain
{ {
Entry(); Entry();
bool set(QuadTreeNode* node, bool visible); bool set(QuadTreeNode* node);
QuadTreeNode* mNode; QuadTreeNode* mNode;
bool mVisible;
unsigned int mLodFlags; unsigned int mLodFlags;
osg::ref_ptr<osg::Node> mRenderingNode; osg::ref_ptr<osg::Node> mRenderingNode;