Seite 1 von 1

[BULLET] Problem mit Quaternionen

Verfasst: 19.12.2010, 19:36
von Jonsc1
Huhu
Ich bin gerade dabei mich mit der Physikbibiothek Bullet vertraut zu machen, und habe dort ein kleines Problem bezüglich der Rotation von Objekten.
Keine Angst, es geht nicht um Bullet an sich, sondern eigentlich um Quaternionen.
Bullet liefert mir die momentane Drehung meines Objektes so zurück:

Code: Alles auswählen

dynamicsWorld->stepSimulation(1/100.f,10);
btTransform trans;
fallRigidBody->getMotionState()->getWorldTransform(trans);
btQuaternion rot = trans.getRotation();

// Das funktioniert (logischerweise) nicht so wie es soll
Kugel.SetRotation(rot.x() , rot.y(), rot.z() );
Meine Funktion ISEN_Object::SetRotation(float x, float y, float z) macht eigentlich nicht viel mehr als die entsprechende D3DX10 Funktion zu wrappen:

Code: Alles auswählen

void ISEN_Object::SetRotation(float x, float y, float z)
{
	m_fRotationX = x;
	m_fRotationY = y;
	m_fRotationZ = z;

	D3DXMATRIX matRotateX;
	D3DXMATRIX matRotateY;
	D3DXMATRIX matRotateZ;

	D3DXMatrixRotationX(&matRotateX, m_fRotationX);
	D3DXMatrixRotationY(&matRotateY, m_fRotationY);
	D3DXMatrixRotationZ(&matRotateZ, m_fRotationZ);
	m_matRotate = matRotateX * matRotateY * matRotateZ;  // Rotationsmatrix neu bestimmen
	m_matWorldTransform = m_matRotate * m_matScale * m_matTranslate;    // Worldmatrix neu bestimmen
}
Ich benötige also irgendeine Möglichkeit aus dem Quaternion die Winkel zu bekommen, um sie an meine Funktion übergeben zu können.
Nun habe ich leider absolut KEINE Ahnung wie Quaternionen genau funktionieren, ich benutze sie ja auch nicht, nur besteht Bullet halt leider darauf das so zurückzugeben.
Also meine Frage:
Wie kann ich das sinnvoll umwandeln?

Danke im Vorraus!

Re: [BULLET] Problem mit Quaternionen

Verfasst: 19.12.2010, 20:43
von eXile
Also die x-, y- und z-Kompontente eines Quartenions gibt nicht den Eulerwinkel um die jeweilge Achse an! Normalweise stellt ein Quarternion eine Rotation um eine Achse (getAxis) mit einem bestimmten Winkel (getAngle) dar. Nun gibt es mehrere Möglichkeiten, ein Quarternion in etwas anderes zu konvertieren.

In deinem Falle wäre wohl die Konvertierung in eine Rotationsmatrix (dabei ist W die reelle Komponente und X, Y, Z sind die imaginären Komponenten) die direkte Lösung. Alternativ kann man auch den Umweg nehmen, das zuerst in Eulerwinkel (dabei ist q_0 die reelle Komponente und q_1, q_2, q_3 sind die imaginären Komponenten) zu konvertieren, und dann aus den Eulerwinkeln eine Rotationsmatrix zu erstellen (so, wie es dein Code andeutet).

Ich würde den ersten Weg mit der direkte Konvertierung gehen. Hierzu kannst du dir auch einmal D3DXMatrixRotationQuaternion anschauen, was die Konvertierung korrekt erledigen sollte.

Re: [BULLET] Problem mit Quaternionen

Verfasst: 19.12.2010, 21:53
von Jonsc1
Meine Klasse ISEN_Object merkt sich die Eulerwinkel in Membervariablen und stellt auch Funktionen wie Rotate(x, y, z) zur Verfügung, die basierend auf den intern gespeicherten Winkeln das Objekt weiterdreht (statt eine absolute Rotation zu setzen). Desswegen möchte ich keine Rotationsmatrix setzen, da diese dann ja nicht mehr zu den internen Winkeln passt.

