From e1525f86f47afbcd7268a44b90430c81f17e7888 Mon Sep 17 00:00:00 2001 From: devw4r <108442943+devw4r@users.noreply.github.com> Date: Thu, 11 Jul 2024 22:06:18 -0600 Subject: [PATCH] Python bindings. - Add HasADTs() - Add FindPointInBetweenVectors() --- pathfind/Map.cpp | 56 +++++++++++++++++++++++++++++++++++++++++++++ pathfind/Map.hpp | 6 +++++ pathfind/python.cpp | 31 +++++++++++++++++++++++++ utility/Vector.hpp | 6 +++++ 4 files changed, 99 insertions(+) diff --git a/pathfind/Map.cpp b/pathfind/Map.cpp index cad99e9..33932f6 100644 --- a/pathfind/Map.cpp +++ b/pathfind/Map.cpp @@ -407,6 +407,18 @@ std::shared_ptr Map::EnsureWmoModelLoaded(const std::string& mpq_path) return model; } +bool Map::HasADTs() const +{ + for (int y = 0; y < MeshSettings::Adts; ++y) + for (int x = 0; x < MeshSettings::Adts; ++x) { + if (m_hasADT[x][y]) { + return true; + } + } + + return false; +} + bool Map::HasADT(int x, int y) const { return m_hasADT[x][y]; @@ -720,6 +732,50 @@ bool Map::FindNextZ(const Tile* tile, float x, float y, float zHint, return true; } +bool Map::FindPointInBetweenVectors(const math::Vertex& start, const math::Vertex& end, + const float distance, + math::Vertex& inBetweenPoint) const +{ + const float generalDistance = math::Vector3::GetDistance(start, end); + if (generalDistance < distance) { + return false; + } + + const float factor = distance / generalDistance; + const float dx = start.X + factor * (end.X - start.X); + const float dy = start.Y + factor * (end.Y - start.Y); + constexpr float extents[] = {1.f, 1.f, 1.f}; + + const math::Vertex v1 {dx, dy, start.Z}; + const math::Vertex v2 {dx, dy, end.Z}; + + + float recastMiddle[3]; + math::Convert::VertexToRecast(v1, recastMiddle); + + dtPolyRef polyRef; + if (m_navQuery.findNearestPoly(recastMiddle, extents, &m_queryFilter, + &polyRef, nullptr) != DT_SUCCESS) + { + math::Convert::VertexToRecast(v2, recastMiddle); + if (m_navQuery.findNearestPoly(recastMiddle, extents, &m_queryFilter, + &polyRef, nullptr) != DT_SUCCESS) + { + return false; + } + } + + float outputPoint[3]; + if (m_navQuery.closestPointOnPoly(polyRef, recastMiddle, outputPoint, NULL) != + DT_SUCCESS) { + return false; + } + + math::Convert::VertexToWow(outputPoint, inBetweenPoint); + + return true; +} + bool Map::FindRandomPointAroundCircle(const math::Vertex& centerPosition, const float radius, math::Vertex& randomPoint) const diff --git a/pathfind/Map.hpp b/pathfind/Map.hpp index 7573e65..b25ded0 100644 --- a/pathfind/Map.hpp +++ b/pathfind/Map.hpp @@ -110,6 +110,7 @@ class Map Map(const std::filesystem::path& dataPath, const std::string& mapName); bool HasADT(int x, int y) const; + bool HasADTs() const; bool IsADTLoaded(int x, int y) const; bool LoadADT(int x, int y); void UnloadADT(int x, int y); @@ -159,6 +160,11 @@ class Map float radius, math::Vertex& randomPoint) const; + bool FindPointInBetweenVectors(const math::Vertex& start, + const math::Vertex& end, + const float distance, + math::Vertex& inBetweenPoint) const; + const dtNavMesh& GetNavMesh() const { return m_navMesh; } const dtNavMeshQuery& GetNavMeshQuery() const { return m_navQuery; } }; diff --git a/pathfind/python.cpp b/pathfind/python.cpp index cc8eb16..8bb3636 100644 --- a/pathfind/python.cpp +++ b/pathfind/python.cpp @@ -66,6 +66,10 @@ bool adt_loaded(pathfind::Map& map, int adt_x, int adt_y) { return map.IsADTLoaded(adt_x, adt_y); } +bool has_adts(pathfind::Map& map) { + return map.HasADTs(); +} + py::list python_query_heights(const pathfind::Map& map, float x, float y) { py::list result; @@ -106,6 +110,18 @@ py::object get_zone_and_area(pathfind::Map& map, float x, float y, float z) return py::make_tuple(zone, area); } +py::object find_point_in_between_vectors(pathfind::Map& map, float distance, float x1, float y1, float z1, float x2, float y2, float z2) +{ + const math::Vertex start {x1, y1, z1}; + const math::Vertex end {x2, y2, z2}; + math::Vertex in_between_point {}; + if (!map.FindPointInBetweenVectors(start, end, distance, in_between_point)) { + return py::none(); + } + + return py::make_tuple(in_between_point.X, in_between_point.Y, in_between_point.Z); +} + py::object find_random_point_around_circle(pathfind::Map& map, float x, float y, float z, float radius) { const math::Vertex start {x, y, z}; @@ -181,6 +197,17 @@ This is the value that would be achieved by walking from start to stop.)del", py::arg("y"), py::arg("z") ) + .def("find_point_in_between_vectors", + &find_point_in_between_vectors, + "Returns a point in between two vectors given a distance.", + py::arg("distance"), + py::arg("x1"), + py::arg("y1"), + py::arg("z1"), + py::arg("x2"), + py::arg("y2"), + py::arg("z2") + ) .def("find_random_point_around_circle", &find_random_point_around_circle, "Returns a random point from a circle within or slightly outside of the given radius.", @@ -189,6 +216,10 @@ This is the value that would be achieved by walking from start to stop.)del", py::arg("z"), py::arg("radius") ) + .def("has_adts", + &has_adts, + "Checks if the map has any ADT." + ) .def("adt_loaded", &adt_loaded, "Checks if a specific ADT is loaded.", diff --git a/utility/Vector.hpp b/utility/Vector.hpp index 5f30e34..76eabda 100644 --- a/utility/Vector.hpp +++ b/utility/Vector.hpp @@ -25,6 +25,12 @@ struct Vector3 static Vector3 CrossProduct(const Vector3& a, const Vector3& b); static Vector3 Normalize(const Vector3& a); static Vector3 Transform(const Vector3& position, const Matrix& matrix); + static float GetDistance(const Vector3& a, const Vector3& b) + { + return std::sqrt(std::pow((a.X - b.X), 2) + + std::pow((a.Y - b.Y), 2) + + std::pow((a.Z - b.Z), 2)); + } float X; float Y;