libgdx / fbx-conv

Command line utility using the FBX SDK to convert FBX/Collada/Obj files to a custom text/binary format for static, keyframed and skinned meshes.
Apache License 2.0
447 stars 116 forks source link

Unable to use z-up #102

Open AdrianNostromo opened 7 years ago

AdrianNostromo commented 7 years ago

Hi, i'm using a z-up cordinate system in a libgdx game. I am following this article https://github.com/libgdx/libgdx/wiki/Importing-Blender-models-in-LibGDX to import my 3d model from blender. I set the fbx exporter to y-up to ignore fbx-conv rotation, but it actually does nothing. I tried exporting the model from blender with different up axis but after conversion, the model always looks the same (y-up).

drenghel commented 7 years ago

For what it's worth, I'm also wondering why it doesnt look like my export options in Blender (forward and up) are without effect..

ttencate commented 6 years ago

I was also bitten by this. I suspect that the FBX exporter in Blender has changed since the wiki page was written, so it does not only store the axis system into the FBX file, but also transforms the actual geometry into that axis system. Thus, the conversion that fbx-conv applies simply undoes that, and you end up with the default coordinate system in fbx-conv (Y-up, Z-forward, right-handed) no matter what you do.

If you comment out the axis.ConvertScene(scene) line in FbxConverter.h, it is possible to get different results for different settings in Blender. For me, setting Z-up and Y-forward worked well after this change.

I don't want to keep carrying around a hacked up fbx-conv fork though, so I just added some code to rotate the model nodes after loading:

    modelData.nodes.forEach { node ->
        node.translation = node.translation ?: Vector3()
        node.rotation = node.rotation ?: Quaternion()
        // This uses the same underlying code as Node#calculateLocalTransform()
        val nodeTransform = Matrix4(node.translation, node.rotation, identityScale)

        val newNodeTransform = Matrix4(preRotation)
        newNodeTransform.mul(nodeTransform)

        newNodeTransform.getTranslation(node.translation)
        newNodeTransform.getRotation(node.rotation)
    }

It's Kotlin but I hope the idea is clear. Note that I'm not rotating node.scale, because this breaks the output. I think this is because the scale is applied before the rotation, but I haven't checked.