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/mwphysics/physicssystem.cpp b/apps/openmw/mwphysics/physicssystem.cpp index c94f16f5f6..5f13fef571 100644 --- a/apps/openmw/mwphysics/physicssystem.cpp +++ b/apps/openmw/mwphysics/physicssystem.cpp @@ -481,11 +481,9 @@ namespace MWPhysics mHeightFields.erase(heightfield); } - const HeightField* PhysicsSystem::getHeightField(ESM::ExteriorCellLocation cellIndex) const + const HeightField* PhysicsSystem::getHeightField(int x, int y) const { - if (ESM::isEsm4Ext(cellIndex.mWorldspace)) - return nullptr; - const auto heightField = mHeightFields.find(std::make_pair(cellIndex.mX, cellIndex.mY)); + const auto heightField = mHeightFields.find(std::make_pair(x, y)); if (heightField == mHeightFields.end()) return nullptr; return heightField->second.get(); diff --git a/apps/openmw/mwphysics/physicssystem.hpp b/apps/openmw/mwphysics/physicssystem.hpp index d73a87509e..e4c1b63776 100644 --- a/apps/openmw/mwphysics/physicssystem.hpp +++ b/apps/openmw/mwphysics/physicssystem.hpp @@ -189,7 +189,7 @@ namespace MWPhysics void removeHeightField(int x, int y); - const HeightField* getHeightField(ESM::ExteriorCellLocation cellIndex) const; + const HeightField* getHeightField(int x, int y) const; bool toggleCollisionMode(); 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/apps/openmw/mwworld/scene.cpp b/apps/openmw/mwworld/scene.cpp index 766aaf627e..78c8ccab1d 100644 --- a/apps/openmw/mwworld/scene.cpp +++ b/apps/openmw/mwworld/scene.cpp @@ -346,10 +346,7 @@ namespace MWWorld if (cell->getCell()->isExterior()) { - if (mPhysics->getHeightField(ESM::ExteriorCellLocation(cellX, cellY, cell->getCell()->getWorldSpace())) - != nullptr) - mNavigator.removeHeightfield(osg::Vec2i(cellX, cellY), navigatorUpdateGuard); - + mNavigator.removeHeightfield(osg::Vec2i(cellX, cellY), navigatorUpdateGuard); mPhysics->removeHeightField(cellX, cellY); } @@ -414,7 +411,7 @@ namespace MWWorld mPhysics->addHeightField(defaultHeight.data(), cellX, cellY, worldsize, verts, ESM::Land::DEFAULT_HEIGHT, ESM::Land::DEFAULT_HEIGHT, land.get()); } - if (const auto heightField = mPhysics->getHeightField(cellIndex)) + if (const auto heightField = mPhysics->getHeightField(cellX, cellY)) { const osg::Vec2i cellPosition(cellX, cellY); const btVector3& origin = heightField->getCollisionObject()->getWorldTransform().getOrigin(); @@ -469,7 +466,7 @@ namespace MWWorld if (cellVariant.isExterior()) { - if (const auto heightField = mPhysics->getHeightField(cellIndex)) + if (const auto heightField = mPhysics->getHeightField(cellX, cellY)) mNavigator.addWater( osg::Vec2i(cellX, cellY), ESM::Land::REAL_SIZE, waterLevel, navigatorUpdateGuard); } 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