GodotVR / godot-xr-template

Godot XR Template project containing needed plugins, XR Tools and a very simple demo game
MIT License
130 stars 15 forks source link

Player collision with table #24

Open fangzhangmnm opened 10 months ago

fangzhangmnm commented 10 months ago

I WAS PUSHED BACK UNEXPECTEDLY when I leaned my body to pick an item on the table. It is because the capsule collider follows the head, and thus collides with the table, although physically I'm just leaning myself without moving

BastiaanOlij commented 10 months ago

This is a limitation in Godot XR Tools, because we're moving the player body forward to where the head position is, the player attempts to walk through the table and is pushed back.

It is something we have on the list of things to solve, hopefully soon.

firescaleVR commented 10 months ago

What are you guys thinking of? Separate colliders for head and body, body trails behind head-or not needed, collision with either stops movement of the characterbody from the joystick, collision with body only allows headset movement within a range? -> Weird edge case where player is over a railing.

Malcolmnixon commented 10 months ago

What are you guys thinking of? Separate colliders for head and body, body trails behind head-or not needed, collision with either stops movement of the characterbody from the joystick, collision with body only allows headset movement within a range? -> Weird edge case where player is over a railing.

There's indications (especially as demonstrated recently with the Quest Pro and Quest 3 updates) that headsets with downward-facing cameras will be providing full-body skeletons in the near (comparatively speaking) future via new OpenXR extensions.

The full-body tracking is the only way to find out if the player is truly "bending over" a table or railing; however not all systems will have full-body tracking, and so an alternate implementation is needed for those systems that works well enough.

For systems without full-body tracking, the only data we have are the locations of the headset and hands... as well as any player-height calibration that may have been performed. If we calibrate the "standing" height of the player then we could attribute the headset being lower as some type of "bending over".

I think an approach may be to use how much lower the head is from the calibrated player height to infer a "bending over" angle, and then model it with two colliders attached to the CharacterBody3D: image

firescaleVR commented 10 months ago

Hmm interesting; it might not be physically accurate when the player is ducking by bending their legs, but I wonder if the visual effect will be good enough. I'm also concerned about the case of seated to standing and back, I usually play vr games while seated most of the time.

The move to full body tracking is unexpected, I've actually been avoiding using xr-toolkit because of the heavy use of floating hands/ baked in gesture poses and instead rolling my own IK based physical body.

fangzhangmnm commented 10 months ago

Can I post my old Unity code here? I used a sphere collider for the head.

    Vector3 ResolveCollision(bool resolveHead = true)
    {
        Vector3 totalMoved = Vector3.zero;
        //Head Collision Resolving(?)
        int overlapCount; bool tmp;
        if (resolveHead)
        {
            overlapCount = Physics.OverlapSphereNonAlloc(headCollider.transform.position, headCollider.radius * scale, colliderBuffer, environmentLayers, QueryTriggerInteraction.Ignore);
            tmp = headCollider.enabled;
            headCollider.enabled = true;
            for (int i = 0; i < overlapCount; ++i)
            {
                var c = colliderBuffer[i];
                if (c == capsuleCollider || c == headCollider) continue;
                if (Physics.ComputePenetration(headCollider, headCollider.transform.position, headCollider.transform.rotation, c, c.transform.position, c.transform.rotation,
                    out Vector3 resolveDir, out float resolveDist))
                {
                    transform.position += resolveDir * resolveDist;
                    totalMoved += resolveDir * resolveDist;
                }
            }
            headCollider.enabled = tmp;
        }

        //Body Collision Resolving
        overlapCount = Physics.OverlapCapsuleNonAlloc(P1, P2, R * scale * 1.1f, colliderBuffer, environmentLayers, QueryTriggerInteraction.Ignore);
        tmp = capsuleCollider.enabled;
        capsuleCollider.enabled = true;
        for (int i = 0; i < overlapCount; ++i)
        {
            var c = colliderBuffer[i];
            if (c == capsuleCollider || c == headCollider) continue;
            if (Physics.ComputePenetration(capsuleCollider, capsuleCollider.transform.position, capsuleCollider.transform.rotation, c, c.transform.position, c.transform.rotation,
                out Vector3 resolveDir, out float resolveDist))
            {
                transform.position += resolveDir * resolveDist;
                totalMoved += resolveDir * resolveDist;
            }
        }
        capsuleCollider.enabled = tmp;
        return totalMoved;
    }
image

There is a spherecollider attached to the head node