From a0600b4ca3fc4fbd38341c2b785f0651cd719718 Mon Sep 17 00:00:00 2001 From: Brendan Finney LoBuglio Date: Mon, 14 Jan 2019 17:39:23 -0800 Subject: [PATCH 1/2] ClampLocationToNavigableWorld pulls in the result by a tiny margin, fixing a crash where locations that get clamped to a maximum world dimension would then round to an invalid index in VolumeIdAt (e.g. clamping 150 to 100, which then rounds to invalid index 100 instead of 99 in a 100-voxel world) --- .../DonAINavigation/Classes/DonNavigationManager.h | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/Source/DonAINavigation/Classes/DonNavigationManager.h b/Source/DonAINavigation/Classes/DonNavigationManager.h index a2108a9..c2e41d7 100644 --- a/Source/DonAINavigation/Classes/DonNavigationManager.h +++ b/Source/DonAINavigation/Classes/DonNavigationManager.h @@ -998,17 +998,20 @@ class DONAINAVIGATION_API ADonNavigationManager : public AActor return VolumeAtSafe(x, y, z); } - /* Clamps a vector to the navigation bounds as defined by the grid configuration of the navigation object you've placed in the map*/ + /* Clamps a vector within the navigation bounds, as defined by the grid configuration of the navigation object you've placed in the map, + * brought in by a margin of InnerMarginOffset */ UFUNCTION(BlueprintPure, Category = "DoN Navigation") - FVector ClampLocationToNavigableWorld(FVector DesiredLocation) + FVector ClampLocationToNavigableWorld(FVector DesiredLocation, float InnerMarginOffset = 0.001f) { if (bIsUnbound) return DesiredLocation; FVector origin = GetActorLocation(); - float xClamped = FMath::Clamp(DesiredLocation.X, origin.X, origin.X + XGridSize * VoxelSize); - float yClamped = FMath::Clamp(DesiredLocation.Y, origin.Y, origin.Y + YGridSize * VoxelSize); - float zClamped = FMath::Clamp(DesiredLocation.Z, origin.Z, origin.Z + ZGridSize * VoxelSize); + // We bring the clamped vector in by an extra innerMarginOffset cm. Necessary because VolumeIdAt does a float-to-int rounding, and thus clamping + // to a max world dimension would otherwise round to an invalid index (e.g. rounding to index 100 instead of 99 in a 100-voxel world) + float xClamped = FMath::Clamp(DesiredLocation.X, origin.X + innerMarginOffset, origin.X + XGridSize * VoxelSize - innerMarginOffset); + float yClamped = FMath::Clamp(DesiredLocation.Y, origin.Y + innerMarginOffset, origin.Y + YGridSize * VoxelSize - innerMarginOffset); + float zClamped = FMath::Clamp(DesiredLocation.Z, origin.Z + innerMarginOffset, origin.Z + ZGridSize * VoxelSize - innerMarginOffset); return FVector(xClamped, yClamped, zClamped); } From 844ae3fd0d3298a01c6b920ab79d5935c46ff6fe Mon Sep 17 00:00:00 2001 From: BrendanLoBuglio Date: Tue, 15 Jan 2019 14:03:24 -0800 Subject: [PATCH 2/2] No longer applying the margin for clamping up values that were too low, as the rounding bug doesn't apply to that case. Fixed a capitalization error. Better comment. --- .../DonAINavigation/Classes/DonNavigationManager.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Source/DonAINavigation/Classes/DonNavigationManager.h b/Source/DonAINavigation/Classes/DonNavigationManager.h index c2e41d7..0b55fd1 100644 --- a/Source/DonAINavigation/Classes/DonNavigationManager.h +++ b/Source/DonAINavigation/Classes/DonNavigationManager.h @@ -998,8 +998,8 @@ class DONAINAVIGATION_API ADonNavigationManager : public AActor return VolumeAtSafe(x, y, z); } - /* Clamps a vector within the navigation bounds, as defined by the grid configuration of the navigation object you've placed in the map, - * brought in by a margin of InnerMarginOffset */ + /** Clamps a vector within the navigation bounds, as defined by the grid configuration of the navigation object you've placed in the map, + * brought in by a margin of InnerMarginOffset when clamping downward to prevent rounding errors */ UFUNCTION(BlueprintPure, Category = "DoN Navigation") FVector ClampLocationToNavigableWorld(FVector DesiredLocation, float InnerMarginOffset = 0.001f) { @@ -1007,11 +1007,11 @@ class DONAINAVIGATION_API ADonNavigationManager : public AActor return DesiredLocation; FVector origin = GetActorLocation(); - // We bring the clamped vector in by an extra innerMarginOffset cm. Necessary because VolumeIdAt does a float-to-int rounding, and thus clamping - // to a max world dimension would otherwise round to an invalid index (e.g. rounding to index 100 instead of 99 in a 100-voxel world) - float xClamped = FMath::Clamp(DesiredLocation.X, origin.X + innerMarginOffset, origin.X + XGridSize * VoxelSize - innerMarginOffset); - float yClamped = FMath::Clamp(DesiredLocation.Y, origin.Y + innerMarginOffset, origin.Y + YGridSize * VoxelSize - innerMarginOffset); - float zClamped = FMath::Clamp(DesiredLocation.Z, origin.Z + innerMarginOffset, origin.Z + ZGridSize * VoxelSize - innerMarginOffset); + // When clamping down, bring the vector in by an extra InnerMarginOffset cm. Necessary because VolumeIdAt does a float-to-int rounding, and thus clamping + // to a max world dimension would otherwise round to an invalid index (e.g. rounding 100.5 to invalid index 100 instead of 99 in a 100-voxel world) + float xClamped = FMath::Clamp(DesiredLocation.X, origin.X, origin.X + XGridSize * VoxelSize - InnerMarginOffset); + float yClamped = FMath::Clamp(DesiredLocation.Y, origin.Y, origin.Y + YGridSize * VoxelSize - InnerMarginOffset); + float zClamped = FMath::Clamp(DesiredLocation.Z, origin.Z, origin.Z + ZGridSize * VoxelSize - InnerMarginOffset); return FVector(xClamped, yClamped, zClamped); }