1
$\begingroup$

I import a mesh in Blender, export it with setting axis_forward='-Z', axis_up='Y', import in NVIDIA's FleX, rotate it and store it on disk; I call this mesh X. I also import the mesh in Blender and rotate it the same amount; I call this mesh Y. After I imported X in Blender (setting axis_forward='-Z', axis_up='Y') I realized that X has a different rotation which means that FleX is either using a different global axes (I think it's -Y forward and Z up) or it applies the rotations in a different order or a combination of both. So I am pretty confused now. I do not want to change anything on the FleX side. However, I want to rotate Y in a way that it matches with what FleX exports (X) after rotation. I also tried with Quaternions but I'm still unable to figure out the way FleX is transforming the object. The only thing that I've been able to figure out empirically is that the value for rx rotation is applied the same way for both FleX and Blender. This means that objects X and Y would overlap completely if imported in on scene in Blender.

My goal is to rotate the object in FleX so that object Y's rotation matches exactly with object X when I import X in Blender. For instance, I want FleX rotate the object the same way as Blender rotates it with the Euler rotation vector of [rx, ry, rz]. How can I achieve this?

Note that I am not changing the rotation order in Blender and I'm using the default XYZ rotation.

Here I are some images of the visual differences between FleX and Blender for such transformations:

Euler rotation vector: [0, 89.9, 0] in for object Y in Blender.

After applying the rotation in Blender (object Y): enter image description here

After applying the same rotation ([0, 89.9, 0]) in FleX and importing the object X in Blender: enter image description here

Euler rotation vector: [0, 0, 89.9] for object Y in Blender. enter image description here

After applying the same rotation ([0, 0, 89.9]) in FleX and importing the object X in Blender: enter image description here

It might look it is easy to guess from the images that FleX swaps the ry and rz when applying the rotation. If I also swap ry and rz when applying the rotations in Blender then both X and Y overlap. However, this only works if all components of the rotation vector are zero except one of them. If the rotation vector is something like [-43.964176, 20.641195, -1.2689421] X and Y do not overlap anymore and discrepancies start to show up as shown below:

enter image description here

