2009-11-04 13 views
18

Obecnie analizuję Bullet Physics Library dla kosmicznej gry 3D, którą piszę używając C++ i Ogre3D. Zauważyłem, że Ogre3D i Bullet zostały wcielone w całość dzięki pochodzeniu z btMotionState i podłączeniu moich SceneNodes, ale teraz mam problem z obliczeniem wartości, które należy przekazać do metod btRigidBody :: applyCentralImpulse i btRigidBody :: applyTorqueImpulse w celu osiągnięcia wyniki, których szukam.Bullet Physics - Apply Torque Impulse w lokalnej przestrzeni ciała

Kiedy naciskam klawisze LEWO lub PRAWO na klawiaturze, chcę, aby statek kosmiczny toczył się na lokalnej osi Z. Kiedy wciskam W GÓRĘ lub W DÓŁ, ​​chcę, aby był ustawiony na lokalnej osi X. Kiedy naciskam A lub Z, chcę, żeby przyspieszył/zwalniał w kierunku lokalnej osi Z. Mogę to osiągnąć doskonale w Ogre, używając matematyki kwaternionowej i stosując translate/rotation bezpośrednio na SceneNode, ale naprawdę chcę zastosować te wartości w silniku Bullet, stosując metody force/torque, aby kontynuować ruch/pitch/roll nawet po tym, jak użytkownik przestaje naciskać klawisze, a więc tarcie działa na obiekt, aby spowolnić go w razie potrzeby.

Jak więc obliczyć wartości niezbędne do zapewnienia tych dwóch metod impulsowych, aby upewnić się, że impuls działa w oparciu o bieżącą orientację ciała, zamiast korzystać z osi świata?

Dzięki, Marc

Aktualizacja:

udało mi się wypracować impulsy potrzebne do przodu i do tyłu ruch, ale ja wciąż zmaga się z jak reorientacji Yaw/łuk/wartości rolki w celu ich użycia z metodą impulsu momentu obrotowego. Oto jak to zrobiłem z przodu/do tyłu ruch:

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

Czy możesz przekazać kwaternionę do impulsu API lub w jakiś sposób przekonwertować kwaternionę na coś, co możesz przekazać? – fbrereto

+0

Z tego, co widzę w interfejsie API, wynika, że ​​metoda liniowego impulsu akceptuje tylko wektor x, y, z kierunkiem we współrzędnych świata, a metoda impulsu kątowego akceptuje wektor y, p, r dla odchylenia, wysokość i ruch na współrzędnych świata. Podczas gdy matematyka może nieznacznie przekraczać moją głowę (trudno mi sobie wyobrazić rzeczy takie jak produkty dot i cross), sam interfejs Bullet API jest WAY ponad moją głową i zupełnie nowy dla mnie ... połączenie tych dwóch czyni mój życie niemożliwe w tej chwili. – Lusid

Odpowiedz

3

Więc patrząc na btRigidBody.h

Zauważyłem następujący kod:

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

Teraz jak rozumiem, chcesz swoją Torque być równym stałym wektorom rotacyjnym wokół osi x (lub z) związanym z twoim statkiem kosmicznym.

Jak wiadomo uogólniona macierz obrotu może być określona w następujący sposób:

  1. Obrót sposób wyrównać osi preformy
  2. obrotowo wokół kanonicznej osi
  3. Odwrócenie etapie 1

oznacza to, jeśli potrafisz zidentyfikować moment obrotowy osi (którego nie znam z góry mojej głowy), możesz przekształcić go za pomocą:

mBody->getWorldTransform()*axisAlignedXTorque 

Który zgodnie z http://www.bulletphysics.com/Bullet/BulletFull/classbtTransform.html operator tutaj jest nadpisany, aby wykonać światową transformację wektora Torque.

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

Po długim okresie frustracji, I wreszcie ciała lokalnego moment obrotowy do pracy przy użyciu wyżej jako wejście do applyTorqueImpulse (lub applyTorque). Nie udaje mi, że rozumiem, dlaczego działa w tym momencie, ale tak jest.

Od Bullet:

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

Może to właśnie tzenes było wspomnieć o produkcji oś wyrównany moment. Ale jestem zdziwiony, że nie mogę znaleźć żadnego przykładu, by ktokolwiek inny robił to w ten sposób. Z pewnością ktoś inny chciał mieć moment obrotowy zastosowany w lokalnej przestrzeni ciała? Ale nic, co znalazłem online, w ogóle nie działało, mimo że wyglądało na to, że powinno.

Jeśli zastosujesz tylko transformację * moment obrotowy, będzie to wyglądało tak, jakby działało na początku, dopóki nie zaczniesz się oddalać od źródła swojego świata. Więc jeśli czuje się trudniej obrócić dalej, jesteś daleko od początku, lub jeśli rzeczy zaczynają się obracać w odwrotnym kierunku, w zależności od tego, gdzie jest ciało, to jest to prawdopodobnie twój problem.

EDIT: Aha, i oto jak mam tłumaczenia.

btVector3 m = ciało-> getWorldTransform() getBasis() * btVector3 (strafe, ruch, wzrost);

Powiązane problemy