Skip to content

Commit

Permalink
Make use of NavigationObstacle3D's transform
Browse files Browse the repository at this point in the history
  • Loading branch information
tracefree committed Sep 10, 2024
1 parent 5675c76 commit 9114ab6
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 4 deletions.
8 changes: 7 additions & 1 deletion 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);

Ref<InputEventMouseButton> mb = p_event;

Expand Down Expand Up @@ -541,6 +546,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
15 changes: 12 additions & 3 deletions modules/navigation/3d/nav_mesh_generator_3d.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@

#include "core/config/project_settings.h"
#include "core/math/convex_hull.h"
#include "core/math/vector3.h"
#include "core/os/thread.h"
#include "scene/3d/mesh_instance_3d.h"
#include "scene/3d/multimesh_instance_3d.h"
Expand Down Expand Up @@ -595,9 +596,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());
// 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();
// Obstacles are projected to the xz-plane, so only rotation around the y-axis can be taken into account.
Transform3D node_xform;
node_xform.origin = obstacle->get_global_position();
node_xform.scale_basis(safe_scale);
node_xform.rotate_basis(Vector3(0.0, 1.0, 0.0), obstacle->get_global_rotation().y);
node_xform = p_source_geometry_data->root_node_transform * node_xform;

const float obstacle_radius = safe_scale[safe_scale.max_axis_index()] * obstacle->get_radius();

if (obstacle_radius > 0.0) {
Vector<Vector3> obstruction_circle_vertices;
Expand Down Expand Up @@ -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, obstacle->get_global_position().y + p_source_geometry_data->root_node_transform.origin.y, 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
30 changes: 30 additions & 0 deletions scene/3d/navigation_obstacle_3d.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@
#include "navigation_obstacle_3d.h"

#include "core/math/geometry_2d.h"
#include "core/math/transform_3d.h"
#include "core/math/vector3.h"
#include "servers/navigation_server_3d.h"

void NavigationObstacle3D::_bind_methods() {
Expand Down Expand Up @@ -168,13 +170,22 @@ void NavigationObstacle3D::_notification(int p_what) {
}
#ifdef DEBUG_ENABLED
if (fake_agent_radius_debug_instance.is_valid() && radius > 0.0) {
// Prevent non-positive scaling.
const Vector3 safe_scale = get_global_basis().get_scale().abs().maxf(0.001);
Transform3D debug_transform;
debug_transform.origin = get_global_position();
// Agent radius is a scalar value and does not support non-uniform scaling, choose the largest axis.
debug_transform.scale_basis(safe_scale[safe_scale.max_axis_index()] * Vector3(1.0, 1.0, 1.0));
RS::get_singleton()->instance_set_transform(fake_agent_radius_debug_instance, debug_transform);
}
if (static_obstacle_debug_instance.is_valid() && get_vertices().size() > 0) {
// 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.
Transform3D debug_transform;
debug_transform.origin = get_global_position();
debug_transform.scale_basis(safe_scale);
debug_transform.rotate_basis(Vector3(0.0, 1.0, 0.0), get_global_rotation().y);
RS::get_singleton()->instance_set_transform(static_obstacle_debug_instance, debug_transform);
}
#endif // DEBUG_ENABLED
Expand Down Expand Up @@ -346,6 +357,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

0 comments on commit 9114ab6

Please sign in to comment.