Sign in to follow this  

Skinned Model Screwy

This topic is 1958 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

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:
[img]http://i1223.photobucket.com/albums/dd517/DrakkenKuchen/SteveRender.jpg[/img]
[img]http://i1223.photobucket.com/albums/dd517/DrakkenKuchen/Deformity.png[/img]

My Custom Shader:

[code]
//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[i]] * input.Weights[i];
}
input.Position = mul(input.Position, skinning);
}
[/code]

And my Steve model is [url="https://dl.dropbox.com/u/10337688/Steve.blend"]here[/url] 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. Edited by Drakken255

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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:

[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();
}
[/code]

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

[img]http://i1223.photobucket.com/albums/dd517/DrakkenKuchen/Deformity2.png[/img]

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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:

[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;

[/code]

EDIT: On a side note, when I loaded Steve in the XNA Model Viewer [url="http://modelviewer.codeplex.com/"]at Codeplex[/url] It looked perfectly fine until I pressed the Animation Play button. Steve then proceeded to break once again... Edited by Drakken255

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites

This topic is 1958 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this