slerp - Quaternion berechnen

dayaftereh

Top Contributor
Hallo,

Ich bin gerade Quaternion interpolation und slerp. Mit der slerp funktion kann ich zwischen zwei Quaternion interpolieren über den Wert t [0,1], nur ist jetzt meine Frage wie kann ich die beiden Quaternion q1 und q2 aus zwei Punktion im R3 berechnen.

zum Beispiel habe ich p1 = (1,0,0) und p2 = (0,1,0). Wie bekomme ich jetzt die beiden Quaternion von diesen Punkten um die dann zu interpolieren?

Ich hoffe dir Frage ist hier passent, wenn nicht Bitte auf ein anderes Fourm verweisen!

Danke schonmal!
 
M

MainFrame

Gast
Hallo,

Ich bin gerade Quaternion interpolation und slerp. Mit der slerp funktion kann ich zwischen zwei Quaternion interpolieren über den Wert t [0,1], nur ist jetzt meine Frage wie kann ich die beiden Quaternion q1 und q2 aus zwei Punktion im R3 berechnen.

zum Beispiel habe ich p1 = (1,0,0) und p2 = (0,1,0). Wie bekomme ich jetzt die beiden Quaternion von diesen Punkten um die dann zu interpolieren?

Ich hoffe dir Frage ist hier passent, wenn nicht Bitte auf ein anderes Fourm verweisen!

Danke schonmal!
Ich hoffe ich erinnere mich ein wenig daran aber das ganze läuft im ganzen folgender maßen ab:
wir dir schon bekannt ist, solltest Du SLERP für die Interpolation der beiden Orientierung nutzen.

die Formel für SLERP = slerp(q1,q2,t)= q1 *[sin ( (1-t)*w) ]/sin(w) + q2 [sin (1*w) ]/sin(w)

wenn Du jetzt deine beiden Quaternionen einsetzt, bekommst du die Orientierung zum zeitpunkt t zwischen q1 und q2.

Diese muss du jetzt mit dem startpunkt, in deinem falle p1 nach der mit dem q1 Multiplizieren, also
p'=q*p*q^1 bzw. ist q dank slerp ein unit q.

Was haben wir jetzt erreicht ? Richtig ! eine Interpolation der Orientierung :)
D.h. du musst jetzt nur noch zwischen deinen beiden punkten p1 und p2 bezogen auf t und der orienzierung zu diesem Zeitpunkt bestehende Orientierung interpolieren, also zwischen p'1 und p2.

Ich hoffe, dass das alles hier stimmt.
 

Empire Phoenix

Top Contributor
Also nochmal von vorne du willst rotationen(quaterions) mithilfe von zwei positionen interpolieren? Das gibt null sinn, ausserdem hat die jme engine ne gute wiki mit mathe basis sachen...

Denke du suchst eher eine einführung in was sind Quaternions und wie interpoliere ich Vectoren linear?

(Startvector + t*vector zu punkt zwei) t €[0,1]
 

dayaftereh

Top Contributor
Danke für die Antworten.

Also was ich machen muss ist ein Slerp der Kamera. Das Bedeutet für mich das ich zwei Punkt habe, einmal die Position der Kamera und einmal der Punkt wo ich hin will, dabei ist der Uhrsprung der Punkt um den sich alles Dreht. Ich habe mir mal die slerp-Funktion von der JMonkeyengine angeschaut: Quaternion.java - jmonkeyengine - jMonkeyEngine is a modern 3D game engine written entirely in Java - Google Project Hosting. Also was ich jetzt mach ist, meine Beiden Start und Endpunkte zu einheits Quaternione und stecke die dann in diese Funktion. Da ich leider keine Engine nehmen kann und das ganze in OpenGL programmiere, mache ich jetzt das Quaternione was ich aus der slerp-Funktion bekomme zu einer Matrix und drehe mit dieser Matrix meine Kamera. Nur leider Klappt das noch nicht so würglich, was passiert ist das mein Object die ganze zeigt um 180 grad gedreht wird. der Slerp selbst klappt nur das mit dem hin und her springen mit dem Object stört noch?
 

Marco13

Top Contributor
Sicher kein Fehler in der Konvertierung Quternion->Matrix? (Ist kompliziert, AFAIR). Ansonsten wäre es gut, zu wissen, wie du interpolierst und wann du die Matrix wie anwendest.
 

dayaftereh

