J'ai mis en place une caméra à la première personne à l'aide de Bullet - c'est un corps rigide avec une forme de capsule. Je n'utilise Bullet que depuis quelques jours et les moteurs physiques sont nouveaux pour moi. Je l'utilise btRigidBody::setLinearVelocity()
pour le déplacer et il entre parfaitement en contact avec le monde. Le seul problème est que la valeur Y se déplace librement, ce que j'ai résolu temporairement en définissant la valeur Y du vecteur de translation à zéro avant le déplacement du corps. Cela fonctionne dans tous les cas sauf en cas de chute de hauteur.
Lorsque le corps laisse tomber un objet de grande taille, vous pouvez toujours planer puisque la valeur Y du vecteur de translation est réglée sur zéro, jusqu'à ce que vous arrêtiez de bouger et tombiez au sol (la vitesse n'est définie que lors du déplacement). Donc, pour résoudre ce problème, je voudrais essayer de lancer un rayon vers le bas du corps pour déterminer la valeur Y du monde, et vérifier la différence entre cette valeur et la valeur Y du corps de la caméra, et désactiver ou ralentir le mouvement si la différence est assez grande.
Je suis un peu coincé à simplement lancer un rayon et à déterminer la valeur Y du monde où il a frappé. J'ai implémenté ce rappel:
struct AllRayResultCallback : public btCollisionWorld::RayResultCallback{
AllRayResultCallback(const btVector3& rayFromWorld, const btVector3& rayToWorld)
: m_rayFromWorld(rayFromWorld), m_rayToWorld(rayToWorld), m_closestHitFraction(1.0){}
btVector3 m_rayFromWorld;
btVector3 m_rayToWorld;
btVector3 m_hitNormalWorld;
btVector3 m_hitPointWorld;
float m_closestHitFraction;
virtual btScalar addSingleResult(btCollisionWorld::LocalRayResult& rayResult, bool normalInWorldSpace)
{
if(rayResult.m_hitFraction < m_closestHitFraction)
m_closestHitFraction = rayResult.m_hitFraction;
m_collisionObject = rayResult.m_collisionObject;
if(normalInWorldSpace){
m_hitNormalWorld = rayResult.m_hitNormalLocal;
}
else{
m_hitNormalWorld = m_collisionObject->getWorldTransform().getBasis() * rayResult.m_hitNormalLocal;
}
m_hitPointWorld.setInterpolate3(m_rayFromWorld, m_rayToWorld, m_closestHitFraction);
return 1.0f;
}
};
Et dans la fonction de mouvement, j'ai ce code:
btVector3 from(pos.x, pos.y + 1000, pos.z); // pos is the camera's rigid body position
btVector3 to(pos.x, 0, pos.z); // not sure if 0 is correct for Y
AllRayResultCallback callback(from, to);
Base::getSingletonPtr()->m_btWorld->rayTest(from, to, callback);
J'ai donc le callback.m_hitPointWorld
vecteur, qui semble simplement montrer la position de la caméra à chaque image. J'ai cherché sur Google des exemples de lancer de rayons, ainsi que la documentation de Bullet, et il a été difficile de trouver un exemple. Un exemple est vraiment tout ce dont j'ai besoin.
Ou peut-être existe-t-il une méthode dans Bullet pour garder le corps rigide au sol?
J'utilise Ogre3D comme moteur de rendu, et lancer un rayon vers le bas est assez simple avec cela, mais je veux garder tout le lancer de rayon dans Bullet pour plus de simplicité.
Quelqu'un pourrait-il m'orienter dans la bonne direction? Merci.