Hi, I have a question about skinning a rigged mesh. In the draw call, the skeleton transforms are given in an array of matrices. How can Monogame know which matrix applies to which bone?
I have a horrible feeling that every bone in the skeleton must be included even those that are not being animated, is this correct?
Bones (matrices) are referenced by index, so all bones must be passed when rendering the mesh, even if they aren’t changing.
My model has 166 bones in total and 5 sub meshes, each sub mesh has a list of bones (Vertex Groups) that affect it, each group on its own is less than the 72 bone limit.
If each mesh needs just the bones in that vertex group I can pass each mesh a separate list and all is fine. If however each mesh expects a list of every single bone in the whole model, then that would seem to be a major limitation of monogame. If so, would a custom skinned shader fix this or is it part of monogame that means I’m stuck with simple skeletons?
The limit for dx9 is 256 vertex shader constants, so it should work either way, right? (Much more for dx11)
Work either way? No because if I have to pass all 166 bones that is more than MonoGames upper limit of 72. If I can’t pass only the bones needed for each mesh part I will have to write a custom shader.
I wonder why MG has a limit as low as this when most game engines have 256 because of vertex shader limit you mentioned.
If each submesh has a list of bones, and the bone indices in the vertices in that submesh are relative to that list of bones, then you only need to send that submesh’s matrices (bones) when rendering that submesh.
I’m not a modeler but I believe the model actually has the skeleton defined separately from the individual mesh nodes. The vertex groups under each mesh are probably just for grouping areas while modeling or weight painting. It appears that each mesh expects the full skeleton, maybe this is a bug when importing collada, should each mesh have a subset of bones taken from the vertex group data? I know most people here use FBX so maybe collada is over looked.
Collada is indeed not used much, even in the game industry generally. I’m not a modeler either, so I’m not 100% certain of the correct setup.
Ok, this is what i have found out and its not looking like its going to be easy for me to fix.
My model was intentionally created using separate mesh for head, upper body and lower body etc. This was so each part could be passed only the bones relevant to that part of the model. The whole model has 166 bones but because each mesh has less than 72 it should work.
Assimp loads the model and reads the bones from all 5 submesh correctly and as separate lists. MonoGame import code lumps them all together in a single list stored in the Model class. Now there is no way to know which bones go with which submesh, shouldn’t ModelMesh class also have a list of bones that are specific to that mesh?
That could certainly be done in a different Model class. It’s an implementation detail. Our Model class is a re-implementation of XNA’s Model class which had one list of bones for the model. The XNA Model class was intended to be used for simple models, and back when it was created 72 bones was more than enough. Anything more complex than that should have its own model class and custom processor in the content pipeline that implements exactly what the developer wants. In your case, this would be a separate bone list per mesh.
Rigged collada mesh get converted with weights and blend indices based on the merged bone list so using a subset is not possible. Also the extra data written to Model.tag which the sample reads as ModelExtra is not created for collada files. This is I assume because although they are rigged they do not contain any actual animation data.
@KonajuGames can you point me to the place in the content pipeline code that determines if this extra data is written as I am unable to find it. I can see in the ModelWriter that it writes the ModelContent.Tag at the end, but there appears to be no place in the code that assign a value to the tag.
The reason I need to use a model with so many bones is that I want to support facial morphs, hand gestures and attaching rigged mesh models from a game inventory with more options that a standard humanoid rig with out needing a new model for every option. The skeleton includes wings, hind legs, and tail bones for example.
I have decided not to write a custom content reader because it would just be a clone of the existing one with a few minor changes and i would then have to keep an eye on changes to the original import code. I have decided to take the data from monogame and do some post processing to rebuild the blend indices to the subsets of bones. I just need the original list of bones in the skeleton that should be part of the model tag data.
Another odd thing i have noticed is the SkinnedEffect for each part of the collada model is the same instance. When i change the texture on one part, all parts then show that texture. With the FBX sample, each part retains its texture.
Any pointers would be greatly appreciated as right now progress is slow and frustrating. Thanks