Top Contributor
Hier habe ich jetzt mal meine Quaternion Klasse
Java:
class Quaternion(object):

    def __init__(self,w,x,y,z):
        self.w = w
        self.x = x
        self.y = y
        self.z = z

    def length(self):
        return sqrt(self.w**2.0 +
                    self.x**2.0 +
                    self.y**2.0 +
                    self.z**2.0)

    def normalize(self):
        l = self.length()
        self.w = self.w / l
        self.x = self.x / l
        self.y = self.y / l
        self.z = self.z / l


    def __mul__(self, q):

        w = self.w*q.w - self.x*q.x - self.y*q.y - self.z*q.z
        x = self.w*q.x + q.w*self.x + self.y*q.z - self.z*q.y
        y = self.w*q.y + q.w*self.y - self.x*q.z - self.z*q.x
        z = self.w*q.z + q.w*self.z + self.x*q.y - self.y*q.x

        return Quaternion(w, x, y, z)

    def toMatrix(self):
        q = (self.w, self.x, self.y, self.z)
               
        xs = q[1]
        ys = q[2]
        zs = q[3]
        wx = q[0] * xs
        wy = q[0] * ys
        wz = q[0] * zs
        xx = q[1] * xs
        xy = q[1] * ys
        xz = q[1] * zs
        yy = q[2] * ys
        yz = q[2] * zs
        zz = q[3] * zs
        
        m = [0]*16
        m[ 0] = 1.0 - 2.0*(yy + zz)
        m[ 1] = 2.0 *(xy + wz)
        m[ 2] = 2.0 *(xz - wy)
        m[ 3] = 0.0

        m[ 4] = 2.0 * (xy - wz)
        m[ 5] = 1.0 - 2.0 * (xx + zz)
        m[ 6] = 2.0 * (yz + wx)
        m[ 7] = 0.0

        m[ 8] = 2.0 * (xz + wy)
        m[ 9] = 2.0 * (yz - wx)
        m[10] = 1.0 - 2.0 * (xx + yy)
        m[11] = 0.0

        m[12] = 0.0
        m[13] = 0.0
        m[14] = 0.0
        m[15] = 1.0

        return m
    
    def conjugate(self):
        x = -self.x
        y = -self.y
        z = -self.z

        return Quaternion(self.w,x,y,z)
        


    def interpolate(self,q1,q2,t):
        q1.normalize()
        q2.normalize()
        dot = q1.w*q2.w + q1.x*q2.x + q1.y*q2.y + q1.z*q2.z

        if dot < 0:
            q2.w = -q2.w
            q2.x = -q2.x
            q2.y = -q2.y
            q2.z = -q2.z
            dot = -dot

        if (1.0 - dot) > 0.00001:
            om = acos(dot)
            sinom = sin (dot)
            scale0 = sin ((1.0-t)*om)/sinom
            scale1 = sin (t*om) / sinom
        else:
            scale0 = 1.0 - t
            scale1 = t

        x = (scale0 * q1.x) + (scale1 * q2.x)
        y = (scale0 * q1.y) + (scale1 * q2.y)
        z = (scale0 * q1.z) + (scale1 * q2.z)
        w = (scale0 * q1.w) + (scale1 * q2.w)

        q = Quaternion(w,x,y,z)        
        q.normalize()
        return q

Und so nutze ich sie: Zu erst erzuege ich mir die zwei Quaternione für die Position P1 = (0,0,10) und P2 = (10,10,5):
Java:
q1 = Quaternion(0.0,0.0,0.0,10.0)
q2 = Quaternion(0.0,10.0,10.0,5.0)

Jetzt habe ich eine Funktion die in einem Bestimmten zeit abstand aufgerufen wird und dort zähle ich jetzt mein t für die Interpolation hoch und rechne mir mein neues Camera Quaternion aus(das Camera Quaternion ist am anfang [1,0,0,0]):
Java:
if t <= 1.0:        
        t += 0.01
        q = cameraquat.interpolate(q1,q2,t)              
        cameraquat = q * cameraquat

Um jetzt die Camera zu verschieben rufe ich das folgender Massen auf.
Java:
gluLookAt(e.x,e.y,e.z,    f.x,f.y,f.z,    up.x,up.y,up.z)
glMultMatrixf(cameraquat.toMatrix())

Mein Problem ist das meine Objecte die ganze zeit dürch die gegent flippen aber im Große klappt die Camera Fahrt.
 

MainFrame

Neues Mitglied
Eine generelle Frage zu deinem beispiel:

Muss man den anfangvector nicht erstmal mit der startorientierung multiplizieren:

p'1 = q1*p*q^-1

und p2

S(t)= p'1 + t*p2*slerp(q1,q2,t)
 

MainFrame

Neues Mitglied
gehen wir das mal gemeinsam durch:


p1 = (1,0,0)
p2 = (0,1,0)

p1 soll zb 90° um (0,1,0)

p2 soll zb 180° um (1,0,0)

quaternion aufstellen:

q1= [cos(90/2),sin(9/2)*(0,1,0)]

q2= [cos(180/2),sin(180/2)*(0,1,0)]


p'1 = q1*p1*q1^-1
qs = slerp(q1,q2,t)
p'=qs(t*p2)qs^-1
s(t) = p'1 + p';
p' ist der verschobene Punkt. Eine Verschiebung des Punktes p2 ändert nichts an seiner orientierung
 

Ähnliche Java Themen


Oben