I'm working on vertex skinning by loading animation data from compiled model objects(.CMO) that visual studio generates from .FBX models.
here is what i have:
This is totaly wrong but i dont know why!
here is my code for rendering animations:
for (auto it = model->meshes.cbegin(); it != model->meshes.cend(); ++it)
{
auto mesh = it->get();
if (mesh->enableSkinning)
{
for (int i = 0;i < mesh->bones.size();i++)
{
mesh->armatureBuffer.Const.Bones[i]= mesh->bones[i]->LocalTransform;
}
//Animate
Keyframe * lastKeyForBones =
new Keyframe[mesh->bones.size()];
bool *lerpedBones = new bool[mesh->bones.size()];
for (int i = 0;i < mesh->bones.size();i++)
{
//lerpedBones[i] = false;
}
for (int i = 0;i < mesh->animationClips[1]->Keys;i++)
{
Keyframe * frame =
mesh->animationClips[1]->keyFrames[i];
if (elapsedTime >= frame->Time)
{
lastKeyForBones
[frame->BoneIndex]
= *frame;
mesh->armatureBuffer.Const.Bones
[frame->BoneIndex] =
frame->Transform;
}
else
{
if (!lerpedBones
[frame->BoneIndex])
{
Keyframe * prevFrame;
if (&lastKeyForBones
[frame->BoneIndex] != nullptr)
{
prevFrame =
&lastKeyForBones[frame->BoneIndex];
}
else
continue;
lerpedBones[frame->BoneIndex] = true;
float lenght = frame->Time
- prevFrame->Time;
float timeDiff = elapsedTime - prevFrame->Time;
float amount = timeDiff / lenght;
DirectX::XMVECTOR t1, t2, s1, s2, r1, r2;
DirectX::XMMatrixDecompose(
&s1, &r1, &t1,
DirectX::XMLoadFloat4x4
(&prevFrame->Transform));
DirectX::XMMatrixDecompose(
&s2, &r2, &t2,
DirectX::XMLoadFloat4x4
(&frame->Transform));
DirectX::XMVECTOR lerpedScale =
DirectX::XMVectorLerp(s1, s2, amount);
DirectX::XMVECTOR lerpedtranslation =
DirectX::XMVectorLerp(t1, t2, amount);
DirectX::XMVECTOR lerpedrotation =
DirectX::XMQuaternionSlerp(r1, r2, amount);
DirectX::XMStoreFloat4x4
(&mesh->armatureBuffer.Const.Bones
[frame->BoneIndex],
DirectX::XMMatrixScaling(
lerpedScale.m128_f32[0],
lerpedScale.m128_f32[1],
lerpedScale.m128_f32[2])
*
DirectX::XMMatrixRotationQuaternion(
lerpedrotation)
*
DirectX::XMMatrixTranslation(
lerpedtranslation.m128_f32[0]
, lerpedtranslation.m128_f32[1],
lerpedtranslation.m128_f32[2]));
}
}
}
OutputDebugStringA("\n");
OutputDebugStringA(std::to_string(elapsedTime).c_str());
for (int i = 0;i < mesh->bones.size();i++)
{
if (mesh->bones[i]->ParentIndex>-1)
{
DirectX::XMFLOAT4X4 parentTransform
= mesh->bones[mesh->bones[i]->ParentIndex]->LocalTransform;
DirectX::XMStoreFloat4x4(
&mesh->armatureBuffer.Const.Bones[i],
DirectX::XMMatrixMultiply(
DirectX::XMLoadFloat4x4(&mesh->armatureBuffer.Const.Bones[i])
, DirectX::XMLoadFloat4x4(&parentTransform)));
}
}
for (int i = 0;i < mesh->bones.size();i++)
{
DirectX::XMStoreFloat4x4(&mesh->armatureBuffer.Const.Bones[i],
DirectX::XMMatrixTranspose(
DirectX::XMMatrixMultiply(
DirectX::XMLoadFloat4x4(&mesh->bones[i]->InvBindPos)
, DirectX::XMLoadFloat4x4(&mesh->armatureBuffer.Const.Bones[i]))));
}
if (elapsedTime > mesh->animationClips[1]->end)
{
elapsedTime = 0.0f;
}
}
}
elapsedTime += timer.GetElapsedSeconds();
the animation plays but the model seems messing up! i think there is something wrong with matrix constructions. also i adapt this code from Direct3D rendering cook book that its written in C#!
Also model render correctly when i render it without skinning.
also here is vertex shade code:
PS_IN_MESH OUT = (PS_IN_MESH)0;
float4x3 skinning = 0;
[unroll]
for (int i = 0; i <2 ; i++)
{
skinning += Bones[IN.Indices[i]] * IN.Weights[i];
}
float3 skinnedPos = mul(IN.PosL, skinning);
OUT.position = mul(float4(skinnedPos,1.0f), WVP);
OUT.positionVS = mul((IN.PosL), World).xyz;
OUT.texCoord = IN.UV;
//OUT.tangentVS = mul(IN.Tangent, World).xyz;
OUT.normalVS = mul(IN.Normal, World).xyz;
float4 posCurrent = OUT.position;
float4 posLast= mul((IN.PosL), WVPLast);
//posCurrent /= posCurrent.w;
//posLast /= posLast.w;
float2 velocity = posCurrent - posLast;
velocity /= 2.0f;
OUT.velocity = velocity;
OUT.binormalVS = cross(OUT.tangentVS, OUT.normalVS);
OUT.shadowPosH = mul((IN.PosL), World);
OUT.shadowPosH = mul(OUT.shadowPosH, lightViewMatrix);
OUT.shadowPosH = mul(OUT.shadowPosH, lightProjectionMatrix);
//Skinning
//if (IN.Weights.x != 0)
return OUT;
Any one have idea what is wrong with it?
if you want more information tell me :)