diff --git a/components/CMakeLists.txt b/components/CMakeLists.txt index 8b019e470..6430dbfce 100644 --- a/components/CMakeLists.txt +++ b/components/CMakeLists.txt @@ -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 diff --git a/components/terrain/viewdata.cpp b/components/terrain/viewdata.cpp new file mode 100644 index 000000000..aff20cd54 --- /dev/null +++ b/components/terrain/viewdata.cpp @@ -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; isetViewer(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(); +} + + +} diff --git a/components/terrain/viewdata.hpp b/components/terrain/viewdata.hpp new file mode 100644 index 000000000..0ceb8313f --- /dev/null +++ b/components/terrain/viewdata.hpp @@ -0,0 +1,78 @@ +#ifndef OPENMW_COMPONENTS_TERRAIN_VIEWDATA_H +#define OPENMW_COMPONENTS_TERRAIN_VIEWDATA_H + +#include +#include + +#include + +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 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 mEntries; + unsigned int mNumEntries; + unsigned int mFrameLastUsed; + bool mChanged; + bool mPersistent; + osg::ref_ptr 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 mViewVector; + + typedef std::map Map; + Map mViews; + + std::deque mUnusedViews; + }; + +} + +#endif