Tuesday, March 3, 2020

Quaternion Exponentiation

For instance I have 45 degree rotation quaternion p. and if I take p ^ (1/3) then I'll get 15 degree rotation quaternion. This is geometric interpretation of quaternion exponentiation use case.

Let say I have q^(1/3) which is 1/3 power of quaternion q.

Mathematically we can define

log q = [0 alpha*n], n is the rotation axis.

exp q = [cos(alpha) n*sin(alpha)], alpha is the rotation angle.


Quaternion Exponentiation is defined down below.

q^(t) = exp(t log q)



Quaternion QuaternionExp(Quaternion q, float t)
{
    Quaternion newQ = q;

    float currentAngle = Mathf.Acos(newQ.w);

    // At the moment newQ's x, y, z has normal and already applied sin(w)

    // q' = exp(t * log q)
    // log q = [0 alpha*n]
    // exp p = [cos(alpha) n*sin(alpha)]

    float newAngle = currentAngle * t; // cos(alpha) term
       
    // what / Mathf.Sin(currentAngle) does is extract normal vector from the appllied nx, ny, nz
    float newX = newQ.x / Mathf.Sin(currentAngle) * Mathf.Sin(newAngle);
    float newY = newQ.y / Mathf.Sin(currentAngle) * Mathf.Sin(newAngle);
    float newZ = newQ.z / Mathf.Sin(currentAngle) * Mathf.Sin(newAngle);
       
    newQ.x = newX;
    newQ.y = newY;
    newQ.z = newZ;
    newQ.w = Mathf.Cos(newAngle);

    return newQ;
}

QuaternionExp is the implementation of Quaternion Exponentiation in C#.

Like I mentioned that we have 45 degree rotation quaternion q.

Quaternion q = Quaternion.Euler(0, 45, 0);

and 1/3 degree of 45 is 15 degree so if I take q^(1/3) then I'll have 15 degree rotation quaternion and I can apply it to gameobject.



Quaternion q = Quaternion.Euler(0, 45, 0);

// q is the 45 degree rotation.
// q^(1/3) will be 15 degree rotation.       
q = QuaternionExp(q, 1.0f / 3.0f);
       
this.transform.localRotation = q;




Last thing I want to describe is why we took / Mathf.Sin(currentAngle) when we calculate newX, newY, newZ.

This is because newQ's x, y, z values are already applied sin(theta) which we needed to extract from the value. so we divide Sin(currentAngle) from all of the newQ's x, y, z and apply Sin(newAngle).

That's all!



No comments:

Post a Comment

Task in UnrealEngine

 https://www.youtube.com/watch?v=1lBadANnJaw