Comments and answers for "How to scale Mesh.bindPose correctly"
http://answers.unity.com/questions/1243954/how-to-scale-meshbindpose-correctly.html
The latest comments and answers for the question "How to scale Mesh.bindPose correctly"Comment by SoxwareInteractive on SoxwareInteractive's comment
http://answers.unity.com/comments/1246273/view.html
@Bunny83: Thanks for the hint with the mesh. The scaling is correct when using the skinnedMeshRenderer.localToWorldMatrix, but the rotation and the position is wrong. Further investigations showed me that the "armature" transform still plays a roll. So I'm using now:
Matrix4x4 invertBindPose = armatureTransform.localToWorldMatrix * skinnedMeshRenderer.localToWorldMatrix * bindPose.inverse;
With this formular, the rotation and the scaling seems to be correct but the position is still wrong (all bones get a world space offset). I don't understand how the SkinnedMeshRenderer calculates it's end result based on the different matrices (what is multiplied in which order)...
Also, if you change the transform parameters of the SkinnedMeshRenderer in the inspector nothing happens. So those values don't seem to be used by the "SkinnedMeshRenderer" directly???Tue, 20 Sep 2016 19:30:20 GMTSoxwareInteractiveComment by Bunny83 on Bunny83's comment
http://answers.unity.com/comments/1244642/view.html
Ahh, i got your problem now ^^. I'll edit my answer...Fri, 16 Sep 2016 16:32:05 GMTBunny83Comment by SoxwareInteractive on SoxwareInteractive's answer
http://answers.unity.com/comments/1244575/view.html
Thanks for your answer @Bunny83. Yes you are right 1/40 won't work. In the real code the factor is calculated and not hard coded as in the sample above so this was a mistake when I've written the question. Sorry for that...
My goal is to reset a model back to it's initial bind pose position at runtime. So I'm extracting the position, rotation and scale out of the resulting matrix and assign those to the corresponding bone transform. This works great with some models but not with all because of the mentioned scaling problem.
Here is my code that works resetting the bones of most of my models (but has the scaling issue):
Matrix4x4 bindPose = skinnedRenderer.sharedMesh.bindposes[boneIndex];
// armatureTransform is the transform named "Armature" which is the parent transform of all bones
// everytime you drag and drop an imported model into the scene.
Matrix4x4 invertBindPose = armatureTransform.localToWorldMatrix * bindPose.inverse;
boneTransform.position = matrix.GetColumn(3);
boneTransform.rotation = Quaternion.LookRotation(matrix.GetColumn(2), matrix.GetColumn(1));
boneTransform.localScale = new Vector3( matrix.GetColumn(0).magnitude,
matrix.GetColumn(1).magnitude,
matrix.GetColumn(2).magnitude);
Trying to reset this [free spider model][1] from the asset store for example doesn't work with this code as bindPose.inverse has a scale of 40 for this model (I checked the magnitudes of column 0 - 2 with the debugger --> scale = 40) and my other models that work have 1. So I wanted to know how to scale down the bindPose.inverse to also have a scale of 1.
[1]: https://www.assetstore.unity3d.com/en/#!/content/11869Fri, 16 Sep 2016 14:10:00 GMTSoxwareInteractiveAnswer by Bunny83
http://answers.unity.com/answers/1244321/view.html
Your calculation doesn't make much sense ^^. The bindpose matrix is a matrix that should transform a point from the mesh's local space into the localspace of the bone. Once in that space Unity's animation system would then transform the position from the bones local space into world space using the current localToWorld matrix of the bone.
Next thing is this won't work:
Vector3 scale = new Vector3(1/40, 1/40, 1/40);
this will give you a (0, 0, 0) vector because 1 and 40 are both integer values.
Matrix4x4 normalizeScale = Matrix4x4.Scale(Vector3.one / 40f);
Since it's the bones local space which is wrongly scaled you want the scaling to happen after all the other transformations. So you have to put your matrix infront of your original bindpose:
bindPose = normalizeScale * bindPose;
Next thing is it'S not clear what you do with your "result". Keep in mind that `sharedMesh.bindposes` is a property, so you can't assign seperate matrices to that array. You have to use a temp array, modify your matrices and finally assign the whole array back to sharedMesh.bindposes.
Final Note: Messing with bindposes of imported models isn't a good idea. It will most likely mess up all animations you have. If there is an issue in the model itself, it should be fixed in the modelling tool.
If you just want to change the scale factor of the model, check out the model inspector of the imported model. You can specify a scale factor there. It will reimport the model and will guarantee that everything will still work (as long as the model doesn't have an error already ^^).
***edit***
Ahh, thanks to your comment i think we can solve that problem ^^. Your mistake is that you used the Amature transform. You have to use the mesh transform.
![Spider][1]
The mesh is actually rendered by the SkinnedMeshRenderer. So the transform of the object with the SkinnedMeshRenderer is the one you have to use when you revert the bindpose.
So the original bindpose matrix converts the local vertex coordinates from the **local mesh space** into the local space of the bone. When you invert the matrix you convert from bone to local mesh space. So then using the localToWorld matrix of the SkinnedMeshRenderer you would get back the bone matrix.
[1]: /storage/temp/78363-spider-mesh-scale.pngThu, 15 Sep 2016 21:35:27 GMTBunny83Answer by theANMATOR2b
http://answers.unity.com/answers/1244100/view.html
This forum post by hippocoder seems to be relevant.
http://forum.unity3d.com/threads/assetpostprocessor-skinned-mesh-renderer-bone-index-reorder-solved.401872/#post-2787571Thu, 15 Sep 2016 12:54:48 GMTtheANMATOR2b