diff options
Diffstat (limited to 'modules/navigation')
-rw-r--r-- | modules/navigation/SCsub | 18 | ||||
-rw-r--r-- | modules/navigation/godot_navigation_server.cpp | 91 | ||||
-rw-r--r-- | modules/navigation/godot_navigation_server.h | 2 | ||||
-rw-r--r-- | modules/navigation/nav_agent.cpp | 15 | ||||
-rw-r--r-- | modules/navigation/nav_link.cpp | 9 | ||||
-rw-r--r-- | modules/navigation/nav_map.cpp | 101 | ||||
-rw-r--r-- | modules/navigation/nav_region.cpp | 16 | ||||
-rw-r--r-- | modules/navigation/navigation_mesh_generator.cpp | 1 |
8 files changed, 152 insertions, 101 deletions
diff --git a/modules/navigation/SCsub b/modules/navigation/SCsub index 18a8d550ec..46bcb0fba4 100644 --- a/modules/navigation/SCsub +++ b/modules/navigation/SCsub @@ -37,12 +37,10 @@ if env["builtin_recastnavigation"]: if env["builtin_rvo2_2d"]: thirdparty_dir = "#thirdparty/rvo2/rvo2_2d/" thirdparty_sources = [ - "Agent2d.cc", - "Obstacle2d.cc", - "KdTree2d.cc", - "Line.cc", - "RVOSimulator2d.cc", - "Vector2.cc", + "Agent2d.cpp", + "Obstacle2d.cpp", + "KdTree2d.cpp", + "RVOSimulator2d.cpp", ] thirdparty_sources = [thirdparty_dir + file for file in thirdparty_sources] @@ -56,11 +54,9 @@ if env["builtin_rvo2_2d"]: if env["builtin_rvo2_3d"]: thirdparty_dir = "#thirdparty/rvo2/rvo2_3d/" thirdparty_sources = [ - "Agent3d.cc", - "KdTree3d.cc", - "Plane.cc", - "RVOSimulator3d.cc", - "Vector3.cc", + "Agent3d.cpp", + "KdTree3d.cpp", + "RVOSimulator3d.cpp", ] thirdparty_sources = [thirdparty_dir + file for file in thirdparty_sources] diff --git a/modules/navigation/godot_navigation_server.cpp b/modules/navigation/godot_navigation_server.cpp index 0ec0c9545f..b73c5ca3e2 100644 --- a/modules/navigation/godot_navigation_server.cpp +++ b/modules/navigation/godot_navigation_server.cpp @@ -358,22 +358,9 @@ COMMAND_2(region_set_map, RID, p_region, RID, p_map) { NavRegion *region = region_owner.get_or_null(p_region); ERR_FAIL_COND(region == nullptr); - if (region->get_map() != nullptr) { - if (region->get_map()->get_self() == p_map) { - return; // Pointless - } - - region->get_map()->remove_region(region); - region->set_map(nullptr); - } - - if (p_map.is_valid()) { - NavMap *map = map_owner.get_or_null(p_map); - ERR_FAIL_COND(map == nullptr); + NavMap *map = map_owner.get_or_null(p_map); - map->add_region(region); - region->set_map(map); - } + region->set_map(map); } COMMAND_2(region_set_transform, RID, p_region, Transform3D, p_transform) { @@ -459,10 +446,13 @@ COMMAND_2(region_set_navigation_mesh, RID, p_region, Ref<NavigationMesh>, p_navi region->set_mesh(p_navigation_mesh); } +#ifndef DISABLE_DEPRECATED void GodotNavigationServer::region_bake_navigation_mesh(Ref<NavigationMesh> p_navigation_mesh, Node *p_root_node) { ERR_FAIL_COND(p_navigation_mesh.is_null()); ERR_FAIL_COND(p_root_node == nullptr); + WARN_PRINT_ONCE("NavigationServer3D::region_bake_navigation_mesh() is deprecated due to core threading changes. To upgrade existing code, first create a NavigationMeshSourceGeometryData3D resource. Use this resource with method parse_source_geometry_data() to parse the SceneTree for nodes that should contribute to the navigation mesh baking. The SceneTree parsing needs to happen on the main thread. After the parsing is finished use the resource with method bake_from_source_geometry_data() to bake a navigation mesh.."); + #ifndef _3D_DISABLED NavigationMeshGenerator::get_singleton()->clear(p_navigation_mesh); Ref<NavigationMeshSourceGeometryData3D> source_geometry_data; @@ -471,6 +461,7 @@ void GodotNavigationServer::region_bake_navigation_mesh(Ref<NavigationMesh> p_na NavigationMeshGenerator::get_singleton()->bake_from_source_geometry_data(p_navigation_mesh, source_geometry_data); #endif } +#endif // DISABLE_DEPRECATED int GodotNavigationServer::region_get_connections_count(RID p_region) const { NavRegion *region = region_owner.get_or_null(p_region); @@ -506,22 +497,9 @@ COMMAND_2(link_set_map, RID, p_link, RID, p_map) { NavLink *link = link_owner.get_or_null(p_link); ERR_FAIL_COND(link == nullptr); - if (link->get_map() != nullptr) { - if (link->get_map()->get_self() == p_map) { - return; // Pointless - } - - link->get_map()->remove_link(link); - link->set_map(nullptr); - } - - if (p_map.is_valid()) { - NavMap *map = map_owner.get_or_null(p_map); - ERR_FAIL_COND(map == nullptr); + NavMap *map = map_owner.get_or_null(p_map); - map->add_link(link); - link->set_map(map); - } + link->set_map(map); } RID GodotNavigationServer::link_get_map(const RID p_link) const { @@ -673,27 +651,9 @@ COMMAND_2(agent_set_map, RID, p_agent, RID, p_map) { NavAgent *agent = agent_owner.get_or_null(p_agent); ERR_FAIL_COND(agent == nullptr); - if (agent->get_map()) { - if (agent->get_map()->get_self() == p_map) { - return; // Pointless - } - - agent->get_map()->remove_agent(agent); - } - - agent->set_map(nullptr); - - if (p_map.is_valid()) { - NavMap *map = map_owner.get_or_null(p_map); - ERR_FAIL_COND(map == nullptr); - - agent->set_map(map); - map->add_agent(agent); + NavMap *map = map_owner.get_or_null(p_map); - if (agent->has_avoidance_callback()) { - map->set_agent_as_controlled(agent); - } - } + agent->set_map(map); } COMMAND_2(agent_set_paused, RID, p_agent, bool, p_paused) { @@ -875,23 +835,9 @@ COMMAND_2(obstacle_set_map, RID, p_obstacle, RID, p_map) { NavObstacle *obstacle = obstacle_owner.get_or_null(p_obstacle); ERR_FAIL_COND(obstacle == nullptr); - if (obstacle->get_map()) { - if (obstacle->get_map()->get_self() == p_map) { - return; // Pointless - } - - obstacle->get_map()->remove_obstacle(obstacle); - } - - obstacle->set_map(nullptr); - - if (p_map.is_valid()) { - NavMap *map = map_owner.get_or_null(p_map); - ERR_FAIL_COND(map == nullptr); + NavMap *map = map_owner.get_or_null(p_map); - obstacle->set_map(map); - map->add_obstacle(obstacle); - } + obstacle->set_map(map); } RID GodotNavigationServer::obstacle_get_map(RID p_obstacle) const { @@ -1050,17 +996,16 @@ void GodotNavigationServer::internal_free_agent(RID p_object) { void GodotNavigationServer::internal_free_obstacle(RID p_object) { NavObstacle *obstacle = obstacle_owner.get_or_null(p_object); if (obstacle) { + NavAgent *obstacle_agent = obstacle->get_agent(); + if (obstacle_agent) { + RID _agent_rid = obstacle_agent->get_self(); + internal_free_agent(_agent_rid); + obstacle->set_agent(nullptr); + } if (obstacle->get_map() != nullptr) { obstacle->get_map()->remove_obstacle(obstacle); obstacle->set_map(nullptr); } - if (obstacle->get_agent()) { - if (obstacle->get_agent()->get_self() != RID()) { - RID _agent_rid = obstacle->get_agent()->get_self(); - obstacle->set_agent(nullptr); - internal_free_agent(_agent_rid); - } - } obstacle_owner.free(p_object); } } diff --git a/modules/navigation/godot_navigation_server.h b/modules/navigation/godot_navigation_server.h index 6b394157bc..95aa88194e 100644 --- a/modules/navigation/godot_navigation_server.h +++ b/modules/navigation/godot_navigation_server.h @@ -154,7 +154,9 @@ public: virtual uint32_t region_get_navigation_layers(RID p_region) const override; COMMAND_2(region_set_transform, RID, p_region, Transform3D, p_transform); COMMAND_2(region_set_navigation_mesh, RID, p_region, Ref<NavigationMesh>, p_navigation_mesh); +#ifndef DISABLE_DEPRECATED virtual void region_bake_navigation_mesh(Ref<NavigationMesh> p_navigation_mesh, Node *p_root_node) override; +#endif // DISABLE_DEPRECATED virtual int region_get_connections_count(RID p_region) const override; virtual Vector3 region_get_connection_pathway_start(RID p_region, int p_connection_id) const override; virtual Vector3 region_get_connection_pathway_end(RID p_region, int p_connection_id) const override; diff --git a/modules/navigation/nav_agent.cpp b/modules/navigation/nav_agent.cpp index 19b73dc633..010bd2d7c0 100644 --- a/modules/navigation/nav_agent.cpp +++ b/modules/navigation/nav_agent.cpp @@ -90,8 +90,23 @@ void NavAgent::_update_rvo_agent_properties() { } void NavAgent::set_map(NavMap *p_map) { + if (map == p_map) { + return; + } + + if (map) { + map->remove_agent(this); + } + map = p_map; agent_dirty = true; + + if (map) { + map->add_agent(this); + if (avoidance_enabled) { + map->set_agent_as_controlled(this); + } + } } bool NavAgent::is_map_changed() { diff --git a/modules/navigation/nav_link.cpp b/modules/navigation/nav_link.cpp index 5607a3253e..d712987a46 100644 --- a/modules/navigation/nav_link.cpp +++ b/modules/navigation/nav_link.cpp @@ -36,8 +36,17 @@ void NavLink::set_map(NavMap *p_map) { if (map == p_map) { return; } + + if (map) { + map->remove_link(this); + } + map = p_map; link_dirty = true; + + if (map) { + map->add_link(this); + } } void NavLink::set_bidirectional(bool p_bidirectional) { diff --git a/modules/navigation/nav_map.cpp b/modules/navigation/nav_map.cpp index 2595a02a61..3a1d412618 100644 --- a/modules/navigation/nav_map.cpp +++ b/modules/navigation/nav_map.cpp @@ -301,6 +301,46 @@ Vector<Vector3> NavMap::get_path(Vector3 p_origin, Vector3 p_destination, bool p } } + // Search all faces of start polygon as well. + bool closest_point_on_start_poly = false; + for (size_t point_id = 2; point_id < begin_poly->points.size(); point_id++) { + Face3 f(begin_poly->points[0].pos, begin_poly->points[point_id - 1].pos, begin_poly->points[point_id].pos); + Vector3 spoint = f.get_closest_point_to(p_destination); + real_t dpoint = spoint.distance_to(p_destination); + if (dpoint < end_d) { + end_point = spoint; + end_d = dpoint; + closest_point_on_start_poly = true; + } + } + + if (closest_point_on_start_poly) { + // No point to run PostProcessing when start and end convex polygon is the same. + if (r_path_types) { + r_path_types->resize(2); + r_path_types->write[0] = begin_poly->owner->get_type(); + r_path_types->write[1] = begin_poly->owner->get_type(); + } + + if (r_path_rids) { + r_path_rids->resize(2); + (*r_path_rids)[0] = begin_poly->owner->get_self(); + (*r_path_rids)[1] = begin_poly->owner->get_self(); + } + + if (r_path_owners) { + r_path_owners->resize(2); + r_path_owners->write[0] = begin_poly->owner->get_owner_id(); + r_path_owners->write[1] = begin_poly->owner->get_owner_id(); + } + + Vector<Vector3> path; + path.resize(2); + path.write[0] = begin_point; + path.write[1] = end_point; + return path; + } + // Reset open and navigation_polys gd::NavigationPoly np = navigation_polys[0]; navigation_polys.clear(); @@ -346,9 +386,44 @@ Vector<Vector3> NavMap::get_path(Vector3 p_origin, Vector3 p_destination, bool p } } - // If we did not find a route, return an empty path. + // We did not find a route but we have both a start polygon and an end polygon at this point. + // Usually this happens because there was not a single external or internal connected edge, e.g. our start polygon is an isolated, single convex polygon. if (!found_route) { - return Vector<Vector3>(); + end_d = FLT_MAX; + // Search all faces of the start polygon for the closest point to our target position. + for (size_t point_id = 2; point_id < begin_poly->points.size(); point_id++) { + Face3 f(begin_poly->points[0].pos, begin_poly->points[point_id - 1].pos, begin_poly->points[point_id].pos); + Vector3 spoint = f.get_closest_point_to(p_destination); + real_t dpoint = spoint.distance_to(p_destination); + if (dpoint < end_d) { + end_point = spoint; + end_d = dpoint; + } + } + + if (r_path_types) { + r_path_types->resize(2); + r_path_types->write[0] = begin_poly->owner->get_type(); + r_path_types->write[1] = begin_poly->owner->get_type(); + } + + if (r_path_rids) { + r_path_rids->resize(2); + (*r_path_rids)[0] = begin_poly->owner->get_self(); + (*r_path_rids)[1] = begin_poly->owner->get_self(); + } + + if (r_path_owners) { + r_path_owners->resize(2); + r_path_owners->write[0] = begin_poly->owner->get_owner_id(); + r_path_owners->write[1] = begin_poly->owner->get_owner_id(); + } + + Vector<Vector3> path; + path.resize(2); + path.write[0] = begin_point; + path.write[1] = end_point; + return path; } Vector<Vector3> path; @@ -1042,16 +1117,16 @@ void NavMap::_update_rvo_obstacles_tree_2d() { rvo_2d_obstacle->avoidance_layers_ = _obstacle_avoidance_layers; if (i != 0) { - rvo_2d_obstacle->previous_ = raw_obstacles.back(); - rvo_2d_obstacle->previous_->next_ = rvo_2d_obstacle; + rvo_2d_obstacle->prevObstacle_ = raw_obstacles.back(); + rvo_2d_obstacle->prevObstacle_->nextObstacle_ = rvo_2d_obstacle; } if (i == rvo_2d_vertices.size() - 1) { - rvo_2d_obstacle->next_ = raw_obstacles[obstacleNo]; - rvo_2d_obstacle->next_->previous_ = rvo_2d_obstacle; + rvo_2d_obstacle->nextObstacle_ = raw_obstacles[obstacleNo]; + rvo_2d_obstacle->nextObstacle_->prevObstacle_ = rvo_2d_obstacle; } - rvo_2d_obstacle->direction_ = normalize(rvo_2d_vertices[(i == rvo_2d_vertices.size() - 1 ? 0 : i + 1)] - rvo_2d_vertices[i]); + rvo_2d_obstacle->unitDir_ = normalize(rvo_2d_vertices[(i == rvo_2d_vertices.size() - 1 ? 0 : i + 1)] - rvo_2d_vertices[i]); if (rvo_2d_vertices.size() == 2) { rvo_2d_obstacle->isConvex_ = true; @@ -1099,9 +1174,9 @@ void NavMap::_update_rvo_simulation() { } void NavMap::compute_single_avoidance_step_2d(uint32_t index, NavAgent **agent) { - (*(agent + index))->get_rvo_agent_2d()->computeNeighbors(rvo_simulation_2d.kdTree_); - (*(agent + index))->get_rvo_agent_2d()->computeNewVelocity(rvo_simulation_2d.timeStep_); - (*(agent + index))->get_rvo_agent_2d()->update(rvo_simulation_2d.timeStep_); + (*(agent + index))->get_rvo_agent_2d()->computeNeighbors(&rvo_simulation_2d); + (*(agent + index))->get_rvo_agent_2d()->computeNewVelocity(&rvo_simulation_2d); + (*(agent + index))->get_rvo_agent_2d()->update(&rvo_simulation_2d); (*(agent + index))->update(); } @@ -1124,9 +1199,9 @@ void NavMap::step(real_t p_deltatime) { WorkerThreadPool::get_singleton()->wait_for_group_task_completion(group_task); } else { for (NavAgent *agent : active_2d_avoidance_agents) { - agent->get_rvo_agent_2d()->computeNeighbors(rvo_simulation_2d.kdTree_); - agent->get_rvo_agent_2d()->computeNewVelocity(rvo_simulation_2d.timeStep_); - agent->get_rvo_agent_2d()->update(rvo_simulation_2d.timeStep_); + agent->get_rvo_agent_2d()->computeNeighbors(&rvo_simulation_2d); + agent->get_rvo_agent_2d()->computeNewVelocity(&rvo_simulation_2d); + agent->get_rvo_agent_2d()->update(&rvo_simulation_2d); agent->update(); } } diff --git a/modules/navigation/nav_region.cpp b/modules/navigation/nav_region.cpp index bf4fec1ac8..9c0ce3e71e 100644 --- a/modules/navigation/nav_region.cpp +++ b/modules/navigation/nav_region.cpp @@ -36,10 +36,18 @@ void NavRegion::set_map(NavMap *p_map) { if (map == p_map) { return; } + + if (map) { + map->remove_region(this); + } + map = p_map; polygons_dirty = true; - if (!map) { - connections.clear(); + + connections.clear(); + + if (map) { + map->add_region(this); } } @@ -107,11 +115,11 @@ void NavRegion::update_polygons() { #ifdef DEBUG_ENABLED if (!Math::is_equal_approx(double(map->get_cell_size()), double(mesh->get_cell_size()))) { - ERR_PRINT_ONCE("Navigation map synchronization error. Attempted to update a navigation region with a navigation mesh that uses a different `cell_size` than the `cell_size` set on the navigation map."); + ERR_PRINT_ONCE(vformat("Navigation map synchronization error. Attempted to update a navigation region with a navigation mesh that uses a `cell_size` of %s while assigned to a navigation map set to a `cell_size` of %s. The cell size for navigation maps can be changed by using the NavigationServer map_set_cell_size() function. The cell size for default navigation maps can also be changed in the ProjectSettings.", double(map->get_cell_size()), double(mesh->get_cell_size()))); } if (!Math::is_equal_approx(double(map->get_cell_height()), double(mesh->get_cell_height()))) { - ERR_PRINT_ONCE("Navigation map synchronization error. Attempted to update a navigation region with a navigation mesh that uses a different `cell_height` than the `cell_height` set on the navigation map."); + ERR_PRINT_ONCE(vformat("Navigation map synchronization error. Attempted to update a navigation region with a navigation mesh that uses a `cell_height` of %s while assigned to a navigation map set to a `cell_height` of %s. The cell height for navigation maps can be changed by using the NavigationServer map_set_cell_height() function. The cell height for default navigation maps can also be changed in the ProjectSettings.", double(map->get_cell_height()), double(mesh->get_cell_height()))); } if (map && Math::rad_to_deg(map->get_up().angle_to(transform.basis.get_column(1))) >= 90.0f) { diff --git a/modules/navigation/navigation_mesh_generator.cpp b/modules/navigation/navigation_mesh_generator.cpp index 18c8256255..89afb4a8ea 100644 --- a/modules/navigation/navigation_mesh_generator.cpp +++ b/modules/navigation/navigation_mesh_generator.cpp @@ -738,6 +738,7 @@ void NavigationMeshGenerator::bake_from_source_geometry_data(Ref<NavigationMesh> nav_vertices.push_back(Vector3(v[0], v[1], v[2])); } p_navigation_mesh->set_vertices(nav_vertices); + p_navigation_mesh->clear_polygons(); for (int i = 0; i < detail_mesh->nmeshes; i++) { const unsigned int *detail_mesh_m = &detail_mesh->meshes[i * 4]; |