Skip to content

Commit 848d908

Browse files
committed
Merge pull request #96730 from tracefree/properly_transforming_obstacles
Make use of NavigationObstacle3D's transform
2 parents a5873ff + 44ef3d3 commit 848d908

File tree

4 files changed

+57
-68
lines changed

4 files changed

+57
-68
lines changed

editor/plugins/navigation_obstacle_3d_editor_plugin.cpp

Lines changed: 12 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -115,9 +115,14 @@ EditorPlugin::AfterGUIInput NavigationObstacle3DEditor::forward_3d_gui_input(Cam
115115
return EditorPlugin::AFTER_GUI_INPUT_PASS;
116116
}
117117

118-
Transform3D gt = obstacle_node->get_global_transform();
118+
// Use special transformation rules for NavigationObstacle3D: Only take global y-rotation into account and limit scaling to positive values.
119+
Transform3D gt;
120+
gt.origin = obstacle_node->get_global_position();
121+
gt.scale_basis(obstacle_node->get_global_basis().get_scale().abs().maxf(0.001));
122+
gt.rotate_basis(Vector3(0.0, 1.0, 0.0), obstacle_node->get_global_rotation().y);
119123
Transform3D gi = gt.affine_inverse();
120124
Plane p(Vector3(0.0, 1.0, 0.0), gt.origin);
125+
point_lines_meshinstance->set_transform(gt.translated(Vector3(0.0, 0.0, 0.00001)));
121126

122127
Ref<InputEventMouseButton> mb = p_event;
123128

