- Home /
Help needed with combining skinned mesh bindposes
(Originally posted as a forum thread here)
I'm trying to merge together several skinned meshes into a single SkinnedMeshRenderer, for performance reasons. I can do the basic concatenation of the mesh OK, but some of the parts reference the same bones, and so concatenation means those bones are getting referenced more than once - it makes for 80 bones total, rather than 60. So I want to try and patch up the mesh when I combine it so that it shares bones correctly.
Question 1: Is this actually possible?
What I'm finding is that I need to patch up the vertex positions, because the new mesh has different bindposes to the old one.
Question 2: Does it actually make sense that this would be the case?
I'm still fuzzy on exactly what the bindposes are so I'm not entirely sure what determines whether they're the same or different. I have this vague understanding that they map from mesh-local space to bone-local space. The runtime then maps from bone-local space to world space. So, if I want to use different bindpose matrices, I should only need to alter the mesh-local vertex positions so that they end up in the same bone-local space positions.
So I thought I had to do this:
var boneLocalPosition = oldBindPoses[bone].MultiplyPoint3x4(vertex);
var newVertex = newBindPoses[bone].inverse.MultiplyPoint3x4(boneLocalPosition);
but this produces something that, while roughly correct (no horrendous distortion) doesn't have the parts in quite the right places, and it begins to distort horribly when the character starts animating.
Question 3: Why didn't this work?
If you're with me this far, then hopefully you can answer the most important question:
Question 4: How do I patch the vertices in my skinned meshes to account for new bindpose matrices, in a way that is visually identical to running the meshes through separate SkinnedMeshRenderers on the same skeleton?
Oh btw, you should crosslink this question in your forums post as well ;)
Your solution works for me, thanks. $$anonymous$$aybe your problem in other like couple of bones affect one vertex, so in multiply you should take bone weight in account
Answer by Bunny83 · May 01, 2012 at 04:12 PM
This is almost correct, however why does the bones have a new bind pose? That doesn't make much sense if the skeleton is the same. As you already guessed, the bindposes virtually parent a vertex to a bone by transfering the vertex position into the bones local space.
That's why it's called bind pose. The skeleton hierarchy and the vertices are completely seperate in the beginning. Now you place the skeleton into the mesh so the bones are relatively to your mesh at the correct position. At this point you take a snapshot of the bones position / rotation / scale as a reference. Together with the boneWeights you've bound the vertices to the skeleton in the current position.
Usually if you used the same skeleton, the bind poses should be the same. If you use two completely different but similar skeletons it's almost impossible to merge them. If both models were rigged correctly to different but similar skeletons, the way you've done the convertion is correct. Are you sure you match up the same bones? if they are different skeletons the bone-order doesn't have to be the same. You might want to use the bone names to reference them. If the order is different you have to fix the boneWeights of the vertices as well (the bone indices).
Can you post a screenshot of the model(s)? I can't imagine two models that can be merged into one except a character and a seperate cloth mesh maybe ;)
The skeletons are, I think, almost the same - certainly the names and parent/child relationships are the same - but I think some of the position/rotation/scale values may be different or something. The meshes in question are bodies and heads. At the moment I've just got separate Skinned$$anonymous$$eshRenderer components for each mesh part, referencing the same bones, and it all comes out correctly so the rigs are certainly similar enough for that to work.
I'm pretty certain that I'm matching the bones up correctly; I am indeed using bone names (or, well, paths relative to the root).
So the bindPose matrices are the localToWorldTransform values from those 'rest pose' transforms, effectively? Or are they worldToLocalTransform?
$$anonymous$$esh vertices are in the local space of the meshrenderer. The bindposes matrix have to transform a point into the bones local space. So usually, like in this example you create a matrix that transforms a vertex from mesh-local space into worldspace (the renderers localToWorld matrix) and then from world space into the bones localspace(the bones worldToLocal matrix). Due to matrix multiplication order it has to be
bones.worldToLocal * renderer.localToWorld
The multiplication happens from right to left.
I'm a bit confused how those two models have been created. Usually when you plan something like that you use the same rig for all submodels.
Actually when you put both meshes together and they have almost the same rig the bindposes should also be almost the same. If not i don't see any logical connection that tells you how you should put two different meshes together without re-rigging one of them. I'm not an artist so i can't really give you an advise on such an issue.
@Bunny83 - I'm having a total nightmare with this - trying to merge skinned meshes all looks fine if I don't set the bindposes, but then it doesn't animate (though moving the rig (not rotating it) moves the model so I guess I've got the bone weighting right).
If I set the bind poses - I think following your advice/the example - my mesh is nowhere to be seen!
Sorry for the late reply. I've never done this myself, so i can't tell you what's wrong. $$anonymous$$aybe it makes a difference if you use "transform.localToWorld" ins$$anonymous$$d of "renderer.localToWorld". They should actually be the same, but if you read the docs on renderer.localToWorld there must be a difference.
Hey no problem - actually the reason the damn thing wouldn't animate is because I'd manage to put the animation on the wrong element in the hierarchy! So in summary, I've no idea what is happening with the bindposes, but apparently I don't need to set them in my case... Go figure.
Anyway it's working now -> http://youtu.be/ziY_EaichbE
Your answer
Follow this Question
Related Questions
Why is the bindposes matrix not immediately equal to the bone representation? 0 Answers
Ripped model requires skinned mesh 1 Answer
Skinned models look different when building the game to both Oculus&HTC Vive 0 Answers
how to combine 2 quaternion components? 2 Answers
Combining two transparent shaders with diffuse lighting 0 Answers