2024-12-15 20:31:13 +01:00
/**************************************************************************/
2025-02-26 11:48:13 +01:00
/* nav_map_builder_2d.cpp */
2024-12-15 20:31:13 +01:00
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
2025-02-26 11:48:13 +01:00
# include "nav_map_builder_2d.h"
2024-12-15 20:31:13 +01:00
2025-02-26 11:48:13 +01:00
# include "../nav_link_2d.h"
# include "../nav_map_2d.h"
# include "../nav_region_2d.h"
# include "../triangle2.h"
# include "nav_map_iteration_2d.h"
# include "nav_region_iteration_2d.h"
2024-12-15 20:31:13 +01:00
2025-05-12 16:59:53 -07:00
using namespace Nav2D ;
2024-12-15 20:31:13 +01:00
2025-02-26 11:48:13 +01:00
PointKey NavMapBuilder2D : : get_point_key ( const Vector2 & p_pos , const Vector2 & p_cell_size ) {
2024-12-15 20:31:13 +01:00
const int x = static_cast < int > ( Math : : floor ( p_pos . x / p_cell_size . x ) ) ;
const int y = static_cast < int > ( Math : : floor ( p_pos . y / p_cell_size . y ) ) ;
2025-02-26 11:42:07 +01:00
PointKey p ;
2024-12-15 20:31:13 +01:00
p . key = 0 ;
p . x = x ;
p . y = y ;
return p ;
}
2025-02-26 11:48:13 +01:00
void NavMapBuilder2D : : build_navmap_iteration ( NavMapIterationBuild2D & r_build ) {
2025-02-26 11:42:07 +01:00
PerformanceData & performance_data = r_build . performance_data ;
2024-12-26 04:50:33 +01:00
performance_data . pm_polygon_count = 0 ;
performance_data . pm_edge_count = 0 ;
performance_data . pm_edge_merge_count = 0 ;
performance_data . pm_edge_connection_count = 0 ;
performance_data . pm_edge_free_count = 0 ;
2024-12-15 20:31:13 +01:00
_build_step_gather_region_polygons ( r_build ) ;
_build_step_find_edge_connection_pairs ( r_build ) ;
_build_step_merge_edge_connection_pairs ( r_build ) ;
_build_step_edge_connection_margin_connections ( r_build ) ;
_build_step_navlink_connections ( r_build ) ;
_build_update_map_iteration ( r_build ) ;
}
2025-02-26 11:48:13 +01:00
void NavMapBuilder2D : : _build_step_gather_region_polygons ( NavMapIterationBuild2D & r_build ) {
2025-02-26 11:42:07 +01:00
PerformanceData & performance_data = r_build . performance_data ;
2025-02-26 11:48:13 +01:00
NavMapIteration2D * map_iteration = r_build . map_iteration ;
2024-12-26 04:50:33 +01:00
2025-06-11 00:40:36 +02:00
const LocalVector < Ref < NavRegionIteration2D > > & regions = map_iteration - > region_iterations ;
HashMap < const NavBaseIteration2D * , LocalVector < Connection > > & region_external_connections = map_iteration - > external_region_connections ;
map_iteration - > navbases_polygons_external_connections . clear ( ) ;
2024-12-15 20:31:13 +01:00
// Remove regions connections.
2024-12-26 04:50:33 +01:00
region_external_connections . clear ( ) ;
2024-12-15 20:31:13 +01:00
2024-12-26 04:50:33 +01:00
// Copy all region polygons in the map.
2025-01-02 15:35:29 +01:00
int polygon_count = 0 ;
2025-06-11 00:40:36 +02:00
for ( const Ref < NavRegionIteration2D > & region : regions ) {
const uint32_t polygons_size = region - > navmesh_polygons . size ( ) ;
polygon_count + = polygons_size ;
region_external_connections [ region . ptr ( ) ] = LocalVector < Connection > ( ) ;
map_iteration - > navbases_polygons_external_connections [ region . ptr ( ) ] = LocalVector < LocalVector < Connection > > ( ) ;
map_iteration - > navbases_polygons_external_connections [ region . ptr ( ) ] . resize ( polygons_size ) ;
2024-12-15 20:31:13 +01:00
}
performance_data . pm_polygon_count = polygon_count ;
r_build . polygon_count = polygon_count ;
}
2025-02-26 11:48:13 +01:00
void NavMapBuilder2D : : _build_step_find_edge_connection_pairs ( NavMapIterationBuild2D & r_build ) {
2025-02-26 11:42:07 +01:00
PerformanceData & performance_data = r_build . performance_data ;
2025-02-26 11:48:13 +01:00
NavMapIteration2D * map_iteration = r_build . map_iteration ;
2025-01-02 15:35:29 +01:00
int polygon_count = r_build . polygon_count ;
2025-06-11 00:40:36 +02:00
2025-02-26 11:42:07 +01:00
HashMap < EdgeKey , EdgeConnectionPair , EdgeKey > & connection_pairs_map = r_build . iter_connection_pairs_map ;
2024-12-15 20:31:13 +01:00
2024-12-26 04:50:33 +01:00
// Group all edges per key.
connection_pairs_map . clear ( ) ;
2025-01-02 15:35:29 +01:00
connection_pairs_map . reserve ( polygon_count ) ;
2024-12-26 04:50:33 +01:00
int free_edges_count = 0 ; // How many ConnectionPairs have only one Connection.
2025-06-11 00:40:36 +02:00
for ( const Ref < NavRegionIteration2D > & region : map_iteration - > region_iterations ) {
for ( const ConnectableEdge & connectable_edge : region - > get_external_edges ( ) ) {
const EdgeKey & ek = connectable_edge . ek ;
2024-12-26 04:50:33 +01:00
2025-06-11 00:40:36 +02:00
HashMap < EdgeKey , EdgeConnectionPair , EdgeKey > : : Iterator pair_it = connection_pairs_map . find ( ek ) ;
if ( ! pair_it ) {
pair_it = connection_pairs_map . insert ( ek , EdgeConnectionPair ( ) ) ;
performance_data . pm_edge_count + = 1 ;
+ + free_edges_count ;
}
EdgeConnectionPair & pair = pair_it - > value ;
if ( pair . size < 2 ) {
// Add the polygon/edge tuple to this key.
Connection new_connection ;
new_connection . polygon = & region - > navmesh_polygons [ connectable_edge . polygon_index ] ;
new_connection . pathway_start = connectable_edge . pathway_start ;
new_connection . pathway_end = connectable_edge . pathway_end ;
pair . connections [ pair . size ] = new_connection ;
+ + pair . size ;
if ( pair . size = = 2 ) {
- - free_edges_count ;
2024-12-15 20:31:13 +01:00
}
2024-12-26 04:50:33 +01:00
2025-06-11 00:40:36 +02:00
} else {
// The edge is already connected with another edge, skip.
ERR_PRINT_ONCE ( " Navigation map synchronization error. Attempted to merge a navigation mesh polygon edge with another already-merged edge. This is usually caused by crossing edges, overlapping polygons, or a mismatch of the NavigationMesh / NavigationPolygon baked 'cell_size' and navigation map 'cell_size'. If you're certain none of above is the case, change 'navigation/3d/merge_rasterizer_cell_scale' to 0.001. " ) ;
2024-12-15 20:31:13 +01:00
}
}
}
2024-12-26 04:50:33 +01:00
r_build . free_edge_count = free_edges_count ;
2024-12-15 20:31:13 +01:00
}
2025-02-26 11:48:13 +01:00
void NavMapBuilder2D : : _build_step_merge_edge_connection_pairs ( NavMapIterationBuild2D & r_build ) {
2025-02-26 11:42:07 +01:00
PerformanceData & performance_data = r_build . performance_data ;
2024-12-15 20:31:13 +01:00
2025-02-26 11:42:07 +01:00
HashMap < EdgeKey , EdgeConnectionPair , EdgeKey > & connection_pairs_map = r_build . iter_connection_pairs_map ;
2025-06-11 00:40:36 +02:00
LocalVector < Connection > & free_edges = r_build . iter_free_edges ;
2024-12-26 04:50:33 +01:00
int free_edges_count = r_build . free_edge_count ;
bool use_edge_connections = r_build . use_edge_connections ;
2024-12-15 20:31:13 +01:00
2024-12-26 04:50:33 +01:00
free_edges . clear ( ) ;
free_edges . reserve ( free_edges_count ) ;
2024-12-15 20:31:13 +01:00
2025-06-11 00:40:36 +02:00
NavMapIteration2D * map_iteration = r_build . map_iteration ;
HashMap < const NavBaseIteration2D * , LocalVector < LocalVector < Nav2D : : Connection > > > & navbases_polygons_external_connections = map_iteration - > navbases_polygons_external_connections ;
2025-02-26 11:42:07 +01:00
for ( const KeyValue < EdgeKey , EdgeConnectionPair > & pair_it : connection_pairs_map ) {
const EdgeConnectionPair & pair = pair_it . value ;
2024-12-15 20:31:13 +01:00
if ( pair . size = = 2 ) {
// Connect edge that are shared in different polygons.
2025-06-11 00:40:36 +02:00
const Connection & c1 = pair . connections [ 0 ] ;
const Connection & c2 = pair . connections [ 1 ] ;
navbases_polygons_external_connections [ c1 . polygon - > owner ] [ c1 . polygon - > id ] . push_back ( c2 ) ;
navbases_polygons_external_connections [ c2 . polygon - > owner ] [ c2 . polygon - > id ] . push_back ( c1 ) ;
performance_data . pm_edge_connection_count + = 1 ;
2024-12-15 20:31:13 +01:00
} else {
CRASH_COND_MSG ( pair . size ! = 1 , vformat ( " Number of connection != 1. Found: %d " , pair . size ) ) ;
2024-12-26 04:50:33 +01:00
if ( use_edge_connections & & pair . connections [ 0 ] . polygon - > owner - > get_use_edge_connections ( ) ) {
free_edges . push_back ( pair . connections [ 0 ] ) ;
2024-12-15 20:31:13 +01:00
}
}
}
}
2025-02-26 11:48:13 +01:00
void NavMapBuilder2D : : _build_step_edge_connection_margin_connections ( NavMapIterationBuild2D & r_build ) {
2025-02-26 11:42:07 +01:00
PerformanceData & performance_data = r_build . performance_data ;
2025-02-26 11:48:13 +01:00
NavMapIteration2D * map_iteration = r_build . map_iteration ;
2024-12-26 04:50:33 +01:00
real_t edge_connection_margin = r_build . edge_connection_margin ;
2025-06-11 00:40:36 +02:00
LocalVector < Connection > & free_edges = r_build . iter_free_edges ;
HashMap < const NavBaseIteration2D * , LocalVector < Connection > > & region_external_connections = map_iteration - > external_region_connections ;
HashMap < const NavBaseIteration2D * , LocalVector < LocalVector < Nav2D : : Connection > > > & navbases_polygons_external_connections = map_iteration - > navbases_polygons_external_connections ;
2024-12-26 04:50:33 +01:00
2024-12-15 20:31:13 +01:00
// Find the compatible near edges.
//
// Note:
// Considering that the edges must be compatible (for obvious reasons)
// to be connected, create new polygons to remove that small gap is
// not really useful and would result in wasteful computation during
// connection, integration and path finding.
2024-12-26 04:50:33 +01:00
performance_data . pm_edge_free_count = free_edges . size ( ) ;
2024-12-15 20:31:13 +01:00
const real_t edge_connection_margin_squared = edge_connection_margin * edge_connection_margin ;
2024-12-26 04:50:33 +01:00
for ( uint32_t i = 0 ; i < free_edges . size ( ) ; i + + ) {
2025-06-11 00:40:36 +02:00
const Connection & free_edge = free_edges [ i ] ;
const Vector2 & edge_p1 = free_edge . pathway_start ;
const Vector2 & edge_p2 = free_edge . pathway_end ;
2024-12-15 20:31:13 +01:00
2024-12-26 04:50:33 +01:00
for ( uint32_t j = 0 ; j < free_edges . size ( ) ; j + + ) {
2025-06-11 00:40:36 +02:00
const Connection & other_edge = free_edges [ j ] ;
2024-12-15 20:31:13 +01:00
if ( i = = j | | free_edge . polygon - > owner = = other_edge . polygon - > owner ) {
continue ;
}
2025-06-11 00:40:36 +02:00
const Vector2 & other_edge_p1 = other_edge . pathway_start ;
const Vector2 & other_edge_p2 = other_edge . pathway_end ;
2024-12-15 20:31:13 +01:00
2025-06-11 00:40:36 +02:00
// Compute the projection of the opposite edge on the current one
2025-02-26 11:48:13 +01:00
Vector2 edge_vector = edge_p2 - edge_p1 ;
2025-06-11 00:40:36 +02:00
real_t projected_p1_ratio = edge_vector . dot ( other_edge_p1 - edge_p1 ) / ( edge_vector . length_squared ( ) ) ;
real_t projected_p2_ratio = edge_vector . dot ( other_edge_p2 - edge_p1 ) / ( edge_vector . length_squared ( ) ) ;
2024-12-15 20:31:13 +01:00
if ( ( projected_p1_ratio < 0.0 & & projected_p2_ratio < 0.0 ) | | ( projected_p1_ratio > 1.0 & & projected_p2_ratio > 1.0 ) ) {
continue ;
}
// Check if the two edges are close to each other enough and compute a pathway between the two regions.
2025-02-26 11:48:13 +01:00
Vector2 self1 = edge_vector * CLAMP ( projected_p1_ratio , 0.0 , 1.0 ) + edge_p1 ;
Vector2 other1 ;
2024-12-15 20:31:13 +01:00
if ( projected_p1_ratio > = 0.0 & & projected_p1_ratio < = 1.0 ) {
other1 = other_edge_p1 ;
} else {
other1 = other_edge_p1 . lerp ( other_edge_p2 , ( 1.0 - projected_p1_ratio ) / ( projected_p2_ratio - projected_p1_ratio ) ) ;
}
if ( other1 . distance_squared_to ( self1 ) > edge_connection_margin_squared ) {
continue ;
}
2025-02-26 11:48:13 +01:00
Vector2 self2 = edge_vector * CLAMP ( projected_p2_ratio , 0.0 , 1.0 ) + edge_p1 ;
Vector2 other2 ;
2024-12-15 20:31:13 +01:00
if ( projected_p2_ratio > = 0.0 & & projected_p2_ratio < = 1.0 ) {
other2 = other_edge_p2 ;
} else {
other2 = other_edge_p1 . lerp ( other_edge_p2 , ( 0.0 - projected_p1_ratio ) / ( projected_p2_ratio - projected_p1_ratio ) ) ;
}
if ( other2 . distance_squared_to ( self2 ) > edge_connection_margin_squared ) {
continue ;
}
// The edges can now be connected.
2025-06-11 00:40:36 +02:00
Connection new_connection = other_edge ;
2024-12-15 20:31:13 +01:00
new_connection . pathway_start = ( self1 + other1 ) / 2.0 ;
new_connection . pathway_end = ( self2 + other2 ) / 2.0 ;
2025-06-11 00:40:36 +02:00
//free_edge.polygon->connections.push_back(new_connection);
2024-12-15 20:31:13 +01:00
// Add the connection to the region_connection map.
2025-06-11 00:40:36 +02:00
region_external_connections [ free_edge . polygon - > owner ] . push_back ( new_connection ) ;
navbases_polygons_external_connections [ free_edge . polygon - > owner ] [ free_edge . polygon - > id ] . push_back ( new_connection ) ;
2024-12-15 20:31:13 +01:00
performance_data . pm_edge_connection_count + = 1 ;
}
}
}
2025-02-26 11:48:13 +01:00
void NavMapBuilder2D : : _build_step_navlink_connections ( NavMapIterationBuild2D & r_build ) {
NavMapIteration2D * map_iteration = r_build . map_iteration ;
2024-12-26 04:50:33 +01:00
2024-12-15 20:31:13 +01:00
real_t link_connection_radius = r_build . link_connection_radius ;
2024-12-26 04:50:33 +01:00
2025-06-11 00:40:36 +02:00
const LocalVector < Ref < NavLinkIteration2D > > & links = map_iteration - > link_iterations ;
2024-12-15 20:31:13 +01:00
int polygon_count = r_build . polygon_count ;
2024-12-26 04:50:33 +01:00
real_t link_connection_radius_sqr = link_connection_radius * link_connection_radius ;
2024-12-15 20:31:13 +01:00
2025-06-11 00:40:36 +02:00
HashMap < const NavBaseIteration2D * , LocalVector < LocalVector < Nav2D : : Connection > > > & navbases_polygons_external_connections = map_iteration - > navbases_polygons_external_connections ;
LocalVector < Nav2D : : Polygon > & navlink_polygons = map_iteration - > navlink_polygons ;
navlink_polygons . clear ( ) ;
navlink_polygons . resize ( links . size ( ) ) ;
uint32_t navlink_index = 0 ;
2024-12-15 20:31:13 +01:00
// Search for polygons within range of a nav link.
2025-06-11 00:40:36 +02:00
for ( const Ref < NavLinkIteration2D > & link : links ) {
polygon_count + + ;
Polygon & new_polygon = navlink_polygons [ navlink_index + + ] ;
new_polygon . id = 0 ;
new_polygon . owner = link . ptr ( ) ;
const Vector2 link_start_pos = link - > get_start_position ( ) ;
const Vector2 link_end_pos = link - > get_end_position ( ) ;
2024-12-15 20:31:13 +01:00
2025-02-26 11:42:07 +01:00
Polygon * closest_start_polygon = nullptr ;
2024-12-15 20:31:13 +01:00
real_t closest_start_sqr_dist = link_connection_radius_sqr ;
2025-02-26 11:48:13 +01:00
Vector2 closest_start_point ;
2024-12-15 20:31:13 +01:00
2025-02-26 11:42:07 +01:00
Polygon * closest_end_polygon = nullptr ;
2024-12-15 20:31:13 +01:00
real_t closest_end_sqr_dist = link_connection_radius_sqr ;
2025-02-26 11:48:13 +01:00
Vector2 closest_end_point ;
2024-12-15 20:31:13 +01:00
2025-06-11 00:40:36 +02:00
for ( const Ref < NavRegionIteration2D > & region : map_iteration - > region_iterations ) {
Rect2 region_bounds = region - > get_bounds ( ) . grow ( link_connection_radius ) ;
2025-01-02 15:35:29 +01:00
if ( ! region_bounds . has_point ( link_start_pos ) & & ! region_bounds . has_point ( link_end_pos ) ) {
continue ;
}
2024-12-26 04:50:33 +01:00
2025-06-11 00:40:36 +02:00
for ( Polygon & polyon : region - > navmesh_polygons ) {
2025-04-10 01:03:58 +02:00
for ( uint32_t point_id = 2 ; point_id < polyon . vertices . size ( ) ; point_id + = 1 ) {
const Triangle2 triangle ( polyon . vertices [ 0 ] , polyon . vertices [ point_id - 1 ] , polyon . vertices [ point_id ] ) ;
2025-01-02 15:35:29 +01:00
{
2025-02-26 11:48:13 +01:00
const Vector2 start_point = triangle . get_closest_point_to ( link_start_pos ) ;
2025-01-02 15:35:29 +01:00
const real_t sqr_dist = start_point . distance_squared_to ( link_start_pos ) ;
// Pick the polygon that is within our radius and is closer than anything we've seen yet.
if ( sqr_dist < closest_start_sqr_dist ) {
closest_start_sqr_dist = sqr_dist ;
closest_start_point = start_point ;
closest_start_polygon = & polyon ;
}
2024-12-15 20:31:13 +01:00
}
2025-01-02 15:35:29 +01:00
{
2025-02-26 11:48:13 +01:00
const Vector2 end_point = triangle . get_closest_point_to ( link_end_pos ) ;
2025-01-02 15:35:29 +01:00
const real_t sqr_dist = end_point . distance_squared_to ( link_end_pos ) ;
2024-12-15 20:31:13 +01:00
2025-01-02 15:35:29 +01:00
// Pick the polygon that is within our radius and is closer than anything we've seen yet.
if ( sqr_dist < closest_end_sqr_dist ) {
closest_end_sqr_dist = sqr_dist ;
closest_end_point = end_point ;
closest_end_polygon = & polyon ;
}
2024-12-15 20:31:13 +01:00
}
}
}
}
// If we have both a start and end point, then create a synthetic polygon to route through.
if ( closest_start_polygon & & closest_end_polygon ) {
2025-04-10 01:03:58 +02:00
new_polygon . vertices . resize ( 4 ) ;
2024-12-15 20:31:13 +01:00
// Build a set of vertices that create a thin polygon going from the start to the end point.
2025-04-10 01:03:58 +02:00
new_polygon . vertices [ 0 ] = closest_start_point ;
new_polygon . vertices [ 1 ] = closest_start_point ;
new_polygon . vertices [ 2 ] = closest_end_point ;
new_polygon . vertices [ 3 ] = closest_end_point ;
2024-12-15 20:31:13 +01:00
// Setup connections to go forward in the link.
{
2025-06-11 00:40:36 +02:00
Connection entry_connection ;
2024-12-15 20:31:13 +01:00
entry_connection . polygon = & new_polygon ;
entry_connection . edge = - 1 ;
2025-04-10 01:03:58 +02:00
entry_connection . pathway_start = new_polygon . vertices [ 0 ] ;
entry_connection . pathway_end = new_polygon . vertices [ 1 ] ;
2025-06-11 00:40:36 +02:00
navbases_polygons_external_connections [ closest_start_polygon - > owner ] [ closest_start_polygon - > id ] . push_back ( entry_connection ) ;
2024-12-15 20:31:13 +01:00
2025-06-11 00:40:36 +02:00
Connection exit_connection ;
2024-12-15 20:31:13 +01:00
exit_connection . polygon = closest_end_polygon ;
exit_connection . edge = - 1 ;
2025-04-10 01:03:58 +02:00
exit_connection . pathway_start = new_polygon . vertices [ 2 ] ;
exit_connection . pathway_end = new_polygon . vertices [ 3 ] ;
2025-06-11 00:40:36 +02:00
navbases_polygons_external_connections [ link . ptr ( ) ] . push_back ( LocalVector < Nav2D : : Connection > ( ) ) ;
navbases_polygons_external_connections [ link . ptr ( ) ] [ new_polygon . id ] . push_back ( exit_connection ) ;
2024-12-15 20:31:13 +01:00
}
// If the link is bi-directional, create connections from the end to the start.
2025-06-11 00:40:36 +02:00
if ( link - > is_bidirectional ( ) ) {
Connection entry_connection ;
2024-12-15 20:31:13 +01:00
entry_connection . polygon = & new_polygon ;
entry_connection . edge = - 1 ;
2025-04-10 01:03:58 +02:00
entry_connection . pathway_start = new_polygon . vertices [ 2 ] ;
entry_connection . pathway_end = new_polygon . vertices [ 3 ] ;
2025-06-11 00:40:36 +02:00
navbases_polygons_external_connections [ closest_end_polygon - > owner ] [ closest_end_polygon - > id ] . push_back ( entry_connection ) ;
2024-12-15 20:31:13 +01:00
2025-06-11 00:40:36 +02:00
Connection exit_connection ;
2024-12-15 20:31:13 +01:00
exit_connection . polygon = closest_start_polygon ;
exit_connection . edge = - 1 ;
2025-04-10 01:03:58 +02:00
exit_connection . pathway_start = new_polygon . vertices [ 0 ] ;
exit_connection . pathway_end = new_polygon . vertices [ 1 ] ;
2025-06-11 00:40:36 +02:00
navbases_polygons_external_connections [ link . ptr ( ) ] . push_back ( LocalVector < Nav2D : : Connection > ( ) ) ;
navbases_polygons_external_connections [ link . ptr ( ) ] [ new_polygon . id ] . push_back ( exit_connection ) ;
2024-12-15 20:31:13 +01:00
}
}
}
2025-04-10 22:47:02 +02:00
r_build . polygon_count = polygon_count ;
2024-12-15 20:31:13 +01:00
}
2025-02-26 11:48:13 +01:00
void NavMapBuilder2D : : _build_update_map_iteration ( NavMapIterationBuild2D & r_build ) {
NavMapIteration2D * map_iteration = r_build . map_iteration ;
2024-12-15 20:31:13 +01:00
2025-01-02 15:35:29 +01:00
map_iteration - > navmesh_polygon_count = r_build . polygon_count ;
2024-12-15 20:31:13 +01:00
2025-06-11 00:40:36 +02:00
uint32_t navmesh_polygon_count = r_build . polygon_count ;
uint32_t total_polygon_count = navmesh_polygon_count ;
2024-12-15 20:31:13 +01:00
map_iteration - > path_query_slots_mutex . lock ( ) ;
2025-02-26 11:48:13 +01:00
for ( NavMeshQueries2D : : PathQuerySlot & p_path_query_slot : map_iteration - > path_query_slots ) {
2024-12-15 20:31:13 +01:00
p_path_query_slot . traversable_polys . clear ( ) ;
2025-06-11 00:40:36 +02:00
p_path_query_slot . traversable_polys . reserve ( navmesh_polygon_count * 0.25 ) ;
2024-12-26 04:50:33 +01:00
p_path_query_slot . path_corridor . clear ( ) ;
2025-06-11 00:40:36 +02:00
p_path_query_slot . path_corridor . resize ( total_polygon_count ) ;
p_path_query_slot . poly_to_id . clear ( ) ;
p_path_query_slot . poly_to_id . reserve ( total_polygon_count ) ;
int polygon_id = 0 ;
for ( Ref < NavRegionIteration2D > & region : map_iteration - > region_iterations ) {
for ( const Polygon & polygon : region - > navmesh_polygons ) {
p_path_query_slot . poly_to_id [ & polygon ] = polygon_id ;
polygon_id + + ;
}
}
for ( const Polygon & polygon : map_iteration - > navlink_polygons ) {
p_path_query_slot . poly_to_id [ & polygon ] = polygon_id ;
polygon_id + + ;
}
DEV_ASSERT ( p_path_query_slot . path_corridor . size ( ) = = p_path_query_slot . poly_to_id . size ( ) ) ;
2024-12-15 20:31:13 +01:00
}
2025-06-11 00:40:36 +02:00
2024-12-15 20:31:13 +01:00
map_iteration - > path_query_slots_mutex . unlock ( ) ;
}