x


Converting Matrix4x4 to Quaternion & Vector3

I'm attempting to convert a Matrix4x4 which is being currently being applied to a camera using camera.worldToCameraMatrix and works fine.

I'm able to get the position out with:

Vector4 newCameraPos = matrix.GetColumn(3);
Camera.main.transform.position = Vector3(newCameraPos.x,newCameraPos.y,newCameraPos.z);

But at the moment can't get the quaternion to come out. I've pulled some code from a matrix and quaternion FAQ I stumbled across and have partially implemented, but at the moment its not behaving.

Quaternion matrixToQuaternionx(Matrix4x4 m1){ float T = 1 + m1[0] + m1[5] + m1[10];

 Quaternion q = Quaternion.identity;

 if ( T > 0.00000001f ){
     float S = Mathf.Sqrt(T) * 2;
     q.x = ( m1[9] - m1[6] ) / S;
     q.y = ( m1[2] - m1[8] ) / S;
     q.z = ( m1[4] - m1[1] ) / S;
     q.w = 0.25f * S;
 }else{
     Debug.Log("more to calculate here");
 }

 return q;

}

If I turn off the camera.worldToCameraMatrix, and rely on the Vector and Quaternion I get out (ignoring cases where it gets to the 'more to calculate here') the position of the camera looks fine, but its rotation is way off.

more ▼

asked Feb 11, 2010 at 07:15 AM

Leigh gravatar image

Leigh
59 4 4 11

(comments are locked)
10|3000 characters needed characters left

3 answers: sort voted first

For getting a quaternion from a Matrix4x4, this function works:

public static Quaternion QuaternionFromMatrix(Matrix4x4 m) {
    // Adapted from: http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/index.htm
    Quaternion q = new Quaternion();
    q.w = Mathf.Sqrt( Mathf.Max( 0, 1 + m[0,0] + m[1,1] + m[2,2] ) ) / 2; 
    q.x = Mathf.Sqrt( Mathf.Max( 0, 1 + m[0,0] - m[1,1] - m[2,2] ) ) / 2; 
    q.y = Mathf.Sqrt( Mathf.Max( 0, 1 - m[0,0] + m[1,1] - m[2,2] ) ) / 2; 
    q.z = Mathf.Sqrt( Mathf.Max( 0, 1 - m[0,0] - m[1,1] + m[2,2] ) ) / 2; 
    q.x = Mathf.Sign( q.x  ( m[2,1] - m[1,2] ) );
    q.y = Mathf.Sign( q.y  ( m[0,2] - m[2,0] ) );
    q.z = Mathf.Sign( q.z  ( m[1,0] - m[0,1] ) );
    return q;
}

For getting the position, GetColumn(3) works fine.

more ▼

answered Feb 11, 2010 at 11:08 AM

runevision gravatar image

runevision ♦♦
9.2k 55 113 198

such a great solution, thank you Rune!

Jan 30, 2011 at 06:12 PM 3Duaun

What about the inverse operation? Obtaining a 4x4 out of a quaternion. Is that possible?

Sep 15, 2011 at 07:27 AM roamcel

@roamcel (or anyone else reading this more realistically)

You can in fact get the reverse (4x4mat from a quat). The following is python code I wrote so it shouldn't be too hard to read and write in your preferred language:

 from math import *
 
 q = (0, 1.87, 3.22, 6.43)
 
 q2 = [0,0,0,0]
 
 q2[0] = q[0] / sqrt(q[0]**2 + q[1]**2 + q[2]**2 + q[3]**2)
 q2[1] = q[1] / sqrt(q[0]**2 + q[1]**2 + q[2]**2 + q[3]**2)
 q2[2] = q[2] / sqrt(q[0]**2 + q[1]**2 + q[2]**2 + q[3]**2)
 q2[3] = q[3] / sqrt(q[0]**2 + q[1]**2 + q[2]**2 + q[3]**2)
 
 print q2, "\n"
 
 quat_Matrix = [
                [1 - 2*q2[2]**2 - 2*q2[3]**2, 2*q2[1]*q2[2] - 2*q2[3]*q2[0], 2*q2[1]*q2[3] + 2*q2[2]*q2[0]],
                [2*q2[1]*q2[2] + 2*q2[3]*q2[0], 1 - 2*q2[1]**2 - 2*q2[3]**2, 2*q2[2]*q2[3] - 2*q2[1]*q2[0]],
                [2*q2[1]*q2[3] - 2*q2[2]*q2[0], 2*q2[2]*q2[3] + 2*q2[1]*q2[0], 1 - 2*q2[1]**2 - 2*q2[2]**2]
               ]
 
 for i in quat_Matrix:
     print i
Aug 30, 2013 at 11:58 PM JoryRFerrell

@roamcel @JoryRFerrell Unity provides a nice easy way:

 Matrix4x4 m = Matrix4x4.TRS(Vector3.zero, quaterion, Vector3.one);

As for matrix decomposition (the question subject) here is the approach which I use:

http://answers.unity3d.com/questions/402280/how-to-decompose-a-trs-matrix.html

Aug 31, 2013 at 04:52 PM numberkruncher

Thanks!

It should be noted that if you're attempting to convert a valid worldToCameraMatrix to a quaternion rotation you'll need to adjust for the reversed z on camera and call something like:

Camera.main.transform.rotation = Quaternion.QuaternionFromMatrix(matrixToSet.inverse * Matrix4x4.TRS(Vector3.zero, Quaternion.identity, new Vector3(1,1,-1)));

Feb 14, 2010 at 11:29 PM Leigh
(comments are locked)
10|3000 characters needed characters left

Here's a faster and easier solution:

public static Quaternion QuaternionFromMatrix(Matrix4x4 m) { return Quaternion.LookRotation(m.GetColumn(2), m.GetColumn(1)); }

more ▼

answered May 21, 2012 at 09:50 AM

Leto gravatar image

Leto
45 1

(comments are locked)
10|3000 characters needed characters left

Actually I can confirm that the

"For getting a quaternion from a Matrix4x4, this function works: ..."

Doesn't work, and the

"Here's a faster and easier solution: ..."

Works.

I'm making a voxel engine that performs all sorts of transforms and the first method produces: alt text

While the second función produces alt text

And the control test uses Graphics.DrawMesh() with the matrix transform as a parameter

more ▼

answered Jul 25, 2012 at 01:08 AM

peacefulshade gravatar image

peacefulshade
46

(comments are locked)
10|3000 characters needed characters left
Your answer
toggle preview:

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this question

By Email:

Once you sign in you will be able to subscribe for any updates here

By RSS:

Answers

Answers and Comments

Topics:

x3858
x394

asked: Feb 11, 2010 at 07:15 AM

Seen: 12260 times

Last Updated: Aug 31, 2013 at 04:53 PM