mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-01-26 09:35:28 +00:00
Merge branch 'vfs_normalized_path_17' into 'master'
Use normalized path for groundcover (#8138) See merge request OpenMW/openmw!4403
This commit is contained in:
commit
4ac1b13871
@ -1,5 +1,7 @@
|
||||
#include "groundcover.hpp"
|
||||
|
||||
#include <span>
|
||||
|
||||
#include <osg/AlphaFunc>
|
||||
#include <osg/BlendFunc>
|
||||
#include <osg/ComputeBoundsVisitor>
|
||||
@ -46,13 +48,13 @@ namespace MWRender
|
||||
class InstancedComputeNearFarCullCallback : public osg::DrawableCullCallback
|
||||
{
|
||||
public:
|
||||
InstancedComputeNearFarCullCallback(const std::vector<Groundcover::GroundcoverEntry>& instances,
|
||||
explicit InstancedComputeNearFarCullCallback(std::span<const Groundcover::GroundcoverEntry> instances,
|
||||
const osg::Vec3& chunkPosition, const osg::BoundingBox& instanceBounds)
|
||||
: mInstanceMatrices()
|
||||
, mInstanceBounds(instanceBounds)
|
||||
{
|
||||
mInstanceMatrices.reserve(instances.size());
|
||||
for (const auto& instance : instances)
|
||||
for (const Groundcover::GroundcoverEntry& instance : instances)
|
||||
mInstanceMatrices.emplace_back(computeInstanceMatrix(instance, chunkPosition));
|
||||
}
|
||||
|
||||
@ -191,7 +193,8 @@ namespace MWRender
|
||||
class InstancingVisitor : public osg::NodeVisitor
|
||||
{
|
||||
public:
|
||||
InstancingVisitor(std::vector<Groundcover::GroundcoverEntry>& instances, osg::Vec3f& chunkPosition)
|
||||
explicit InstancingVisitor(
|
||||
std::span<const Groundcover::GroundcoverEntry> instances, osg::Vec3f& chunkPosition)
|
||||
: osg::NodeVisitor(TRAVERSE_ALL_CHILDREN)
|
||||
, mInstances(instances)
|
||||
, mChunkPosition(chunkPosition)
|
||||
@ -252,7 +255,7 @@ namespace MWRender
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<Groundcover::GroundcoverEntry> mInstances;
|
||||
std::span<const Groundcover::GroundcoverEntry> mInstances;
|
||||
osg::Vec3f mChunkPosition;
|
||||
};
|
||||
|
||||
@ -411,12 +414,15 @@ namespace MWRender
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& pair : refs)
|
||||
for (auto& [refNum, cellRef] : refs)
|
||||
{
|
||||
ESM::CellRef& ref = pair.second;
|
||||
const std::string& model = mGroundcoverStore.getGroundcoverModel(ref.mRefID);
|
||||
if (!model.empty())
|
||||
instances[model].emplace_back(std::move(ref));
|
||||
const VFS::Path::NormalizedView model = mGroundcoverStore.getGroundcoverModel(cellRef.mRefID);
|
||||
if (model.empty())
|
||||
continue;
|
||||
auto it = instances.find(model);
|
||||
if (it == instances.end())
|
||||
it = instances.emplace_hint(it, VFS::Path::Normalized(model), std::vector<GroundcoverEntry>());
|
||||
it->second.emplace_back(std::move(cellRef));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -426,9 +432,9 @@ namespace MWRender
|
||||
{
|
||||
osg::ref_ptr<osg::Group> group = new osg::Group;
|
||||
osg::Vec3f worldCenter = osg::Vec3f(center.x(), center.y(), 0) * ESM::Land::REAL_SIZE;
|
||||
for (auto& pair : instances)
|
||||
for (const auto& [model, entries] : instances)
|
||||
{
|
||||
const osg::Node* temp = mSceneManager->getTemplate(VFS::Path::toNormalized(pair.first));
|
||||
const osg::Node* temp = mSceneManager->getTemplate(model);
|
||||
osg::ref_ptr<osg::Node> node = static_cast<osg::Node*>(temp->clone(osg::CopyOp::DEEP_COPY_NODES
|
||||
| osg::CopyOp::DEEP_COPY_DRAWABLES | osg::CopyOp::DEEP_COPY_USERDATA | osg::CopyOp::DEEP_COPY_ARRAYS
|
||||
| osg::CopyOp::DEEP_COPY_PRIMITIVES));
|
||||
@ -436,7 +442,7 @@ namespace MWRender
|
||||
// Keep link to original mesh to keep it in cache
|
||||
group->getOrCreateUserDataContainer()->addUserObject(new Resource::TemplateRef(temp));
|
||||
|
||||
InstancingVisitor visitor(pair.second, worldCenter);
|
||||
InstancingVisitor visitor(entries, worldCenter);
|
||||
node->accept(visitor);
|
||||
group->addChild(node);
|
||||
}
|
||||
|
@ -4,6 +4,7 @@
|
||||
#include <components/esm3/loadcell.hpp>
|
||||
#include <components/resource/scenemanager.hpp>
|
||||
#include <components/terrain/quadtreeworld.hpp>
|
||||
#include <components/vfs/pathutil.hpp>
|
||||
|
||||
namespace MWWorld
|
||||
{
|
||||
@ -46,13 +47,14 @@ namespace MWRender
|
||||
};
|
||||
|
||||
private:
|
||||
using InstanceMap = std::map<VFS::Path::Normalized, std::vector<GroundcoverEntry>, std::less<>>;
|
||||
|
||||
Resource::SceneManager* mSceneManager;
|
||||
float mDensity;
|
||||
osg::ref_ptr<osg::StateSet> mStateset;
|
||||
osg::ref_ptr<osg::Program> mProgramTemplate;
|
||||
const MWWorld::GroundcoverStore& mGroundcoverStore;
|
||||
|
||||
typedef std::map<std::string, std::vector<GroundcoverEntry>> InstanceMap;
|
||||
osg::ref_ptr<osg::Node> createChunk(InstanceMap& instances, const osg::Vec2f& center);
|
||||
void collectInstances(InstanceMap& instances, float size, const osg::Vec2f& center);
|
||||
};
|
||||
|
@ -21,29 +21,27 @@ namespace MWWorld
|
||||
query.mLoadCells = true;
|
||||
|
||||
ESM::ReadersCache readers;
|
||||
const ::EsmLoader::EsmData content
|
||||
::EsmLoader::EsmData content
|
||||
= ::EsmLoader::loadEsmData(query, groundcoverFiles, fileCollections, readers, encoder, listener);
|
||||
|
||||
static constexpr std::string_view prefix = "grass\\";
|
||||
static constexpr std::string_view prefix = "grass/";
|
||||
for (const ESM::Static& stat : statics)
|
||||
{
|
||||
std::string model = Misc::StringUtils::lowerCase(stat.mModel);
|
||||
std::replace(model.begin(), model.end(), '/', '\\');
|
||||
if (!model.starts_with(prefix))
|
||||
VFS::Path::Normalized model = VFS::Path::toNormalized(stat.mModel);
|
||||
if (!model.value().starts_with(prefix))
|
||||
continue;
|
||||
mMeshCache[stat.mId] = Misc::ResourceHelpers::correctMeshPath(model);
|
||||
}
|
||||
|
||||
for (const ESM::Static& stat : content.mStatics)
|
||||
{
|
||||
std::string model = Misc::StringUtils::lowerCase(stat.mModel);
|
||||
std::replace(model.begin(), model.end(), '/', '\\');
|
||||
if (!model.starts_with(prefix))
|
||||
VFS::Path::Normalized model = VFS::Path::toNormalized(stat.mModel);
|
||||
if (!model.value().starts_with(prefix))
|
||||
continue;
|
||||
mMeshCache[stat.mId] = Misc::ResourceHelpers::correctMeshPath(model);
|
||||
}
|
||||
|
||||
for (const ESM::Cell& cell : content.mCells)
|
||||
for (ESM::Cell& cell : content.mCells)
|
||||
{
|
||||
if (!cell.isExterior())
|
||||
continue;
|
||||
@ -52,15 +50,6 @@ namespace MWWorld
|
||||
}
|
||||
}
|
||||
|
||||
std::string GroundcoverStore::getGroundcoverModel(const ESM::RefId& id) const
|
||||
{
|
||||
auto search = mMeshCache.find(id);
|
||||
if (search == mMeshCache.end())
|
||||
return std::string();
|
||||
|
||||
return search->second;
|
||||
}
|
||||
|
||||
void GroundcoverStore::initCell(ESM::Cell& cell, int cellX, int cellY) const
|
||||
{
|
||||
cell.blank();
|
||||
|
@ -2,6 +2,8 @@
|
||||
#define GAME_MWWORLD_GROUNDCOVER_STORE_H
|
||||
|
||||
#include <components/esm/refid.hpp>
|
||||
#include <components/vfs/pathutil.hpp>
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
@ -36,7 +38,7 @@ namespace MWWorld
|
||||
class GroundcoverStore
|
||||
{
|
||||
private:
|
||||
std::map<ESM::RefId, std::string> mMeshCache;
|
||||
std::map<ESM::RefId, VFS::Path::Normalized> mMeshCache;
|
||||
std::map<std::pair<int, int>, std::vector<ESM::ESM_Context>> mCellContexts;
|
||||
|
||||
public:
|
||||
@ -44,7 +46,14 @@ namespace MWWorld
|
||||
const std::vector<std::string>& groundcoverFiles, ToUTF8::Utf8Encoder* encoder,
|
||||
Loading::Listener* listener);
|
||||
|
||||
std::string getGroundcoverModel(const ESM::RefId& id) const;
|
||||
VFS::Path::NormalizedView getGroundcoverModel(ESM::RefId id) const
|
||||
{
|
||||
auto it = mMeshCache.find(id);
|
||||
if (it == mMeshCache.end())
|
||||
return {};
|
||||
return it->second;
|
||||
}
|
||||
|
||||
void initCell(ESM::Cell& cell, int cellX, int cellY) const;
|
||||
};
|
||||
}
|
||||
|
@ -94,6 +94,8 @@ namespace VFS::Path
|
||||
|
||||
constexpr std::string_view value() const noexcept { return mValue; }
|
||||
|
||||
constexpr bool empty() const noexcept { return mValue.empty(); }
|
||||
|
||||
friend constexpr bool operator==(const NormalizedView& lhs, const NormalizedView& rhs) = default;
|
||||
|
||||
friend constexpr bool operator==(const NormalizedView& lhs, const auto& rhs) { return lhs.mValue == rhs; }
|
||||
|
Loading…
x
Reference in New Issue
Block a user