Best way to check if touching to the ground?

Post Reply
TonyS
Posts: 10
Joined: Sat May 27, 2017 8:16 am

Best way to check if touching to the ground?

Post by TonyS »

I am using just a box rigidbody to fake the whole locomotion. It is very basic and I am not raycasting for the wheels.

The faked locomotion is good enough for my purpose.

My problem is not to drive it while it is not on the ground.

If I just raycast from the center, it does not work on the ramps (which makes perfect sense as the right and left edge will be touching to the ground where as the center is in the air).

So, I was thinking about raycasting 4 lines from 4 bottom corners of the rigidbody in the -Y axis direction + center. So if at least 1 of them hits, that means it is grounded.

On the other hand, I am also thinking about using convexTest?

Which one would be better for the performance? Just shape casting looks like the perfect solution but I would be glad if you share your experience with me.
User avatar
drleviathan
Posts: 849
Joined: Tue Sep 30, 2014 6:03 pm
Location: San Francisco

Re: Best way to check if touching to the ground?

Post by drleviathan »

Would you want to disable driving the box when it is actually touching the ground, or do you want to disable it when it is above the ground almost touching?

If you want to rely on contacts with the ground you can harvest the contact manifolds every frame and look for one between the box and something below it. Here is code that might work (dunno if this even compiles):

Code: Select all

// given:  collisionDispatcher, boxBody, and worldUp

int numManifolds = collisionDispatcher->getNumManifolds();
for (int i = 0; i < numManifolds; ++i) {
    btPersistentManifold* contactManifold =  collisionDispatcher->getManifoldByIndexInternal(i);
    if (contactManifold->getNumContacts() > 0) {
        const btCollisionObject* objectA = static_cast<const btCollisionObject*>(contactManifold->getBody0());
        const btCollisionObject* objectB = static_cast<const btCollisionObject*>(contactManifold->getBody1());

        // Note: the order of the objects A and B is arbitrary, but the contactPoint's normal
        // always points from objectB toward objectA, so we figure out which one is boxBody and
        // reverse the direction if the normal when boxBody is objectB.
        btRigidBody* otherBody = nullptr;
        btScalar sign = 1.0f;
        if (objectA == boxBody) {
            otherBody == static_cast<btRigidBody*>(objectB);
        } else if (objectB == boxBody) {
            otherBody == static_cast<btRigidBody*>(objectA);
            sign = -1.0f;
        }

        if (otherBody) {
            btVector3 normal = sign * contactManifold->getContactPoint(0).m_normalWorldOnB;
            const btScalar UPWARD_NORMAL_THRESHOLD = 0.0f;  // maybe should be non-zero?
            if (normal.dot(worldUp) > UPWARD_NORMAL_THRESHOLD) {
                // boxBody is probably bumping into something below it
                // TODO: figure out what to do:
                //   break here?
                //   continue to analyze the rest of the manifold (which can have up to four points)?
                //   continue to look for more manifolds with other objects below bodyBox?
            }   
        }   
    }   
}
Post Reply