[BULLET] Problem mit Quaternionen

Design Patterns, Erklärungen zu Algorithmen, Optimierung, Softwarearchitektur
Forumsregeln
Wenn das Problem mit einer Programmiersprache direkt zusammenhängt, bitte HIER posten.
Antworten
Jonsc1
Beiträge: 19
Registriert: 14.08.2006, 18:51

[BULLET] Problem mit Quaternionen

Beitrag 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!
Benutzeravatar
eXile
Establishment
Beiträge: 1136
Registriert: 28.02.2009, 13:27

Re: [BULLET] Problem mit Quaternionen

Beitrag 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.
Jonsc1
Beiträge: 19
Registriert: 14.08.2006, 18:51

Re: [BULLET] Problem mit Quaternionen

Beitrag 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!
Benutzeravatar
Schrompf
Moderator
Beiträge: 4859
Registriert: 25.02.2009, 23:44
Benutzertext: Lernt nur selten dazu
Echter Name: Thomas Ziegenhagen
Wohnort: Dresden
Kontaktdaten:

Re: [BULLET] Problem mit Quaternionen

Beitrag 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.
Früher mal Dreamworlds. Früher mal Open Asset Import Library. Heutzutage nur noch so rumwursteln.
Benutzeravatar
eXile
Establishment
Beiträge: 1136
Registriert: 28.02.2009, 13:27

Re: [BULLET] Problem mit Quaternionen

Beitrag 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.
Crush
Beiträge: 30
Registriert: 23.02.2002, 14:39
Wohnort: Stuttgart

Re: [BULLET] Problem mit Quaternionen

Beitrag von Crush »

Liefert atan2() nicht falsche Werte, wenn beide Parameter 0 sind?
klickverbot
Establishment
Beiträge: 191
Registriert: 01.03.2009, 19:22
Echter Name: David N.

Re: [BULLET] Problem mit Quaternionen

Beitrag 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…
Benutzeravatar
eXile
Establishment
Beiträge: 1136
Registriert: 28.02.2009, 13:27

Re: [BULLET] Problem mit Quaternionen

Beitrag 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. ;)
Antworten