From a871e785af99dc0a613bc3df34681249982ecee6 Mon Sep 17 00:00:00 2001 From: Tim Blume Date: Thu, 6 Jun 2024 22:58:42 +0200 Subject: [PATCH] stuff --- CMakeLists.txt | 1 - godot-cpp | 2 +- src/RecastConfig.cpp | 58 ++++++++++++++++- src/RecastConfig.hpp | 57 ++++++++++++----- src/RecastContext.cpp | 17 +++++ src/RecastContext.hpp | 19 ++++++ src/RecastNavMesh.cpp | 141 +++++++++++++++++++++++++++++++++++------- src/RecastNavMesh.hpp | 124 +++++++++++++++++++++++++++++++++++-- src/registration.cpp | 2 - 9 files changed, 372 insertions(+), 49 deletions(-) create mode 100644 src/RecastContext.cpp create mode 100644 src/RecastContext.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 3ce6919..fe04474 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -12,7 +12,6 @@ add_subdirectory(recastnavigation) add_library(godot-recast-navigation SHARED src/registration.cpp -src/RecastConfig.cpp src/RecastNavMesh.cpp ) diff --git a/godot-cpp b/godot-cpp index a62f633..21d526e 160000 --- a/godot-cpp +++ b/godot-cpp @@ -1 +1 @@ -Subproject commit a62f633cebee4b36356dc903d00670733cd28fb1 +Subproject commit 21d526e5e5b1e5d8b6be4db05a704c2c2e7837a9 diff --git a/src/RecastConfig.cpp b/src/RecastConfig.cpp index 7bc33f5..437404a 100644 --- a/src/RecastConfig.cpp +++ b/src/RecastConfig.cpp @@ -7,24 +7,78 @@ godot::RecastConfig::~RecastConfig() { } void godot::RecastConfig::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_width", "width"), &RecastConfig::set_width); - ClassDB::bind_method(D_METHOD("set_height", "height"), &RecastConfig::set_height); + ClassDB::bind_method(D_METHOD("get_width"), &RecastConfig::get_width); + ClassDB::bind_method(D_METHOD("get_height"), &RecastConfig::get_height); + ClassDB::bind_method(D_METHOD("set_tile_size", "tile_size"), &RecastConfig::set_tile_size); + ClassDB::bind_method(D_METHOD("get_tile_size"), &RecastConfig::get_tile_size); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "tile_size"), "set_tile_size", "get_tile_size"); + ClassDB::bind_method(D_METHOD("set_border_size", "border_size"), &RecastConfig::set_border_size); + ClassDB::bind_method(D_METHOD("get_border_size"), &RecastConfig::get_border_size); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "border_size"), "set_border_size", "get_border_size"); + ClassDB::bind_method(D_METHOD("set_cs", "cs"), &RecastConfig::set_cs); + ClassDB::bind_method(D_METHOD("get_cs"), &RecastConfig::get_cs); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "cell_size"), "set_cs", "get_cs"); + ClassDB::bind_method(D_METHOD("set_ch", "ch"), &RecastConfig::set_ch); + ClassDB::bind_method(D_METHOD("get_ch"), &RecastConfig::get_ch); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "cell_height"), "set_ch", "get_ch"); + ClassDB::bind_method(D_METHOD("set_bmin", "bmin"), &RecastConfig::set_bmin); + ClassDB::bind_method(D_METHOD("get_bmin"), &RecastConfig::get_bmin); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "bounds_min"), "set_bmin", "get_bmin"); + ClassDB::bind_method(D_METHOD("set_bmax", "bmax"), &RecastConfig::set_bmax); + ClassDB::bind_method(D_METHOD("get_bmax"), &RecastConfig::get_bmax); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "bounds_max"), "set_bmax", "get_bmax"); + ClassDB::bind_method(D_METHOD("set_walkable_slope_angle", "walkable_slope_angle"), &RecastConfig::set_walkable_slope_angle); + ClassDB::bind_method(D_METHOD("get_walkable_slope_angle"), &RecastConfig::get_walkable_slope_angle); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "walkable_slope_angle"), "set_walkable_slope_angle", "get_walkable_slope_angle"); + ClassDB::bind_method(D_METHOD("set_walkable_height", "walkable_height"), &RecastConfig::set_walkable_height); + ClassDB::bind_method(D_METHOD("get_walkable_height"), &RecastConfig::get_walkable_height); + ADD_PROPERTY(PropertyInfo(Variant::INT, "walkable_height"), "set_walkable_height", "get_walkable_height"); + ClassDB::bind_method(D_METHOD("set_walkable_climb", "walkable_climb"), &RecastConfig::set_walkable_climb); + ClassDB::bind_method(D_METHOD("get_walkable_climb"), &RecastConfig::get_walkable_climb); + ADD_PROPERTY(PropertyInfo(Variant::INT, "walkable_climb"), "set_walkable_climb", "get_walkable_climb"); + ClassDB::bind_method(D_METHOD("set_walkable_radius", "walkable_radius"), &RecastConfig::set_walkable_radius); + ClassDB::bind_method(D_METHOD("get_walkable_radius"), &RecastConfig::get_walkable_radius); + ADD_PROPERTY(PropertyInfo(Variant::INT, "walkable_radius"), "set_walkable_radius", "get_walkable_radius"); + ClassDB::bind_method(D_METHOD("set_max_edge_len", "max_edge_len"), &RecastConfig::set_max_edge_len); + ClassDB::bind_method(D_METHOD("get_max_edge_len"), &RecastConfig::get_max_edge_len); + ADD_PROPERTY(PropertyInfo(Variant::INT, "max_edge_length"), "set_max_edge_len", "get_max_edge_len"); + ClassDB::bind_method(D_METHOD("set_max_simplification_error", "max_simplification_error"), &RecastConfig::set_max_simplification_error); + ClassDB::bind_method(D_METHOD("get_max_simplification_error"), &RecastConfig::get_max_simplification_error); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "max_simplification_error"), "set_max_simplification_error", "get_max_simplification_error"); + ClassDB::bind_method(D_METHOD("set_min_region_area", "min_region_area"), &RecastConfig::set_min_region_area); + ClassDB::bind_method(D_METHOD("get_min_region_area"), &RecastConfig::get_min_region_area); + ADD_PROPERTY(PropertyInfo(Variant::INT, "min_region_area"), "set_min_region_area", "get_min_region_area"); + ClassDB::bind_method(D_METHOD("set_merge_region_area", "merge_region_area"), &RecastConfig::set_merge_region_area); + ClassDB::bind_method(D_METHOD("get_merge_region_area"), &RecastConfig::get_merge_region_area); + ADD_PROPERTY(PropertyInfo(Variant::INT, "merge_region_area"), "set_merge_region_area", "get_merge_region_area"); + ClassDB::bind_method(D_METHOD("set_max_verts_per_poly", "max_verts_per_poly"), &RecastConfig::set_max_verts_per_poly); + ClassDB::bind_method(D_METHOD("get_max_verts_per_poly"), &RecastConfig::get_max_verts_per_poly); + ADD_PROPERTY(PropertyInfo(Variant::INT, "max_verts_per_poly"), "set_max_verts_per_poly", "get_max_verts_per_poly"); + ClassDB::bind_method(D_METHOD("set_detail_sample_dist", "detail_sample_dist"), &RecastConfig::set_detail_sample_dist); + ClassDB::bind_method(D_METHOD("get_detail_sample_dist"), &RecastConfig::get_detail_sample_dist); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "detail_sample_dist"), "set_detail_sample_dist", "get_detail_sample_dist"); + ClassDB::bind_method(D_METHOD("set_detail_sample_max_error", "detail_sample_max_error"), &RecastConfig::set_detail_sample_max_error); + ClassDB::bind_method(D_METHOD("get_detail_sample_max_error"), &RecastConfig::get_detail_sample_max_error); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "detail_sample_max_error"), "set_detail_sample_max_error", "get_detail_sample_max_error"); + ClassDB::bind_method(D_METHOD("set_partition_type", "partition_type"), &RecastConfig::set_partition_type); + ClassDB::bind_method(D_METHOD("get_partition_type"), &RecastConfig::get_partition_type); + ADD_PROPERTY(PropertyInfo(Variant::INT, "partition_type", PROPERTY_HINT_ENUM, "Watershed,Monotone,Layers"), "set_partition_type", "get_partition_type"); } diff --git a/src/RecastConfig.hpp b/src/RecastConfig.hpp index 6a0e95c..4f0d1af 100644 --- a/src/RecastConfig.hpp +++ b/src/RecastConfig.hpp @@ -4,12 +4,7 @@ #include "godot_cpp/classes/object.hpp" #include "godot_cpp/classes/node3d.hpp" - -enum RecastPartitionTypes { - WATERSHED, - MONOTONE, - LAYERS -}; +#include "godot_cpp/variant/string.hpp" namespace godot { struct RecastConfig : public Object { @@ -19,64 +14,93 @@ protected: static void _bind_methods(); public: rcConfig config; - RecastPartitionTypes partition_type = WATERSHED; + RecastPartitionType partition_type = WATERSHED; RecastConfig(); ~RecastConfig(); /// The width of the field along the x-axis. [Limit: >= 0] [Units: vx] - void set_width(int width) { config.width = width; } + int get_width() { return config.width; } /// The height of the field along the z-axis. [Limit: >= 0] [Units: vx] - void set_height(int height) { config.height = height; } + int get_height() { return config.height; } /// The width/height size of tile's on the xz-plane. [Limit: >= 0] [Units: vx] void set_tile_size(float tile_size) { config.tileSize = tile_size; } + float get_tile_size() { return config.tileSize; } /// The size of the non-navigable border around the heightfield. [Limit: >=0] [Units: vx] void set_border_size(int border_size) { config.borderSize = border_size; } + int get_border_size() { return config.borderSize; } /// The xz-plane cell size to use for fields. [Limit: > 0] [Units: wu] - void set_cs(float cs) { config.cs = cs; } + void set_cs(float cs) { + config.cs = cs; + // update width & height of the grid + rcCalcGridSize(config.bmin, config.bmax, config.cs, &config.width, &config.height); + } + float get_cs() { return config.cs; } /// The y-axis cell size to use for fields. [Limit: > 0] [Units: wu] void set_ch(float ch) { config.ch = ch; } + float get_ch() { return config.ch; } /// The minimum bounds of the field's AABB. [(x, y, z)] [Units: wu] void set_bmin(const Vector3& bmin) { // Vector3 can be float or double precision, but Recast expects float config.bmin[0] = bmin.x; config.bmin[1] = bmin.y; config.bmin[2] = bmin.z; + // update width & height of the grid + rcCalcGridSize(config.bmin, config.bmax, config.cs, &config.width, &config.height); + } + Vector3 get_bmin() { + return Vector3(config.bmin[0], config.bmin[1], config.bmin[2]); } /// The maximum bounds of the field's AABB. [(x, y, z)] [Units: wu] void set_bmax(const Vector3& bmax) { config.bmax[0] = bmax.x; config.bmax[1] = bmax.y; config.bmax[2] = bmax.z; + // update width & height of the grid + rcCalcGridSize(config.bmin, config.bmax, config.cs, &config.width, &config.height); + } + Vector3 get_bmax() { + return Vector3(config.bmax[0], config.bmax[1], config.bmax[2]); } /// The maximum slope that is considered walkable. [Limits: 0 <= value < 90] [Units: Degrees] void set_walkable_slope_angle(float walkable_slope_angle) { config.walkableSlopeAngle = walkable_slope_angle; } + float get_walkable_slope_angle() { return config.walkableSlopeAngle; } /// Minimum floor to 'ceiling' height that will still allow the floor area to /// be considered walkable. [Limit: >= 3] [Units: vx] void set_walkable_height(float walkable_height) { config.walkableHeight = walkable_height; } + float get_walkable_height() { return config.walkableHeight; } /// Maximum ledge height that is considered to still be traversable. [Limit: >=0] [Units: vx] void set_walkable_climb(float walkable_climb) { config.walkableClimb = walkable_climb; } + float get_walkable_climb() { return config.walkableClimb; } /// The distance to erode/shrink the walkable area of the heightfield away from /// obstructions. [Limit: >=0] [Units: vx] void set_walkable_radius(float walkable_radius) { config.walkableRadius = walkable_radius; } + float get_walkable_radius() { return config.walkableRadius; } /// The maximum allowed length for contour edges along the border of the mesh. [Limit: >=0] [Units: vx] void set_max_edge_len(int max_edge_len) { config.maxEdgeLen = max_edge_len; } + int get_max_edge_len() { return config.maxEdgeLen; } /// The maximum distance a simplified contour's border edges should deviate /// the original raw contour. [Limit: >=0] [Units: vx] void set_max_simplification_error(float max_simplification_error) { config.maxSimplificationError = max_simplification_error; } + float get_max_simplification_error() { return config.maxSimplificationError; } /// The minimum number of cells allowed to form isolated island areas. [Limit: >=0] [Units: vx] void set_min_region_area(int min_region_area) { config.minRegionArea = min_region_area; } + int get_min_region_area() { return config.minRegionArea; } /// Any regions with a span count smaller than this value will, if possible, /// be merged with larger regions. [Limit: >=0] [Units: vx] void set_merge_region_area(int merge_region_area) { config.mergeRegionArea = merge_region_area; } + int get_merge_region_area() { return config.mergeRegionArea; } /// The maximum number of vertices allowed for polygons generated during the /// contour to polygon conversion process. [Limit: >= 3] void set_max_verts_per_poly(int max_verts_per_poly) { config.maxVertsPerPoly = max_verts_per_poly; } + int get_max_verts_per_poly() { return config.maxVertsPerPoly; } /// Sets the sampling distance to use when generating the detail mesh. /// (For height detail only.) [Limits: 0 or >= 0.9] [Units: wu] void set_detail_sample_dist(float detail_sample_dist) { config.detailSampleDist = detail_sample_dist; } + float get_detail_sample_dist() { return config.detailSampleDist; } /// The maximum distance the detail mesh surface should deviate from heightfield /// data. (For height detail only.) [Limit: >=0] [Units: wu] void set_detail_sample_max_error(float detail_sample_max_error) { config.detailSampleMaxError = detail_sample_max_error; } + float get_detail_sample_max_error() { return config.detailSampleMaxError; } /// The partition type to use for the heightfield. /// /// Allowed values are: @@ -85,14 +109,13 @@ public: /// - LAYERS /// /// Any other value will lead to no change in the partition type. - void set_partition_type(const std::string& partition_type) { - if (partition_type == "WATERSHED") { - this->partition_type = WATERSHED; - } else if (partition_type == "MONOTONE") { - this->partition_type = MONOTONE; - } else if (partition_type == "LAYERS") { - this->partition_type = LAYERS; + void set_partition_type(int partition_type) { + if((partition_type >= 0) && (partition_type < PARTITION_TYPE_COUNT)) { + this->partition_type = (RecastPartitionType)partition_type; } } + int get_partition_type() { + return (int)partition_type; + } }; } diff --git a/src/RecastContext.cpp b/src/RecastContext.cpp new file mode 100644 index 0000000..05d7b5b --- /dev/null +++ b/src/RecastContext.cpp @@ -0,0 +1,17 @@ +#include "RecastContext.hpp" + +godot::RecastContext::RecastContext() { + +} + +godot::RecastContext::~RecastContext() { + +} + +void godot::RecastContext::_bind_methods() { + ADD_SIGNAL(MethodInfo("do_log"), PropertyInfo(Variant::INT, "category"), PropertyInfo(Variant::STRING, "msg")); +} + +void godot::RecastContext::doLog(const rcLogCategory category, const char* msg, const int len) { + +} diff --git a/src/RecastContext.hpp b/src/RecastContext.hpp new file mode 100644 index 0000000..9a904ce --- /dev/null +++ b/src/RecastContext.hpp @@ -0,0 +1,19 @@ +#pragma once + +#include "godot_cpp/classes/node3d.hpp" +#include "Recast.h" + +namespace godot { + + class RecastContext : public Object, public rcContext { + GDCLASS(RecastContext, Object) + private: + protected: + static void _bind_methods(); + virtual void doLog(const rcLogCategory category, const char* msg, const int len); + public: + RecastContext(); + ~RecastContext(); + }; + +} diff --git a/src/RecastNavMesh.cpp b/src/RecastNavMesh.cpp index 186cbbe..0bb2cf0 100644 --- a/src/RecastNavMesh.cpp +++ b/src/RecastNavMesh.cpp @@ -1,7 +1,6 @@ #include "RecastNavMesh.hpp" godot::RecastNavMesh::RecastNavMesh() { - } godot::RecastNavMesh::~RecastNavMesh() { @@ -9,37 +8,135 @@ godot::RecastNavMesh::~RecastNavMesh() { } void godot::RecastNavMesh::_bind_methods() { + // Config + ClassDB::bind_method(D_METHOD("get_width"), &RecastNavMesh::get_width); + ClassDB::bind_method(D_METHOD("get_height"), &RecastNavMesh::get_height); + + ClassDB::bind_method(D_METHOD("set_tile_size", "tile_size"), &RecastNavMesh::set_tile_size); + ClassDB::bind_method(D_METHOD("get_tile_size"), &RecastNavMesh::get_tile_size); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "tile_size"), "set_tile_size", "get_tile_size"); + + ClassDB::bind_method(D_METHOD("set_border_size", "border_size"), &RecastNavMesh::set_border_size); + ClassDB::bind_method(D_METHOD("get_border_size"), &RecastNavMesh::get_border_size); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "border_size"), "set_border_size", "get_border_size"); + + ClassDB::bind_method(D_METHOD("set_cs", "cs"), &RecastNavMesh::set_cs); + ClassDB::bind_method(D_METHOD("get_cs"), &RecastNavMesh::get_cs); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "cell_size"), "set_cs", "get_cs"); + + ClassDB::bind_method(D_METHOD("set_ch", "ch"), &RecastNavMesh::set_ch); + ClassDB::bind_method(D_METHOD("get_ch"), &RecastNavMesh::get_ch); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "cell_height"), "set_ch", "get_ch"); + + ClassDB::bind_method(D_METHOD("set_bmin", "bmin"), &RecastNavMesh::set_bmin); + ClassDB::bind_method(D_METHOD("get_bmin"), &RecastNavMesh::get_bmin); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "bounds_min"), "set_bmin", "get_bmin"); + + ClassDB::bind_method(D_METHOD("set_bmax", "bmax"), &RecastNavMesh::set_bmax); + ClassDB::bind_method(D_METHOD("get_bmax"), &RecastNavMesh::get_bmax); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "bounds_max"), "set_bmax", "get_bmax"); + + ClassDB::bind_method(D_METHOD("set_walkable_slope_angle", "walkable_slope_angle"), &RecastNavMesh::set_walkable_slope_angle); + ClassDB::bind_method(D_METHOD("get_walkable_slope_angle"), &RecastNavMesh::get_walkable_slope_angle); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "walkable_slope_angle"), "set_walkable_slope_angle", "get_walkable_slope_angle"); + + ClassDB::bind_method(D_METHOD("set_walkable_height", "walkable_height"), &RecastNavMesh::set_walkable_height); + ClassDB::bind_method(D_METHOD("get_walkable_height"), &RecastNavMesh::get_walkable_height); + ADD_PROPERTY(PropertyInfo(Variant::INT, "walkable_height"), "set_walkable_height", "get_walkable_height"); + + ClassDB::bind_method(D_METHOD("set_walkable_climb", "walkable_climb"), &RecastNavMesh::set_walkable_climb); + ClassDB::bind_method(D_METHOD("get_walkable_climb"), &RecastNavMesh::get_walkable_climb); + ADD_PROPERTY(PropertyInfo(Variant::INT, "walkable_climb"), "set_walkable_climb", "get_walkable_climb"); + + ClassDB::bind_method(D_METHOD("set_walkable_radius", "walkable_radius"), &RecastNavMesh::set_walkable_radius); + ClassDB::bind_method(D_METHOD("get_walkable_radius"), &RecastNavMesh::get_walkable_radius); + ADD_PROPERTY(PropertyInfo(Variant::INT, "walkable_radius"), "set_walkable_radius", "get_walkable_radius"); + + ClassDB::bind_method(D_METHOD("set_max_edge_len", "max_edge_len"), &RecastNavMesh::set_max_edge_len); + ClassDB::bind_method(D_METHOD("get_max_edge_len"), &RecastNavMesh::get_max_edge_len); + ADD_PROPERTY(PropertyInfo(Variant::INT, "max_edge_length"), "set_max_edge_len", "get_max_edge_len"); + + ClassDB::bind_method(D_METHOD("set_max_simplification_error", "max_simplification_error"), &RecastNavMesh::set_max_simplification_error); + ClassDB::bind_method(D_METHOD("get_max_simplification_error"), &RecastNavMesh::get_max_simplification_error); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "max_simplification_error"), "set_max_simplification_error", "get_max_simplification_error"); + + ClassDB::bind_method(D_METHOD("set_min_region_area", "min_region_area"), &RecastNavMesh::set_min_region_area); + ClassDB::bind_method(D_METHOD("get_min_region_area"), &RecastNavMesh::get_min_region_area); + ADD_PROPERTY(PropertyInfo(Variant::INT, "min_region_area"), "set_min_region_area", "get_min_region_area"); + + ClassDB::bind_method(D_METHOD("set_merge_region_area", "merge_region_area"), &RecastNavMesh::set_merge_region_area); + ClassDB::bind_method(D_METHOD("get_merge_region_area"), &RecastNavMesh::get_merge_region_area); + ADD_PROPERTY(PropertyInfo(Variant::INT, "merge_region_area"), "set_merge_region_area", "get_merge_region_area"); + + ClassDB::bind_method(D_METHOD("set_max_verts_per_poly", "max_verts_per_poly"), &RecastNavMesh::set_max_verts_per_poly); + ClassDB::bind_method(D_METHOD("get_max_verts_per_poly"), &RecastNavMesh::get_max_verts_per_poly); + ADD_PROPERTY(PropertyInfo(Variant::INT, "max_verts_per_poly"), "set_max_verts_per_poly", "get_max_verts_per_poly"); + + ClassDB::bind_method(D_METHOD("set_detail_sample_dist", "detail_sample_dist"), &RecastNavMesh::set_detail_sample_dist); + ClassDB::bind_method(D_METHOD("get_detail_sample_dist"), &RecastNavMesh::get_detail_sample_dist); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "detail_sample_dist"), "set_detail_sample_dist", "get_detail_sample_dist"); + + ClassDB::bind_method(D_METHOD("set_detail_sample_max_error", "detail_sample_max_error"), &RecastNavMesh::set_detail_sample_max_error); + ClassDB::bind_method(D_METHOD("get_detail_sample_max_error"), &RecastNavMesh::get_detail_sample_max_error); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "detail_sample_max_error"), "set_detail_sample_max_error", "get_detail_sample_max_error"); + + ClassDB::bind_method(D_METHOD("set_partition_type", "partition_type"), &RecastNavMesh::set_partition_type); + ClassDB::bind_method(D_METHOD("get_partition_type"), &RecastNavMesh::get_partition_type); + ADD_PROPERTY(PropertyInfo(Variant::INT, "partition_type", PROPERTY_HINT_ENUM, "Watershed,Monotone,Layers"), "set_partition_type", "get_partition_type"); + + // Recast calls ClassDB::bind_method(D_METHOD("clear_vertices"), &RecastNavMesh::clear_vertices); ClassDB::bind_method(D_METHOD("add_vertices", "vertices", "area_id"), &RecastNavMesh::add_vertices); ClassDB::bind_method(D_METHOD("recalculate_navmesh"), &RecastNavMesh::recalculate_navmesh); ClassDB::bind_method(D_METHOD("is_calculated"), &RecastNavMesh::is_calculated); } -void godot::RecastNavMesh::cleanup() { - /* - delete [] m_triareas; - m_triareas = 0; - rcFreeHeightField(m_solid); - m_solid = 0; - rcFreeCompactHeightfield(m_chf); - m_chf = 0; - rcFreeContourSet(m_cset); - m_cset = 0; - rcFreePolyMesh(m_pmesh); - m_pmesh = 0; - rcFreePolyMeshDetail(m_dmesh); - m_dmesh = 0; - dtFreeNavMesh(m_navMesh); - m_navMesh = 0; - */ -} +bool godot::RecastNavMesh::init() { + cleanup(); + rcCalcGridSize(config.bmin, config.bmax, config.cs, &config.width, &config.height); + m_heightfield = rcAllocHeightfield(); + if(!m_heightfield) { + return false; + } + //if(!rcCreateHeightfield(m_ctx)) { -bool godot::RecastNavMesh::add_vertices(const PackedByteArray& vertices, unsigned char area_id) { + //} + // return false; } -bool godot::RecastNavMesh::recalculate_navmesh() { +void godot::RecastNavMesh::cleanup() { + + if(m_heightfield) { + rcFreeHeightField(m_heightfield); + m_heightfield = NULL; + } + /* + delete [] m_triareas; + m_triareas = 0; + rcFreeHeightField(m_solid); + m_solid = 0; + rcFreeCompactHeightfield(m_chf); + m_chf = 0; + rcFreeContourSet(m_cset); + m_cset = 0; + rcFreePolyMesh(m_pmesh); + m_pmesh = 0; + rcFreePolyMeshDetail(m_dmesh); + m_dmesh = 0; + dtFreeNavMesh(m_navMesh); + m_navMesh = 0; + */ +} + +void godot::RecastNavMesh::add_vertices(PackedByteArray vertices, unsigned char area_id) { } -void godot::RecastNavMesh::clear_vertices() {} +bool godot::RecastNavMesh::recalculate_navmesh() { + return false; +} + +void godot::RecastNavMesh::clear_vertices() { + +} diff --git a/src/RecastNavMesh.hpp b/src/RecastNavMesh.hpp index 217624e..ff43134 100644 --- a/src/RecastNavMesh.hpp +++ b/src/RecastNavMesh.hpp @@ -1,24 +1,140 @@ #pragma once #include "godot_cpp/classes/node3d.hpp" +#include "godot_cpp/templates/vector.hpp" + +#include "Recast.h" namespace godot { + enum RecastPartitionType { + WATERSHED = 0, + MONOTONE, + LAYERS, + PARTITION_TYPE_COUNT + }; + class RecastNavMesh : public Node3D { GDCLASS(RecastNavMesh, Node3D) private: - bool calculated = false; + bool m_calculated = false; + rcConfig config; + RecastPartitionType partition_type = WATERSHED; + rcHeightfield* m_heightfield; protected: static void _bind_methods(); public: RecastNavMesh(); ~RecastNavMesh(); + // config + + /// The width of the field along the x-axis. [Limit: >= 0] [Units: vx] + int get_width() { return config.width; } + /// The height of the field along the z-axis. [Limit: >= 0] [Units: vx] + int get_height() { return config.height; } + /// The width/height size of tile's on the xz-plane. [Limit: >= 0] [Units: vx] + void set_tile_size(float tile_size) { config.tileSize = tile_size; } + float get_tile_size() { return config.tileSize; } + /// The size of the non-navigable border around the heightfield. [Limit: >=0] [Units: vx] + void set_border_size(int border_size) { config.borderSize = border_size; } + int get_border_size() { return config.borderSize; } + /// The xz-plane cell size to use for fields. [Limit: > 0] [Units: wu] + void set_cs(float cs) { + config.cs = cs; + // update width & height of the grid + rcCalcGridSize(config.bmin, config.bmax, config.cs, &config.width, &config.height); + } + float get_cs() { return config.cs; } + /// The y-axis cell size to use for fields. [Limit: > 0] [Units: wu] + void set_ch(float ch) { config.ch = ch; } + float get_ch() { return config.ch; } + /// The minimum bounds of the field's AABB. [(x, y, z)] [Units: wu] + void set_bmin(const Vector3& bmin) { + // Vector3 can be float or double precision, but Recast expects float + config.bmin[0] = bmin.x; + config.bmin[1] = bmin.y; + config.bmin[2] = bmin.z; + // update width & height of the grid + rcCalcGridSize(config.bmin, config.bmax, config.cs, &config.width, &config.height); + } + Vector3 get_bmin() { + return Vector3(config.bmin[0], config.bmin[1], config.bmin[2]); + } + /// The maximum bounds of the field's AABB. [(x, y, z)] [Units: wu] + void set_bmax(const Vector3& bmax) { + config.bmax[0] = bmax.x; + config.bmax[1] = bmax.y; + config.bmax[2] = bmax.z; + // update width & height of the grid + rcCalcGridSize(config.bmin, config.bmax, config.cs, &config.width, &config.height); + } + Vector3 get_bmax() { + return Vector3(config.bmax[0], config.bmax[1], config.bmax[2]); + } + /// The maximum slope that is considered walkable. [Limits: 0 <= value < 90] [Units: Degrees] + void set_walkable_slope_angle(float walkable_slope_angle) { config.walkableSlopeAngle = walkable_slope_angle; } + float get_walkable_slope_angle() { return config.walkableSlopeAngle; } + /// Minimum floor to 'ceiling' height that will still allow the floor area to + /// be considered walkable. [Limit: >= 3] [Units: vx] + void set_walkable_height(float walkable_height) { config.walkableHeight = walkable_height; } + float get_walkable_height() { return config.walkableHeight; } + /// Maximum ledge height that is considered to still be traversable. [Limit: >=0] [Units: vx] + void set_walkable_climb(float walkable_climb) { config.walkableClimb = walkable_climb; } + float get_walkable_climb() { return config.walkableClimb; } + /// The distance to erode/shrink the walkable area of the heightfield away from + /// obstructions. [Limit: >=0] [Units: vx] + void set_walkable_radius(float walkable_radius) { config.walkableRadius = walkable_radius; } + float get_walkable_radius() { return config.walkableRadius; } + /// The maximum allowed length for contour edges along the border of the mesh. [Limit: >=0] [Units: vx] + void set_max_edge_len(int max_edge_len) { config.maxEdgeLen = max_edge_len; } + int get_max_edge_len() { return config.maxEdgeLen; } + /// The maximum distance a simplified contour's border edges should deviate + /// the original raw contour. [Limit: >=0] [Units: vx] + void set_max_simplification_error(float max_simplification_error) { config.maxSimplificationError = max_simplification_error; } + float get_max_simplification_error() { return config.maxSimplificationError; } + /// The minimum number of cells allowed to form isolated island areas. [Limit: >=0] [Units: vx] + void set_min_region_area(int min_region_area) { config.minRegionArea = min_region_area; } + int get_min_region_area() { return config.minRegionArea; } + /// Any regions with a span count smaller than this value will, if possible, + /// be merged with larger regions. [Limit: >=0] [Units: vx] + void set_merge_region_area(int merge_region_area) { config.mergeRegionArea = merge_region_area; } + int get_merge_region_area() { return config.mergeRegionArea; } + /// The maximum number of vertices allowed for polygons generated during the + /// contour to polygon conversion process. [Limit: >= 3] + void set_max_verts_per_poly(int max_verts_per_poly) { config.maxVertsPerPoly = max_verts_per_poly; } + int get_max_verts_per_poly() { return config.maxVertsPerPoly; } + /// Sets the sampling distance to use when generating the detail mesh. + /// (For height detail only.) [Limits: 0 or >= 0.9] [Units: wu] + void set_detail_sample_dist(float detail_sample_dist) { config.detailSampleDist = detail_sample_dist; } + float get_detail_sample_dist() { return config.detailSampleDist; } + /// The maximum distance the detail mesh surface should deviate from heightfield + /// data. (For height detail only.) [Limit: >=0] [Units: wu] + void set_detail_sample_max_error(float detail_sample_max_error) { config.detailSampleMaxError = detail_sample_max_error; } + float get_detail_sample_max_error() { return config.detailSampleMaxError; } + /// The partition type to use for the heightfield. + /// + /// Allowed values are: + /// - WATERSHED + /// - MONOTONE + /// - LAYERS + /// + /// Any other value will lead to no change in the partition type. + void set_partition_type(int partition_type) { + if((partition_type >= 0) && (partition_type < PARTITION_TYPE_COUNT)) { + this->partition_type = (RecastPartitionType)partition_type; + } + } + int get_partition_type() { + return (int)partition_type; + } + + // Recast + bool init(); void cleanup(); void clear_vertices(); - bool add_vertices(const PackedByteArray& vertices, unsigned char area_id); + void add_vertices(PackedByteArray vertices, unsigned char area_id); bool recalculate_navmesh(); - bool is_calculated() { return calculated; } + bool is_calculated() { return m_calculated; } }; } - diff --git a/src/registration.cpp b/src/registration.cpp index 15aede6..ae8df29 100644 --- a/src/registration.cpp +++ b/src/registration.cpp @@ -1,7 +1,6 @@ #include #include -#include "RecastConfig.hpp" #include "RecastNavMesh.hpp" void register_gameplay_types(godot::ModuleInitializationLevel p_level) { @@ -9,7 +8,6 @@ void register_gameplay_types(godot::ModuleInitializationLevel p_level) { return; } - godot::ClassDB::register_class(); godot::ClassDB::register_class(); }