diff --git a/src/RecastNavMesh.cpp b/src/RecastNavMesh.cpp index 90de5b8..97e5e8d 100644 --- a/src/RecastNavMesh.cpp +++ b/src/RecastNavMesh.cpp @@ -102,9 +102,9 @@ void godot::RecastNavMesh::_bind_methods() { 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("get_walkable_triangles", "vertices", "indices", "areas"), &RecastNavMesh::get_walkable_triangles); 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("build"), &RecastNavMesh::build); ClassDB::bind_method(D_METHOD("is_calculated"), &RecastNavMesh::is_calculated); } @@ -138,20 +138,14 @@ void godot::RecastNavMesh::cleanup() { rcFreeContourSet(m_contour_set); m_contour_set = NULL; } - /* - 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; - */ + if(m_poly_mesh) { + rcFreePolyMesh(m_poly_mesh); + m_poly_mesh = NULL; + } + if(m_poly_mesh_detail) { + rcFreePolyMeshDetail(m_poly_mesh_detail); + m_poly_mesh_detail = NULL; + } } void godot::RecastNavMesh::get_walkable_triangles(PackedFloat32Array vertices, PackedInt32Array indices, PackedByteArray areas) { @@ -192,5 +186,88 @@ bool godot::RecastNavMesh::build() { rcFreeHeightField(m_heightfield); m_heightfield = NULL; + + if (!rcErodeWalkableArea(this, config.walkableRadius, *m_compact_heightfield)) + { + log(RC_LOG_ERROR, "buildNavigation: Could not erode."); + return false; + } + + if (partition_type == WATERSHED) + { + // Prepare for region partitioning, by calculating distance field along the walkable surface. + if (!rcBuildDistanceField(this, *m_compact_heightfield)) + { + log(RC_LOG_ERROR, "buildNavigation: Could not build distance field."); + return false; + } + + // Partition the walkable surface into simple regions without holes. + if (!rcBuildRegions(this, *m_compact_heightfield, 0, config.minRegionArea, config.mergeRegionArea)) + { + log(RC_LOG_ERROR, "buildNavigation: Could not build watershed regions."); + return false; + } + } + else if (partition_type == MONOTONE) + { + // Partition the walkable surface into simple regions without holes. + // Monotone partitioning does not need distancefield. + if (!rcBuildRegionsMonotone(this, *m_compact_heightfield, 0, config.minRegionArea, config.mergeRegionArea)) + { + log(RC_LOG_ERROR, "buildNavigation: Could not build monotone regions."); + return false; + } + } + else // SAMPLE_PARTITION_LAYERS + { + // Partition the walkable surface into simple regions without holes. + if (!rcBuildLayerRegions(this, *m_compact_heightfield, 0, config.minRegionArea)) + { + log(RC_LOG_ERROR, "buildNavigation: Could not build layer regions."); + return false; + } + } + + m_contour_set = rcAllocContourSet(); + if(!m_contour_set) { + log(RC_LOG_ERROR, "couldn't alloc contour set!"); + return false; + } + + if(!rcBuildContours(this, *m_compact_heightfield, config.maxSimplificationError, config.maxEdgeLen, *m_contour_set)) { + log(RC_LOG_ERROR, "couldn't build contours!"); + return false; + } + + m_poly_mesh = rcAllocPolyMesh(); + if(!m_poly_mesh) { + log(RC_LOG_ERROR, "couldn't alloc poly mesh!"); + return false; + } + + if(!rcBuildPolyMesh(this, *m_contour_set, config.maxVertsPerPoly, *m_poly_mesh)) { + log(RC_LOG_ERROR, "couldn't build poly mesh!"); + return false; + } + + m_poly_mesh_detail = rcAllocPolyMeshDetail(); + if(!m_poly_mesh_detail) { + log(RC_LOG_ERROR, "couldn't alloc detail mesh!"); + return false; + } + + if(!rcBuildPolyMeshDetail(this, *m_poly_mesh, *m_compact_heightfield, config.detailSampleDist, config.detailSampleMaxError, *m_poly_mesh_detail)) { + log(RC_LOG_ERROR, "couldn't build detail mesh!"); + return false; + } + + rcFreeCompactHeightfield(m_compact_heightfield); + m_compact_heightfield = NULL; + rcFreeContourSet(m_contour_set); + m_contour_set = NULL; + + m_calculated = true; + return true; }