#ifndef OPENMW_COMPONENTS_DETOURNAVIGATOR_SETTINGSUTILS_H #define OPENMW_COMPONENTS_DETOURNAVIGATOR_SETTINGSUTILS_H #include "settings.hpp" #include "tilebounds.hpp" #include "tileposition.hpp" #include #include #include #include namespace DetourNavigator { inline float toNavMeshCoordinates(const RecastSettings& settings, float value) { return value * settings.mRecastScaleFactor; } inline osg::Vec2f toNavMeshCoordinates(const RecastSettings& settings, osg::Vec2f position) { return position * settings.mRecastScaleFactor; } inline osg::Vec3f toNavMeshCoordinates(const RecastSettings& settings, osg::Vec3f position) { std::swap(position.y(), position.z()); return position * settings.mRecastScaleFactor; } inline TileBounds toNavMeshCoordinates(const RecastSettings& settings, const TileBounds& value) { return TileBounds{ toNavMeshCoordinates(settings, value.mMin), toNavMeshCoordinates(settings, value.mMax) }; } inline float fromNavMeshCoordinates(const RecastSettings& settings, float value) { return value / settings.mRecastScaleFactor; } inline osg::Vec3f fromNavMeshCoordinates(const RecastSettings& settings, osg::Vec3f position) { const auto factor = 1.0f / settings.mRecastScaleFactor; position *= factor; std::swap(position.y(), position.z()); return position; } // Returns value in NavMesh coordinates inline float getTileSize(const RecastSettings& settings) { return static_cast(settings.mTileSize) * settings.mCellSize; } inline int getTilePosition(const RecastSettings& settings, float position) { const float v = std::floor(position / getTileSize(settings)); if (v < static_cast(std::numeric_limits::min())) return std::numeric_limits::min(); if (v > static_cast(std::numeric_limits::max() - 1)) return std::numeric_limits::max() - 1; return static_cast(v); } // Returns integer tile position for position in navmesh coordinates inline TilePosition getTilePosition(const RecastSettings& settings, const osg::Vec2f& position) { return TilePosition(getTilePosition(settings, position.x()), getTilePosition(settings, position.y())); } // Returns integer tile position for position in navmesh coordinates inline TilePosition getTilePosition(const RecastSettings& settings, const osg::Vec3f& position) { return getTilePosition(settings, osg::Vec2f(position.x(), position.z())); } // Returns tile bounds in navmesh coordinates inline TileBounds makeTileBounds(const RecastSettings& settings, const TilePosition& tilePosition) { return TileBounds{ osg::Vec2f(tilePosition.x(), tilePosition.y()) * getTileSize(settings), osg::Vec2f(tilePosition.x() + 1, tilePosition.y() + 1) * getTileSize(settings), }; } // Returns border size relative to cell size inline float getBorderSize(const RecastSettings& settings) { return static_cast(settings.mBorderSize) * settings.mCellSize; } inline float getRealTileSize(const RecastSettings& settings) { return settings.mTileSize * settings.mCellSize / settings.mRecastScaleFactor; } inline float getMaxNavmeshAreaRadius(const Settings& settings) { return std::floor(std::sqrt(settings.mMaxTilesNumber / osg::PI)) - 1; } // Returns tile bounds in real coordinates inline TileBounds makeRealTileBoundsWithBorder(const RecastSettings& settings, const TilePosition& tilePosition) { TileBounds result = makeTileBounds(settings, tilePosition); const float border = getBorderSize(settings); result.mMin -= osg::Vec2f(border, border); result.mMax += osg::Vec2f(border, border); result.mMin /= settings.mRecastScaleFactor; result.mMax /= settings.mRecastScaleFactor; return result; } } #endif