2009-11-04 27 views
18

Attualmente sto valutando lo Bullet Physics Library per un gioco spaziale 3D che sto scrivendo usando C++ e Ogre3D. Ho ottenuto che Ogre3D e Bullet si integrassero bene derivando da btMotionState e collegando i miei SceneNodes, ma ora sto avendo molti problemi a calcolare quali valori dovrei passare ai metodi btRigidBody :: applyCentralImpulse e btRigidBody :: applyTorqueImpulse per raggiungere i risultati che sto cercando.Fisica di proiettile - Applicare l'impulso di coppia nello spazio locale del corpo

Quando premo i tasti LEFT o RIGHT sulla tastiera, voglio che l'astronave rotoli sull'asse Z locale. Quando premo SU o GIÙ, voglio che passi sull'asse X locale. Quando premo A o Z, desidero accelerare/decelerare nella direzione dell'asse Z locale. Posso ottenere questo risultato perfettamente in Ogre usando un po 'di matematica quaternion e applicando la traduzione/rotazione direttamente sullo SceneNode, ma voglio davvero applicare questi valori nel motore Bullet usando i metodi forza/coppia in modo che continui a muoversi/avanzare/rollare anche dopo che l'utente ha smesso di premere i tasti, e quindi l'attrito agirà sull'oggetto per rallentarlo, se necessario.

Quindi, come faccio a calcolare i valori necessari per fornire a questi due metodi di impulso al fine di garantire che l'impulso agisca in base all'orientamento corrente del corpo anziché utilizzare gli assi del mondo?

Grazie, Marc

Aggiornamento:

sono stato in grado di elaborare gli impulsi necessari per il movimento in avanti e indietro, ma io sto ancora lottando con il modo di riorientare/campo valori di imbardata/roll per poterli utilizzare con il metodo dell'impulso di coppia. Ecco come ho fatto il movimento avanti/indietro:

if (mKeyboard->isKeyDown(OIS::KC_A)) 
    mBody->applyCentralImpulse(mBody->getWorldTransform().getBasis().getColumn(2) * 20 * time); 
if (mKeyboard->isKeyDown(OIS::KC_Z)) 
    mBody->applyCentralImpulse(mBody->getWorldTransform().getBasis().getColumn(2) * -20 * time); 
+0

Puoi passare il quaternion all'API impulso o in qualche modo convertire il quaternario in qualcosa che puoi passare? – fbrereto

+0

Da quello che vedo nell'API, sembra che il metodo di impulso lineare accetti solo un vettore x, y, z della direzione nelle coordinate del mondo, e il metodo dell'impulso angolare accetta solo un vettore y, p, r per l'imbardata, passo e rotolare in coordinate del mondo. Mentre la matematica può essere leggermente sopra la mia testa (ho difficoltà a visualizzare cose come i prodotti punto e croce), la vera e propria API Bullet è WAY sopra la mia testa e completamente nuova per me ... la combinazione di questi due sta rendendo il mio la vita è impossibile al momento. – Lusid

risposta

3

Così guardando btRigidBody.h

ho notato il seguente codice:

 void applyTorqueImpulse(const btVector3& torque) 
    { 
        m_angularVelocity += m_invInertiaTensorWorld * torque * m_angularFactor; 
    } 

Ora se ho capito bene, si desidera che il Torque per essere uguale ad alcune volte costanti il ​​vettore rotazionale attorno all'asse x (o z) associato alla tua astronave.

Come sappiamo la matrice di rotazione generalizzato può essere determinata come segue:

  1. Ruota per allineare Axis preforme
  2. rotazione intorno canonica Axis
  3. Inversa della fase 1

Questi mezzi che se riesci a identificare un momento torcente allineato sull'asse (che non so in cima alla mia testa) puoi trasformarlo con il tuo:

mBody->getWorldTransform()*axisAlignedXTorque 

Che in base a http://www.bulletphysics.com/Bullet/BulletFull/classbtTransform.html l'operatore * qui viene ignorato per preformare la trasformazione del mondo sul vettore Torque.

1
body->getInvInertiaTensorWorld().inverse()*(body->getWorldTransform().getBasis()*torque) 

Dopo un lungo periodo di frustrazione, finalmente ho coppia corpo locale per funzionare utilizzando il sopra come input per applyTorqueImpulse (o applyTorque). Non pretendo di capire perché funzioni a questo punto, ma lo fa.

Da pallottola:

void applyTorqueImpulse(const btVector3& torque) 
{ 
     m_angularVelocity += m_invInertiaTensorWorld * torque * m_angularFactor; 
} 

Forse questo è ciò tzenes accennavo di produrre l'asse allineato coppia. Ma sono perplesso sul fatto che non riesca a trovare nessun esempio di altri che lo fanno in questo modo. Sicuramente qualcun altro ha voluto applicare la coppia nello spazio locale del corpo? Ma niente di quello che ho trovato online funzionava affatto, nonostante sembrasse come dovrebbe.

Se si applica solo la coppia di trasformazione *, sembrerà che funzioni inizialmente, finché non si inizia a spostarsi dall'origine del proprio mondo. Quindi, se ti senti più difficile ruotare più lontano sei lontano dall'origine, o se le cose iniziano a ruotare all'indietro a seconda di dove è il corpo, questo è probabilmente il tuo problema.

EDIT: Oh, ed ecco come ho le mie traduzioni:.

btVector3 m = corpo-> getWorldTransform() getBasis() * btVector3 (strafe, spostare, salita);