From 942a987d528de8202e15c63607a20539675d3b85 Mon Sep 17 00:00:00 2001 From: dteviot Date: Sun, 16 Aug 2015 18:55:02 +1200 Subject: [PATCH] centralize the world/cell coordinate conversion logic. --- apps/openmw/CMakeLists.txt | 2 +- apps/openmw/mwmechanics/aiwander.cpp | 13 ++---- .../mwmechanics/coordinateconverter.cpp | 43 +++++++++++++++++++ .../mwmechanics/coordinateconverter.hpp | 37 ++++++++++++++++ apps/openmw/mwmechanics/pathfinding.cpp | 24 +++++------ apps/openmw/mwmechanics/pathgrid.cpp | 20 ++------- apps/openmw/mwrender/pathgrid.cpp | 7 +-- 7 files changed, 99 insertions(+), 47 deletions(-) create mode 100644 apps/openmw/mwmechanics/coordinateconverter.cpp create mode 100644 apps/openmw/mwmechanics/coordinateconverter.hpp diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index cd1ac31ec..c33b711e6 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -82,7 +82,7 @@ add_openmw_dir (mwmechanics drawstate spells activespells npcstats aipackage aisequence aipursue alchemy aiwander aitravel aifollow aiavoiddoor aiescort aiactivate aicombat repair enchanting pathfinding pathgrid security spellsuccess spellcasting disease pickpocket levelledlist combat steering obstacle autocalcspell difficultyscaling aicombataction actor summoning - character actors objects aistate + character actors objects aistate coordinateconverter ) add_openmw_dir (mwstate diff --git a/apps/openmw/mwmechanics/aiwander.cpp b/apps/openmw/mwmechanics/aiwander.cpp index 440814fb7..afe34218e 100644 --- a/apps/openmw/mwmechanics/aiwander.cpp +++ b/apps/openmw/mwmechanics/aiwander.cpp @@ -20,6 +20,7 @@ #include "creaturestats.hpp" #include "steering.hpp" #include "movement.hpp" +#include "coordinateconverter.hpp" @@ -587,11 +588,7 @@ namespace MWMechanics void AiWander::ToWorldCoordinates(ESM::Pathgrid::Point& point, const ESM::Cell * cell) { - if (cell->isExterior()) - { - point.mX += cell->mData.mX * ESM::Land::REAL_SIZE; - point.mY += cell->mData.mY * ESM::Land::REAL_SIZE; - } + CoordinateConverter(cell).ToWorld(point); } void AiWander::trimAllowedNodes(std::vector& nodes, @@ -749,11 +746,7 @@ namespace MWMechanics { // get NPC's position in local (i.e. cell) co-ordinates osg::Vec3f npcPos(mInitialActorPosition); - if(cell->isExterior()) - { - npcPos[0] = npcPos[0] - static_cast(cell->mData.mX * ESM::Land::REAL_SIZE); - npcPos[1] = npcPos[1] - static_cast(cell->mData.mY * ESM::Land::REAL_SIZE); - } + CoordinateConverter(cell).ToLocal(npcPos); // mAllowedNodes for this actor with pathgrid point indexes based on mDistance // NOTE: mPoints and mAllowedNodes are in local co-ordinates diff --git a/apps/openmw/mwmechanics/coordinateconverter.cpp b/apps/openmw/mwmechanics/coordinateconverter.cpp new file mode 100644 index 000000000..583ac41c5 --- /dev/null +++ b/apps/openmw/mwmechanics/coordinateconverter.cpp @@ -0,0 +1,43 @@ +#include "coordinateconverter.hpp" + +#include +#include + +namespace MWMechanics +{ + CoordinateConverter::CoordinateConverter(const ESM::Cell* cell) + : mCellX(0), mCellY(0) + { + if (cell->isExterior()) + { + mCellX = cell->mData.mX * ESM::Land::REAL_SIZE; + mCellY = cell->mData.mY * ESM::Land::REAL_SIZE; + } + } + + void CoordinateConverter::ToWorld(ESM::Pathgrid::Point& point) + { + point.mX += mCellX; + point.mY += mCellY; + } + + void CoordinateConverter::ToWorld(osg::Vec3f& point) + { + point.x() += static_cast(mCellX); + point.y() += static_cast(mCellY); + } + + void CoordinateConverter::ToLocal(osg::Vec3f& point) + { + point.x() -= static_cast(mCellX); + point.y() -= static_cast(mCellY); + } + + osg::Vec3f CoordinateConverter::ToLocalVec3(const ESM::Pathgrid::Point& point) + { + return osg::Vec3f( + static_cast(point.mX - mCellX), + static_cast(point.mY - mCellY), + static_cast(point.mZ)); + } +} diff --git a/apps/openmw/mwmechanics/coordinateconverter.hpp b/apps/openmw/mwmechanics/coordinateconverter.hpp new file mode 100644 index 000000000..2c4d3d3ba --- /dev/null +++ b/apps/openmw/mwmechanics/coordinateconverter.hpp @@ -0,0 +1,37 @@ +#ifndef GAME_MWMECHANICS_COORDINATECONVERTER_H +#define GAME_MWMECHANICS_COORDINATECONVERTER_H + +#include +#include + +namespace ESM +{ + struct Cell; +} + +namespace MWMechanics +{ + /// \brief convert coordinates between world and local cell + class CoordinateConverter + { + public: + CoordinateConverter(const ESM::Cell* cell); + + /// in-place conversion from local to world + void ToWorld(ESM::Pathgrid::Point& point); + + /// in-place conversion from local to world + void ToWorld(osg::Vec3f& point); + + /// in-place conversion from world to local + void ToLocal(osg::Vec3f& point); + + osg::Vec3f ToLocalVec3(const ESM::Pathgrid::Point& point); + + private: + int mCellX; + int mCellY; + }; +} + +#endif diff --git a/apps/openmw/mwmechanics/pathfinding.cpp b/apps/openmw/mwmechanics/pathfinding.cpp index d8e6a37b7..1147371b1 100644 --- a/apps/openmw/mwmechanics/pathfinding.cpp +++ b/apps/openmw/mwmechanics/pathfinding.cpp @@ -5,6 +5,7 @@ #include "../mwworld/esmstore.hpp" #include "../mwworld/cellstore.hpp" +#include "coordinateconverter.hpp" namespace { @@ -106,11 +107,6 @@ namespace MWMechanics return sqrt(x * x + y * y + z * z); } - osg::Vec3f ToLocalCoordinates(const ESM::Pathgrid::Point &point, float xCell, float yCell) - { - return osg::Vec3f(point.mX - xCell, point.mY - yCell, static_cast(point.mZ)); - } - PathFinder::PathFinder() : mPathgrid(NULL), mCell(NULL) @@ -194,23 +190,17 @@ namespace MWMechanics } // NOTE: getClosestPoint expects local co-ordinates - float xCell = 0; - float yCell = 0; - if (mCell->isExterior()) - { - xCell = static_cast(mCell->getCell()->mData.mX * ESM::Land::REAL_SIZE); - yCell = static_cast(mCell->getCell()->mData.mY * ESM::Land::REAL_SIZE); - } + CoordinateConverter converter(mCell->getCell()); // NOTE: It is possible that getClosestPoint returns a pathgrind point index // that is unreachable in some situations. e.g. actor is standing // outside an area enclosed by walls, but there is a pathgrid // point right behind the wall that is closer than any pathgrid // point outside the wall - osg::Vec3f startPointInLocalCoords(ToLocalCoordinates(startPoint, xCell, yCell)); + osg::Vec3f startPointInLocalCoords(converter.ToLocalVec3(startPoint)); int startNode = getClosestPoint(mPathgrid, startPointInLocalCoords); - osg::Vec3f endPointInLocalCoords(ToLocalCoordinates(endPoint, xCell, yCell)); + osg::Vec3f endPointInLocalCoords(converter.ToLocalVec3(endPoint)); std::pair endNode = getClosestReachablePoint(mPathgrid, cell, endPointInLocalCoords, startNode); @@ -229,6 +219,12 @@ namespace MWMechanics mPath = mCell->aStarSearch(startNode, endNode.first); assert(!mPath.empty()); + // convert supplied path to world co-ordinates + for (std::list::iterator iter(mPath.begin()); iter != mPath.end(); ++iter) + { + converter.ToWorld(*iter); + } + // If endNode found is NOT the closest PathGrid point to the endPoint, // assume endPoint is not reachable from endNode. In which case, // path ends at endNode. diff --git a/apps/openmw/mwmechanics/pathgrid.cpp b/apps/openmw/mwmechanics/pathgrid.cpp index 66af864ea..871baecdc 100644 --- a/apps/openmw/mwmechanics/pathgrid.cpp +++ b/apps/openmw/mwmechanics/pathgrid.cpp @@ -312,29 +312,15 @@ namespace MWMechanics if(current != goal) return path; // for some reason couldn't build a path - // reconstruct path to return, using world co-ordinates - int xCell = 0; - int yCell = 0; - if (mIsExterior) - { - xCell = mPathgrid->mData.mX * ESM::Land::REAL_SIZE; - yCell = mPathgrid->mData.mY * ESM::Land::REAL_SIZE; - } - + // reconstruct path to return, using local co-ordinates while(graphParent[current] != -1) { - ESM::Pathgrid::Point pt = mPathgrid->mPoints[current]; - pt.mX += xCell; - pt.mY += yCell; - path.push_front(pt); + path.push_front(mPathgrid->mPoints[current]); current = graphParent[current]; } // add first node to path explicitly - ESM::Pathgrid::Point pt = mPathgrid->mPoints[start]; - pt.mX += xCell; - pt.mY += yCell; - path.push_front(pt); + path.push_front(mPathgrid->mPoints[start]); return path; } } diff --git a/apps/openmw/mwrender/pathgrid.cpp b/apps/openmw/mwrender/pathgrid.cpp index 9fffd76d1..bd22446de 100644 --- a/apps/openmw/mwrender/pathgrid.cpp +++ b/apps/openmw/mwrender/pathgrid.cpp @@ -17,6 +17,7 @@ #include "../mwworld/cellstore.hpp" #include "../mwworld/esmstore.hpp" #include "../mwmechanics/pathfinding.hpp" +#include "../mwmechanics/coordinateconverter.hpp" #include "vismask.hpp" @@ -207,11 +208,7 @@ void Pathgrid::enableCellPathgrid(const MWWorld::CellStore *store) if (!pathgrid) return; osg::Vec3f cellPathGridPos(0, 0, 0); - if (store->getCell()->isExterior()) - { - cellPathGridPos.x() = static_cast(store->getCell()->mData.mX * ESM::Land::REAL_SIZE); - cellPathGridPos.y() = static_cast(store->getCell()->mData.mY * ESM::Land::REAL_SIZE); - } + MWMechanics::CoordinateConverter(store->getCell()).ToWorld(cellPathGridPos); osg::ref_ptr cellPathGrid = new osg::PositionAttitudeTransform; cellPathGrid->setPosition(cellPathGridPos);