The discrepancies are more visible if I put a cloth on X in FleX, import the cloth and Y in Blender and rotate Y by [-43.964176, -1.2689421, 20.641195] (notice that I've swapped ry and rz when applying the rotation in Blender, not in FleX):

enter image description here

Note that if I import X here, the cloth would be perfectly covering it while touching it on the surface:

enter image description here

After doing some hacking for the last example, I noticed that if I apply the rotation vector [-43.964176, 1.2689421, 20.641195] (rx, -rz, ry) the objects overlap almost perfectly:

enter image description here

For another example, I want to apply the rotation [87.68034, 79.94778, 82.697876] in Blender which should ideally give me something like this:

enter image description here

However, FleX is giving me the following (no swapping before passing the rotation vector to FleX):

enter image description here

I was thinking maybe applying the rotation in order of (rx, -rz, ry) in Blender would give me the perfectly overlapping result that I got for the previous example, but instead I got very weird results for another as shown below. Note that I wanted to rotate the object by [87.68034, 79.94778, 82.697876]`:

enter image description here

By manually rotating the object in Blender I could eventually get it as close as possible to Y (exported from FleX). Surprisingly, the rotation vector that overlaps X and Y is way different than [87.68034, 79.94778, 82.697876] in (rx, ry, rz) or [87.68034 -82.697876, 79.94778] in (rx, -rz, ry). It is something around [5.38, -10.1, 88.6] in `(rx, ry, rz) as shown below:

enter image description here

Although you might need more information to figure out exactly what's going out but below I post the code that is used in FleX to compute its rotation matrices. The top one is used when Euler angles are used and the second one is used when Quaternions are input:

// generate a rotation matrix around an axis, from PBRT p74
inline Mat44 RotationMatrix(float angle, const Vec3& axis)
{
    Vec3 a = Normalize(axis);
    float s = sinf(angle);
    float c = cosf(angle);

    float m[4][4];

    m[0][0] = a.x * a.x + (1.0f - a.x * a.x) * c;
    m[0][1] = a.x * a.y * (1.0f - c) + a.z * s;
    m[0][2] = a.x * a.z * (1.0f - c) - a.y * s;
    m[0][3] = 0.0f;

    m[1][0] = a.x * a.y * (1.0f - c) - a.z * s;
    m[1][1] = a.y * a.y + (1.0f - a.y * a.y) * c;
    m[1][2] = a.y * a.z * (1.0f - c) + a.x * s;
    m[1][3] = 0.0f;

    m[2][0] = a.x * a.z * (1.0f - c) + a.y * s;
    m[2][1] = a.y * a.z * (1.0f - c) - a.x * s;
    m[2][2] = a.z * a.z + (1.0f - a.z * a.z) * c;
    m[2][3] = 0.0f;

    m[3][0] = 0.0f;
    m[3][1] = 0.0f;
    m[3][2] = 0.0f;
    m[3][3] = 1.0f;

    return Mat44(&m[0][0]);
}


inline Mat44 RotationMatrix(Quat q)
{
    Matrix33 rotation(q);

    Matrix44 m;
    m.SetAxis(0, rotation.cols[0]);
    m.SetAxis(1, rotation.cols[1]);
    m.SetAxis(2, rotation.cols[2]);
    m.SetTranslation(Point3(0.0f));

    return m;
}

And here's how I apply the Euler rotation vector:

obj->Transform(RotationMatrix(op.rotate.x, Vec3(1.0f, 0.0f, 0.0f)));
obj->Transform(RotationMatrix(op.rotate.y, Vec3(0.0f, 1.0f, 0.0f)));
obj->Transform(RotationMatrix(op.rotate.z, Vec3(0.0f, 0.0f, 1.0f)));

And I think this should be how Transform() is defined:

void Mesh::Transform(const Matrix44& m)
{
    for (uint32_t i=0; i < m_positions.size(); ++i)
    {
        m_positions[i] = m*m_positions[i];
        m_normals[i] = m*m_normals[i];
    }
}
$\endgroup$
  • $\begingroup$ Related $\endgroup$ – batFINGER Nov 6 '18 at 14:22
  • $\begingroup$ @batFINGER Could you please explain more? The connection is not immediate to me ... $\endgroup$ – Amir Nov 6 '18 at 14:28
  • $\begingroup$ I don't have Flex to test. The conversion matrix converts from one coordinate system to another using up and forward of source and destination. If you have correct conversion, will have model facing forward as desired in each software. The rotation part of transform matrix is sorted for you. Flex may use a pitch roll yaw rotationnote here could be x-y-x order of rot. $\endgroup$ – batFINGER Nov 7 '18 at 10:56
  • $\begingroup$ @batFINGER I eventually changed the rotation matrix to the following: 1st row --> [1.0, 0, 0], second row --> [0, 0, -1.0], third row --> [0, 1.0, 0] and everything works perfect. So in practice I changed obj->Transform(RotationMatrix(op.rotate.y, Vec3(0.0f, 1.0f, 0.0f))); to obj->Transform(RotationMatrix(op.rotate.y, Vec3(0.0f, 0.0f, -1.0f))); and obj->Transform(RotationMatrix(op.rotate.z, Vec3(0.0f, 0.0f, 1.0f))); to obj->Transform(RotationMatrix(op.rotate.z, Vec3(0.0f, 1.0f, 0.0f))); $\endgroup$ – Amir Nov 7 '18 at 20:41
  • $\begingroup$ @batFINGER However, I am going to use Quaternions in my work and I realized that I should do the same for Quaternions as well. I wonder, how can I get an equivalent version of the rotation matrix for Quaternions? $\endgroup$ – Amir Nov 8 '18 at 2:14
2
$\begingroup$

Some software use left-handed coordinate system instead of right-handed. Blender instead uses a right-handed coordinate system. (Look here for more info)

usually left-handed coordinate systems use Y as up axis but in blender the Z axis is used for up axis. so you need a rotation for converting previous up axis to new up axis.

Your problem rises either because Flex's coordinate system is left-handed or its up axis is Y or X.

$\endgroup$
  • $\begingroup$ Sorry I'm not able to follow clearly. What is the solution to fix the issue? $\endgroup$ – Amir Nov 6 '18 at 13:08
  • $\begingroup$ the rotation maps the up axis to blender's up axis:_Z_ . the key is that once you find the rotation of one object in conversion, you can apply that to the whole objects and animations ( you can create a parent for all of your objects and rotate the parent) $\endgroup$ – MohammadHossein Jamshidi Nov 6 '18 at 13:17
  • $\begingroup$ Sorry I'm not very good at rotation stuff. Do you mean that I should do a lot of trial and error to fimd the right way of rotating the objects? Can you post a more through answer and explain how you would go about doing this? $\endgroup$ – Amir Nov 6 '18 at 13:41
  • $\begingroup$ Sorry I'm not very good at rotation stuff. Just note that I am exporting my meshes with axis_forward='-Z', axis_up='Y' and importing them with the same settings. Do you mean that I should do a lot of trial and error to find the right way of rotating the objects? You say "you need a rotation for converting previous up axis to new up axis". You also say: "the key is that once you find the rotation of one object in conversion". What do these mean? How can I get this rotation? Can you update your answer and post more details? $\endgroup$ – Amir Nov 7 '18 at 3:29
  • $\begingroup$ I updated my question and gave more explanations of what I do at the beginning and what my goal is. I also added more figures. Could you please read it over once more and see if you can think of a more clear solution to my problem? $\endgroup$ – Amir Nov 7 '18 at 4:11

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.