Add view data structure for efficient collection of LOD nodes to use for a given camera/intersection

pull/185/head
scrawl 8 years ago
parent 0efc54c749
commit e36bdb490e

@ -114,7 +114,7 @@ add_component_dir (translation
)
add_component_dir (terrain
storage world buffercache defs terraingrid material terraindrawable texturemanager chunkmanager compositemaprenderer quadtreeworld quadtreenode
storage world buffercache defs terraingrid material terraindrawable texturemanager chunkmanager compositemaprenderer quadtreeworld quadtreenode viewdata
)
add_component_dir (loadinglistener

@ -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…
Cancel
Save