From ac652463894412517c783159009b9397d0e095bc Mon Sep 17 00:00:00 2001 From: Petr Mikheev Date: Tue, 16 May 2023 02:49:42 +0200 Subject: [PATCH] Speedup ESM4 cell loading; load objects from permanent cells (exterior doors in particular) --- apps/openmw/mwworld/cellstore.cpp | 8 +++----- apps/openmw/mwworld/esmstore.cpp | 1 + apps/openmw/mwworld/store.cpp | 27 +++++++++++++++++++++++++++ apps/openmw/mwworld/store.hpp | 8 ++++++++ 4 files changed, 39 insertions(+), 5 deletions(-) diff --git a/apps/openmw/mwworld/cellstore.cpp b/apps/openmw/mwworld/cellstore.cpp index b86d341e80..c9be8c0a96 100644 --- a/apps/openmw/mwworld/cellstore.cpp +++ b/apps/openmw/mwworld/cellstore.cpp @@ -760,12 +760,10 @@ namespace MWWorld template static void visitCell4References(const ESM4::Cell& cell, ESM::ReadersCache& readers, ReferenceInvocable&& invocable) { - for (const ESM4::Reference& ref : MWBase::Environment::get().getESMStore()->get()) + for (const ESM4::Reference* ref : + MWBase::Environment::get().getESMStore()->get().getByCell(cell.mId)) { - if (ref.mParent == cell.mId) - { - invocable(ref); - } + invocable(*ref); } } diff --git a/apps/openmw/mwworld/esmstore.cpp b/apps/openmw/mwworld/esmstore.cpp index d569b155cb..ae539fcab1 100644 --- a/apps/openmw/mwworld/esmstore.cpp +++ b/apps/openmw/mwworld/esmstore.cpp @@ -447,6 +447,7 @@ namespace MWWorld getWritable().setUp(); getWritable().setUp(); getWritable().setUp(); + getWritable().preprocessReferences(get()); } void ESMStore::validateRecords(ESM::ReadersCache& readers) diff --git a/apps/openmw/mwworld/store.cpp b/apps/openmw/mwworld/store.cpp index b87cf6e445..ec984e030d 100644 --- a/apps/openmw/mwworld/store.cpp +++ b/apps/openmw/mwworld/store.cpp @@ -1155,6 +1155,33 @@ namespace MWWorld } MWWorld::TypedDynamicStore::clearDynamic(); } + + // ESM4 Reference + //========================================================================= + + void Store::preprocessReferences(const Store& cells) + { + for (auto& [_, ref] : mStatic) + { + const ESM4::Cell* cell = cells.find(ref.mParent); + if (cell->isExterior() && (cell->mFlags & ESM4::Rec_Persistent)) + { + const ESM4::Cell* actualCell + = cells.searchExterior(positionToCellIndex(ref.mPos.pos[0], ref.mPos.pos[1], cell->mParent)); + if (actualCell) + ref.mParent = actualCell->mId; + } + mPerCellReferences[ref.mParent].push_back(&ref); + } + } + + std::span Store::getByCell(ESM::RefId cellId) const + { + auto it = mPerCellReferences.find(cellId); + if (it == mPerCellReferences.end()) + return {}; + return it->second; + } } template class MWWorld::TypedDynamicStore; diff --git a/apps/openmw/mwworld/store.hpp b/apps/openmw/mwworld/store.hpp index 75c41af25e..35e4de63eb 100644 --- a/apps/openmw/mwworld/store.hpp +++ b/apps/openmw/mwworld/store.hpp @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -552,6 +553,13 @@ namespace MWWorld template <> class Store : public TypedDynamicStore { + public: + void preprocessReferences(const Store& cells); + + std::span getByCell(ESM::RefId cellId) const; + + private: + std::unordered_map> mPerCellReferences; }; } // end namespace