diff --git a/apps/openmw/mwmechanics/aicombat.cpp b/apps/openmw/mwmechanics/aicombat.cpp index 6daa8ea011..dbe83eab42 100644 --- a/apps/openmw/mwmechanics/aicombat.cpp +++ b/apps/openmw/mwmechanics/aicombat.cpp @@ -371,7 +371,8 @@ namespace MWMechanics && !actor.getClass().isPureWaterCreature(actor)) { ESM::Pathgrid::PointList points; - Misc::CoordinateConverter coords(*storage.mCell->getCell()); + const Misc::CoordinateConverter coords + = Misc::makeCoordinateConverter(*storage.mCell->getCell()); osg::Vec3f localPos = actor.getRefData().getPosition().asVec3(); coords.toLocal(localPos); diff --git a/apps/openmw/mwmechanics/aipackage.cpp b/apps/openmw/mwmechanics/aipackage.cpp index cc5b667f6f..183c30bfb7 100644 --- a/apps/openmw/mwmechanics/aipackage.cpp +++ b/apps/openmw/mwmechanics/aipackage.cpp @@ -421,7 +421,7 @@ bool MWMechanics::AiPackage::isNearInactiveCell(osg::Vec3f position) if (playerCell->isExterior()) { // get actor's distance from origin of center cell - Misc::CoordinateConverter(*playerCell).toLocal(position); + Misc::makeCoordinateConverter(*playerCell).toLocal(position); // currently assumes 3 x 3 grid for exterior cells, with player at center cell. // AI shuts down actors before they reach edges of 3 x 3 grid. diff --git a/apps/openmw/mwmechanics/aiwander.cpp b/apps/openmw/mwmechanics/aiwander.cpp index 4e3e29c4fb..60c37ac33c 100644 --- a/apps/openmw/mwmechanics/aiwander.cpp +++ b/apps/openmw/mwmechanics/aiwander.cpp @@ -730,7 +730,7 @@ namespace MWMechanics auto& prng = MWBase::Environment::get().getWorld()->getPrng(); int index = Misc::Rng::rollDice(storage.mAllowedNodes.size(), prng); ESM::Pathgrid::Point worldDest = storage.mAllowedNodes[index]; - auto converter = Misc::CoordinateConverter(*actor.getCell()->getCell()); + const Misc::CoordinateConverter converter = Misc::makeCoordinateConverter(*actor.getCell()->getCell()); ESM::Pathgrid::Point dest = converter.toLocalPoint(worldDest); bool isPathGridOccupied = MWBase::Environment::get().getMechanicsManager()->isAnyActorInRange( @@ -835,7 +835,7 @@ namespace MWMechanics if (mDistance && storage.mCanWanderAlongPathGrid && !actor.getClass().isPureWaterCreature(actor)) { // get NPC's position in local (i.e. cell) coordinates - auto converter = Misc::CoordinateConverter(*cellStore->getCell()); + const Misc::CoordinateConverter converter = Misc::makeCoordinateConverter(*cellStore->getCell()); const osg::Vec3f npcPos = converter.toLocalVec3(mInitialActorPosition); // Find closest pathgrid point diff --git a/apps/openmw/mwmechanics/pathfinding.cpp b/apps/openmw/mwmechanics/pathfinding.cpp index 417a238f15..192cbdfe22 100644 --- a/apps/openmw/mwmechanics/pathfinding.cpp +++ b/apps/openmw/mwmechanics/pathfinding.cpp @@ -189,7 +189,7 @@ namespace MWMechanics return; // NOTE: getClosestPoint expects local coordinates - Misc::CoordinateConverter converter(*mCell->getCell()); + const Misc::CoordinateConverter converter = Misc::makeCoordinateConverter(*mCell->getCell()); // NOTE: It is possible that getClosestPoint returns a pathgrind point index // that is unreachable in some situations. e.g. actor is standing diff --git a/apps/openmw/mwrender/pathgrid.cpp b/apps/openmw/mwrender/pathgrid.cpp index bb1e0b9c11..a39ba86a60 100644 --- a/apps/openmw/mwrender/pathgrid.cpp +++ b/apps/openmw/mwrender/pathgrid.cpp @@ -116,7 +116,7 @@ namespace MWRender return; osg::Vec3f cellPathGridPos(0, 0, 0); - Misc::CoordinateConverter(*store->getCell()).toWorld(cellPathGridPos); + Misc::makeCoordinateConverter(*store->getCell()).toWorld(cellPathGridPos); osg::ref_ptr cellPathGrid = new osg::PositionAttitudeTransform; cellPathGrid->setPosition(cellPathGridPos); diff --git a/components/detournavigator/navigatorimpl.cpp b/components/detournavigator/navigatorimpl.cpp index 7af425fcfd..514a70b336 100644 --- a/components/detournavigator/navigatorimpl.cpp +++ b/components/detournavigator/navigatorimpl.cpp @@ -133,7 +133,7 @@ namespace DetourNavigator void NavigatorImpl::addPathgrid(const ESM::Cell& cell, const ESM::Pathgrid& pathgrid) { - Misc::CoordinateConverter converter(&cell); + const Misc::CoordinateConverter converter = Misc::makeCoordinateConverter(cell); for (const auto& edge : pathgrid.mEdges) { const auto src = Misc::Convert::makeOsgVec3f(converter.toWorldPoint(pathgrid.mPoints[edge.mV0])); diff --git a/components/esm3/loadcell.hpp b/components/esm3/loadcell.hpp index 3d33c7c370..b7cf6bf2eb 100644 --- a/components/esm3/loadcell.hpp +++ b/components/esm3/loadcell.hpp @@ -5,11 +5,14 @@ #include #include -#include "cellref.hpp" #include "components/esm/defs.hpp" #include "components/esm/esmcommon.hpp" #include "components/esm/refid.hpp" +#include + +#include "cellref.hpp" + namespace MWWorld { class ESMStore; @@ -70,6 +73,8 @@ namespace ESM constexpr static RecNameInts sRecordId = REC_CELL; + static constexpr int sSize = Constants::CellSizeInUnits; + /// Return a string descriptor for this record type. Currently used for debugging / error logs only. static std::string_view getRecordType() { return "Cell"; } diff --git a/components/esm4/loadcell.hpp b/components/esm4/loadcell.hpp index c2fb506975..58d1f0da43 100644 --- a/components/esm4/loadcell.hpp +++ b/components/esm4/loadcell.hpp @@ -35,6 +35,7 @@ #include #include #include +#include #include "lighting.hpp" @@ -62,6 +63,8 @@ namespace ESM4 // The cells need to be organised under world spaces. struct Cell { + static constexpr int sSize = Constants::ESM4CellSizeInUnits; + ESM::RefId mId; // from the header std::uint32_t mFlags = 0; // from the header, see enum type RecordFlag for details diff --git a/components/misc/coordinateconverter.hpp b/components/misc/coordinateconverter.hpp index 9c829e91cd..7853880809 100644 --- a/components/misc/coordinateconverter.hpp +++ b/components/misc/coordinateconverter.hpp @@ -3,9 +3,9 @@ #include #include -#include #include #include +#include namespace Misc { @@ -13,21 +13,9 @@ namespace Misc class CoordinateConverter { public: - CoordinateConverter(bool exterior, int cellX, int cellY) - : mCellX(exterior ? cellX * ESM::Land::REAL_SIZE : 0) - , mCellY(exterior ? cellY * ESM::Land::REAL_SIZE : 0) - { - } - - explicit CoordinateConverter(const ESM::CellVariant& cell) - : CoordinateConverter(cell.isEsm4() ? cell.getEsm4().isExterior() : cell.getEsm3().isExterior(), - cell.isEsm4() ? cell.getEsm4().getGridX() : cell.getEsm3().getGridX(), - cell.isEsm4() ? cell.getEsm4().getGridY() : cell.getEsm3().getGridY()) - { - } - - explicit CoordinateConverter(const ESM::Cell* cell) - : CoordinateConverter(cell->isExterior(), cell->getGridX(), cell->getGridY()) + explicit CoordinateConverter(int cellX, int cellY) + : mCellX(cellX) + , mCellY(cellY) { } @@ -81,6 +69,29 @@ namespace Misc int mCellX; int mCellY; }; + + template + CoordinateConverter makeCoordinateConverterImpl(const T& cell) + { + if (cell.isExterior()) + return CoordinateConverter(cell.sSize * cell.getGridX(), cell.sSize * cell.getGridY()); + return CoordinateConverter(0, 0); + } + + inline CoordinateConverter makeCoordinateConverter(const ESM::Cell& cell) + { + return makeCoordinateConverterImpl(cell); + } + + inline CoordinateConverter makeCoordinateConverter(const ESM4::Cell& cell) + { + return makeCoordinateConverterImpl(cell); + } + + inline CoordinateConverter makeCoordinateConverter(const ESM::CellVariant& cell) + { + return visit([](const auto& v) { return makeCoordinateConverterImpl(v); }, cell); + } } #endif