1
0
Fork 1
mirror of https://github.com/TES3MP/openmw-tes3mp.git synced 2025-01-15 16:49:55 +00:00
openmw-tes3mp/components/terrain/viewdata.cpp
bzzt 63ab7345be Reuse traversal result for different traversal with same view point
Rename eyePoint to viewPoint to match OSG conventions (eyePoint is the camera position, viewPoint is for LOD handling)
2019-04-07 11:14:37 +04:00

217 lines
4.3 KiB
C++

#include "viewdata.hpp"
namespace Terrain
{
ViewData::ViewData()
: mNumEntries(0)
, mFrameLastUsed(0)
, mChanged(false)
, mHasViewPoint(false)
{
}
ViewData::~ViewData()
{
}
void ViewData::copyFrom(const ViewData& other)
{
mNumEntries = other.mNumEntries;
mEntries = other.mEntries;
mChanged = other.mChanged;
mHasViewPoint = other.mHasViewPoint;
mViewPoint = other.mViewPoint;
}
void ViewData::add(QuadTreeNode *node, bool visible)
{
unsigned int index = mNumEntries++;
if (index+1 > mEntries.size())
mEntries.resize(index+1);
Entry& entry = mEntries[index];
if (entry.set(node, visible))
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;
}
void ViewData::reset()
{
// clear any unused entries
for (unsigned int i=mNumEntries; i<mEntries.size(); ++i)
mEntries[i].set(nullptr, false);
// reset index for next frame
mNumEntries = 0;
mChanged = false;
}
void ViewData::clear()
{
for (unsigned int i=0; i<mEntries.size(); ++i)
mEntries[i].set(nullptr, false);
mNumEntries = 0;
mFrameLastUsed = 0;
mChanged = false;
mHasViewPoint = false;
}
bool ViewData::contains(QuadTreeNode *node)
{
for (unsigned int i=0; i<mNumEntries; ++i)
if (mEntries[i].mNode == node)
return true;
return false;
}
ViewData::Entry::Entry()
: mNode(nullptr)
, mVisible(true)
, mLodFlags(0)
{
}
bool ViewData::Entry::set(QuadTreeNode *node, bool visible)
{
mVisible = visible;
if (node == mNode)
return false;
else
{
mNode = node;
// clear cached data
mRenderingNode = nullptr;
return true;
}
}
bool suitable(ViewData* vd, const osg::Vec3f& viewPoint, float& maxDist)
{
return vd->hasViewPoint() && (vd->getViewPoint() - viewPoint).length2() < maxDist*maxDist;
}
ViewData *ViewDataMap::getViewData(osg::Object *viewer, const osg::Vec3f& viewPoint, bool& needsUpdate)
{
Map::const_iterator found = mViews.find(viewer);
ViewData* vd = nullptr;
if (found == mViews.end())
{
vd = createOrReuseView();
vd->setViewer(viewer);
mViews[viewer] = vd;
}
else
vd = found->second;
if (!suitable(vd, viewPoint, mReuseDistance))
{
for (Map::const_iterator other = mViews.begin(); other != mViews.end(); ++other)
{
if (suitable(other->second, viewPoint, mReuseDistance) && other->second->getNumEntries())
{
vd->copyFrom(*other->second);
needsUpdate = false;
return vd;
}
}
vd->setViewPoint(viewPoint);
needsUpdate = true;
}
else
needsUpdate = false;
return vd;
}
ViewData *ViewDataMap::createOrReuseView()
{
if (mUnusedViews.size())
{
ViewData* vd = mUnusedViews.front();
mUnusedViews.pop_front();
return vd;
}
else
{
mViewVector.push_back(ViewData());
return &mViewVector.back();
}
}
void ViewDataMap::clearUnusedViews(unsigned int frame)
{
for (Map::iterator it = mViews.begin(); it != mViews.end(); )
{
ViewData* vd = it->second;
if (vd->getFrameLastUsed() + 2 < frame)
{
vd->clear();
mUnusedViews.push_back(vd);
mViews.erase(it++);
}
else
++it;
}
}
void ViewDataMap::clear()
{
mViews.clear();
mUnusedViews.clear();
mViewVector.clear();
}
void ViewDataMap::setDefaultViewer(osg::Object *viewer)
{
mDefaultViewer = viewer;
}
bool ViewDataMap::getDefaultViewPoint(osg::Vec3f& viewPoint)
{
Map::const_iterator found = mViews.find(mDefaultViewer);
if (found != mViews.end() && found->second->hasViewPoint())
{
viewPoint = found->second->getViewPoint();
return true;
}
else
return false;
}
}