From 7fa2c4667517eff75b954637214c739d1acea24f Mon Sep 17 00:00:00 2001 From: aclegg3 Date: Wed, 31 Aug 2022 16:37:49 -0700 Subject: [PATCH] added better API documentation for NavMeshSettings --- .../colabs/ECCV_2020_Navigation.ipynb | 2 + .../nb_python/ECCV_2020_Navigation.py | 2 + src/esp/bindings/ShortestPathBindings.cpp | 68 +++++++++++++------ src/esp/nav/PathFinder.h | 56 +++++++++++---- 4 files changed, 97 insertions(+), 31 deletions(-) diff --git a/examples/tutorials/colabs/ECCV_2020_Navigation.ipynb b/examples/tutorials/colabs/ECCV_2020_Navigation.ipynb index 1e83321adc..39b7b689b0 100644 --- a/examples/tutorials/colabs/ECCV_2020_Navigation.ipynb +++ b/examples/tutorials/colabs/ECCV_2020_Navigation.ipynb @@ -902,6 +902,8 @@ "\n", "When computing the NavMesh at runtime, configuration options are available to customize the result based on the intended use case.\n", "\n", + "To learn more, visit [this blog](http://digestingduck.blogspot.com/2009/08/recast-settings-uncovered.html) by the author of Recast.\n", + "\n", "These settings include (all quantities in world units):\n", "- **Voxelization parameters**:\n", "\n", diff --git a/examples/tutorials/nb_python/ECCV_2020_Navigation.py b/examples/tutorials/nb_python/ECCV_2020_Navigation.py index bc4cb2171f..3a37a98221 100644 --- a/examples/tutorials/nb_python/ECCV_2020_Navigation.py +++ b/examples/tutorials/nb_python/ECCV_2020_Navigation.py @@ -742,6 +742,8 @@ def display_map(topdown_map, key_points=None): # # When computing the NavMesh at runtime, configuration options are available to customize the result based on the intended use case. # +# To learn more, visit [this blog](http://digestingduck.blogspot.com/2009/08/recast-settings-uncovered.html) by the author of Recast. +# # These settings include (all quantities in world units): # - **Voxelization parameters**: # diff --git a/src/esp/bindings/ShortestPathBindings.cpp b/src/esp/bindings/ShortestPathBindings.cpp index a4d9099ea8..4c5984d528 100644 --- a/src/esp/bindings/ShortestPathBindings.cpp +++ b/src/esp/bindings/ShortestPathBindings.cpp @@ -51,25 +51,55 @@ void initShortestPathBindings(py::module& m) { py::class_(m, "NavMeshSettings") .def(py::init(&NavMeshSettings::create<>)) - .def_readwrite("cell_size", &NavMeshSettings::cellSize) - .def_readwrite("cell_height", &NavMeshSettings::cellHeight) - .def_readwrite("agent_height", &NavMeshSettings::agentHeight) - .def_readwrite("agent_radius", &NavMeshSettings::agentRadius) - .def_readwrite("agent_max_climb", &NavMeshSettings::agentMaxClimb) - .def_readwrite("agent_max_slope", &NavMeshSettings::agentMaxSlope) - .def_readwrite("region_min_size", &NavMeshSettings::regionMinSize) - .def_readwrite("region_merge_size", &NavMeshSettings::regionMergeSize) - .def_readwrite("edge_max_len", &NavMeshSettings::edgeMaxLen) - .def_readwrite("edge_max_error", &NavMeshSettings::edgeMaxError) - .def_readwrite("verts_per_poly", &NavMeshSettings::vertsPerPoly) - .def_readwrite("detail_sample_dist", &NavMeshSettings::detailSampleDist) - .def_readwrite("detail_sample_max_error", - &NavMeshSettings::detailSampleMaxError) - .def_readwrite("filter_low_hanging_obstacles", - &NavMeshSettings::filterLowHangingObstacles) - .def_readwrite("filter_ledge_spans", &NavMeshSettings::filterLedgeSpans) - .def_readwrite("filter_walkable_low_height_spans", - &NavMeshSettings::filterWalkableLowHeightSpans) + .def_readwrite( + "cell_size", &NavMeshSettings::cellSize, + R"(XZ-plane cell size in world units. Size of square voxel sides in XZ.)") + .def_readwrite("cell_height", &NavMeshSettings::cellHeight, + R"(Y-axis cell height in world units. Voxel height.)") + .def_readwrite( + "agent_height", &NavMeshSettings::agentHeight, + R"(Minimum floor to 'ceiling' height that will still allow the floor area to be considered unobstructed in world units. Will be rounded up to a multiple of cellHeight.)") + .def_readwrite( + "agent_radius", &NavMeshSettings::agentRadius, + R"(Agent radius in world units. The distance to erode/shrink the walkable area of the heightfield away from obstructions. Will be rounded up to a multiple of cellSize.)") + .def_readwrite( + "agent_max_climb", &NavMeshSettings::agentMaxClimb, + R"(Maximum ledge height that is considered to be traversable in world units (e.g. for stair steps). Will be truncated to a multiple of cellHeight.)") + .def_readwrite( + "agent_max_slope", &NavMeshSettings::agentMaxSlope, + R"(The maximum slope that is considered walkable in degrees.)") + .def_readwrite( + "region_min_size", &NavMeshSettings::regionMinSize, + R"(Region minimum size in voxels. regionMinSize = sqrt(regionMinArea) The minimum number of cells allowed to form isolated island areas.)") + .def_readwrite( + "region_merge_size", &NavMeshSettings::regionMergeSize, + R"(Region merge size in voxels. regionMergeSize = sqrt(regionMergeArea) Any 2-D regions with a smaller span (cell count) will, if possible, be merged with larger regions.)") + .def_readwrite( + "edge_max_len", &NavMeshSettings::edgeMaxLen, + R"(Edge max length in world units. The maximum allowed length for contour edges along the border of the mesh. Extra vertices will be inserted as needed to keep contour edges below this length. A value of zero effectively disables this feature. A good value for edgeMaxLen is something like agenRadius*8. Will be rounded to a multiple of cellSize.)") + .def_readwrite( + "edge_max_error", &NavMeshSettings::edgeMaxError, + R"(The maximum distance a simplfied contour's border edges should deviate the original raw contour. Good values are between 1.1-1.5 (1.3 usually yield good results). More results in jaggies, less cuts corners.)") + .def_readwrite( + "verts_per_poly", &NavMeshSettings::vertsPerPoly, + R"(The maximum number of vertices allowed for polygons generated during the contour to polygon conversion process. [Limit: >= 3])") + .def_readwrite( + "detail_sample_dist", &NavMeshSettings::detailSampleDist, + R"(Detail sample distance in voxels. Sets the sampling distance to use when generating the detail mesh. (For height detail only.) [Limits: 0 or >= 0.9] [x cell_size])") + .def_readwrite( + "detail_sample_max_error", &NavMeshSettings::detailSampleMaxError, + R"(Detail sample max error in voxel heights. The maximum distance the detail mesh surface should deviate from heightfield data. (For height detail only.) [Limit: >=0] [x cell_height])") + .def_readwrite( + "filter_low_hanging_obstacles", + &NavMeshSettings::filterLowHangingObstacles, + R"(Marks navigable spans as non-navigable if the clearence above the span is less than the specified height. Default True.)") + .def_readwrite( + "filter_ledge_spans", &NavMeshSettings::filterLedgeSpans, + R"(Marks spans that are ledges as non-navigable. This filter reduces the impact of the overestimation of conservative voxelization so the resulting mesh will not have regions hanging in the air over ledges. Default True.)") + .def_readwrite( + "filter_walkable_low_height_spans", + &NavMeshSettings::filterWalkableLowHeightSpans, + R"(Marks navigable spans as non-navigable if the clearence above the span is less than the specified height. Allows the formation of navigable regions that will flow over low lying objects such as curbs, and up structures such as stairways. Default True.)") .def("set_defaults", &NavMeshSettings::setDefaults) .def(py::self == py::self) .def(py::self != py::self); diff --git a/src/esp/nav/PathFinder.h b/src/esp/nav/PathFinder.h index 5450031178..e908bc161f 100644 --- a/src/esp/nav/PathFinder.h +++ b/src/esp/nav/PathFinder.h @@ -101,35 +101,67 @@ struct MultiGoalShortestPath { ESP_SMART_POINTERS_WITH_UNIQUE_PIMPL(MultiGoalShortestPath) }; +//! Configuration structure for NavMesh generation with recast. See +//! http://digestingduck.blogspot.com/2009/08/recast-settings-uncovered.html for +//! more details on configuring these parameters for your use case. struct NavMeshSettings { - //! Cell size in world units + //! XZ-plane cell size in world units. Size of square voxel sides in XZ. float cellSize{}; - //! Cell height in world units + //! Y-axis cell height in world units. Voxel height. float cellHeight{}; - //! Agent height in world units + //! Minimum floor to 'ceiling' height that will still allow the floor area to + //! be considered unobstructed in world units. Will be rounded up to a + //! multiple of cellHeight. float agentHeight{}; - //! Agent radius in world units + //! Agent radius in world units. The distance to erode/shrink the walkable + //! area of the heightfield away from obstructions. Will be rounded up to a + //! multiple of cellSize. float agentRadius{}; - //! Agent max climb in world units + //! Maximum ledge height that is considered to be traversable in world units + //! (e.g. for stair steps). Will be truncated to a multiple of cellHeight. float agentMaxClimb{}; - //! Agent max slope in degrees + //! The maximum slope that is considered walkable in degrees. float agentMaxSlope{}; - //! Region minimum size in voxels. regionMinSize = sqrt(regionMinArea) + //! Region minimum size in voxels. regionMinSize = sqrt(regionMinArea) The + //! minimum number of cells allowed to form isolated island areas. float regionMinSize{}; - //! Region merge size in voxels. regionMergeSize = sqrt(regionMergeArea) + //! Region merge size in voxels. regionMergeSize = sqrt(regionMergeArea) Any + //! 2-D regions with a smaller span (cell count) will, if possible, be merged + //! with larger regions. float regionMergeSize{}; - //! Edge max length in world units + //! Edge max length in world units. The maximum allowed length for contour + //! edges along the border of the mesh. Extra vertices will be inserted as + //! needed to keep contour edges below this length. A value of zero + //! effectively disables this feature. A good value for edgeMaxLen is + //! something like agenRadius*8. Will be rounded to a multiple of cellSize. float edgeMaxLen{}; - //! Edge max error in voxels + //! The maximum distance a simplfied contour's border edges should deviate the + //! original raw contour. Good values are between 1.1-1.5 (1.3 usually yield + //! good results). More results in jaggies, less cuts corners. float edgeMaxError{}; + //! The maximum number of vertices allowed for polygons generated during the + //! contour to polygon conversion process. [Limit: >= 3] float vertsPerPoly{}; - //! Detail sample distance in voxels + //! Detail sample distance in voxels. Sets the sampling distance to use when + //! generating the detail mesh. (For height detail only.) [Limits: 0 or >= + //! 0.9] [x cell_size] float detailSampleDist{}; - //! Detail sample max error in voxel heights. + //! Detail sample max error in voxel heights. The maximum distance the detail + //! mesh surface should deviate from heightfield data. (For height detail + //! only.) [Limit: >=0] [x cell_height] float detailSampleMaxError{}; + //! Marks navigable spans as non-navigable if the clearence above the span is + //! less than the specified height. bool filterLowHangingObstacles{}; + //! Marks spans that are ledges as non-navigable. This filter reduces the + //! impact of the overestimation of conservative voxelization so the resulting + //! mesh will not have regions hanging in the air over ledges. bool filterLedgeSpans{}; + //! Marks navigable spans as non-navigable if the clearence above the span is + //! less than the specified height. Allows the formation of navigable regions + //! that will flow over low lying objects such as curbs, and up structures + //! such as stairways. bool filterWalkableLowHeightSpans{}; void setDefaults() {