Calculating the AABB of a mesh deformed by bones

  Kiến thức lập trình

A follow up to this question,

I’ve been trying to calculate the AABB inspired by this post but also taking into account weights as such:

func get_precise_aabb(mesh_instance : MeshInstance3D):
    
    # get the mesh's data
    var skeleton:Skeleton3D = mesh_instance.get_node_or_null(mesh_instance.skeleton)
    var data : Array = mesh_instance.mesh.surface_get_arrays(0)
    var vertices : Array =  data[Mesh.ARRAY_VERTEX]
    var bones: Array = data[Mesh.ARRAY_BONES]
    var weights: Array = data[Mesh.ARRAY_WEIGHTS]
    var bone_count :int = len(weights)/len(vertices)
    
    # find the mesh's vertices that stick out the farthest
    var low : Vector3 = Vector3.INF
    var high : Vector3 = -Vector3.INF
    for vert_idx in len(vertices):
        var vert = vertices[vert_idx]
        var deformed_transformation := Transform3D.IDENTITY
        
        for i in bone_count: # apply bone transformations on vertex
            var weight = weights[vert_idx * bone_count + i]
            var bone_idx = bones[vert_idx * bone_count + i]
            var bone_relative_transform = skeleton.get_bone_global_pose(bone_idx) * skeleton.get_bone_global_rest(bone_idx).inverse()
            var bone_frame_transform = Transform3D(
                lerp(Transform3D.IDENTITY.basis, bone_relative_transform.basis, weight),
                lerp(Transform3D.IDENTITY.origin, bone_relative_transform.origin, weight)
            )
            deformed_transformation = deformed_transformation * skeleton.global_transform * bone_frame_transform
        
        
        vert = deformed_transformation * vert
        
        
        low.x = vert.x if low.x > vert.x else low.x
        high.x = vert.x if vert.x > high.x else high.x
        
        low.y = vert.y if low.y > vert.y else low.y
        high.y = vert.y if vert.y > high.y else high.y
        
        low.z = vert.z if low.z > vert.z else low.z
        high.z = vert.z if vert.z > high.z else high.z
    
    
    return AABB(low, high - low)

combining it with tool mode like this:

@tool
extends Node3D

@export var btn: bool = false :set=set_bth

func set_bth(value: bool):
    if !value:
        return
    
    var precise_aabb = get_precise_aabb($Skeleton3D/Cube)
    var bounding_box = $BoundingBox
    bounding_box.scale = precise_aabb.size
    bounding_box.global_position = precise_aabb.position + precise_aabb.size / 2

but it doesn’t seem to give the perfect AABB and I’m not sure why

Editor Screenshot

Minimal reproduction project

LEAVE A COMMENT