Implementé una cámara en primera persona usando Bullet: es un cuerpo rígido con forma de cápsula. Solo he estado usando Bullet durante unos días y los motores de física son nuevos para mí. Solía btRigidBody::setLinearVelocity()
moverlo y choca perfectamente con el mundo. El único problema es que el valor Y se mueve libremente, lo que resolví temporalmente estableciendo el valor Y del vector de traducción a cero antes de mover el cuerpo. Esto funciona para todos los casos excepto cuando cae desde una altura.
Cuando el cuerpo deja caer un objeto alto, aún puede deslizarse ya que el valor Y del vector de traslación se establece en cero, hasta que deja de moverse y cae al suelo (la velocidad solo se establece cuando se mueve). Entonces, para resolver esto, me gustaría intentar lanzar un rayo desde el cuerpo para determinar el valor Y del mundo y verificar la diferencia entre ese valor y el valor Y del cuerpo de la cámara, y desactivar o ralentizar el movimiento si La diferencia es lo suficientemente grande.
Estoy un poco atascado en simplemente lanzar un rayo y determinar el valor Y del mundo donde golpeó. He implementado esta devolución de llamada:
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;
}
};
Y en la función de movimiento, tengo este código:
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);
Así que tengo el callback.m_hitPointWorld
vector, que parece mostrar la posición de la cámara en cada fotograma. He buscado en Google ejemplos de rayos de lanzamiento, así como la documentación de Bullet, y ha sido difícil encontrar un ejemplo. Un ejemplo es realmente todo lo que necesito.
¿O tal vez hay algún método en Bullet para mantener el cuerpo rígido en el suelo?
Estoy usando Ogre3D como motor de renderizado, y lanzar un rayo hacia abajo es bastante sencillo con eso, sin embargo, quiero mantener todo el lanzamiento de rayos dentro de Bullet por simplicidad.
¿Alguien podría señalarme en la dirección correcta? Gracias.
fuente