diff --git a/apps/openmw/mwrender/landmanager.cpp b/apps/openmw/mwrender/landmanager.cpp index e3b19ca47..560c1ba72 100644 --- a/apps/openmw/mwrender/landmanager.cpp +++ b/apps/openmw/mwrender/landmanager.cpp @@ -12,16 +12,15 @@ namespace MWRender { LandManager::LandManager(int loadFlags) - : ResourceManager(nullptr) + : GenericResourceManager >(nullptr) , mLoadFlags(loadFlags) { + mCache = new CacheType; } osg::ref_ptr LandManager::getLand(int x, int y) { - std::string idstr = std::to_string(x) + " " + std::to_string(y); - - osg::ref_ptr obj = mCache->getRefFromObjectCache(idstr); + osg::ref_ptr obj = mCache->getRefFromObjectCache(std::make_pair(x,y)); if (obj) return static_cast(obj.get()); else @@ -30,7 +29,7 @@ osg::ref_ptr LandManager::getLand(int x, int y) if (!land) return nullptr; osg::ref_ptr landObj (new ESMTerrain::LandObject(land, mLoadFlags)); - mCache->addEntryToObjectCache(idstr, landObj.get()); + mCache->addEntryToObjectCache(std::make_pair(x,y), landObj.get()); return landObj; } } diff --git a/apps/openmw/mwrender/landmanager.hpp b/apps/openmw/mwrender/landmanager.hpp index 81253bba3..0d37097d8 100644 --- a/apps/openmw/mwrender/landmanager.hpp +++ b/apps/openmw/mwrender/landmanager.hpp @@ -3,6 +3,7 @@ #include +#include #include #include @@ -14,7 +15,7 @@ namespace ESM namespace MWRender { - class LandManager : public Resource::ResourceManager + class LandManager : public Resource::GenericResourceManager > { public: LandManager(int loadFlags); diff --git a/components/resource/objectcache.cpp b/components/resource/objectcache.cpp deleted file mode 100644 index ffe150c74..000000000 --- a/components/resource/objectcache.cpp +++ /dev/null @@ -1,165 +0,0 @@ -/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield - * - * This library is open source and may be redistributed and/or modified under - * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or - * (at your option) any later version. The full license is in LICENSE file - * included with this distribution, and on the openscenegraph.org website. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * OpenSceneGraph Public License for more details. -*/ - -#include "objectcache.hpp" - -#include -#include - -namespace Resource -{ - -//////////////////////////////////////////////////////////////////////////////////////////// -// -// ObjectCache -// -ObjectCache::ObjectCache(): - osg::Referenced(true) -{ -} - -ObjectCache::~ObjectCache() -{ -} - -void ObjectCache::addEntryToObjectCache(const std::string& filename, osg::Object* object, double timestamp) -{ - if (!object) - { - OSG_ALWAYS << " trying to add NULL object to cache for " << filename << std::endl; - return; - } - OpenThreads::ScopedLock lock(_objectCacheMutex); - _objectCache[filename]=ObjectTimeStampPair(object,timestamp); -} - -osg::ref_ptr ObjectCache::getRefFromObjectCache(const std::string& fileName) -{ - OpenThreads::ScopedLock lock(_objectCacheMutex); - ObjectCacheMap::iterator itr = _objectCache.find(fileName); - if (itr!=_objectCache.end()) - { - return itr->second.first; - } - else return 0; -} - -bool ObjectCache::checkInObjectCache(const std::string &fileName, double timeStamp) -{ - OpenThreads::ScopedLock lock(_objectCacheMutex); - ObjectCacheMap::iterator itr = _objectCache.find(fileName); - if (itr!=_objectCache.end()) - { - itr->second.second = timeStamp; - return true; - } - else return false; -} - -void ObjectCache::updateTimeStampOfObjectsInCacheWithExternalReferences(double referenceTime) -{ - OpenThreads::ScopedLock lock(_objectCacheMutex); - - // look for objects with external references and update their time stamp. - for(ObjectCacheMap::iterator itr=_objectCache.begin(); - itr!=_objectCache.end(); - ++itr) - { - // If ref count is greater than 1, the object has an external reference. - // If the timestamp is yet to be initialized, it needs to be updated too. - if (itr->second.first->referenceCount()>1 || itr->second.second == 0.0) - { - // So update it. - itr->second.second = referenceTime; - } - } -} - -void ObjectCache::removeExpiredObjectsInCache(double expiryTime) -{ - std::vector > objectsToRemove; - - { - OpenThreads::ScopedLock lock(_objectCacheMutex); - - // Remove expired entries from object cache - ObjectCacheMap::iterator oitr = _objectCache.begin(); - while(oitr != _objectCache.end()) - { - if (oitr->second.second<=expiryTime) - { - objectsToRemove.push_back(oitr->second.first); - _objectCache.erase(oitr++); - } - else - { - ++oitr; - } - } - } - - // note, actual unref happens outside of the lock - objectsToRemove.clear(); -} - -void ObjectCache::removeFromObjectCache(const std::string& fileName) -{ - OpenThreads::ScopedLock lock(_objectCacheMutex); - ObjectCacheMap::iterator itr = _objectCache.find(fileName); - if (itr!=_objectCache.end()) _objectCache.erase(itr); -} - -void ObjectCache::clear() -{ - OpenThreads::ScopedLock lock(_objectCacheMutex); - _objectCache.clear(); -} - -void ObjectCache::releaseGLObjects(osg::State* state) -{ - OpenThreads::ScopedLock lock(_objectCacheMutex); - - for(ObjectCacheMap::iterator itr = _objectCache.begin(); - itr != _objectCache.end(); - ++itr) - { - osg::Object* object = itr->second.first.get(); - object->releaseGLObjects(state); - } -} - -void ObjectCache::accept(osg::NodeVisitor &nv) -{ - OpenThreads::ScopedLock lock(_objectCacheMutex); - - for(ObjectCacheMap::iterator itr = _objectCache.begin(); - itr != _objectCache.end(); - ++itr) - { - osg::Object* object = itr->second.first.get(); - if (object) - { - osg::Node* node = dynamic_cast(object); - if (node) - node->accept(nv); - } - } -} - -unsigned int ObjectCache::getCacheSize() const -{ - OpenThreads::ScopedLock lock(_objectCacheMutex); - return _objectCache.size(); -} - -} diff --git a/components/resource/objectcache.hpp b/components/resource/objectcache.hpp index 72db835e8..cfd41f19c 100644 --- a/components/resource/objectcache.hpp +++ b/components/resource/objectcache.hpp @@ -1,5 +1,8 @@ // Resource ObjectCache for OpenMW, forked from osgDB ObjectCache by Robert Osfield, see copyright notice below. -// The main change from the upstream version is that removeExpiredObjectsInCache no longer keeps a lock while the unref happens. +// Changes: +// - removeExpiredObjectsInCache no longer keeps a lock while the unref happens. +// - template allows customized KeyType. +// - objects with uninitialized time stamp are not removed. /* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield * @@ -19,6 +22,7 @@ #include #include +#include #include #include @@ -32,11 +36,13 @@ namespace osg namespace Resource { -class ObjectCache : public osg::Referenced +template +class GenericObjectCache : public osg::Referenced { public: - ObjectCache(); + GenericObjectCache() + : osg::Referenced(true) {} /** For each object in the cache which has an reference count greater than 1 * (and therefore referenced by elsewhere in the application) set the time stamp @@ -44,59 +50,149 @@ class ObjectCache : public osg::Referenced * This would typically be called once per frame by applications which are doing database paging, * and need to prune objects that are no longer required. * The time used should be taken from the FrameStamp::getReferenceTime().*/ - void updateTimeStampOfObjectsInCacheWithExternalReferences(double referenceTime); + void updateTimeStampOfObjectsInCacheWithExternalReferences(double referenceTime) + { + // look for objects with external references and update their time stamp. + OpenThreads::ScopedLock lock(_objectCacheMutex); + for(typename ObjectCacheMap::iterator itr=_objectCache.begin(); itr!=_objectCache.end(); ++itr) + { + // If ref count is greater than 1, the object has an external reference. + // If the timestamp is yet to be initialized, it needs to be updated too. + if (itr->second.first->referenceCount()>1 || itr->second.second == 0.0) + itr->second.second = referenceTime; + } + } /** Removed object in the cache which have a time stamp at or before the specified expiry time. * This would typically be called once per frame by applications which are doing database paging, * and need to prune objects that are no longer required, and called after the a called * after the call to updateTimeStampOfObjectsInCacheWithExternalReferences(expirtyTime).*/ - void removeExpiredObjectsInCache(double expiryTime); + void removeExpiredObjectsInCache(double expiryTime) + { + std::vector > objectsToRemove; + { + OpenThreads::ScopedLock lock(_objectCacheMutex); + // Remove expired entries from object cache + typename ObjectCacheMap::iterator oitr = _objectCache.begin(); + while(oitr != _objectCache.end()) + { + if (oitr->second.second<=expiryTime) + { + objectsToRemove.push_back(oitr->second.first); + _objectCache.erase(oitr++); + } + else + ++oitr; + } + } + // note, actual unref happens outside of the lock + objectsToRemove.clear(); + } /** Remove all objects in the cache regardless of having external references or expiry times.*/ - void clear(); + void clear() + { + OpenThreads::ScopedLock lock(_objectCacheMutex); + _objectCache.clear(); + } - /** Add a filename,object,timestamp triple to the Registry::ObjectCache.*/ - void addEntryToObjectCache(const std::string& filename, osg::Object* object, double timestamp = 0.0); + /** Add a key,object,timestamp triple to the Registry::ObjectCache.*/ + void addEntryToObjectCache(const KeyType& key, osg::Object* object, double timestamp = 0.0) + { + OpenThreads::ScopedLock lock(_objectCacheMutex); + _objectCache[key]=ObjectTimeStampPair(object,timestamp); + } /** Remove Object from cache.*/ - void removeFromObjectCache(const std::string& fileName); + void removeFromObjectCache(const KeyType& key) + { + OpenThreads::ScopedLock lock(_objectCacheMutex); + typename ObjectCacheMap::iterator itr = _objectCache.find(key); + if (itr!=_objectCache.end()) _objectCache.erase(itr); + } /** Get an ref_ptr from the object cache*/ - osg::ref_ptr getRefFromObjectCache(const std::string& fileName); + osg::ref_ptr getRefFromObjectCache(const KeyType& key) + { + OpenThreads::ScopedLock lock(_objectCacheMutex); + typename ObjectCacheMap::iterator itr = _objectCache.find(key); + if (itr!=_objectCache.end()) + return itr->second.first; + else return 0; + } /** Check if an object is in the cache, and if it is, update its usage time stamp. */ - bool checkInObjectCache(const std::string& fileName, double timeStamp); + bool checkInObjectCache(const KeyType& key, double timeStamp) + { + OpenThreads::ScopedLock lock(_objectCacheMutex); + typename ObjectCacheMap::iterator itr = _objectCache.find(key); + if (itr!=_objectCache.end()) + { + itr->second.second = timeStamp; + return true; + } + else return false; + } /** call releaseGLObjects on all objects attached to the object cache.*/ - void releaseGLObjects(osg::State* state); + void releaseGLObjects(osg::State* state) + { + OpenThreads::ScopedLock lock(_objectCacheMutex); + for(typename ObjectCacheMap::iterator itr = _objectCache.begin(); itr != _objectCache.end(); ++itr) + { + osg::Object* object = itr->second.first.get(); + object->releaseGLObjects(state); + } + } /** call node->accept(nv); for all nodes in the objectCache. */ - void accept(osg::NodeVisitor& nv); + void accept(osg::NodeVisitor& nv) + { + OpenThreads::ScopedLock lock(_objectCacheMutex); + for(typename ObjectCacheMap::iterator itr = _objectCache.begin(); itr != _objectCache.end(); ++itr) + { + osg::Object* object = itr->second.first.get(); + if (object) + { + osg::Node* node = dynamic_cast(object); + if (node) + node->accept(nv); + } + } + } /** call operator()(osg::Object*) for each object in the cache. */ template void call(Functor& f) { OpenThreads::ScopedLock lock(_objectCacheMutex); - for (ObjectCacheMap::iterator it = _objectCache.begin(); it != _objectCache.end(); ++it) + for (typename ObjectCacheMap::iterator it = _objectCache.begin(); it != _objectCache.end(); ++it) f(it->second.first.get()); } /** Get the number of objects in the cache. */ - unsigned int getCacheSize() const; + unsigned int getCacheSize() const + { + OpenThreads::ScopedLock lock(_objectCacheMutex); + return _objectCache.size(); + } protected: - virtual ~ObjectCache(); + virtual ~GenericObjectCache() {} typedef std::pair, double > ObjectTimeStampPair; - typedef std::map ObjectCacheMap; + typedef std::map ObjectCacheMap; ObjectCacheMap _objectCache; mutable OpenThreads::Mutex _objectCacheMutex; }; +class ObjectCache : public GenericObjectCache +{ +}; + } #endif diff --git a/components/resource/resourcemanager.cpp b/components/resource/resourcemanager.cpp deleted file mode 100644 index c0e99674e..000000000 --- a/components/resource/resourcemanager.cpp +++ /dev/null @@ -1,46 +0,0 @@ -#include "resourcemanager.hpp" - -#include "objectcache.hpp" - -namespace Resource -{ - - ResourceManager::ResourceManager(const VFS::Manager *vfs) - : mVFS(vfs) - , mCache(new Resource::ObjectCache) - , mExpiryDelay(0.0) - { - - } - - ResourceManager::~ResourceManager() - { - } - - void ResourceManager::updateCache(double referenceTime) - { - mCache->updateTimeStampOfObjectsInCacheWithExternalReferences(referenceTime); - mCache->removeExpiredObjectsInCache(referenceTime - mExpiryDelay); - } - - void ResourceManager::clearCache() - { - mCache->clear(); - } - - void ResourceManager::setExpiryDelay(double expiryDelay) - { - mExpiryDelay = expiryDelay; - } - - const VFS::Manager* ResourceManager::getVFS() const - { - return mVFS; - } - - void ResourceManager::releaseGLObjects(osg::State *state) - { - mCache->releaseGLObjects(state); - } - -} diff --git a/components/resource/resourcemanager.hpp b/components/resource/resourcemanager.hpp index 6031ecc01..a5ae27c6a 100644 --- a/components/resource/resourcemanager.hpp +++ b/components/resource/resourcemanager.hpp @@ -3,6 +3,8 @@ #include +#include "objectcache.hpp" + namespace VFS { class Manager; @@ -16,37 +18,67 @@ namespace osg namespace Resource { - class ObjectCache; + + class BaseResourceManager + { + public: + virtual ~BaseResourceManager() {} + virtual void updateCache(double referenceTime) {} + virtual void clearCache() {} + virtual void setExpiryDelay(double expiryDelay) {} + virtual void reportStats(unsigned int frameNumber, osg::Stats* stats) const {} + virtual void releaseGLObjects(osg::State* state) {} + }; /// @brief Base class for managers that require a virtual file system and object cache. /// @par This base class implements clearing of the cache, but populating it and what it's used for is up to the individual sub classes. - class ResourceManager + template + class GenericResourceManager : public BaseResourceManager { public: - ResourceManager(const VFS::Manager* vfs); - virtual ~ResourceManager(); + typedef GenericObjectCache CacheType; + + GenericResourceManager(const VFS::Manager* vfs) + : mVFS(vfs) + , mCache(new CacheType) + , mExpiryDelay(0.0) + { + } + + virtual ~GenericResourceManager() {} /// Clear cache entries that have not been referenced for longer than expiryDelay. - virtual void updateCache(double referenceTime); + virtual void updateCache(double referenceTime) + { + mCache->updateTimeStampOfObjectsInCacheWithExternalReferences(referenceTime); + mCache->removeExpiredObjectsInCache(referenceTime - mExpiryDelay); + } /// Clear all cache entries. - virtual void clearCache(); + virtual void clearCache() { mCache->clear(); } /// How long to keep objects in cache after no longer being referenced. - void setExpiryDelay (double expiryDelay); + void setExpiryDelay (double expiryDelay) { mExpiryDelay = expiryDelay; } - const VFS::Manager* getVFS() const; + const VFS::Manager* getVFS() const { return mVFS; } virtual void reportStats(unsigned int frameNumber, osg::Stats* stats) const {} - virtual void releaseGLObjects(osg::State* state); + virtual void releaseGLObjects(osg::State* state) { mCache->releaseGLObjects(state); } protected: const VFS::Manager* mVFS; - osg::ref_ptr mCache; + osg::ref_ptr mCache; double mExpiryDelay; }; + + class ResourceManager : public GenericResourceManager + { + public: + ResourceManager(const VFS::Manager* vfs) : GenericResourceManager(vfs) {} + }; + } #endif diff --git a/components/resource/resourcesystem.cpp b/components/resource/resourcesystem.cpp index 4d61dce69..2015ba874 100644 --- a/components/resource/resourcesystem.cpp +++ b/components/resource/resourcesystem.cpp @@ -54,7 +54,7 @@ namespace Resource void ResourceSystem::setExpiryDelay(double expiryDelay) { - for (std::vector::iterator it = mResourceManagers.begin(); it != mResourceManagers.end(); ++it) + for (std::vector::iterator it = mResourceManagers.begin(); it != mResourceManagers.end(); ++it) (*it)->setExpiryDelay(expiryDelay); // NIF files aren't needed any more once the converted objects are cached in SceneManager / BulletShapeManager, @@ -64,24 +64,24 @@ namespace Resource void ResourceSystem::updateCache(double referenceTime) { - for (std::vector::iterator it = mResourceManagers.begin(); it != mResourceManagers.end(); ++it) + for (std::vector::iterator it = mResourceManagers.begin(); it != mResourceManagers.end(); ++it) (*it)->updateCache(referenceTime); } void ResourceSystem::clearCache() { - for (std::vector::iterator it = mResourceManagers.begin(); it != mResourceManagers.end(); ++it) + for (std::vector::iterator it = mResourceManagers.begin(); it != mResourceManagers.end(); ++it) (*it)->clearCache(); } - void ResourceSystem::addResourceManager(ResourceManager *resourceMgr) + void ResourceSystem::addResourceManager(BaseResourceManager *resourceMgr) { mResourceManagers.push_back(resourceMgr); } - void ResourceSystem::removeResourceManager(ResourceManager *resourceMgr) + void ResourceSystem::removeResourceManager(BaseResourceManager *resourceMgr) { - std::vector::iterator found = std::find(mResourceManagers.begin(), mResourceManagers.end(), resourceMgr); + std::vector::iterator found = std::find(mResourceManagers.begin(), mResourceManagers.end(), resourceMgr); if (found != mResourceManagers.end()) mResourceManagers.erase(found); } @@ -93,13 +93,13 @@ namespace Resource void ResourceSystem::reportStats(unsigned int frameNumber, osg::Stats *stats) const { - for (std::vector::const_iterator it = mResourceManagers.begin(); it != mResourceManagers.end(); ++it) + for (std::vector::const_iterator it = mResourceManagers.begin(); it != mResourceManagers.end(); ++it) (*it)->reportStats(frameNumber, stats); } void ResourceSystem::releaseGLObjects(osg::State *state) { - for (std::vector::const_iterator it = mResourceManagers.begin(); it != mResourceManagers.end(); ++it) + for (std::vector::const_iterator it = mResourceManagers.begin(); it != mResourceManagers.end(); ++it) (*it)->releaseGLObjects(state); } diff --git a/components/resource/resourcesystem.hpp b/components/resource/resourcesystem.hpp index 396bdb8fa..db8bbafc9 100644 --- a/components/resource/resourcesystem.hpp +++ b/components/resource/resourcesystem.hpp @@ -22,7 +22,7 @@ namespace Resource class ImageManager; class NifFileManager; class KeyframeManager; - class ResourceManager; + class BaseResourceManager; /// @brief Wrapper class that constructs and provides access to the most commonly used resource subsystems. /// @par Resource subsystems can be used with multiple OpenGL contexts, just like the OSG equivalents, but @@ -48,10 +48,10 @@ namespace Resource /// Add this ResourceManager to be handled by the ResourceSystem. /// @note Does not transfer ownership. - void addResourceManager(ResourceManager* resourceMgr); + void addResourceManager(BaseResourceManager* resourceMgr); /// @note Do nothing if resourceMgr does not exist. /// @note Does not delete resourceMgr. - void removeResourceManager(ResourceManager* resourceMgr); + void removeResourceManager(BaseResourceManager* resourceMgr); /// How long to keep objects in cache after no longer being referenced. void setExpiryDelay(double expiryDelay); @@ -72,7 +72,7 @@ namespace Resource // Store the base classes separately to get convenient access to the common interface // Here users can register their own resourcemanager as well - std::vector mResourceManagers; + std::vector mResourceManagers; const VFS::Manager* mVFS; diff --git a/components/terrain/chunkmanager.cpp b/components/terrain/chunkmanager.cpp index a22d43d74..41b1fdbe1 100644 --- a/components/terrain/chunkmanager.cpp +++ b/components/terrain/chunkmanager.cpp @@ -22,7 +22,7 @@ namespace Terrain { ChunkManager::ChunkManager(Storage *storage, Resource::SceneManager *sceneMgr, TextureManager* textureManager, CompositeMapRenderer* renderer) - : ResourceManager(nullptr) + : GenericResourceManager(nullptr) , mStorage(storage) , mSceneManager(sceneMgr) , mTextureManager(textureManager) @@ -35,12 +35,9 @@ ChunkManager::ChunkManager(Storage *storage, Resource::SceneManager *sceneMgr, T } -osg::ref_ptr ChunkManager::getChunk(float size, const osg::Vec2f ¢er, int lod, unsigned int lodFlags) +osg::ref_ptr ChunkManager::getChunk(float size, const osg::Vec2f ¢er, unsigned char lod, unsigned int lodFlags) { - std::ostringstream stream; - stream << size << " " << center.x() << " " << center.y() << " " << lod << " " << lodFlags; - std::string id = stream.str(); - + ChunkId id = std::make_tuple(center, lod, lodFlags); osg::ref_ptr obj = mCache->getRefFromObjectCache(id); if (obj) return obj->asNode(); @@ -59,14 +56,14 @@ void ChunkManager::reportStats(unsigned int frameNumber, osg::Stats *stats) cons void ChunkManager::clearCache() { - ResourceManager::clearCache(); + GenericResourceManager::clearCache(); mBufferCache.clearCache(); } void ChunkManager::releaseGLObjects(osg::State *state) { - ResourceManager::releaseGLObjects(state); + GenericResourceManager::releaseGLObjects(state); mBufferCache.releaseGLObjects(state); } @@ -164,7 +161,7 @@ std::vector > ChunkManager::createPasses(float chunk return ::Terrain::createPasses(useShaders, &mSceneManager->getShaderManager(), layers, blendmapTextures, blendmapScale, blendmapScale); } -osg::ref_ptr ChunkManager::createChunk(float chunkSize, const osg::Vec2f &chunkCenter, int lod, unsigned int lodFlags) +osg::ref_ptr ChunkManager::createChunk(float chunkSize, const osg::Vec2f &chunkCenter, unsigned char lod, unsigned int lodFlags) { osg::Vec2f worldCenter = chunkCenter*mStorage->getCellWorldSize(); osg::ref_ptr transform (new SceneUtil::PositionAttitudeTransform); diff --git a/components/terrain/chunkmanager.hpp b/components/terrain/chunkmanager.hpp index 27201864f..2dea1cf92 100644 --- a/components/terrain/chunkmanager.hpp +++ b/components/terrain/chunkmanager.hpp @@ -1,6 +1,8 @@ #ifndef OPENMW_COMPONENTS_TERRAIN_CHUNKMANAGER_H #define OPENMW_COMPONENTS_TERRAIN_CHUNKMANAGER_H +#include + #include #include "buffercache.hpp" @@ -24,13 +26,15 @@ namespace Terrain class Storage; class CompositeMap; + typedef std::tuple ChunkId; // Center, Lod, Lod Flags + /// @brief Handles loading and caching of terrain chunks - class ChunkManager : public Resource::ResourceManager + class ChunkManager : public Resource::GenericResourceManager { public: ChunkManager(Storage* storage, Resource::SceneManager* sceneMgr, TextureManager* textureManager, CompositeMapRenderer* renderer); - osg::ref_ptr getChunk(float size, const osg::Vec2f& center, int lod, unsigned int lodFlags); + osg::ref_ptr getChunk(float size, const osg::Vec2f& center, unsigned char lod, unsigned int lodFlags); void setCullingActive(bool active) { mCullingActive = active; } void setCompositeMapSize(unsigned int size) { mCompositeMapSize = size; } @@ -44,7 +48,7 @@ namespace Terrain void releaseGLObjects(osg::State* state) override; private: - osg::ref_ptr createChunk(float size, const osg::Vec2f& center, int lod, unsigned int lodFlags); + osg::ref_ptr createChunk(float size, const osg::Vec2f& center, unsigned char lod, unsigned int lodFlags); osg::ref_ptr createCompositeMapRTT();