Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make use of NavigationObstacle3D's transform #96730

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 12 additions & 59 deletions editor/plugins/navigation_obstacle_3d_editor_plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -115,9 +115,14 @@ EditorPlugin::AfterGUIInput NavigationObstacle3DEditor::forward_3d_gui_input(Cam
return EditorPlugin::AFTER_GUI_INPUT_PASS;
}

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

Ref<InputEventMouseButton> mb = p_event;

Expand Down Expand Up @@ -374,9 +379,12 @@ void NavigationObstacle3DEditor::_polygon_draw() {
point_handle_mesh->clear_surfaces();
point_lines_mesh->clear_surfaces();
point_lines_meshinstance->set_material_override(line_material);
point_lines_mesh->surface_begin(Mesh::PRIMITIVE_LINES);

Rect2 rect;
if (poly.is_empty()) {
return;
}

point_lines_mesh->surface_begin(Mesh::PRIMITIVE_LINES);

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

if (i == 0) {
rect.position = p;
} else {
rect.expand_to(p);
}

Vector3 point = Vector3(p.x, 0.0, p.y);
Vector3 next_point = Vector3(p2.x, 0.0, p2.y);

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

rect = rect.grow(1);

AABB r;
r.position.x = rect.position.x;
r.position.y = 0.0;
r.position.z = rect.position.y;
r.size.x = rect.size.x;
r.size.y = 0;
r.size.z = rect.size.y;

point_lines_mesh->surface_set_color(Color(0.8, 0.8, 0.8, 0.2));
point_lines_mesh->surface_add_vertex(r.position);
point_lines_mesh->surface_set_color(Color(0.8, 0.8, 0.8, 0.2));
point_lines_mesh->surface_add_vertex(r.position + Vector3(0.3, 0, 0));
point_lines_mesh->surface_set_color(Color(0.8, 0.8, 0.8, 0.2));
point_lines_mesh->surface_add_vertex(r.position);
point_lines_mesh->surface_set_color(Color(0.8, 0.8, 0.8, 0.2));
point_lines_mesh->surface_add_vertex(r.position + Vector3(0.0, 0.3, 0));

point_lines_mesh->surface_set_color(Color(0.8, 0.8, 0.8, 0.2));
point_lines_mesh->surface_add_vertex(r.position + Vector3(r.size.x, 0, 0));
point_lines_mesh->surface_set_color(Color(0.8, 0.8, 0.8, 0.2));
point_lines_mesh->surface_add_vertex(r.position + Vector3(r.size.x, 0, 0) - Vector3(0.3, 0, 0));
point_lines_mesh->surface_set_color(Color(0.8, 0.8, 0.8, 0.2));
point_lines_mesh->surface_add_vertex(r.position + Vector3(r.size.x, 0, 0));
point_lines_mesh->surface_set_color(Color(0.8, 0.8, 0.8, 0.2));
point_lines_mesh->surface_add_vertex(r.position + Vector3(r.size.x, 0, 0) + Vector3(0, 0.3, 0));

point_lines_mesh->surface_set_color(Color(0.8, 0.8, 0.8, 0.2));
point_lines_mesh->surface_add_vertex(r.position + Vector3(0, r.size.y, 0));
point_lines_mesh->surface_set_color(Color(0.8, 0.8, 0.8, 0.2));
point_lines_mesh->surface_add_vertex(r.position + Vector3(0, r.size.y, 0) - Vector3(0, 0.3, 0));
point_lines_mesh->surface_set_color(Color(0.8, 0.8, 0.8, 0.2));
point_lines_mesh->surface_add_vertex(r.position + Vector3(0, r.size.y, 0));
point_lines_mesh->surface_set_color(Color(0.8, 0.8, 0.8, 0.2));
point_lines_mesh->surface_add_vertex(r.position + Vector3(0, r.size.y, 0) + Vector3(0.3, 0, 0));

point_lines_mesh->surface_set_color(Color(0.8, 0.8, 0.8, 0.2));
point_lines_mesh->surface_add_vertex(r.position + r.size);
point_lines_mesh->surface_set_color(Color(0.8, 0.8, 0.8, 0.2));
point_lines_mesh->surface_add_vertex(r.position + r.size - Vector3(0.3, 0, 0));
point_lines_mesh->surface_set_color(Color(0.8, 0.8, 0.8, 0.2));
point_lines_mesh->surface_add_vertex(r.position + r.size);
point_lines_mesh->surface_set_color(Color(0.8, 0.8, 0.8, 0.2));
point_lines_mesh->surface_add_vertex(r.position + r.size - Vector3(0.0, 0.3, 0));

point_lines_mesh->surface_end();

if (poly.size() == 0) {
return;
}

Array point_handle_mesh_array;
point_handle_mesh_array.resize(Mesh::ARRAY_MAX);
Vector<Vector3> point_handle_mesh_vertices;
Expand Down Expand Up @@ -541,6 +493,7 @@ NavigationObstacle3DEditor::NavigationObstacle3DEditor() {
point_lines_mesh.instantiate();
point_lines_meshinstance->set_mesh(point_lines_mesh);
point_lines_meshinstance->set_transform(Transform3D(Basis(), Vector3(0, 0, 0.00001)));
point_lines_meshinstance->set_as_top_level(true);

line_material = Ref<StandardMaterial3D>(memnew(StandardMaterial3D));
line_material->set_shading_mode(StandardMaterial3D::SHADING_MODE_UNSHADED);
Expand Down
19 changes: 14 additions & 5 deletions modules/navigation/3d/nav_mesh_generator_3d.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -595,11 +595,17 @@ void NavMeshGenerator3D::generator_parse_navigationobstacle_node(const Ref<Navig
return;
}

const Transform3D node_xform = p_source_geometry_data->root_node_transform * Transform3D(Basis(), obstacle->get_global_position());

const float elevation = obstacle->get_global_position().y + p_source_geometry_data->root_node_transform.origin.y;
// Prevent non-positive scaling.
const Vector3 safe_scale = obstacle->get_global_basis().get_scale().abs().maxf(0.001);
const float obstacle_radius = obstacle->get_radius();

if (obstacle_radius > 0.0) {
// Radius defined obstacle should be uniformly scaled from obstacle basis max scale axis.
const float scaling_max_value = safe_scale[safe_scale.max_axis_index()];
const Vector3 uniform_max_scale = Vector3(scaling_max_value, scaling_max_value, scaling_max_value);
const Transform3D obstacle_circle_transform = p_source_geometry_data->root_node_transform * Transform3D(Basis().scaled(uniform_max_scale), obstacle->get_global_position());

Vector<Vector3> obstruction_circle_vertices;

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

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

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());
p_source_geometry_data->add_projected_obstruction(obstruction_circle_vertices, elevation - obstacle_radius, scaling_max_value * obstacle_radius, obstacle->get_carve_navigation_mesh());
}

// Obstacles are projected to the xz-plane, so only rotation around the y-axis can be taken into account.
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());

