Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fixes getViewDistance #3207

Merged
merged 10 commits into from
Oct 31, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 25 additions & 11 deletions components/terrain/quadtreeworld.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,7 @@ QuadTreeWorld::QuadTreeWorld(osg::Group *parent, osg::Group *compileRoot, Resour
, mViewDistance(std::numeric_limits<float>::max())
, mMinSize(1/8.f)
, mDebugTerrainChunks(debugChunks)
, mRevalidateDistance(0.f)
{
mChunkManager->setCompositeMapSize(compMapResolution);
mChunkManager->setCompositeMapLevel(compMapLevel);
Expand Down Expand Up @@ -346,22 +347,25 @@ unsigned int getLodFlags(QuadTreeNode* node, int ourLod, int vertexLodMod, const
return lodFlags;
}

void loadRenderingNode(ViewData::Entry& entry, ViewData* vd, int vertexLodMod, float cellWorldSize, const osg::Vec4i &gridbounds, const std::vector<QuadTreeWorld::ChunkManager*>& chunkManagers, bool compile, float reuseDistance)
void QuadTreeWorld::loadRenderingNode(ViewDataEntry& entry, ViewData* vd, float cellWorldSize, const osg::Vec4i &gridbounds, bool compile, float reuseDistance)
{
if (!vd->hasChanged() && entry.mRenderingNode)
return;

int ourLod = getVertexLod(entry.mNode, vertexLodMod);
int ourLod = getVertexLod(entry.mNode, mVertexLodMod);

if (vd->hasChanged())
{
// have to recompute the lodFlags in case a neighbour has changed LOD.
unsigned int lodFlags = getLodFlags(entry.mNode, ourLod, vertexLodMod, vd);
unsigned int lodFlags = getLodFlags(entry.mNode, ourLod, mVertexLodMod, vd);
if (lodFlags != entry.mLodFlags)
{
entry.mRenderingNode = nullptr;
entry.mLodFlags = lodFlags;
}
// have to revalidate chunks within a custom view distance.
if (mRevalidateDistance && entry.mNode->distance(vd->getViewPoint()) <= mRevalidateDistance + reuseDistance)
entry.mRenderingNode = nullptr;
}

if (!entry.mRenderingNode)
Expand All @@ -372,9 +376,9 @@ void loadRenderingNode(ViewData::Entry& entry, ViewData* vd, int vertexLodMod, f
const osg::Vec2f& center = entry.mNode->getCenter();
bool activeGrid = (center.x() > gridbounds.x() && center.y() > gridbounds.y() && center.x() < gridbounds.z() && center.y() < gridbounds.w());

for (QuadTreeWorld::ChunkManager* m : chunkManagers)
for (QuadTreeWorld::ChunkManager* m : mChunkManagers)
{
if (m->getViewDistance() && entry.mNode->distance(vd->getViewPoint()) > m->getViewDistance() + reuseDistance)
if (mRevalidateDistance && m->getViewDistance() && entry.mNode->distance(vd->getViewPoint()) > m->getViewDistance() + reuseDistance)
continue;
osg::ref_ptr<osg::Node> n = m->getChunk(entry.mNode->getSize(), entry.mNode->getCenter(), ourLod, entry.mLodFlags, activeGrid, vd->getViewPoint(), compile);
if (n) pat->addChild(n);
Expand All @@ -398,7 +402,7 @@ void updateWaterCullingView(HeightCullCallback* callback, ViewData* vd, osgUtil:
static bool debug = getenv("OPENMW_WATER_CULLING_DEBUG") != nullptr;
for (unsigned int i=0; i<vd->getNumEntries(); ++i)
{
ViewData::Entry& entry = vd->getEntry(i);
ViewDataEntry& entry = vd->getEntry(i);
osg::BoundingBox bb = static_cast<TerrainDrawable*>(entry.mRenderingNode->asGroup()->getChild(0))->getWaterBoundingBox();
if (!bb.valid())
continue;
Expand Down Expand Up @@ -457,15 +461,15 @@ void QuadTreeWorld::accept(osg::NodeVisitor &nv)

for (unsigned int i=0; i<vd->getNumEntries(); ++i)
{
ViewData::Entry& entry = vd->getEntry(i);
loadRenderingNode(entry, vd, mVertexLodMod, cellWorldSize, mActiveGrid, mChunkManagers, false, mViewDataMap->getReuseDistance());
ViewDataEntry& entry = vd->getEntry(i);
loadRenderingNode(entry, vd, cellWorldSize, mActiveGrid, false, mViewDataMap->getReuseDistance());
entry.mRenderingNode->accept(nv);
}

if (mHeightCullCallback && isCullVisitor)
updateWaterCullingView(mHeightCullCallback, vd, static_cast<osgUtil::CullVisitor*>(&nv), mStorage->getCellWorldSize(), !isGridEmpty());

vd->markUnchanged();
vd->setChanged(false);

double referenceTime = nv.getFrameStamp() ? nv.getFrameStamp()->getReferenceTime() : 0.0;
if (referenceTime != 0.0)
Expand Down Expand Up @@ -540,9 +544,9 @@ void QuadTreeWorld::preload(View *view, const osg::Vec3f &viewPoint, const osg::
const float reuseDistance = std::max(mViewDataMap->getReuseDistance(), std::abs(distanceModifier));
for (unsigned int i=startEntry; i<vd->getNumEntries() && !abort; ++i)
{
ViewData::Entry& entry = vd->getEntry(i);
ViewDataEntry& entry = vd->getEntry(i);

loadRenderingNode(entry, vd, mVertexLodMod, cellWorldSize, grid, mChunkManagers, true, reuseDistance);
loadRenderingNode(entry, vd, cellWorldSize, grid, true, reuseDistance);
if (pass==0) reporter.addProgress(entry.mNode->getSize());
entry.mNode = nullptr; // Clear node lest we break the neighbours search for the next pass
}
Expand Down Expand Up @@ -579,11 +583,21 @@ void QuadTreeWorld::addChunkManager(QuadTreeWorld::ChunkManager* m)
{
mChunkManagers.push_back(m);
mTerrainRoot->setNodeMask(mTerrainRoot->getNodeMask()|m->getNodeMask());
if (m->getViewDistance())
mRevalidateDistance = std::max(m->getViewDistance(), mRevalidateDistance);
}

void QuadTreeWorld::rebuildViews()
{
mViewDataMap->rebuildViews();
}

void QuadTreeWorld::setViewDistance(float viewDistance)
{
if (mViewDistance == viewDistance)
return;
mViewDistance = viewDistance;
mViewDataMap->rebuildViews();
}

}
7 changes: 6 additions & 1 deletion components/terrain/quadtreeworld.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ namespace Terrain
{
class RootNode;
class ViewDataMap;
class ViewData;
struct ViewDataEntry;

class DebugChunkManager;

/// @brief Terrain implementation that loads cells into a Quad Tree, with geometry LOD and texture LOD.
Expand All @@ -30,7 +33,7 @@ namespace Terrain

void enable(bool enabled) override;

void setViewDistance(float distance) override { mViewDistance = distance; }
void setViewDistance(float distance) override;

void cacheCell(View *view, int x, int y) override {}
/// @note Not thread safe.
Expand Down Expand Up @@ -60,6 +63,7 @@ namespace Terrain

private:
void ensureQuadTreeBuilt();
void loadRenderingNode(ViewDataEntry& entry, ViewData* vd, float cellWorldSize, const osg::Vec4i &gridbounds, bool compile, float reuseDistance);

osg::ref_ptr<RootNode> mRootNode;

Expand All @@ -75,6 +79,7 @@ namespace Terrain
float mMinSize;
bool mDebugTerrainChunks;
std::unique_ptr<DebugChunkManager> mDebugChunkManager;
float mRevalidateDistance;
};

}
Expand Down
35 changes: 4 additions & 31 deletions components/terrain/viewdata.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,10 @@ ViewData::ViewData()
, mHasViewPoint(false)
, mWorldUpdateRevision(0)
{

}

ViewData::~ViewData()
{

}

void ViewData::copyFrom(const ViewData& other)
Expand All @@ -38,42 +36,17 @@ void ViewData::add(QuadTreeNode *node)
if (index+1 > mEntries.size())
mEntries.resize(index+1);

Entry& entry = mEntries[index];
ViewDataEntry& entry = mEntries[index];
if (entry.set(node))
mChanged = true;
}

unsigned int ViewData::getNumEntries() const
{
return mNumEntries;
}

ViewData::Entry &ViewData::getEntry(unsigned int i)
{
return mEntries[i];
}

bool ViewData::hasChanged() const
{
return mChanged;
}

bool ViewData::hasViewPoint() const
{
return mHasViewPoint;
}

void ViewData::setViewPoint(const osg::Vec3f &viewPoint)
{
mViewPoint = viewPoint;
mHasViewPoint = true;
}

const osg::Vec3f& ViewData::getViewPoint() const
{
return mViewPoint;
}

// NOTE: As a performance optimisation, we cache mRenderingNodes from previous frames here.
// If this cache becomes invalid (e.g. through mWorldUpdateRevision), we need to use clear() instead of reset().
void ViewData::reset()
Expand Down Expand Up @@ -110,14 +83,13 @@ bool ViewData::contains(QuadTreeNode *node) const
return false;
}

ViewData::Entry::Entry()
ViewDataEntry::ViewDataEntry()
: mNode(nullptr)
, mLodFlags(0)
{

}

bool ViewData::Entry::set(QuadTreeNode *node)
bool ViewDataEntry::set(QuadTreeNode *node)
{
if (node == mNode)
return false;
Expand Down Expand Up @@ -173,6 +145,7 @@ ViewData *ViewDataMap::getViewData(osg::Object *viewer, const osg::Vec3f& viewPo
}
vd->setViewPoint(viewPoint);
vd->setActiveGrid(activeGrid);
vd->setChanged(true);
needsUpdate = true;
}
}
Expand Down
43 changes: 22 additions & 21 deletions components/terrain/viewdata.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,18 @@ namespace Terrain

class QuadTreeNode;

struct ViewDataEntry
{
ViewDataEntry();

bool set(QuadTreeNode* node);

QuadTreeNode* mNode;

unsigned int mLodFlags;
osg::ref_ptr<osg::Node> mRenderingNode;
};

class ViewData : public View
{
public:
Expand All @@ -31,33 +43,22 @@ namespace Terrain

void copyFrom(const ViewData& other);

struct Entry
{
Entry();

bool set(QuadTreeNode* node);

QuadTreeNode* mNode;

unsigned int mLodFlags;
osg::ref_ptr<osg::Node> mRenderingNode;
};

unsigned int getNumEntries() const;

Entry& getEntry(unsigned int i);
unsigned int getNumEntries() const { return mNumEntries; }
ViewDataEntry& getEntry(unsigned int i) { return mEntries[i]; }

double getLastUsageTimeStamp() const { return mLastUsageTimeStamp; }
void setLastUsageTimeStamp(double timeStamp) { mLastUsageTimeStamp = timeStamp; }

/// @return Have any nodes changed since the last frame
bool hasChanged() const;
void markUnchanged() { mChanged = false; }
/// Indicates at least one mNode of mEntries has changed or the view point has moved beyond mReuseDistance.
/// @note Such changes may necessitate a revalidation of cached mRenderingNodes elsewhere depending
/// on the parameters that affect the creation of mRenderingNode.
bool hasChanged() const { return mChanged; }
void setChanged(bool changed) { mChanged = changed; }

bool hasViewPoint() const;
bool hasViewPoint() const { return mHasViewPoint; }

void setViewPoint(const osg::Vec3f& viewPoint);
const osg::Vec3f& getViewPoint() const;
const osg::Vec3f& getViewPoint() const { return mViewPoint; }

void setActiveGrid(const osg::Vec4i &grid) { if (grid != mActiveGrid) {mActiveGrid = grid;mEntries.clear();mNumEntries=0;} }
const osg::Vec4i &getActiveGrid() const { return mActiveGrid;}
Expand All @@ -66,7 +67,7 @@ namespace Terrain
void setWorldUpdateRevision(int updateRevision) { mWorldUpdateRevision = updateRevision; }

private:
std::vector<Entry> mEntries;
std::vector<ViewDataEntry> mEntries;
unsigned int mNumEntries;
double mLastUsageTimeStamp;
bool mChanged;
Expand Down