Matrix 4x4: Convert from other software to Unity

Hi!

I am exporting a 4x4 matrix from an other 3D software to XML format. Then I am reading the XML file into Unity and generate a new 4x4 matrix based on the values I exported from the other 3D Software because I want to use the rotations, transformations, etc. so I can put them on GameObjects in Unity.

The problem I have (and I think I am just having problems with Math) is, that the other 3D Software uses a different orientation concerning the X,Y and Z axis:

3D Software:
X = Right
Y = Forward
Z = Up

Unity:
X = Right
Z = Forward
Y = Up

I read a lot of posts on Google and this forum, but I am not able to get the right results. This is basically the code which converts the string of the XML to a 4x4 matrix:

    private Matrix4x4 GetMatrix(string input)
    {
        var transMatrixValues = new float[16];

        input = input.Replace("(", "");
        input = input.Replace(")", "");

        var values = input.Split(',');

        for (var i = 0; i <= values.Length - 1; i++)
        {
            transMatrixValues[i] = (float)Math.Round(double.Parse(values[i]), 3);
        }

        var newMatrix = new Matrix4x4();
        newMatrix.SetColumn(0, new Vector4(transMatrixValues[0], transMatrixValues[4], transMatrixValues[8], transMatrixValues[12]));
        newMatrix.SetColumn(1, new Vector4(transMatrixValues[1], transMatrixValues[5], transMatrixValues[9], transMatrixValues[13]));
        newMatrix.SetColumn(2, new Vector4(transMatrixValues[2], transMatrixValues[6], transMatrixValues[10], transMatrixValues[14]));
        newMatrix.SetColumn(3, new Vector4(transMatrixValues[3], transMatrixValues[7], transMatrixValues[11], transMatrixValues[15]));

        return newMatrix;
    }

So how can I convert this matrix to a matrix I can use in Unity?
Thanks in advance.

I haven’t tested this but it might be as simple as swapping the 2nd and 3rd rows of the matrix. The first row essentially describes the new coordinate space’s X axis, 2nd describes the Y-axis and the 3rd the Z-axis.

You could also create a transform from the Matrix4x4 and then retrieve the eulerAngles from it. They’ll be correct but just in the wrong order so you could then create a new Matrix4x4 by using those eulerAngles in a different order.

After trying the different things you guys mentioned, like swapping rows, etc. it is still not working. It seems like the rotation of the objects is completely off. I have to make further tests, maybe the export of the other 3d software is not working correctly.

Or I am just missing something.
Thanks nevertheless.

You need to swap column 2 and 3, not rows

You should also be aware that matrices in some software is column major while in others it is row major.

1 Like

Thanks for pointing that out. I read about that and also kept it in mind while testing, but it seems it doesn’t work either. So my assumption is that I am doing something wrong in the export itself.

Another thing to consider is the handedness of the rotation, left or right.

If I’m not mistaken, I think swapping the rows of the matrix also changes the handedness.

I don’t know about the 3D software you are using, but Unity is left handed, and uses column major matrices.

First you need to figure out if your 3D software exports as row or column major. This should give you enough information to bring the matrix correctly into Unity. Just bring it in as-is, don’t care about axis or handedness at this point.

What you should do next, is find one or more matrices that you can multiply with your input matrix that will give the correct result. I would start with handedness, if this is wrong. This should give you the correct result, only facing the wrong direction. Then you find another matrix to correct the axis, if you need one. The latter can be achieved instead by having a rotated parent transform, in the same way Unity handles imports from blender.

Ok, that seems like a possible solution.

For multiplying my matrices is it just enough to use the * operator on the two matrices? Or do I need a special function for that?

Yes the Matrix4x4 class implements the * operator.

Ok, it looks like we are getting somewhere. I wrote the following method for the matrix transformation:

private Matrix4x4 TransformMatrix(Matrix4x4 matrix)
    {
        var transformMatrix = new Matrix4x4();

        transformMatrix.SetColumn(0, new Vector4(1, 0, 0, 0));
        transformMatrix.SetColumn(1, new Vector4(0, 0, 1, 0));
        transformMatrix.SetColumn(2, new Vector4(0, 1, 0, 0));
        transformMatrix.SetColumn(3, new Vector4(0, 0, 0, 1));

        return transformMatrix.inverse * (matrix * transformMatrix);
    }

This basically transforms my initial matrix from a right-handed one into a left-handed one. The only thing which is odd right now, is that the rotation around the y-axis is not correct. Its 90 degrees off. How can I fix this?

There are two ways, you can multiply by another matrix to adjust the rotation, or as I suggested in my previous post, create an empty transform as the parent and just set a rotation of 90 degrees on that.

After diving into this topic with a fresh mind, I was able to solve the problem. I made a mistake on the calculation of the transform matrix and I also used the wrong columns for the creation of the rotation for my game objects. So my solution for this is the following:

public static Matrix4x4 TransformMatrix(this Matrix4x4 input)
    {
        var other = new Matrix4x4();

        other.SetColumn(0, new Vector4(1, 0, 0, 0));
        other.SetColumn(1, new Vector4(0, 0, 1, 0));
        other.SetColumn(2, new Vector4(0, 1, 0, 0));
        other.SetColumn(3, new Vector4(0, 0, 0, 1));

        return (other * input);
    }

    private Quaternion MatrixToRotation(Matrix4x4 matrix)
    {
        return Quaternion.LookRotation(matrix.GetColumn(0), matrix.GetColumn(2));
    }