PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Interpolation von Quaternions


Neomi
2010-05-01, 18:11:27
Eigentlich geht es eher um ein mathematisches Problem als um direkte Programmierung. Da wir aber kein Mathematikforum haben, ist das hier wohl am besten untergebracht.

Wenn ich die Position eines Objektes im dreidimensionalen Raum zwischen zwei Keyframes interpolieren möchte, benutze ich dafür Hermitesplines (ganz normale Polynomialsplines 3. Grades), um über eine Serie von Keyframes hinweg eine sanfte Bewegung zu haben, also keine Sprünge in der Geschwindigkeit. Dazu gibt es zusätzlich zur Position pro Keyframe auch noch die Geschwindigkeit. Ob die Geschwindigkeit nun explizit gegeben ist oder implizit durch die Position im vorigen und nachfolgenden Keyframe bestimmt wird, spielt für die Berechnung keine weitere Rolle.

Was bei der Position kein Problem ist, ist bei der Orientierung schon eins. Lineare Interpolation (per Spherical Lerp) reicht nicht, da sich die Rotationsgeschwindigkeit beim Übergang von einem Keyframeintervall in den nächsten schlagartig ändert. Ich habe über Spherical Cubic Interpolation gelesen, nur ist die wegen einer fiesen Einschränkung nicht direkt verwendbar für mich, zumindest die dazugehörige Setup-Funktion. Und zwar werden die beiden Hilfsquaternions, die die beiden Start- und Endquaternions ergänzen, durch eine Folge von 4 Quaternions berechnet, die in gleichen Zeitabständen vorliegen. Wenn ich aber pro Keyframe die Rotationsgeschwindigkeit explizit habe, hilft das nicht. Auch im Fall von einer Sequenz von Keyframes, die keine einheitlichen Zeitabstände haben, hilft das nicht. Die nötige Rotationsgeschwindigkeit pro Keyframe kann ich mir berechnen durch so eine Sequenz, daher beschränkt sich das Problem wohl auf diesen Fall. Die Rotationsgeschwindigkeit liegt übrigens vor als 3er Vektor, dessen Richtung die Achse ist, um die rotiert wird und dessen Länge der Geschwindigkeit der Rotation entspricht. Normalerweise ist die Geschwindigkeit in Bogemaß/s (eine Länge von 2*Pi wäre also eine volle Drehung pro Sekunde), eine Skalierung passend zum Zeitabstand der Keyframes ist aber natürlich auch kein Thema.

Kurz also die Frage:
Wie kann ich die beiden Hilfsquaternions für die übliche Squad-Funktion berechnen, wenn ich nicht zwei weitere Orientierungen in gleichen Zeitabständen vorher und nachher habe, sondern nur die gewünschten Rotationsgeschwindigkeiten zu den Start- und Endorientierungen?

PS:
Das Schreiben dieses Postings hat mich auf eine Spur gebracht, die ich aber nicht direkt verfolgen kann und die evtl. auch gar nicht aufgeht. Also keine Zurückhaltung. ;)

pest
2010-05-01, 18:43:10
Ich scheine keine Ahnung von Mathe zu haben :p

Coda
2010-05-01, 21:09:38
Kannst du nochmal kurz zusammenfassen welche Operation auf Quaternions du genau haben möchtest?

Das aus deinem Posting zu extrahieren ist recht schwierig.

Neomi
2010-05-01, 21:56:34
Quaternion SQuad(
const Quaternion& aOrient1,
const Quaternion& aHelper1,
const Quaternion& aHelper2,
const Quaternion& aOrient2,
const float u)
{
return SLerp(SLerp(aOrient1, aOrient2, u), SLerp(aHelper1, aHelper2, u), 2.0f * u * (1.0f - u));
}

// übliche SQuadSetup-Funktion über vier in gleichen Zeitabständen folgende Orientierungen

void SQuadSetup(
const Quaternion& aOrient0,
const Quaternion& aOrient1,
const Quaternion& aOrient2,
const Quaternion& aOrient3,
Quaternion& aHelper1,
Quaternion& aHelper2)
{
// Berechnung von aHelper1 und aHelper2 ist mir bekannt
}

// benötigte SQuadSetup über nur zwei Orientierungen und dazu zwei Rotationsgeschwindigkeiten

void SQuadSetup(
const Quaternion& aOrient1,
const Vector3& aAngVel1,
const Quaternion& aOrient2,
const Vector3& aAngVel2,
Quaternion& aHelper1,
Quaternion& aHelper2)
{
// das hier ist der Knackpunkt
}

Die Orientierungen aOrient1 und aOrient2 habe ich, aHelper1 und aHelper2 brauche ich. Die SQuadSetup-Funktion, die man häufig im Netz findet und die auch z.B. bei den D3DX-Funktionen mit dabei ist, berechnet diese über vier Orientierungen (aOrient0 und aOrient3 zusätzlich) in regelmäßigen Zeitabständen. Solche zusätzlichen Orientierungen habe ich nicht, stattdessen aber die Geschwindigkeit der Rotation (aAngVel1 und aAngVel2). Diese Rotationsvektoren bestimmen die Rotationsgeschwindigkeit, indem um die Rotationsachse (die Richtung des Vektors) im Uhrzeigersinn (wenn man entlang des Vektors schaut) gedreht wird, die Drehgeschwindigkeit entspricht der Länge des Vektors (also z.B. eine Vierteldrehung pro Sekunde, wenn der Vektor die Länge Pi/2 hat, da im Bogenmaß).