It appears that when GLTFLoader creates SkinnedMesh's, and binds them, the 'matrixWorld' upon binding is always identity:
https://github.com/mrdoob/three.js/blob/dev/examples/js/loaders/GLTFLoader.js#L2823
From debugging (r89), it seems that mesh.parent == null, and thus mesh.matrixWorld is identity (and will still be even after you call updateMatrixWorld).
This results in animations being incorrect when the original mesh transform is not identity. SkinnedMesh.bindMatrix ends up being identity, resulting in incorrect skinning math.
We have implemented a successful work around by calling updateMatrixWorld and then bind on our own. But the loader should do this by default.
Related: https://github.com/KhronosGroup/glTF/pull/1195
Implementation Note: Client implementations should apply only the transform of the skeleton root node to the skinned mesh while ignoring the transform of the skinned mesh node.
OK...I see. I guess we should take the advice of the other implementation note then:
"Implementation Note: The matrix defining how to pose the skin's geometry for use with the joints ("Bind Shape Matrix") should be premultiplied to mesh data or to Inverse Bind Matrices."
Namely, exporting inverse bind matrix as (boneFromWorld) * (worldFromModel).
We'll give this a shot. I'm curious what the pros/cons of this, but it seems Unity does the same thing.
We tried this and it works, so I'll close this. Thanks!
Most helpful comment
We tried this and it works, so I'll close this. Thanks!