Fix bounding boxes
Each time an AABB is rotated, it gets bigger. That means opposite rotations don't cancel out. The previous implementation repeatedly rotates children AABBs as it climbs up the tree. This often resulted in selection boxes looking bigger than their contents. This implementation calculates and applies a single final transformation to each AABB before it is merged with the others. After merging, there are no additional rotations, so AABBs remain accurate. Co-Authored-By: Robert Yevdokimov <105675984+ryevdokimov@users.noreply.github.com>
This commit is contained in:
committed by
Robert Yevdokimov
parent
10e111477d
commit
30914c0434
@@ -2790,8 +2790,7 @@ void Node3DEditorViewport::_notification(int p_what) {
|
||||
}
|
||||
|
||||
Transform3D t = sp->get_global_gizmo_transform();
|
||||
VisualInstance3D *vi = Object::cast_to<VisualInstance3D>(sp);
|
||||
AABB new_aabb = vi ? vi->get_aabb() : _calculate_spatial_bounds(sp);
|
||||
AABB new_aabb = _calculate_spatial_bounds(sp);
|
||||
|
||||
exist = true;
|
||||
if (se->last_xform == t && se->aabb == new_aabb && !se->last_xform_dirty) {
|
||||
@@ -4087,35 +4086,35 @@ Vector3 Node3DEditorViewport::_get_instance_position(const Point2 &p_pos) const
|
||||
return world_pos + world_ray * FALLBACK_DISTANCE;
|
||||
}
|
||||
|
||||
AABB Node3DEditorViewport::_calculate_spatial_bounds(const Node3D *p_parent, bool p_exclude_top_level_transform) {
|
||||
AABB Node3DEditorViewport::_calculate_spatial_bounds(const Node3D *p_parent, const Node3D *p_top_level_parent) {
|
||||
AABB bounds;
|
||||
|
||||
if (!p_top_level_parent) {
|
||||
p_top_level_parent = p_parent;
|
||||
}
|
||||
|
||||
if (!p_parent) {
|
||||
return AABB(Vector3(-0.2, -0.2, -0.2), Vector3(0.4, 0.4, 0.4));
|
||||
}
|
||||
|
||||
Transform3D xform_to_top_level_parent_space = p_top_level_parent->get_global_transform().affine_inverse() * p_parent->get_global_transform();
|
||||
|
||||
const VisualInstance3D *visual_instance = Object::cast_to<VisualInstance3D>(p_parent);
|
||||
if (visual_instance) {
|
||||
bounds = visual_instance->get_aabb();
|
||||
} else {
|
||||
bounds = AABB();
|
||||
}
|
||||
bounds = xform_to_top_level_parent_space.xform(bounds);
|
||||
|
||||
for (int i = 0; i < p_parent->get_child_count(); i++) {
|
||||
Node3D *child = Object::cast_to<Node3D>(p_parent->get_child(i));
|
||||
if (child) {
|
||||
AABB child_bounds = _calculate_spatial_bounds(child, false);
|
||||
|
||||
if (bounds.size == Vector3() && p_parent) {
|
||||
bounds = child_bounds;
|
||||
} else {
|
||||
bounds.merge_with(child_bounds);
|
||||
}
|
||||
AABB child_bounds = _calculate_spatial_bounds(child, p_top_level_parent);
|
||||
bounds.merge_with(child_bounds);
|
||||
}
|
||||
}
|
||||
|
||||
if (bounds.size == Vector3() && !p_parent) {
|
||||
bounds = AABB(Vector3(-0.2, -0.2, -0.2), Vector3(0.4, 0.4, 0.4));
|
||||
}
|
||||
|
||||
if (!p_exclude_top_level_transform) {
|
||||
bounds = p_parent->get_transform().xform(bounds);
|
||||
}
|
||||
|
||||
return bounds;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user