Help with excluding a selection of Bodies from RayCast

Discuss any questions about BEPUphysics or problems encountered.
Post Reply
abego
Posts: 7
Joined: Fri May 31, 2019 7:57 pm

Help with excluding a selection of Bodies from RayCast

Post by abego »

Hello!

I am trying to filter out specific bodies during raycasting. While searching for solutions I found this question asked before: viewtopic.php?f=4&t=2565&p=14245, but I can't seem to get it working, as the RayCast does not register any hits at all. My goal is to have a ragdoll standing upright by keeping the head up with a OneBodyLinearServo, with the Target set 2 meters above ground. The ground is a Box located at (0, 0, 0) with dimensions of (64, 1, 64).

I have fetched the IRayHitHandler from the Grapper class in the Demos, and modified it to this:

Code: Select all

struct RagdollRayHitHandler : IRayHitHandler
{
    public Ragdoll ragdoll;
    public float T;
    public CollidableReference HitCollidable;
    [MethodImpl (MethodImplOptions.AggressiveInlining)]
    public bool AllowTest (CollidableReference collidable)
    {
        return !ragdoll.bodies.Contains (collidable.Handle); <-- I have tried filtering out collidables here, if they are a part of the ragdoll
    }

    [MethodImpl (MethodImplOptions.AggressiveInlining)]
    public void OnRayHit (in BepuPhysics.Trees.RayData ray, ref float maximumT, float t, in Vector3 normal, CollidableReference collidable)
    {
        //We are only interested in the earliest hit. This callback is executing within the traversal, so modifying maximumT informs the traversal
        //that it can skip any AABBs which are more distant than the new maximumT.
        if (t < maximumT)
            maximumT = t;
        if (t < T)
        {
            //Cache the earliest impact.
            T = t;
            HitCollidable = collidable;
        }
    }
}
Ragdoll is a class containing handles to all the bodyparts, created in exactly the same way as in the Ragdoll Demo. The ragdoll.bodies field is a HashSet<int>, where all handles to the bodyparts are stored.

Here is how I cast the ray:

Code: Select all

        simulation.Bodies.GetDescription (ragdoll.handles.Head, out BodyDescription head);

        RagdollRayHitHandler rayHit = new RagdollRayHitHandler ();
        rayHit.ragdoll = ragdoll;
        rayHit.T = 2;

        simulation.RayCast (head.Pose.Position, new Vector3 (0, -1, 0), 2, ref rayHit);

        if (rayHit.T < 2)
        {
            Vector3 target = head.Pose.Position + new Vector3 (0, -1 * rayHit.T + 2, 0);

            if (!ragdoll.hasMotor)
                ragdoll.AddUprightMotor (target, simulation);
            else
                ragdoll.UpdateUprightMotor (target, simulation);
        } else
            ragdoll.RemoveUprightMotor (simulation);
The ray is cast at the same rate that Simulation.Timestep is called.

I have verified that the Ragdoll.AddUprightMotor method is working, as I could fix the ragdoll to a specific Target when it was created in earlier tests.
abego
Posts: 7
Joined: Fri May 31, 2019 7:57 pm

Re: Help with excluding a selection of Bodies from RayCast

Post by abego »

After some more testing I have found that Collidables in Simulation.Bodies and Simulation.Statics can have the same handles, and since the Box that is the ground is the first Static object created, and the hips of the ragdoll is the first dynamic object created, they have the same handle '0'.
To work around this i have added a check in the AllowTest method of the RagdollRayHitHandler that always allows testing if the Collidable is static

Code: Select all

[MethodImpl (MethodImplOptions.AggressiveInlining)]
public bool AllowTest (CollidableReference collidable)
{
    return collidable.Mobility == CollidableMobility.Static || !ragdoll.bodies.Contains (collidable.Handle); //Returns true if collidable is Static, or if collidable is not part of the ragdoll
}
Is this the correct/optimal way to do this, or does anyone know of another way to do this?
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Help with excluding a selection of Bodies from RayCast

Post by Norbo »

Is this the correct/optimal way to do this, or does anyone know of another way to do this?
That's a correct way to do it, yup.

Another approach would be to make use of the CollidableReference's Packed field which packs the dynamic/kinematic/static type into the upper 2 bits. Since dynamic body collidables are encoded with a type of 0, you could check the ragdoll.bodies for collidable.Packed rather than collidable.Handle.
abego
Posts: 7
Joined: Fri May 31, 2019 7:57 pm

Re: Help with excluding a selection of Bodies from RayCast

Post by abego »

Thank you, I'm gonna go with your approach, seems a little cleaner.
Post Reply