mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-03-29 22:20:33 +00:00
Add a dictionary to retrieve the LOD mesh name of a mesh cache
This commit is contained in:
parent
58d08d402a
commit
6a3d27ce82
@ -76,6 +76,7 @@ namespace MWRender
|
|||||||
|
|
||||||
osg::ref_ptr<osg::Node> ObjectPaging::getChunk(float size, const osg::Vec2f& center, unsigned char lod, unsigned int lodFlags, bool activeGrid, const osg::Vec3f& viewPoint, bool compile)
|
osg::ref_ptr<osg::Node> ObjectPaging::getChunk(float size, const osg::Vec2f& center, unsigned char lod, unsigned int lodFlags, bool activeGrid, const osg::Vec3f& viewPoint, bool compile)
|
||||||
{
|
{
|
||||||
|
lod = static_cast<unsigned char>(lodFlags >> (4 * 4));
|
||||||
if (activeGrid && !mActiveGrid)
|
if (activeGrid && !mActiveGrid)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
@ -86,7 +87,7 @@ namespace MWRender
|
|||||||
return static_cast<osg::Node*>(obj.get());
|
return static_cast<osg::Node*>(obj.get());
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
osg::ref_ptr<osg::Node> node = createChunk(size, center, activeGrid, viewPoint, compile);
|
osg::ref_ptr<osg::Node> node = createChunk(size, center, activeGrid, viewPoint, compile, lod);
|
||||||
mCache->addEntryToObjectCache(id, node.get());
|
mCache->addEntryToObjectCache(id, node.get());
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
@ -411,7 +412,7 @@ namespace MWRender
|
|||||||
mMinSizeCostMultiplier = Settings::Manager::getFloat("object paging min size cost multiplier", "Terrain");
|
mMinSizeCostMultiplier = Settings::Manager::getFloat("object paging min size cost multiplier", "Terrain");
|
||||||
}
|
}
|
||||||
|
|
||||||
osg::ref_ptr<osg::Node> ObjectPaging::createChunk(float size, const osg::Vec2f& center, bool activeGrid, const osg::Vec3f& viewPoint, bool compile)
|
osg::ref_ptr<osg::Node> ObjectPaging::createChunk(float size, const osg::Vec2f& center, bool activeGrid, const osg::Vec3f& viewPoint, bool compile, unsigned char lod)
|
||||||
{
|
{
|
||||||
osg::Vec2i startCell = osg::Vec2i(std::floor(center.x() - size/2.f), std::floor(center.y() - size/2.f));
|
osg::Vec2i startCell = osg::Vec2i(std::floor(center.x() - size/2.f), std::floor(center.y() - size/2.f));
|
||||||
|
|
||||||
@ -548,6 +549,17 @@ namespace MWRender
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!activeGrid)
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lock(mLODNameCacheMutex);
|
||||||
|
LODNameCacheKey key{ model, lod };
|
||||||
|
LODNameCache::const_iterator found = mLODNameCache.lower_bound(key);
|
||||||
|
if (found != mLODNameCache.end() && found->first == key)
|
||||||
|
model = found->second;
|
||||||
|
else
|
||||||
|
model = mLODNameCache.insert(found, { key, Misc::ResourceHelpers::getLODMeshName(model, mSceneManager->getVFS(), lod) })->second;
|
||||||
|
}
|
||||||
|
|
||||||
osg::ref_ptr<const osg::Node> cnode = mSceneManager->getTemplate(model, false);
|
osg::ref_ptr<const osg::Node> cnode = mSceneManager->getTemplate(model, false);
|
||||||
|
|
||||||
if (activeGrid)
|
if (activeGrid)
|
||||||
|
@ -29,7 +29,7 @@ namespace MWRender
|
|||||||
|
|
||||||
osg::ref_ptr<osg::Node> getChunk(float size, const osg::Vec2f& center, unsigned char lod, unsigned int lodFlags, bool activeGrid, const osg::Vec3f& viewPoint, bool compile) override;
|
osg::ref_ptr<osg::Node> getChunk(float size, const osg::Vec2f& center, unsigned char lod, unsigned int lodFlags, bool activeGrid, const osg::Vec3f& viewPoint, bool compile) override;
|
||||||
|
|
||||||
osg::ref_ptr<osg::Node> createChunk(float size, const osg::Vec2f& center, bool activeGrid, const osg::Vec3f& viewPoint, bool compile);
|
osg::ref_ptr<osg::Node> createChunk(float size, const osg::Vec2f& center, bool activeGrid, const osg::Vec3f& viewPoint, bool compile, unsigned char lod);
|
||||||
|
|
||||||
unsigned int getNodeMask() override;
|
unsigned int getNodeMask() override;
|
||||||
|
|
||||||
@ -75,6 +75,11 @@ namespace MWRender
|
|||||||
std::mutex mSizeCacheMutex;
|
std::mutex mSizeCacheMutex;
|
||||||
typedef std::map<ESM::RefNum, float> SizeCache;
|
typedef std::map<ESM::RefNum, float> SizeCache;
|
||||||
SizeCache mSizeCache;
|
SizeCache mSizeCache;
|
||||||
|
|
||||||
|
std::mutex mLODNameCacheMutex;
|
||||||
|
typedef std::pair<std::string, unsigned char> LODNameCacheKey; //Key: mesh name, lod level
|
||||||
|
typedef std::map<LODNameCacheKey, std::string> LODNameCache; //Cache: key, mesh name to use
|
||||||
|
LODNameCache mLODNameCache;
|
||||||
};
|
};
|
||||||
|
|
||||||
class RefnumMarker : public osg::Object
|
class RefnumMarker : public osg::Object
|
||||||
|
@ -5,9 +5,14 @@
|
|||||||
|
|
||||||
namespace Misc
|
namespace Misc
|
||||||
{
|
{
|
||||||
|
inline size_t findExtension(std::string_view file)
|
||||||
|
{
|
||||||
|
return file.find_last_of('.');
|
||||||
|
}
|
||||||
|
|
||||||
inline std::string_view getFileExtension(std::string_view file)
|
inline std::string_view getFileExtension(std::string_view file)
|
||||||
{
|
{
|
||||||
if (auto extPos = file.find_last_of('.'); extPos != std::string::npos)
|
if (auto extPos = findExtension(file); extPos != std::string::npos)
|
||||||
{
|
{
|
||||||
file.remove_prefix(extPos + 1);
|
file.remove_prefix(extPos + 1);
|
||||||
return file;
|
return file;
|
||||||
|
@ -4,9 +4,11 @@
|
|||||||
#include <string_view>
|
#include <string_view>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
|
#include <components/misc/pathhelpers.hpp>
|
||||||
#include <components/misc/strings/lower.hpp>
|
#include <components/misc/strings/lower.hpp>
|
||||||
#include <components/misc/strings/algorithm.hpp>
|
#include <components/misc/strings/algorithm.hpp>
|
||||||
|
|
||||||
|
#include <components/settings/settings.hpp>
|
||||||
#include <components/vfs/manager.hpp>
|
#include <components/vfs/manager.hpp>
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
@ -164,3 +166,38 @@ bool Misc::ResourceHelpers::isHiddenMarker(std::string_view id)
|
|||||||
{
|
{
|
||||||
return Misc::StringUtils::ciEqual(id, "prisonmarker") || Misc::StringUtils::ciEqual(id, "divinemarker") || Misc::StringUtils::ciEqual(id, "templemarker") || Misc::StringUtils::ciEqual(id, "northmarker");
|
return Misc::StringUtils::ciEqual(id, "prisonmarker") || Misc::StringUtils::ciEqual(id, "divinemarker") || Misc::StringUtils::ciEqual(id, "templemarker") || Misc::StringUtils::ciEqual(id, "northmarker");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
std::string getLODMeshNameImpl(std::string resPath, const VFS::Manager* vfs, std::string_view pattern)
|
||||||
|
{
|
||||||
|
if (auto w = Misc::findExtension(resPath); w != std::string::npos)
|
||||||
|
resPath.insert(w, pattern);
|
||||||
|
return vfs->normalizeFilename(resPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string getBestLODMeshName(std::string const& resPath, const VFS::Manager* vfs, std::string_view pattern)
|
||||||
|
{
|
||||||
|
if (const auto& result = getLODMeshNameImpl(resPath, vfs, pattern); vfs->exists(result))
|
||||||
|
return result;
|
||||||
|
return resPath;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Misc::ResourceHelpers::getLODMeshName(std::string resPath, const VFS::Manager* vfs, unsigned char lod)
|
||||||
|
{
|
||||||
|
static const std::string distantMeshPattern = Settings::Manager::getString("distant mesh pattern", "Terrain");
|
||||||
|
std::string meshName = getBestLODMeshName(resPath, vfs, distantMeshPattern + "_" + std::to_string(lod));
|
||||||
|
if (meshName != resPath)
|
||||||
|
return meshName;
|
||||||
|
|
||||||
|
for (char l = lod; l >= 0; --l)
|
||||||
|
{
|
||||||
|
std::stringstream patern;
|
||||||
|
patern << distantMeshPattern << "_" << int(l);
|
||||||
|
meshName = getBestLODMeshName(resPath, vfs, patern.str());
|
||||||
|
if (meshName != resPath)
|
||||||
|
return meshName;
|
||||||
|
}
|
||||||
|
return getBestLODMeshName(resPath, vfs, distantMeshPattern);
|
||||||
|
}
|
||||||
|
@ -30,6 +30,7 @@ namespace Misc
|
|||||||
|
|
||||||
/// marker objects that have a hardcoded function in the game logic, should be hidden from the player
|
/// marker objects that have a hardcoded function in the game logic, should be hidden from the player
|
||||||
bool isHiddenMarker(std::string_view id);
|
bool isHiddenMarker(std::string_view id);
|
||||||
|
std::string getLODMeshName(std::string resPath, const VFS::Manager* vfs, unsigned char lod = 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -205,3 +205,12 @@ object paging min size cost multiplier
|
|||||||
This setting adjusts the calculated cost of merging an object used in the mentioned functionality.
|
This setting adjusts the calculated cost of merging an object used in the mentioned functionality.
|
||||||
The larger this value is, the less expensive objects can be before they are discarded.
|
The larger this value is, the less expensive objects can be before they are discarded.
|
||||||
See the formula above to figure out the math.
|
See the formula above to figure out the math.
|
||||||
|
|
||||||
|
distant mesh pattern
|
||||||
|
------------------
|
||||||
|
|
||||||
|
:Type: string
|
||||||
|
:Range:
|
||||||
|
:Default: _dist
|
||||||
|
|
||||||
|
The mesh filename pattern to look for when detecting distant meshes (it will replace original mesh outside active grid)
|
||||||
|
@ -119,6 +119,9 @@ object paging min size merge factor = 0.3
|
|||||||
# Controls how inexpensive an object needs to be to utilize 'min size merge factor'.
|
# Controls how inexpensive an object needs to be to utilize 'min size merge factor'.
|
||||||
object paging min size cost multiplier = 25
|
object paging min size cost multiplier = 25
|
||||||
|
|
||||||
|
# The mesh filename pattern to look for when detecting distant meshes (it will replace original mesh outside active grid)
|
||||||
|
distant mesh pattern = _dist
|
||||||
|
|
||||||
[Fog]
|
[Fog]
|
||||||
|
|
||||||
# If true, use extended fog parameters for distant terrain not controlled by
|
# If true, use extended fog parameters for distant terrain not controlled by
|
||||||
|
Loading…
x
Reference in New Issue
Block a user