Edit:
Habe basierend auf der Formel aus Wikipedia jetzt mal den x-Winkel so berechnet:

Code: Alles auswählen

float rotx = atan2(2*(rot.w()*rot.x() + rot.y()*rot.z()), 1 - 2*( pow( rot.x(), 2) + pow(rot.y(),2)));
Edit2:
noch den y- und z-Winkel, falls mal jemand via google auf das hier stösst:

Code: Alles auswählen

float rotx = atan2(2*(rot.w()*rot.x() + rot.y()*rot.z()), 1 - 2*( pow( rot.x(), 2) + pow(rot.y(),2)));
float roty = asin(2*(rot.w()*rot.y() - rot.z() * rot.x()));
float rotz = atan2( 2 * (rot.w()*rot.z() + rot.x() * rot.y()), 1 - 2*(pow(rot.y(), 2) + pow(rot.z(), 2)));
und das scheint zu funktionieren. Zumindest rollt die Kugel jetzt wie erwartet in der Gegend rum :)
Danke dafür!

Re: [BULLET] Problem mit Quaternionen

Verfasst: 20.12.2010, 08:59
von Schrompf
Du wirst auf Dauer Ärger mit Eulern kriegen. Google mal nach Gimbal Lock. Eine Rotationsmatrix oder ein Quaternion sind meiner Meinung nach auf Dauer nicht vermeidbar.

Re: [BULLET] Problem mit Quaternionen

Verfasst: 20.12.2010, 12:17
von eXile
Schrompf hat geschrieben:Du wirst auf Dauer Ärger mit Eulern kriegen. Google mal nach Gimbal Lock. Eine Rotationsmatrix oder ein Quaternion sind meiner Meinung nach auf Dauer nicht vermeidbar.
Ich bin mittlerweile der Meinung, dass jedes Objekt intern nur noch Quaternionen abspeichern sollte. Das vermeidet einerseits den Gimbal Lock, andererseits kann man in manchen Randfällen mit dem Quaternion Double-Cover noch ein paar nette Sachen anstellen (von der Interpolation ganz zu schweigen). (Eine Ausnahme könnte dann gegeben sein, wenn man sehr sehr häufig die Rotationsmatrizen abfragt -- in diesem Falle bin ich aber für eine doppelte Abspeicherung von Quaternionen und Rotationsmatrix, auch wenn sich dadurch der Aktualisierungsaufwand verdoppelt.)

Im allgemeinen Sprich also auch nichts dagegen, einfach eine Methode zu haben, welche die hinzuzufügende Rotation als Eulerwinkel entgegennimmt -- wenn dann diese Winkel in ein entsprechendes Quaternion umgerechnet werden, und diese dann multipliziert werden.

Re: [BULLET] Problem mit Quaternionen

Verfasst: 20.12.2010, 12:19
von Crush
Liefert atan2() nicht falsche Werte, wenn beide Parameter 0 sind?

Re: [BULLET] Problem mit Quaternionen

Verfasst: 20.12.2010, 13:04
von klickverbot
Crush hat geschrieben:Liefert atan2() nicht falsche Werte, wenn beide Parameter 0 sind?
Wie meinst du »falsche Werte«? {0, 0} ist einfach kein sinnvoller Eingabewert…

Re: [BULLET] Problem mit Quaternionen

Verfasst: 20.12.2010, 13:14
von eXile
klickverbot hat geschrieben:
Crush hat geschrieben:Liefert atan2() nicht falsche Werte, wenn beide Parameter 0 sind?
Wie meinst du »falsche Werte«? {0, 0} ist einfach kein sinnvoller Eingabewert…
Der C-Standard sagt dazu:
C-Standard hat geschrieben:A domain error may occur if both arguments are zero.
Wir sprechen hier allerdings über Einheitsquaternionen, da kann dieser Fall nicht eintreten. ;)