# slerp - Quaternion berechnen



## dayaftereh (20. Jul 2011)

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!


----------



## MainFrame (30. Jul 2011)

dayaftereh hat gesagt.:


> 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.
> 
> ...


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.


----------



## Marco13 (30. Jul 2011)

Kannst dich auch von der VecMath inspirieren lassen: Vecmath: Subversion: trunk: src: javax: vecmath: Quat4f.java &mdash; Java.net


----------



## Empire Phoenix (1. Aug 2011)

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 (2. Aug 2011)

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 (2. Aug 2011)

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 (2. Aug 2011)

Poste nacher mal den Code... ist in Python! denke mal das macht hier kein Problem


----------



## dayaftereh (3. Aug 2011)

Hier habe ich jetzt mal meine Quaternion Klasse

```
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):

```
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]):

```
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.

```
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 (7. Aug 2011)

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)


----------



## dayaftereh (7. Aug 2011)

Hey, das weiß ich nicht... es könnte natürlich daran liegen!


----------



## MainFrame (7. Aug 2011)

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


----------



## dayaftereh (8. Aug 2011)

Danke das habe ich gesucht!


----------

