mirror of
https://github.com/OpenMW/openmw.git
synced 2025-01-30 07:15:34 +00:00
Lookup for terrain template using std::map::lower_bound instead of linear search
This commit is contained in:
parent
b6a3d3c906
commit
6d120f92e0
4 changed files with 73 additions and 34 deletions
|
@ -195,11 +195,21 @@ namespace Resource
|
|||
return _objectCache.size();
|
||||
}
|
||||
|
||||
template <class K>
|
||||
std::optional<std::pair<KeyType, osg::ref_ptr<osg::Object>>> lowerBound(K&& key)
|
||||
{
|
||||
const std::lock_guard<std::mutex> lock(_objectCacheMutex);
|
||||
const auto it = _objectCache.lower_bound(std::forward<K>(key));
|
||||
if (it == _objectCache.end())
|
||||
return std::nullopt;
|
||||
return std::pair(it->first, it->second.first);
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual ~GenericObjectCache() {}
|
||||
|
||||
typedef std::pair<osg::ref_ptr<osg::Object>, double> ObjectTimeStampPair;
|
||||
typedef std::map<KeyType, ObjectTimeStampPair> ObjectCacheMap;
|
||||
typedef std::map<KeyType, ObjectTimeStampPair, std::less<>> ObjectCacheMap;
|
||||
|
||||
ObjectCacheMap _objectCache;
|
||||
mutable std::mutex _objectCacheMutex;
|
||||
|
|
|
@ -21,7 +21,7 @@ namespace Terrain
|
|||
|
||||
ChunkManager::ChunkManager(Storage* storage, Resource::SceneManager* sceneMgr, TextureManager* textureManager,
|
||||
CompositeMapRenderer* renderer, ESM::RefId worldspace)
|
||||
: GenericResourceManager<ChunkId>(nullptr)
|
||||
: GenericResourceManager<ChunkKey>(nullptr)
|
||||
, QuadTreeWorld::ChunkManager(worldspace)
|
||||
, mStorage(storage)
|
||||
, mSceneManager(sceneMgr)
|
||||
|
@ -39,38 +39,26 @@ namespace Terrain
|
|||
mMultiPassRoot->setAttributeAndModes(material, osg::StateAttribute::ON);
|
||||
}
|
||||
|
||||
struct FindChunkTemplate
|
||||
{
|
||||
void operator()(ChunkId id, osg::Object* obj)
|
||||
{
|
||||
if (std::get<0>(id) == std::get<0>(mId) && std::get<1>(id) == std::get<1>(mId))
|
||||
mFoundTemplate = obj;
|
||||
}
|
||||
ChunkId mId;
|
||||
osg::ref_ptr<osg::Object> mFoundTemplate;
|
||||
};
|
||||
|
||||
osg::ref_ptr<osg::Node> ChunkManager::getChunk(float size, const osg::Vec2f& center, unsigned char lod,
|
||||
unsigned int lodFlags, bool activeGrid, const osg::Vec3f& viewPoint, bool compile)
|
||||
{
|
||||
// Override lod with the vertexLodMod adjusted value.
|
||||
// TODO: maybe we can refactor this code by moving all vertexLodMod code into this class.
|
||||
lod = static_cast<unsigned char>(lodFlags >> (4 * 4));
|
||||
ChunkId id = std::make_tuple(center, lod, lodFlags);
|
||||
osg::ref_ptr<osg::Object> obj = mCache->getRefFromObjectCache(id);
|
||||
if (obj)
|
||||
|
||||
const ChunkKey key{ .mCenter = center, .mLod = lod, .mLodFlags = lodFlags };
|
||||
if (osg::ref_ptr<osg::Object> obj = mCache->getRefFromObjectCache(key))
|
||||
return static_cast<osg::Node*>(obj.get());
|
||||
else
|
||||
{
|
||||
FindChunkTemplate find;
|
||||
find.mId = id;
|
||||
mCache->call(find);
|
||||
TerrainDrawable* templateGeometry
|
||||
= find.mFoundTemplate ? static_cast<TerrainDrawable*>(find.mFoundTemplate.get()) : nullptr;
|
||||
osg::ref_ptr<osg::Node> node = createChunk(size, center, lod, lodFlags, compile, templateGeometry);
|
||||
mCache->addEntryToObjectCache(id, node.get());
|
||||
return node;
|
||||
}
|
||||
|
||||
const TerrainDrawable* templateGeometry = nullptr;
|
||||
const TemplateKey templateKey{ .mCenter = center, .mLod = lod };
|
||||
const auto pair = mCache->lowerBound(templateKey);
|
||||
if (pair.has_value() && templateKey == TemplateKey{ .mCenter = pair->first.mCenter, .mLod = pair->first.mLod })
|
||||
templateGeometry = static_cast<const TerrainDrawable*>(pair->second.get());
|
||||
|
||||
osg::ref_ptr<osg::Node> node = createChunk(size, center, lod, lodFlags, compile, templateGeometry);
|
||||
mCache->addEntryToObjectCache(key, node.get());
|
||||
return node;
|
||||
}
|
||||
|
||||
void ChunkManager::reportStats(unsigned int frameNumber, osg::Stats* stats) const
|
||||
|
@ -80,14 +68,14 @@ namespace Terrain
|
|||
|
||||
void ChunkManager::clearCache()
|
||||
{
|
||||
GenericResourceManager<ChunkId>::clearCache();
|
||||
GenericResourceManager<ChunkKey>::clearCache();
|
||||
|
||||
mBufferCache.clearCache();
|
||||
}
|
||||
|
||||
void ChunkManager::releaseGLObjects(osg::State* state)
|
||||
{
|
||||
GenericResourceManager<ChunkId>::releaseGLObjects(state);
|
||||
GenericResourceManager<ChunkKey>::releaseGLObjects(state);
|
||||
mBufferCache.releaseGLObjects(state);
|
||||
}
|
||||
|
||||
|
@ -202,7 +190,7 @@ namespace Terrain
|
|||
}
|
||||
|
||||
osg::ref_ptr<osg::Node> ChunkManager::createChunk(float chunkSize, const osg::Vec2f& chunkCenter, unsigned char lod,
|
||||
unsigned int lodFlags, bool compile, TerrainDrawable* templateGeometry)
|
||||
unsigned int lodFlags, bool compile, const TerrainDrawable* templateGeometry)
|
||||
{
|
||||
osg::ref_ptr<TerrainDrawable> geometry(new TerrainDrawable);
|
||||
|
||||
|
|
|
@ -28,10 +28,51 @@ namespace Terrain
|
|||
class CompositeMap;
|
||||
class TerrainDrawable;
|
||||
|
||||
typedef std::tuple<osg::Vec2f, unsigned char, unsigned int> ChunkId; // Center, Lod, Lod Flags
|
||||
struct TemplateKey
|
||||
{
|
||||
osg::Vec2f mCenter;
|
||||
unsigned char mLod;
|
||||
};
|
||||
|
||||
inline auto tie(const TemplateKey& v)
|
||||
{
|
||||
return std::tie(v.mCenter, v.mLod);
|
||||
}
|
||||
|
||||
inline bool operator<(const TemplateKey& l, const TemplateKey& r)
|
||||
{
|
||||
return tie(l) < tie(r);
|
||||
}
|
||||
|
||||
inline bool operator==(const TemplateKey& l, const TemplateKey& r)
|
||||
{
|
||||
return tie(l) == tie(r);
|
||||
}
|
||||
|
||||
struct ChunkKey
|
||||
{
|
||||
osg::Vec2f mCenter;
|
||||
unsigned char mLod;
|
||||
unsigned mLodFlags;
|
||||
};
|
||||
|
||||
inline auto tie(const ChunkKey& v)
|
||||
{
|
||||
return std::tie(v.mCenter, v.mLod, v.mLodFlags);
|
||||
}
|
||||
|
||||
inline bool operator<(const ChunkKey& l, const ChunkKey& r)
|
||||
{
|
||||
return tie(l) < tie(r);
|
||||
}
|
||||
|
||||
inline bool operator<(const ChunkKey& l, const TemplateKey& r)
|
||||
{
|
||||
return TemplateKey{ .mCenter = l.mCenter, .mLod = l.mLod } < r;
|
||||
}
|
||||
|
||||
/// @brief Handles loading and caching of terrain chunks
|
||||
class ChunkManager : public Resource::GenericResourceManager<ChunkId>, public QuadTreeWorld::ChunkManager
|
||||
class ChunkManager : public Resource::GenericResourceManager<ChunkKey>, public QuadTreeWorld::ChunkManager
|
||||
{
|
||||
public:
|
||||
ChunkManager(Storage* storage, Resource::SceneManager* sceneMgr, TextureManager* textureManager,
|
||||
|
@ -55,7 +96,7 @@ namespace Terrain
|
|||
|
||||
private:
|
||||
osg::ref_ptr<osg::Node> createChunk(float size, const osg::Vec2f& center, unsigned char lod,
|
||||
unsigned int lodFlags, bool compile, TerrainDrawable* templateGeometry);
|
||||
unsigned int lodFlags, bool compile, const TerrainDrawable* templateGeometry);
|
||||
|
||||
osg::ref_ptr<osg::Texture2D> createCompositeMapRTT();
|
||||
|
||||
|
|
|
@ -60,7 +60,7 @@ namespace Terrain
|
|||
const osg::BoundingBox& getWaterBoundingBox() const { return mWaterBoundingBox; }
|
||||
|
||||
void setCompositeMap(CompositeMap* map) { mCompositeMap = map; }
|
||||
CompositeMap* getCompositeMap() { return mCompositeMap; }
|
||||
CompositeMap* getCompositeMap() const { return mCompositeMap; }
|
||||
void setCompositeMapRenderer(CompositeMapRenderer* renderer) { mCompositeMapRenderer = renderer; }
|
||||
|
||||
private:
|
||||
|
|
Loading…
Reference in a new issue