Add view data structure for efficient collection of LOD nodes to use for a given camera/intersection
parent
0efc54c749
commit
e36bdb490e
@ -0,0 +1,132 @@
|
||||
#include "viewdata.hpp"
|
||||
|
||||
namespace Terrain
|
||||
{
|
||||
|
||||
ViewData::ViewData()
|
||||
: mNumEntries(0)
|
||||
, mFrameLastUsed(0)
|
||||
, mChanged(false)
|
||||
, mPersistent(false)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void ViewData::add(QuadTreeNode *node)
|
||||
{
|
||||
int index = mNumEntries++;
|
||||
|
||||
mEntries.resize(index+1);
|
||||
|
||||
Entry& 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];
|
||||
}
|
||||
|
||||
void ViewData::reset(unsigned int frame)
|
||||
{
|
||||
// clear any unused entries
|
||||
for (unsigned int i=mNumEntries; i<mEntries.size(); ++i)
|
||||
mEntries[i].set(NULL);
|
||||
|
||||
// reset index for next frame
|
||||
mNumEntries = 0;
|
||||
|
||||
mFrameLastUsed = frame;
|
||||
}
|
||||
|
||||
void ViewData::clear()
|
||||
{
|
||||
for (unsigned int i=0; i<mEntries.size(); ++i)
|
||||
mEntries[i].set(NULL);
|
||||
mNumEntries = 0;
|
||||
mFrameLastUsed = 0;
|
||||
}
|
||||
|
||||
ViewData::Entry::Entry()
|
||||
: mNode(NULL)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
bool ViewData::Entry::set(QuadTreeNode *node)
|
||||
{
|
||||
if (node == mNode)
|
||||
return false;
|
||||
else
|
||||
{
|
||||
mNode = node;
|
||||
// clear cached data
|
||||
mRenderingNode = NULL;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
ViewData *ViewDataMap::getViewData(osg::Object *viewer, bool ref)
|
||||
{
|
||||
Map::const_iterator found = mViews.find(viewer);
|
||||
if (found == mViews.end())
|
||||
{
|
||||
ViewData* vd = createOrReuseView();
|
||||
if (ref)
|
||||
vd->setViewer(viewer);
|
||||
mViews[viewer] = vd;
|
||||
return vd;
|
||||
}
|
||||
else
|
||||
return found->second;
|
||||
}
|
||||
|
||||
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->getPersistent() &&
|
||||
(!vd->getViewer() // if no ref was held, always need to clear to avoid holding a dangling ref.
|
||||
|| vd->getFrameLastUsed() + 2 < frame))
|
||||
{
|
||||
vd->setViewer(NULL);
|
||||
vd->clear();
|
||||
mUnusedViews.push_back(vd);
|
||||
mViews.erase(it++);
|
||||
}
|
||||
else
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
void ViewDataMap::clear()
|
||||
{
|
||||
mViews.clear();
|
||||
mUnusedViews.clear();
|
||||
mViewVector.clear();
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,78 @@
|
||||
#ifndef OPENMW_COMPONENTS_TERRAIN_VIEWDATA_H
|
||||
#define OPENMW_COMPONENTS_TERRAIN_VIEWDATA_H
|
||||
|
||||
#include <vector>
|
||||
#include <deque>
|
||||
|
||||
#include <osg/Node>
|
||||
|
||||
namespace Terrain
|
||||
{
|
||||
|
||||
class QuadTreeNode;
|
||||
|
||||
class ViewData
|
||||
{
|
||||
public:
|
||||
ViewData();
|
||||
|
||||
void add(QuadTreeNode* node);
|
||||
|
||||
void reset(unsigned int frame);
|
||||
|
||||
void clear();
|
||||
|
||||
struct Entry
|
||||
{
|
||||
Entry();
|
||||
|
||||
bool set(QuadTreeNode* node);
|
||||
|
||||
QuadTreeNode* mNode;
|
||||
|
||||
osg::ref_ptr<osg::Node> mRenderingNode;
|
||||
};
|
||||
|
||||
unsigned int getNumEntries() const;
|
||||
|
||||
Entry& getEntry(unsigned int i);
|
||||
|
||||
bool getPersistent() const { return mPersistent; }
|
||||
|
||||
osg::Object* getViewer() const { return mViewer.get(); }
|
||||
void setViewer(osg::Object* viewer) { mViewer = viewer; }
|
||||
|
||||
unsigned int getFrameLastUsed() const { return mFrameLastUsed; }
|
||||
|
||||
private:
|
||||
std::vector<Entry> mEntries;
|
||||
unsigned int mNumEntries;
|
||||
unsigned int mFrameLastUsed;
|
||||
bool mChanged;
|
||||
bool mPersistent;
|
||||
osg::ref_ptr<osg::Object> mViewer;
|
||||
};
|
||||
|
||||
class ViewDataMap : public osg::Referenced
|
||||
{
|
||||
public:
|
||||
ViewData* getViewData(osg::Object* viewer, bool ref);
|
||||
|
||||
ViewData* createOrReuseView();
|
||||
|
||||
void clearUnusedViews(unsigned int frame);
|
||||
|
||||
void clear();
|
||||
|
||||
private:
|
||||
std::list<ViewData> mViewVector;
|
||||
|
||||
typedef std::map<osg::Object*, ViewData*> Map;
|
||||
Map mViews;
|
||||
|
||||
std::deque<ViewData*> mUnusedViews;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue