#include "viewdata.hpp" #include "quadtreenode.hpp" namespace Terrain { ViewData::ViewData() : mNumEntries(0) , mLastUsageTimeStamp(0.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; mActiveGrid = other.mActiveGrid; } void ViewData::add(QuadTreeNode *node) { unsigned int index = mNumEntries++; if (index+1 > mEntries.size()) 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]; } 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= center.x()-halfSize && pos.y() >= center.y()-halfSize && pos.x() <= center.x()+halfSize && pos.y() <= center.y()+halfSize); } void ViewData::clearCache(const osg::Vec3f &cellPos) { for (Entry& entry : mEntries) if (entry.mNode && intersects(entry.mNode->getCenter(), entry.mNode->getSize()/2.f, cellPos)) entry.mRenderingNode = nullptr; } ViewData::Entry::Entry() : mNode(nullptr) , mLodFlags(0) { } bool ViewData::Entry::set(QuadTreeNode *node) { 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, const osg::Vec4i& activeGrid) { return vd->hasViewPoint() && (vd->getViewPoint() - viewPoint).length2() < maxDist*maxDist && vd->getActiveGrid() == activeGrid; } ViewData *ViewDataMap::getViewData(osg::Object *viewer, const osg::Vec3f& viewPoint, const osg::Vec4i &activeGrid, bool& needsUpdate) { Map::const_iterator found = mViews.find(viewer); ViewData* vd = nullptr; if (found == mViews.end()) { vd = createOrReuseView(); mViews[viewer] = vd; } else vd = found->second; if (!suitable(vd, viewPoint, mReuseDistance, activeGrid)) { for (Map::const_iterator other = mViews.begin(); other != mViews.end(); ++other) { if (suitable(other->second, viewPoint, mReuseDistance, activeGrid) && other->second->getNumEntries()) { vd->copyFrom(*other->second); needsUpdate = false; return vd; } } vd->setViewPoint(viewPoint); vd->setActiveGrid(activeGrid); 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(double referenceTime) { for (Map::iterator it = mViews.begin(); it != mViews.end(); ) { ViewData* vd = it->second; if (vd->getLastUsageTimeStamp() + mExpiryDelay < referenceTime) { vd->clear(); mUnusedViews.push_back(vd); mViews.erase(it++); } else ++it; } } void ViewDataMap::clearCachedViews(const osg::Vec3f &cellPos) { for (auto pair : mViews) pair.second->clearCache(cellPos); } void ViewDataMap::clear() { mViews.clear(); mUnusedViews.clear(); mViewVector.clear(); } }