2009-11-04 12 views
18

Ich werte gerade die Bullet Physics Library für ein 3D-Weltraumspiel aus, das ich mit C++ und Ogre3D schreibe. Ich habe Ogre3D und Bullet integriert, indem ich von btMotionState abgeleitet habe und meine SceneNodes angeschlossen habe, aber jetzt habe ich große Probleme damit, welche Werte ich an btRigidBody :: applyCentralImpulse und btRigidBody :: applyTorqueImpulse Methoden übergeben soll die Ergebnisse, nach denen ich suche.Bullet Physik - Drehmomentimpuls im lokalen Körperbereich anwenden

Wenn ich die LINKS- oder RECHTS-Taste auf der Tastatur drücke, möchte ich das Raumschiff auf der lokalen Z-Achse rollen. Wenn ich UP oder DOWN drücke, möchte ich, dass es auf der lokalen X-Achse positioniert wird. Wenn ich A oder Z drücke, möchte ich, dass es in Richtung der lokalen Z-Achse beschleunigt/verzögert wird. Ich kann das in Ogre perfekt erreichen, indem ich eine Quaternionsmathematik benutze und die Translate/Rotation direkt auf den SceneNode anwende, aber ich möchte diese Werte in der Bullet-Engine mit den Kraft-/Drehmoment-Methoden anwenden, damit sie sich weiter bewegt Selbst nachdem der Benutzer aufhört, auf die Tasten zu drücken, wird Reibung auf das Objekt wirken, um es bei Bedarf zu verlangsamen.

Also, wie berechne ich die notwendigen Werte, um diese beiden Impuls-Methoden zur Verfügung zu stellen, um sicherzustellen, dass der Impuls auf der aktuellen Orientierung des Körpers statt der Verwendung der Achsen der Welt wirkt?

Danke, Marc

Update:

konnte ich die Impulse für die Vorwärts- und Rückwärtsbewegung notwendig, um herauszufinden, aber ich bin immer noch kämpfen mit, wie Gier/Pitch/Roll-Werte neu zu orientieren um sie mit der Drehmoment-Impuls-Methode zu verwenden. Hier ist, wie ich die Vorwärts/Rückwärtsbewegung tat

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

Können Sie die Quaternion an die Impuls-API übergeben oder die Quaternion irgendwie in etwas konvertieren, das Sie weitergeben können? – fbrereto

+0

Aus dem, was ich in der API sehen kann, scheint es, dass die lineare Impulsmethode nur einen x, y, z Vektor der Richtung in Weltkoordinaten akzeptiert und die Winkelimpulsmethode nur einen y, p, r Vektor für das Gieren akzeptiert, Pitch, und rollen in Weltkoordinaten. Während die Mathematik leicht über meinem Kopf sein kann (ich habe eine harte Zeit, Dinge wie Punkt- und Kreuzprodukte zu visualisieren), ist die eigentliche Bullet API selbst WEG über meinen Kopf und völlig neu für mich ... die Kombination dieser beiden macht meine Leben im Moment unmöglich. – Lusid

Antwort

3

So Blick auf btRigidBody.h

ich den folgenden Code fest:

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

Nun, wie ich es verstehe, wollen Sie Ihr Drehmoment um einige konstante Zeiten gleich dem Rotationsvektor um die x- (oder z-) Achse zu sein, die mit deinem Raumschiff verbunden ist.

Wie wir wissen, dass die generalisierte Rotationsmatrix bestimmt werden kann, wie folgt:

  1. Drehen um Achse Preform
  2. Rotation um kanonische Achse
  3. Inverse von Schritt 1

Dieses Mittel ausrichten Wenn Sie ein mit der Achse ausgerichtetes Drehmoment identifizieren können (das ich nicht von oben kenne), können Sie es mit Ihrem:

0 transformieren
mBody->getWorldTransform()*axisAlignedXTorque 

Welche nach http://www.bulletphysics.com/Bullet/BulletFull/classbtTransform.html der * Operator hier ist überschrieben, um die Welt transformieren auf dem Torque-Vektor.

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

Nach einer langen Zeit der Frustration, ich endlich körper lokalen Drehmoment der oben als Eingabe für applyTorqueImpulse zu arbeiten (oder applyTorque). Ich gebe nicht vor zu verstehen, warum es an diesem Punkt funktioniert, aber es tut es.

Bullet:

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

Vielleicht ist es das, was tzenes über war die Erwähnung der Achse ausgerichtet Drehmoment zu erzeugen. Aber ich bin verwirrt, dass ich kein Beispiel dafür finde, dass es jemand anders so macht. Sicherlich hat jemand anderes ein Drehmoment im Körperbereich des Körpers gewünscht? Aber nichts, was ich online fand, funktionierte überhaupt, obwohl es so aussah, wie es sollte.

Wenn Sie nur das Drehmoment transform * anwenden, sieht es so aus, als ob es zuerst funktioniert, bis Sie sich vom Ursprung Ihrer Welt entfernen. Wenn es sich also schwieriger anfühlt, weiter zu rotieren, wenn Sie vom Ursprung entfernt sind, oder wenn sich die Dinge in Abhängigkeit davon, wo sich der Körper befindet, rückwärts drehen, ist dies wahrscheinlich Ihr Problem.

EDIT: Oh, und hier ist, wie ich meine Übersetzungen haben.

btVector3 m = body-> getWorldTransform() getBasis() * btVector3 (strafe, bewegen, steigen);