mirror of
https://github.com/godotengine/godot.git
synced 2024-11-24 13:12:42 +00:00
Merge pull request #96730 from tracefree/properly_transforming_obstacles
Make use of NavigationObstacle3D's transform
This commit is contained in:
commit
848d90837e
@ -115,9 +115,14 @@ EditorPlugin::AfterGUIInput NavigationObstacle3DEditor::forward_3d_gui_input(Cam
|
|||||||
return EditorPlugin::AFTER_GUI_INPUT_PASS;
|
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();
|
Transform3D gi = gt.affine_inverse();
|
||||||
Plane p(Vector3(0.0, 1.0, 0.0), gt.origin);
|
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;
|
Ref<InputEventMouseButton> mb = p_event;
|
||||||
|
|
||||||
@ -374,9 +379,12 @@ void NavigationObstacle3DEditor::_polygon_draw() {
|
|||||||
point_handle_mesh->clear_surfaces();
|
point_handle_mesh->clear_surfaces();
|
||||||
point_lines_mesh->clear_surfaces();
|
point_lines_mesh->clear_surfaces();
|
||||||
point_lines_meshinstance->set_material_override(line_material);
|
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++) {
|
for (int i = 0; i < poly.size(); i++) {
|
||||||
Vector2 p, p2;
|
Vector2 p, p2;
|
||||||
@ -392,12 +400,6 @@ void NavigationObstacle3DEditor::_polygon_draw() {
|
|||||||
p2 = poly[(i + 1) % poly.size()];
|
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 point = Vector3(p.x, 0.0, p.y);
|
||||||
Vector3 next_point = Vector3(p2.x, 0.0, p2.y);
|
Vector3 next_point = Vector3(p2.x, 0.0, p2.y);
|
||||||
|
|
||||||
@ -411,58 +413,8 @@ void NavigationObstacle3DEditor::_polygon_draw() {
|
|||||||
//vpc->draw_texture(handle,point-handle->get_size()*0.5);
|
//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();
|
point_lines_mesh->surface_end();
|
||||||
|
|
||||||
if (poly.size() == 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Array point_handle_mesh_array;
|
Array point_handle_mesh_array;
|
||||||
point_handle_mesh_array.resize(Mesh::ARRAY_MAX);
|
point_handle_mesh_array.resize(Mesh::ARRAY_MAX);
|
||||||
Vector<Vector3> point_handle_mesh_vertices;
|
Vector<Vector3> point_handle_mesh_vertices;
|
||||||
@ -541,6 +493,7 @@ NavigationObstacle3DEditor::NavigationObstacle3DEditor() {
|
|||||||
point_lines_mesh.instantiate();
|
point_lines_mesh.instantiate();
|
||||||
point_lines_meshinstance->set_mesh(point_lines_mesh);
|
point_lines_meshinstance->set_mesh(point_lines_mesh);
|
||||||
point_lines_meshinstance->set_transform(Transform3D(Basis(), Vector3(0, 0, 0.00001)));
|
point_lines_meshinstance->set_transform(Transform3D(Basis(), Vector3(0, 0, 0.00001)));
|
||||||
|
point_lines_meshinstance->set_as_top_level(true);
|
||||||
|
|
||||||
line_material.instantiate();
|
line_material.instantiate();
|
||||||
line_material->set_shading_mode(StandardMaterial3D::SHADING_MODE_UNSHADED);
|
line_material->set_shading_mode(StandardMaterial3D::SHADING_MODE_UNSHADED);
|
||||||
|
@ -595,11 +595,17 @@ void NavMeshGenerator3D::generator_parse_navigationobstacle_node(const Ref<Navig
|
|||||||
return;
|
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();
|
const float obstacle_radius = obstacle->get_radius();
|
||||||
|
|
||||||
if (obstacle_radius > 0.0) {
|
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;
|
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.
|
// 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
|
|||||||
|
|
||||||
for (int i = 0; i < circle_points; i++) {
|
for (int i = 0; i < circle_points; i++) {
|
||||||
const float angle = i * circle_point_step;
|
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();
|
const Vector<Vector3> &obstacle_vertices = obstacle->get_vertices();
|
||||||
|
|
||||||
if (obstacle_vertices.is_empty()) {
|
if (obstacle_vertices.is_empty()) {
|
||||||
@ -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] = node_xform.xform(obstacle_vertices_ptr[i]);
|
||||||
obstruction_shape_vertices_ptrw[i].y = 0.0;
|
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) {
|
void NavMeshGenerator3D::generator_parse_source_geometry_data(const Ref<NavigationMesh> &p_navigation_mesh, Ref<NavigationMeshSourceGeometryData3D> p_source_geometry_data, Node *p_root_node) {
|
||||||
|
@ -176,13 +176,19 @@ void NavigationObstacle3D::_notification(int p_what) {
|
|||||||
}
|
}
|
||||||
#ifdef DEBUG_ENABLED
|
#ifdef DEBUG_ENABLED
|
||||||
if (fake_agent_radius_debug_instance.is_valid() && radius > 0.0) {
|
if (fake_agent_radius_debug_instance.is_valid() && radius > 0.0) {
|
||||||
Transform3D debug_transform;
|
// Prevent non-positive scaling.
|
||||||
debug_transform.origin = get_global_position();
|
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);
|
RS::get_singleton()->instance_set_transform(fake_agent_radius_debug_instance, debug_transform);
|
||||||
}
|
}
|
||||||
if (static_obstacle_debug_instance.is_valid() && get_vertices().size() > 0) {
|
if (static_obstacle_debug_instance.is_valid() && get_vertices().size() > 0) {
|
||||||
Transform3D debug_transform;
|
// Prevent non-positive scaling.
|
||||||
debug_transform.origin = get_global_position();
|
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);
|
RS::get_singleton()->instance_set_transform(static_obstacle_debug_instance, debug_transform);
|
||||||
}
|
}
|
||||||
#endif // DEBUG_ENABLED
|
#endif // DEBUG_ENABLED
|
||||||
@ -354,6 +360,25 @@ bool NavigationObstacle3D::get_carve_navigation_mesh() const {
|
|||||||
return carve_navigation_mesh;
|
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) {
|
void NavigationObstacle3D::_update_map(RID p_map) {
|
||||||
NavigationServer3D::get_singleton()->obstacle_set_map(obstacle, p_map);
|
NavigationServer3D::get_singleton()->obstacle_set_map(obstacle, p_map);
|
||||||
map_current = p_map;
|
map_current = p_map;
|
||||||
|
@ -117,6 +117,8 @@ public:
|
|||||||
void set_carve_navigation_mesh(bool p_enabled);
|
void set_carve_navigation_mesh(bool p_enabled);
|
||||||
bool get_carve_navigation_mesh() const;
|
bool get_carve_navigation_mesh() const;
|
||||||
|
|
||||||
|
PackedStringArray get_configuration_warnings() const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void _update_map(RID p_map);
|
void _update_map(RID p_map);
|
||||||
void _update_position(const Vector3 p_position);
|
void _update_position(const Vector3 p_position);
|
||||||
|
Loading…
Reference in New Issue
Block a user