I recently face-palmed when realizing that once again, I had set my own application up with Y as the up axis, but was importing all my assets from 3dsmax where Z is the up axis. I am using the Physx exporter and importing using the PXU library. Rather than re-write large portions of my code, I decided to just iterate through imported matricies and convert them from Z up to Y up.

When you are no matricies expert, this can be tough, there are a lot of people asking how to do this and there isn’t a whole lot out there to help you, which is why I am writing this post.

Physx uses 4×3 matricies for transformation, being a 3×3 rotation matrix with a 1×3 translation vector.

Converting the position is easy, just swap the Y and Z values:

``````vector3 position;
float temp = position.y;
position.y = position.z;
position.z = temp;
``````

But transforming the rotation vector is a whole lot harder. At first thought you may think “hey, just rotate 90 degrees on the X axis” but no, unfortunately this doesn’t work. The actual solution is just like fixing the position, swap the Y and Z values.

On a 3×3 matrix this is slightly more confusing. What are the Y and Z values? Well, I will assume that you realise a 3×3 matrix is a 3×3 grid of numbers. To swap the Y and Z values, you must swap the second and third columns AND the second and third rows:

``````matrix33 rotation;
vector3 temp;

temp = rotation.column2;
rotation.column2 = rotation.column3;
rotation.column3 = temp;

temp = rotation.row2;
rotation.row2 = rotation.row3;
rotation.row3 = temp;
``````

On a 4x4 matrix:

``````/**
* The method that moves the matrix from Z-up axis to Y-up axis space is as follows:
* - load the matrix directly from blender (it has the Z-up axis orientation)
* - switch the second and third rows in the matrix
* - switch the second and third column in the matrix
* - multiply the values in the third row by -1
* - multiply the values in the third column by -1
*
* The result matrix is now in Y-up axis orientation.
* The procedure was discovered by experimenting but it looks like it's working :)
* The previous procedure transformet the loaded matrix into component (loc, rot, scale),
* switched several values and pu the back into the matrix.
* It worked fine until models with negative scale are used.
* The current method is not touched by that flaw.
*
* @param store
*            the matrix where the result will pe placed
* @return the required matrix
*/
public static Matrix4f getMatrix(Matrix4f store) {
// first switch the second and third row
for (int i = 0; i < 4; ++i) {
float temp = store.get(1, i);
store.set(1, i, store.get(2, i));
store.set(2, i, temp);
}

// then switch the second and third column
for (int i = 0; i < 4; ++i) {
float temp = store.get(i, 1);
store.set(i, 1, store.get(i, 2));
store.set(i, 2, temp);
}

// multiply the values in the third row by -1
store.m20 *= -1;
store.m21 *= -1;
store.m22 *= -1;
store.m23 *= -1;

// multiply the values in the third column by -1
store.m02 *= -1;
store.m12 *= -1;
store.m22 *= -1;
store.m32 *= -1;

return store;
}``````