Ho implementato una fotocamera in prima persona usando Bullet: è un corpo rigido a forma di capsula. Uso Bullet da alcuni giorni e i motori della fisica sono nuovi per me. Lo uso btRigidBody::setLinearVelocity()
per spostarlo e si scontra perfettamente con il mondo. L'unico problema è che il valore Y si muove liberamente, cosa che ho temporaneamente risolto impostando il valore Y del vettore di traslazione su zero prima di spostare il corpo. Funziona in tutti i casi tranne quando si cade da un'altezza.
Quando il corpo cade da un oggetto alto, puoi ancora planare poiché il valore Y del vettore di traslazione viene impostato su zero, fino a quando non smetti di muoverti e cadi a terra (la velocità viene impostata solo quando ti muovi). Quindi, per risolvere questo problema, vorrei provare a scagliare un raggio dal corpo per determinare il valore Y del mondo e controllare la differenza tra quel valore e il valore Y del corpo macchina, e disabilitare o rallentare il movimento se la differenza è abbastanza grande.
Sono un po 'bloccato semplicemente lanciando un raggio e determinando il valore Y del mondo in cui ha colpito. Ho implementato questo callback:
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 nella funzione di movimento, ho questo codice:
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);
Quindi ho il callback.m_hitPointWorld
vettore, che sembra mostrare solo la posizione della telecamera per ogni fotogramma. Ho cercato su Google esempi di casting casting, nonché la documentazione Bullet, ed è stato difficile trovare un esempio. Un esempio è davvero tutto ciò di cui ho bisogno.
O forse c'è qualche metodo in Bullet per mantenere il corpo rigido a terra?
Sto usando Ogre3D come motore di rendering, e lanciare un raggio verso il basso è abbastanza semplice, tuttavia voglio mantenere tutto il casting dei raggi all'interno di Bullet per semplicità.
Qualcuno potrebbe indicarmi la giusta direzione? Grazie.