From 8117773c568e729b410bc4b7a5e3348b1f5202e9 Mon Sep 17 00:00:00 2001 From: David Markowitz Date: Sun, 6 Aug 2023 15:41:38 -0700 Subject: [PATCH 1/4] Add path height correction on world load --- dNavigation/dNavMesh.cpp | 4 ++-- dNavigation/dNavMesh.h | 10 +++++++++- dZoneManager/CMakeLists.txt | 3 ++- dZoneManager/Zone.cpp | 12 +++++++++--- 4 files changed, 22 insertions(+), 7 deletions(-) diff --git a/dNavigation/dNavMesh.cpp b/dNavigation/dNavMesh.cpp index fdba4a2d4..c3366299e 100644 --- a/dNavigation/dNavMesh.cpp +++ b/dNavigation/dNavMesh.cpp @@ -118,7 +118,7 @@ void dNavMesh::LoadNavmesh() { m_NavMesh = mesh; } -float dNavMesh::GetHeightAtPoint(const NiPoint3& location) { +float dNavMesh::GetHeightAtPoint(const NiPoint3& location, const float halfExtentsHeight) const { if (m_NavMesh == nullptr) { return location.y; } @@ -130,7 +130,7 @@ float dNavMesh::GetHeightAtPoint(const NiPoint3& location) { pos[2] = location.z; dtPolyRef nearestRef = 0; - float polyPickExt[3] = { 32.0f, 32.0f, 32.0f }; + float polyPickExt[3] = { 32.0f, halfExtentsHeight, 32.0f }; dtQueryFilter filter{}; m_NavQuery->findNearestPoly(pos, polyPickExt, &filter, &nearestRef, 0); diff --git a/dNavigation/dNavMesh.h b/dNavigation/dNavMesh.h index dc3db854e..600b8b868 100644 --- a/dNavigation/dNavMesh.h +++ b/dNavigation/dNavMesh.h @@ -15,7 +15,15 @@ class dNavMesh { dNavMesh(uint32_t zoneId); ~dNavMesh(); - float GetHeightAtPoint(const NiPoint3& location); + /** + * Get the height at a point + * + * @param location The location to check for height at. This is the center of the search area. + * @param halfExtentsHeight The half extents height of the search area. This is the distance from the center to the top and bottom of the search area. + * The larger the value of halfExtentsHeight is, the larger the performance cost of the query. + * @return float The height at the point. If the point is not on the navmesh, the height of the point is returned. + */ + float GetHeightAtPoint(const NiPoint3& location, const float halfExtentsHeight = 32.0f) const; std::vector GetPath(const NiPoint3& startPos, const NiPoint3& endPos, float speed = 10.0f); class dtNavMesh* GetdtNavMesh() { return m_NavMesh; } diff --git a/dZoneManager/CMakeLists.txt b/dZoneManager/CMakeLists.txt index 1dd3841b7..bbb22ba7d 100644 --- a/dZoneManager/CMakeLists.txt +++ b/dZoneManager/CMakeLists.txt @@ -3,4 +3,5 @@ set(DZONEMANAGER_SOURCES "dZoneManager.cpp" "Spawner.cpp" "Zone.cpp") -add_library(dZoneManager STATIC ${DZONEMANAGER_SOURCES}) +add_library(dZoneManager STATIC ${DZONEMANAGER_SOURCES}) +target_link_libraries(dZoneManager dPhysics) diff --git a/dZoneManager/Zone.cpp b/dZoneManager/Zone.cpp index 6b1537063..534e18b3f 100644 --- a/dZoneManager/Zone.cpp +++ b/dZoneManager/Zone.cpp @@ -13,6 +13,7 @@ #include "CDZoneTableTable.h" #include "Spawner.h" #include "dZoneManager.h" +#include "dpWorld.h" #include "eTriggerCommandType.h" #include "eTriggerEventType.h" @@ -544,10 +545,15 @@ void Zone::LoadPath(std::istream& file) { } } + // We verify the waypoint heights against the navmesh because in many movement paths, + // the waypoint is located near 0 height, + if (path.pathType == PathType::Movement) { + if (dpWorld::Instance().IsLoaded()) { + // 1000 should be large enough for every world. + waypoint.position.y = dpWorld::Instance().GetNavMesh()->GetHeightAtPoint(waypoint.position, 1000.0f); + } + } path.pathWaypoints.push_back(waypoint); } - - - m_Paths.push_back(path); } From 600f0974e7244f99d2eac8265eeda95b4e2a6513 Mon Sep 17 00:00:00 2001 From: David Markowitz Date: Sun, 6 Aug 2023 16:06:12 -0700 Subject: [PATCH 2/4] Increase height because Nexus Tower is tall --- dZoneManager/Zone.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dZoneManager/Zone.cpp b/dZoneManager/Zone.cpp index 534e18b3f..2d68b31e2 100644 --- a/dZoneManager/Zone.cpp +++ b/dZoneManager/Zone.cpp @@ -549,8 +549,8 @@ void Zone::LoadPath(std::istream& file) { // the waypoint is located near 0 height, if (path.pathType == PathType::Movement) { if (dpWorld::Instance().IsLoaded()) { - // 1000 should be large enough for every world. - waypoint.position.y = dpWorld::Instance().GetNavMesh()->GetHeightAtPoint(waypoint.position, 1000.0f); + // 2000 should be large enough for every world. + waypoint.position.y = dpWorld::Instance().GetNavMesh()->GetHeightAtPoint(waypoint.position, 2000.0f); } } path.pathWaypoints.push_back(waypoint); From 8da23df5d6c786d4746c6ef0d6de4f9183f0ea26 Mon Sep 17 00:00:00 2001 From: David Markowitz Date: Tue, 8 Aug 2023 22:25:00 -0700 Subject: [PATCH 3/4] Update height checker - Only go up and down, do not deviate from the point you are on - As a backup, use the nearestPoint on the nearestPoly, should detour be able to find one. - Add a debug assert to fail the program should toReturn differ from nearestPoint[1]. Update dNavMesh.cpp Update dNavMesh.cpp --- dNavigation/dNavMesh.cpp | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/dNavigation/dNavMesh.cpp b/dNavigation/dNavMesh.cpp index c3366299e..c91198939 100644 --- a/dNavigation/dNavMesh.cpp +++ b/dNavigation/dNavMesh.cpp @@ -10,6 +10,7 @@ #include "BinaryPathFinder.h" #include "dZoneManager.h" +#include "DluAssert.h" dNavMesh::dNavMesh(uint32_t zoneId) { m_ZoneId = zoneId; @@ -130,15 +131,25 @@ float dNavMesh::GetHeightAtPoint(const NiPoint3& location, const float halfExten pos[2] = location.z; dtPolyRef nearestRef = 0; - float polyPickExt[3] = { 32.0f, halfExtentsHeight, 32.0f }; + float polyPickExt[3] = { 0.0f, halfExtentsHeight, 0.0f }; + float nearestPoint[3] = { 0.0f, 0.0f, 0.0f }; dtQueryFilter filter{}; - m_NavQuery->findNearestPoly(pos, polyPickExt, &filter, &nearestRef, 0); + auto hasPoly = m_NavQuery->findNearestPoly(pos, polyPickExt, &filter, &nearestRef, nearestPoint); m_NavQuery->getPolyHeight(nearestRef, pos, &toReturn); - +#ifdef _DEBUG + if (toReturn != 0.0f) { + DluAssert(toReturn == nearestPoint[1]); + } +#endif if (toReturn == 0.0f) { toReturn = location.y; + // If we were unable to get the poly height, but the query returned a success, just use the height of the nearest point. + // This is what seems to happen anyways and it is better than returning zero. + } else if (hasPoly == DT_SUCCESS) { + toReturn = nearestPoint[1]; } + // If we failed to even find a poly, do not change the height since we have no idea what it should be. return toReturn; } From 7388d47b90eb74c85735a7b7e1c2f2a6e4573d4c Mon Sep 17 00:00:00 2001 From: David Markowitz Date: Wed, 9 Aug 2023 00:05:37 -0700 Subject: [PATCH 4/4] Fix if condition to actually return the value... --- dNavigation/dNavMesh.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/dNavigation/dNavMesh.cpp b/dNavigation/dNavMesh.cpp index c91198939..14b59055f 100644 --- a/dNavigation/dNavMesh.cpp +++ b/dNavigation/dNavMesh.cpp @@ -143,11 +143,13 @@ float dNavMesh::GetHeightAtPoint(const NiPoint3& location, const float halfExten } #endif if (toReturn == 0.0f) { - toReturn = location.y; - // If we were unable to get the poly height, but the query returned a success, just use the height of the nearest point. - // This is what seems to happen anyways and it is better than returning zero. - } else if (hasPoly == DT_SUCCESS) { - toReturn = nearestPoint[1]; + // If we were unable to get the poly height, but the query returned a success, just use the height of the nearest point. + // This is what seems to happen anyways and it is better than returning zero. + if (hasPoly == DT_SUCCESS) { + toReturn = nearestPoint[1]; + } else { + toReturn = location.y; + } } // If we failed to even find a poly, do not change the height since we have no idea what it should be.