Detect slope angle

Furya
Posts: 24
Joined: Tue Sep 22, 2015 1:34 pm

Detect slope angle

Post by Furya »

Hi,

I am new to bullet, I implement a Character Controller and I want to know slope's angle in my heightmap. How can I do that ?

sorry for my english.

thanks
User avatar
drleviathan
Posts: 849
Joined: Tue Sep 30, 2014 6:03 pm
Location: San Francisco

Re: Detect slope angle

Post by drleviathan »

There are two ways that I know of to obtain the normal of the surface under the character:

(1) After every simulationStep() of the world: scan the ContactManifolds for contact between the character and other objects and harvest the collision normals from the relevant collisions. You can find examples of how to do it in these forums. Here is an example thread. You would have to add code that figures out when the character is one of the objects involved.

(2) After each simulationStep() of the world: perform a short raycast starting near the bottom of the character, down toward the floor. If the raycast hits something harvest the normal. Here is some example code that I pulled out of a project I've worked on: it may help. I'm sure it doesn't actually compile: you would have to modify it to suit your needs:
/

Code: Select all

/ helper class for simple ray-traces from character
class ClosestNotMe : public btCollisionWorld::ClosestRayResultCallback {
public:
    ClosestNotMe(btRigidBody* body) : btCollisionWorld::ClosestRayResultCallback(btVector3(0.0, 0.0, 0.0), btVector3(0.0, 0.0, 0.0)) {
        m_me = body;
        // set the collision group and mask
        m_collisionFilterGroup = btBroadphaseProxy::CharacterFilter;
        m_collisionFilterMask = btBroadphaseProxy::AllFilter;
    }
    virtual btScalar addSingleResult(btCollisionWorld::LocalRayResult& rayResult,bool normalInWorldSpace) {
        if (rayResult.m_collisionObject == m_me) {
            return btScalar(1.0);
        }
        return ClosestRayResultCallback::addSingleResult(rayResult, normalInWorldSpace);
    }
protected:
    btRigidBody* m_me;
};

void MyCharacterController::postStep(btCollisionWorld* collisionWorld) {
    // trace a ray straight down to see if we're standing on the ground
    const btTransform& xform = m_rigidBody->getWorldTransform();
    
    // rayStart is at center of bottom sphere of character capsule
    btVector3 rayStart = xform.getOrigin() - m_halfHeight * m_upDirection;
    
    // rayEnd is some short distance outside bottom sphere
    const btScalar NEARBY = btScalar(0.3) * m_radius;
    btScalar rayLength = m_radius + NEARBY; 
    btVector3 rayEnd = rayStart - rayLength * m_upDirection;
    
    // scan down for nearby floor
    ClosestNotMe rayCallback(m_rigidBody);
    rayCallback.m_closestHitFraction = btScalar(1.0);
    collisionWorld->rayTest(rayStart, rayEnd, rayCallback);
    if (rayCallback.hasHit()) {
        m_floorDistance = rayLength * rayCallback.m_closestHitFraction - m_radius;
        m_floorNormal = rayCallback.m_hitNormalWorld;
    } else {
        m_floorDistance = FLT_MAX;
        m_floorNormal.setValue(0.0, 0.0, 0.0);
    }
}