Eu implementei uma câmera em primeira pessoa usando o Bullet - é um corpo rígido com formato de cápsula. Só uso o Bullet há alguns dias e os mecanismos de física são novos para mim. Eu uso btRigidBody::setLinearVelocity()
para movê-lo e ele colide perfeitamente com o mundo. O único problema é que o valor Y se move livremente, o que resolvi temporariamente definindo o valor Y do vetor de conversão como zero antes de o corpo ser movido. Isso funciona para todos os casos, exceto quando cai de uma altura.
Quando o corpo cai de um objeto alto, você ainda pode deslizar ao redor, já que o valor Y do vetor de conversão está sendo definido como zero, até você parar de se mover e cair no chão (a velocidade é definida apenas ao se mover). Então, para resolver isso, eu gostaria de tentar lançar um raio do corpo para determinar o valor Y do mundo e verificar a diferença entre esse valor e o valor Y do corpo da câmera e desativar ou desacelerar o movimento se a diferença é grande o suficiente.
Estou um pouco preso em simplesmente lançar um raio e determinar o valor Y do mundo onde ele atingiu. Eu implementei esse retorno de chamada:
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;
}
};
E na função de movimento, eu tenho 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);
Então, eu tenho o callback.m_hitPointWorld
vetor, que parece apenas mostrar a posição da câmera em cada quadro. Pesquisei no Google por exemplos de raios de projeção, bem como a documentação do Bullet, e tem sido difícil encontrar apenas um exemplo. Um exemplo é realmente tudo o que preciso.
Ou talvez exista algum método no Bullet para manter o corpo rígido no chão?
Estou usando o Ogre3D como um mecanismo de renderização, e lançar um raio é bastante direto com isso, no entanto, quero manter todo o raio dentro do Bullet por simplicidade.
Alguém poderá me indicar a direção correta? Obrigado.