const Vector<Vector3> &obstacle_vertices = obstacle->get_vertices();

if (obstacle_vertices.is_empty()) {
Expand All @@ -635,7 +644,7 @@ void NavMeshGenerator3D::generator_parse_navigationobstacle_node(const Ref<Navig
obstruction_shape_vertices_ptrw[i] = node_xform.xform(obstacle_vertices_ptr[i]);
obstruction_shape_vertices_ptrw[i].y = 0.0;
}
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());
p_source_geometry_data->add_projected_obstruction(obstruction_shape_vertices, elevation, safe_scale.y * obstacle->get_height(), obstacle->get_carve_navigation_mesh());
}

void NavMeshGenerator3D::generator_parse_source_geometry_data(const Ref<NavigationMesh> &p_navigation_mesh, Ref<NavigationMeshSourceGeometryData3D> p_source_geometry_data, Node *p_root_node) {
Expand Down
33 changes: 29 additions & 4 deletions scene/3d/navigation_obstacle_3d.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -176,13 +176,19 @@ void NavigationObstacle3D::_notification(int p_what) {
}
#ifdef DEBUG_ENABLED
if (fake_agent_radius_debug_instance.is_valid() && radius > 0.0) {
Transform3D debug_transform;
debug_transform.origin = get_global_position();
// Prevent non-positive scaling.
const Vector3 safe_scale = get_global_basis().get_scale().abs().maxf(0.001);
// Agent radius is a scalar value and does not support non-uniform scaling, choose the largest axis.
const float scaling_max_value = safe_scale[safe_scale.max_axis_index()];
const Vector3 uniform_max_scale = Vector3(scaling_max_value, scaling_max_value, scaling_max_value);
const Transform3D debug_transform = Transform3D(Basis().scaled(uniform_max_scale), get_global_position());
RS::get_singleton()->instance_set_transform(fake_agent_radius_debug_instance, debug_transform);
}
if (static_obstacle_debug_instance.is_valid() && get_vertices().size() > 0) {
Transform3D debug_transform;
debug_transform.origin = get_global_position();
// Prevent non-positive scaling.
const Vector3 safe_scale = get_global_basis().get_scale().abs().maxf(0.001);
// Obstacles are projected to the xz-plane, so only rotation around the y-axis can be taken into account.
const Transform3D debug_transform = Transform3D(Basis().scaled(safe_scale).rotated(Vector3(0.0, 1.0, 0.0), get_global_rotation().y), get_global_position());
RS::get_singleton()->instance_set_transform(static_obstacle_debug_instance, debug_transform);
}
#endif // DEBUG_ENABLED
Expand Down Expand Up @@ -354,6 +360,25 @@ bool NavigationObstacle3D::get_carve_navigation_mesh() const {
return carve_navigation_mesh;
}

PackedStringArray NavigationObstacle3D::get_configuration_warnings() const {
PackedStringArray warnings = Node3D::get_configuration_warnings();

if (get_global_rotation().x != 0.0 || get_global_rotation().z != 0.0) {
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."));
}

const Vector3 global_scale = get_global_basis().get_scale();
if (global_scale.x < 0.001 || global_scale.y < 0.001 || global_scale.z < 0.001) {
warnings.push_back(RTR("NavigationObstacle3D does not support negative or zero scaling."));
}

if (radius > 0.0 && !get_global_basis().is_conformal()) {
warnings.push_back(RTR("The agent radius can only be scaled uniformly. The largest scale value along the three axes will be used."));
}

return warnings;
}

void NavigationObstacle3D::_update_map(RID p_map) {
NavigationServer3D::get_singleton()->obstacle_set_map(obstacle, p_map);
map_current = p_map;
Expand Down
2 changes: 2 additions & 0 deletions scene/3d/navigation_obstacle_3d.h
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,8 @@ class NavigationObstacle3D : public Node3D {
void set_carve_navigation_mesh(bool p_enabled);
bool get_carve_navigation_mesh() const;

PackedStringArray get_configuration_warnings() const override;

private:
void _update_map(RID p_map);
void _update_position(const Vector3 p_position);
Expand Down
Loading