@@ -374,9 +379,12 @@ void NavigationObstacle3DEditor::_polygon_draw() {
374379
point_handle_mesh->clear_surfaces();
375380
point_lines_mesh->clear_surfaces();
376381
point_lines_meshinstance->set_material_override(line_material);
377-
point_lines_mesh->surface_begin(Mesh::PRIMITIVE_LINES);
378382

379-
Rect2 rect;
383+
if (poly.is_empty()) {
384+
return;
385+
}
386+
387+
point_lines_mesh->surface_begin(Mesh::PRIMITIVE_LINES);
380388

381389
for (int i = 0; i < poly.size(); i++) {
382390
Vector2 p, p2;
@@ -392,12 +400,6 @@ void NavigationObstacle3DEditor::_polygon_draw() {
392400
p2 = poly[(i + 1) % poly.size()];
393401
}
394402

395-
if (i == 0) {
396-
rect.position = p;
397-
} else {
398-
rect.expand_to(p);
399-
}
400-
401403
Vector3 point = Vector3(p.x, 0.0, p.y);
402404
Vector3 next_point = Vector3(p2.x, 0.0, p2.y);
403405

@@ -411,58 +413,8 @@ void NavigationObstacle3DEditor::_polygon_draw() {
411413
//vpc->draw_texture(handle,point-handle->get_size()*0.5);
412414
}
413415

414-
rect = rect.grow(1);
415-
416-
AABB r;
417-
r.position.x = rect.position.x;
418-
r.position.y = 0.0;
419-
r.position.z = rect.position.y;
420-
r.size.x = rect.size.x;
421-
r.size.y = 0;
422-
r.size.z = rect.size.y;
423-
424-
point_lines_mesh->surface_set_color(Color(0.8, 0.8, 0.8, 0.2));
425-
point_lines_mesh->surface_add_vertex(r.position);
426-
point_lines_mesh->surface_set_color(Color(0.8, 0.8, 0.8, 0.2));
427-
point_lines_mesh->surface_add_vertex(r.position + Vector3(0.3, 0, 0));
428-
point_lines_mesh->surface_set_color(Color(0.8, 0.8, 0.8, 0.2));
429-
point_lines_mesh->surface_add_vertex(r.position);
430-
point_lines_mesh->surface_set_color(Color(0.8, 0.8, 0.8, 0.2));
431-
point_lines_mesh->surface_add_vertex(r.position + Vector3(0.0, 0.3, 0));
432-
433-
point_lines_mesh->surface_set_color(Color(0.8, 0.8, 0.8, 0.2));
434-
point_lines_mesh->surface_add_vertex(r.position + Vector3(r.size.x, 0, 0));
435-
point_lines_mesh->surface_set_color(Color(0.8, 0.8, 0.8, 0.2));
436-
point_lines_mesh->surface_add_vertex(r.position + Vector3(r.size.x, 0, 0) - Vector3(0.3, 0, 0));
437-
point_lines_mesh->surface_set_color(Color(0.8, 0.8, 0.8, 0.2));
438-
point_lines_mesh->surface_add_vertex(r.position + Vector3(r.size.x, 0, 0));
439-
point_lines_mesh->surface_set_color(Color(0.8, 0.8, 0.8, 0.2));
440-
point_lines_mesh->surface_add_vertex(r.position + Vector3(r.size.x, 0, 0) + Vector3(0, 0.3, 0));
441-
442-
point_lines_mesh->surface_set_color(Color(0.8, 0.8, 0.8, 0.2));
443-
point_lines_mesh->surface_add_vertex(r.position + Vector3(0, r.size.y, 0));
444-
point_lines_mesh->surface_set_color(Color(0.8, 0.8, 0.8, 0.2));
445-
point_lines_mesh->surface_add_vertex(r.position + Vector3(0, r.size.y, 0) - Vector3(0, 0.3, 0));
446-
point_lines_mesh->surface_set_color(Color(0.8, 0.8, 0.8, 0.2));
447-
point_lines_mesh->surface_add_vertex(r.position + Vector3(0, r.size.y, 0));
448-
point_lines_mesh->surface_set_color(Color(0.8, 0.8, 0.8, 0.2));
449-
point_lines_mesh->surface_add_vertex(r.position + Vector3(0, r.size.y, 0) + Vector3(0.3, 0, 0));
450-
451-
point_lines_mesh->surface_set_color(Color(0.8, 0.8, 0.8, 0.2));
452-
point_lines_mesh->surface_add_vertex(r.position + r.size);
453-
point_lines_mesh->surface_set_color(Color(0.8, 0.8, 0.8, 0.2));
454-
point_lines_mesh->surface_add_vertex(r.position + r.size - Vector3(0.3, 0, 0));
455-
point_lines_mesh->surface_set_color(Color(0.8, 0.8, 0.8, 0.2));
456-
point_lines_mesh->surface_add_vertex(r.position + r.size);
457-
point_lines_mesh->surface_set_color(Color(0.8, 0.8, 0.8, 0.2));
458-
point_lines_mesh->surface_add_vertex(r.position + r.size - Vector3(0.0, 0.3, 0));
459-
460416
point_lines_mesh->surface_end();
461417

462-
if (poly.size() == 0) {
463-
return;
464-
}
465-
466418
Array point_handle_mesh_array;
467419
point_handle_mesh_array.resize(Mesh::ARRAY_MAX);
468420
Vector<Vector3> point_handle_mesh_vertices;
@@ -541,6 +493,7 @@ NavigationObstacle3DEditor::NavigationObstacle3DEditor() {
541493
point_lines_mesh.instantiate();
542494
point_lines_meshinstance->set_mesh(point_lines_mesh);
543495
point_lines_meshinstance->set_transform(Transform3D(Basis(), Vector3(0, 0, 0.00001)));
496+
point_lines_meshinstance->set_as_top_level(true);
544497

545498
line_material.instantiate();
546499
line_material->set_shading_mode(StandardMaterial3D::SHADING_MODE_UNSHADED);

modules/navigation/3d/nav_mesh_generator_3d.cpp

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -595,11 +595,17 @@ void NavMeshGenerator3D::generator_parse_navigationobstacle_node(const Ref<Navig
595595
return;
596596
}
597597

598-
const Transform3D node_xform = p_source_geometry_data->root_node_transform * Transform3D(Basis(), obstacle->get_global_position());
599-
598+
const float elevation = obstacle->get_global_position().y + p_source_geometry_data->root_node_transform.origin.y;
599+
// Prevent non-positive scaling.
600+
const Vector3 safe_scale = obstacle->get_global_basis().get_scale().abs().maxf(0.001);
600601
const float obstacle_radius = obstacle->get_radius();
601602

602603
if (obstacle_radius > 0.0) {
604+
// Radius defined obstacle should be uniformly scaled from obstacle basis max scale axis.
605+
const float scaling_max_value = safe_scale[safe_scale.max_axis_index()];
606+
const Vector3 uniform_max_scale = Vector3(scaling_max_value, scaling_max_value, scaling_max_value);
607+
const Transform3D obstacle_circle_transform = p_source_geometry_data->root_node_transform * Transform3D(Basis().scaled(uniform_max_scale), obstacle->get_global_position());
608+
603609
Vector<Vector3> obstruction_circle_vertices;
604610

605611
// The point of this is that the moving obstacle can make a simple hole in the navigation mesh and affect the pathfinding.
@@ -613,12 +619,15 @@ void NavMeshGenerator3D::generator_parse_navigationobstacle_node(const Ref<Navig
613619

614620
for (int i = 0; i < circle_points; i++) {
615621
const float angle = i * circle_point_step;
616-
circle_vertices_ptrw[i] = node_xform.xform(Vector3(Math::cos(angle) * obstacle_radius, 0.0, Math::sin(angle) * obstacle_radius));
622+
circle_vertices_ptrw[i] = obstacle_circle_transform.xform(Vector3(Math::cos(angle) * obstacle_radius, 0.0, Math::sin(angle) * obstacle_radius));
617623
}
618624

619-
p_source_geometry_data->add_projected_obstruction(obstruction_circle_vertices, obstacle->get_global_position().y + p_source_geometry_data->root_node_transform.origin.y - obstacle_radius, obstacle_radius, obstacle->get_carve_navigation_mesh());
625+
p_source_geometry_data->add_projected_obstruction(obstruction_circle_vertices, elevation - obstacle_radius, scaling_max_value * obstacle_radius, obstacle->get_carve_navigation_mesh());
620626
}
621627

628+
// Obstacles are projected to the xz-plane, so only rotation around the y-axis can be taken into account.
629+
const Transform3D node_xform = p_source_geometry_data->root_node_transform * Transform3D(Basis().scaled(safe_scale).rotated(Vector3(0.0, 1.0, 0.0), obstacle->get_global_rotation().y), obstacle->get_global_position());
630+
622631
const Vector<Vector3> &obstacle_vertices = obstacle->get_vertices();
623632

624633
if (obstacle_vertices.is_empty()) {
@@ -635,7 +644,7 @@ void NavMeshGenerator3D::generator_parse_navigationobstacle_node(const Ref<Navig
635644
obstruction_shape_vertices_ptrw[i] = node_xform.xform(obstacle_vertices_ptr[i]);
636645
obstruction_shape_vertices_ptrw[i].y = 0.0;
637646
}
638-
p_source_geometry_data->add_projected_obstruction(obstruction_shape_vertices, obstacle->get_global_position().y + p_source_geometry_data->root_node_transform.origin.y, obstacle->get_height(), obstacle->get_carve_navigation_mesh());
647+
p_source_geometry_data->add_projected_obstruction(obstruction_shape_vertices, elevation, safe_scale.y * obstacle->get_height(), obstacle->get_carve_navigation_mesh());
639648
}
640649

641650
void NavMeshGenerator3D::generator_parse_source_geometry_data(const Ref<NavigationMesh> &p_navigation_mesh, Ref<NavigationMeshSourceGeometryData3D> p_source_geometry_data, Node *p_root_node) {

scene/3d/navigation_obstacle_3d.cpp

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -176,13 +176,19 @@ void NavigationObstacle3D::_notification(int p_what) {
176176
}
177177
#ifdef DEBUG_ENABLED
178178
if (fake_agent_radius_debug_instance.is_valid() && radius > 0.0) {
179-
Transform3D debug_transform;
180-
debug_transform.origin = get_global_position();
179+
// Prevent non-positive scaling.
180+
const Vector3 safe_scale = get_global_basis().get_scale().abs().maxf(0.001);
181+
// Agent radius is a scalar value and does not support non-uniform scaling, choose the largest axis.
182+
const float scaling_max_value = safe_scale[safe_scale.max_axis_index()];
183+
const Vector3 uniform_max_scale = Vector3(scaling_max_value, scaling_max_value, scaling_max_value);
184+
const Transform3D debug_transform = Transform3D(Basis().scaled(uniform_max_scale), get_global_position());
181185
RS::get_singleton()->instance_set_transform(fake_agent_radius_debug_instance, debug_transform);
182186
}
183187
if (static_obstacle_debug_instance.is_valid() && get_vertices().size() > 0) {
184-
Transform3D debug_transform;
185-
debug_transform.origin = get_global_position();
188+
// Prevent non-positive scaling.
189+
const Vector3 safe_scale = get_global_basis().get_scale().abs().maxf(0.001);
190+
// Obstacles are projected to the xz-plane, so only rotation around the y-axis can be taken into account.
191+
const Transform3D debug_transform = Transform3D(Basis().scaled(safe_scale).rotated(Vector3(0.0, 1.0, 0.0), get_global_rotation().y), get_global_position());
186192
RS::get_singleton()->instance_set_transform(static_obstacle_debug_instance, debug_transform);
187193
}
188194
#endif // DEBUG_ENABLED
@@ -354,6 +360,25 @@ bool NavigationObstacle3D::get_carve_navigation_mesh() const {
354360
return carve_navigation_mesh;
355361
}
356362

363+
PackedStringArray NavigationObstacle3D::get_configuration_warnings() const {
364+
PackedStringArray warnings = Node3D::get_configuration_warnings();
365+
366+
if (get_global_rotation().x != 0.0 || get_global_rotation().z != 0.0) {
367+
warnings.push_back(RTR("NavigationObstacle3D only takes global rotation around the y-axis into account. Rotations around the x-axis or z-axis might lead to unexpected results."));
368+
}
369+
370+
const Vector3 global_scale = get_global_basis().get_scale();
371+
if (global_scale.x < 0.001 || global_scale.y < 0.001 || global_scale.z < 0.001) {
372+
warnings.push_back(RTR("NavigationObstacle3D does not support negative or zero scaling."));
373+
}
374+
375+
if (radius > 0.0 && !get_global_basis().is_conformal()) {
376+
warnings.push_back(RTR("The agent radius can only be scaled uniformly. The largest scale value along the three axes will be used."));
377+
}
378+
379+
return warnings;
380+
}
381+
357382
void NavigationObstacle3D::_update_map(RID p_map) {
358383
NavigationServer3D::get_singleton()->obstacle_set_map(obstacle, p_map);
359384
map_current = p_map;

scene/3d/navigation_obstacle_3d.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,8 @@ class NavigationObstacle3D : public Node3D {
117117
void set_carve_navigation_mesh(bool p_enabled);
118118
bool get_carve_navigation_mesh() const;
119119

120+
PackedStringArray get_configuration_warnings() const override;
121+
120122
private:
121123
void _update_map(RID p_map);
122124
void _update_position(const Vector3 p_position);

0 commit comments

Comments
 (0)