Skinned Model Screwy

Started by
4 comments, last by Drakken255 11 years, 8 months ago
Hello all,

I'm sure everyone is tired of my questions, but I have one more before I can really get to work on my project. For those of you who don't know, I am creating a basic XNA recreation of Minecraft. My current problem is that my "Steve" model, which is skinned with an armature using vertex groups to deform, is showing up disfigured beyond all reason. I am using a custom shader with skinning imported from the SkinnedEffect from the StockEffects example. I'm sure the effect itself works fine and that my model's groups and weights are the problem. But, to be sure, I will post both.

Pictures:
SteveRender.jpg
Deformity.png

My Custom Shader:


//VertexShader
VertexShaderOutput VertexShaderFunction(VertexShaderInput input)
{
VertexShaderOutput output;
Skin(input, NumBones);
float4x4 worldViewProj = mul(mul(World, View), Projection);
output.Position = mul(input.Position, worldViewProj);
float4 normal = mul(input.Normal, WorldInverseTranspose);
float lightIntensity = dot(normal, DiffuseLightDirection);
output.Color = saturate(DiffuseColor * DiffuseIntensity * lightIntensity);
output.Color.a = 1;
output.TextureCoordinate = input.TextureCoordinate;
return output;
}

//Skin() Method
void Skin(inout VertexShaderInput input, uniform int boneCount)
{
float4x4 skinning = 0;
[unroll]
for (int i = 0; i < boneCount; i++)
{
skinning += Bones[input.Indices] * input.Weights;
}
input.Position = mul(input.Position, skinning);
}


And my Steve model is here in .blend format. The version of Blender I use is 2.6. Pay no attention to the corner-looking piece. That's just there for size comparison when I built him. I export to .fbx with only the mesh and armature selected. No options are selected other than "Export Selected" and "Apply Modifiers". Smoothing is off, Forward is -Z Forward and Up is Y Up. Again, I think the problem is the vertex groups and wights. Everything deforms properly in Blender, but not in XNA.
Advertisement
The shader looks fine so the problem must be with the model itself. Or with how you're loading it.

1) Try to force the model into a specific pose in the shader to make sure the problem isn't due to the bone matrices. (Maybe you need to transpose them?)

2) Make sure the weights add up to 1

3) Ouput the bone indices as the vertex colour to see if they're correct.
"Spending your life waiting for the messiah to come save the world is like waiting around for the straight piece to come in Tetris...even if it comes, by that time you've accumulated a mountain of shit so high that you're fucked no matter what you do. "
Sorry, little too much for my knowledge. I tried to make sure that all vertices had only one group assigned to it. I think I messed my bones up or something. Could you please look at my model file? Also, I'll post the rendering code:


foreach (ModelMesh mesh in steve.Meshes)
{
foreach (ModelMeshPart part in mesh.MeshParts)
{
part.Effect = minecraftEffect;
}
}
foreach (ModelMesh mesh in steve.Meshes)
{
//Tried to move the LegLeft bone
//steveTransforms[13] *= Matrix.CreateRotationX(MathHelper.ToRadians(1f));

//Rotates the whole model.
//steveTransforms[mesh.ParentBone.Index] *= Matrix.CreateRotationY(MathHelper.ToRadians(1f));
foreach (Effect effect in mesh.Effects)
{
effect.Parameters["Bones"].SetValue(steveTransforms);
effect.Parameters["NumBones"].SetValue(steve.Bones.Count);
effect.Parameters["WorldInverseTranspose"].SetValue(Matrix.Transpose(Matrix.Invert(mesh.ParentBone.Transform)));
effect.Parameters["BaseTexture"].SetValue(steveTexture);
effect.Parameters["World"].SetValue(steveTransforms[mesh.ParentBone.Index]);
effect.Parameters["View"].SetValue(view);
effect.Parameters["Projection"].SetValue(projection);
}
mesh.Draw();
}


I just changed setting the parameter "Bones" to steveRelTransforms, which uses CopyBoneTransformsTo instead of CopyAbsoluteBoneTransformsTo, and I got this:

Deformity2.png
I have looked into your blend file and it seemed quiet right to me. But i didnt found some animations so I suppose you build the transform matrices at runtime. Maybe you need to change them because of the hierachical structure of the armature? So you dont pass the world transform rather than a bone transform matrix in relation to the parent bone up to the root bone. Just a thought I dont know if it applies here.
Yes, I am building the matrices at runtime. I had just thought that the bones were being translated relative to the world rather than their parent bone, but that's not the problem... I guess it's the way I'm building the transform matrices. Code:


steveTransforms = new Matrix[steve.Bones.Count];
steveRelTransforms = new Matrix[steve.Bones.Count];

//I originally used this, but it failed. Now I've been using steveRelTransforms.
steve.CopyAbsoluteBoneTransformsTo(steveTransforms);

//Atempt at transforming relative to parents.
steveRelTransforms[steve.Bones["Spine"].Index] = steve.Bones["Spine"].Transform;
steveRelTransforms[steve.Bones["Neck"].Index] *= steve.Bones["Spine"].Transform;
steveRelTransforms[steve.Bones["Head"].Index] *= steve.Bones["Head"].Transform;

steveRelTransforms[steve.Bones["ShoulderLeft"].Index] *= steve.Bones["Spine"].Transform;
steveRelTransforms[steve.Bones["ShoulderRight"].Index] *= steve.Bones["Spine"].Transform;
steveRelTransforms[steve.Bones["ArmLeft"].Index] *= steve.Bones["ShoulderLeft"].Transform;
steveRelTransforms[steve.Bones["ArmRight"].Index] *= steve.Bones["ShoulderRight"].Transform;

steveRelTransforms[steve.Bones["HipLeft"].Index] *= steve.Bones["Spine"].Transform;
steveRelTransforms[steve.Bones["HipRight"].Index] *= steve.Bones["Spine"].Transform;
steveRelTransforms[steve.Bones["LegLeft"].Index] *= steve.Bones["HipLeft"].Transform;
steveRelTransforms[steve.Bones["LegRight"].Index] *= steve.Bones["HipRight"].Transform;



EDIT: On a side note, when I loaded Steve in the XNA Model Viewer at Codeplex It looked perfectly fine until I pressed the Animation Play button. Steve then proceeded to break once again...
I may have fixed the problem... At first, while exporting my Block model, I had thought that drawing with depth was acting screwy because of two options in Blender's FBX Export script: XNA Rotate Hack, and XNA Strict Options. Thus, I did not select these all the times I exported Steve. Re-enabling these seems to have solved the problem. Of course, I will still have to figure out rotation thanks to the enabling of these options disabling rotation from Blender axes to XNA axes.

This topic is closed to new replies.

Advertisement