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
Detect slope angle
-
- Posts: 849
- Joined: Tue Sep 30, 2014 6:03 pm
- Location: San Francisco
Re: Detect slope angle
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:
/
(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);
}
}