Skip to content

Extend SpringBoneSimulator3D to detect collisions to the chain between the joints #14581

Description

@goatchurchprime

Problem or limitation

To a significant extent Godot's SpringBones are an early analog of VRChat's PhysBones which allows for avatars to effectively touch and interact with one another (stroke ears, pat heads, move hair, grab tails).

The first limitation I found on trying out this feature on my basic xr networking framework was that the collisions are only on the spheres around the joints. These are often spaced out enough that colliders added to your hands can pass between them, which is dissatisfying. (See blue spheres on the fingertips.)

Image

Learning this, and going back for a closer look at the Avatar Debug Overlay (Phys Bones) in VRChat, I found that their colliders includes the cylinder or cone between the joint sphere and the previous joint sphere that only moves the tail joint.

In the following pictures, the blue shapes are the bone chains (known as "settings") in the SpringBoneSimulator3D, and the yellow shapes are the SpringBoneCollision3Ds in the form of Capsule shapes (in the Godot feature).

Image Image

Proposed improvement

The actual spring bone simulation happens in SpringBoneSimulator3D::_process_joints()
in a loop that calls SpringBoneCollision3D::collide() on each collider within a loop across all the joints.

Most of the cases resolve down to calling SpringBoneCollisionSphere3D::_collide_sphere(collision_origin_point, collision_radius, current_bone_point, bone_radius) which simply moves the current_bone_point away from the collision_origin_point to the distance of collision_radius + bone_radius if necessary.

This proposal is to add two further parameters to that function: prev_bone_point and prev_bone_radius so the _collide() function can calculate where current_bone_point would have to move to in order to move the whole of the preceding cylinder or cone out of contact with the collision sphere.

The implementation might or might not take account of the distance between the joints. At the moment this is snapped to the correct distance by limit_length() which is called after the collide() function.

Proposal review

  • Yes, this proposal is highly specific and actionable.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions