forked from mirror/openmw-tes3mp
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