Hi guys
I am trying to implement skinning,
here is the source code
http://18ejdq.blu.livefilestore.com/y1p … oad&psid=1
or
http://cid-2f2a55eaad2be759.office.live … ollada.rar
the key file is AnimationMesh.cpp
below I will paste the code how I implement Skinning,the problem is I can’t get right result as I expected.
the skinning method I was refer to Nvidia DirectX SDK 10.5- Smoke.
the problem is skinning result is wrong…
I am sure I get right skinning weights and influnce joints for each vertex.
the key file is
ColladaControllers.cpp
void sController::sSkin::GenerateWeightsAndBonesData()
if someone teach how I make it right,and it works I would like to share full source code for everyone
==============================================================
below is how I implement skinning
Vector3 cAnimationMesh::GetSkinWorldPosBySkinningData(Vector3 e_vPos,float*e_pfWeihts,char*e_pcInflunceBoneIndex,cMatrix44*e_pBoneMatrices)
{
Vector3 l_vFinalPos = Vector3::Zero;
#ifdef _DEBUG
float l_f[4] = {e_pfWeihts[0],e_pfWeihts[1],e_pfWeihts[2],e_pfWeihts[3]};
if( l_f[0]+l_f[1]+l_f[2]+l_f[3]<=0.9f )
{
assert(0);
}
char l_InflunceJointIndex[4] = {e_pcInflunceBoneIndex[0],e_pcInflunceBoneIndex[1],e_pcInflunceBoneIndex[2],e_pcInflunceBoneIndex[3]};
#endif
//if( e_pcInflunceBoneIndex[0] >1 )
// return Vector3(-10,10,10);
cMatrix44 l_mat = cMatrix44::Identity;
//if(e_pfWeihts[0]>MIN_VALID_WEIGHT)
if( e_pcInflunceBoneIndex[0] != -1 )
{
l_vFinalPos += e_pBoneMatrices[e_pcInflunceBoneIndex[0]].TransformVector(e_vPos)*e_pfWeihts[0];
}
//if(e_pfWeihts[1]>MIN_VALID_WEIGHT)
if( e_pcInflunceBoneIndex[1] != -1 )
{
l_vFinalPos += e_pBoneMatrices[e_pcInflunceBoneIndex[1]].TransformVector(e_vPos)*e_pfWeihts[1];
}
//if(e_pfWeihts[2]>MIN_VALID_WEIGHT)
if( e_pcInflunceBoneIndex[2] != -1 )
{
l_vFinalPos += e_pBoneMatrices[e_pcInflunceBoneIndex[2]].TransformVector(e_vPos)*e_pfWeihts[2];
}
//if(e_pfWeihts[3]>MIN_VALID_WEIGHT)
if( e_pcInflunceBoneIndex[3] != -1 )
{
l_vFinalPos += e_pBoneMatrices[e_pcInflunceBoneIndex[3]].TransformVector(e_vPos)*e_pfWeihts[3];
}
return l_vFinalPos;
}
int l_iBoneSize = this->m_AllBoneVector.GetNum();
cBone**l_ppBone = &(*m_AllBoneVector.GetList())[0];
for(int i=0;i<l_iBoneSize;++i)
{
//boneMatrix = boneIt->node->worldXForm * boneIt->invBindPose * instIt->meshBindPose;
//invert multiply
cMatrix44 l_WorldTransform = l_ppBone[i]->GetWorldTransform();
//cMatrix44 l_WorldTransform;// = this->m_matBindPose * l_ppBone[i]->GetInvBindPose() * l_ppBone[i]->GetWorldTransform();
cMatrix44 aaa = l_ppBone[i]->GetInvBindPose();
//l_WorldTransform = l_ppBone[i]->GetWorldTransform() * l_ppBone[i]->GetInvBindPose().Inverted() * this->m_matBindPose;
//m_pAllBonesMatrixForSkinned[i] = l_WorldTransform;
m_pAllBonesMatrixForSkinned[i] = aaa*l_WorldTransform;
//m_pShaderParameter->GetBonesMatrixVariable()->SetMatrixArray((float*)&l_WorldTransform2,i,1);
}
//OutputDebugString(L"FUCK!!!
");
//OutputDebugString(L"glGet GL_ARRAY_BUFFER_BINDING,GL_ELEMENT_ARRAY_BUFFER_BINDING,before get buffer data u have to glBindBuffer(GL_ARRAY_BUFFER, l_uiBufferID);");
//here should get position data by glBindBuffer(GL_ARRAY_BUFFER, l_uiBufferID);.
Vector3 *l_pvPos = 0;
if( !m_pVBOBuffer )
l_pvPos = (Vector3*)this->m_ppfVerticesBuffer[FVF_POS];
else
l_pvPos = (Vector3*)this->m_pVBOBuffer->GetData(POSITION_LOCATION);
float* l_fWeight = this->m_ppfVerticesBuffer[FVF_SKINNING_WEIGHT];
char* l_pcInflunceJoints = (char*)m_ppfVerticesBuffer[FVF_SKINNING_BONE_INDEX];//endusr the size as expected
cMatrix44 l_mat;
for( UINT i=0;i<m_uiVertexBufferCount;++i )
{
Vector3 l_vPos = GetSkinWorldPosBySkinningData(l_pvPos[i],&l_fWeight[i*4],&l_pcInflunceJoints[i*4],m_pAllBonesMatrixForSkinned);
int l_iTest = l_pcInflunceJoints[i*4];
if( l_iTest != 4 )
{
int a=0;
}
m_pvVertexBuferForSkinned[i*3] = l_vPos.x;
m_pvVertexBuferForSkinned[i*3+1] = l_vPos.y;
m_pvVertexBuferForSkinned[i*3+2] = l_vPos.z;
//m_pvVertexBuferForSkinned[i*3] = l_pvPos[i].x;
//m_pvVertexBuferForSkinned[i*3+1] = l_pvPos[i].y;
//m_pvVertexBuferForSkinned[i*3+2] = l_pvPos[i].z;
}
and how I update animation
void cAnimationMesh::UpdateNodes(float e_fTimeValue)
{
assert((e_fTimeValue>=m_fMinKeyTime) && (e_fTimeValue <=m_fMaxKeyTime));
if(m_fLastNodesUpdateTime == e_fTimeValue)
return;
int l_iNum = this->m_AllBoneVector.GetNum();
for(int i=0;i<l_iNum;++i)
{
if(!m_AllBoneVector[i]->GetParent())
UpdateNode(m_AllBoneVector[i],e_fTimeValue);
}
m_fLastNodesUpdateTime = e_fTimeValue;
}
//========================================================
//
//========================================================
void cAnimationMesh::UpdateNode(cBone*e_pBone,float e_fTime)
{
//assert(0&&"only need to update children");
e_pBone->EvaluateLocalXForm(e_fTime);
if (e_pBone->GetFirstChild() != NULL)
{
UpdateNode( (cBone*)e_pBone->GetFirstChild(),e_fTime);
}
if( e_pBone->GetNextSibling() != NULL)
{
UpdateNode( (cBone*)e_pBone->GetNextSibling(),e_fTime);
}
//if( e_pBone->GetParent() )
// e_pBone->SetWorldTransform(e_pBone->GetParent()->GetWorldTransform()*e_pBone->GetLocalTransform());
//else
// e_pBone->SetWorldTransform(e_pBone->GetLocalTransform());
}
//========================================================
//
//========================================================
void cAnimationMesh::Update(float elapsedTime)
{
float newTime(m_fCurrentTime);
// Handle time advance based on animation playback options
if((m_fCurrentTime+elapsedTime) > m_fEndTime)
{
float endMinusStart = m_fEndTime-m_fStartTime;
if( endMinusStart > 0.001)
{
//switch(m_animEndHandling)
//{
//case LOOP:
// {
float overTime = (m_fCurrentTime + elapsedTime - m_fEndTime);
newTime = m_fStartTime + fmod(overTime, endMinusStart);
// }
// break;
//case BLOCK:
//default:
// newTime = m_endTime;
// break;
//}
}
else
{
newTime = m_fCurrentTime;
}
}
else
{
newTime = m_fCurrentTime + elapsedTime;
};
m_fCurrentTime = newTime;
//if(m_fCurrentTime>m_fEndTime)
// m_fCurrentTime -= m_fEndTime;
SetCurrentAnimationTime(m_fCurrentTime);
}
//========================================================
//
//========================================================
void cAnimationMesh::SetCurrentAnimationTime(float e_fCurrentTime)
{
this->m_fCurrentTime = e_fCurrentTime;
assert(this->m_fMinKeyTime <= this->m_fMaxKeyTime);
float l_fUpdateTime = 0;
if(m_fCurrentTime > m_fMaxKeyTime)
UpdateNode(m_pMainRootBone,m_fMaxKeyTime);
//l_fUpdateTime = m_fMaxKeyTime;
else if(m_fCurrentTime< m_fMinKeyTime)
UpdateNode(m_pMainRootBone,m_fMinKeyTime);
//l_fUpdateTime = m_fMinKeyTime;
else
UpdateNode(m_pMainRootBone,m_fCurrentTime);
l_fUpdateTime = m_fCurrentTime;
//for(int i=0;i<this->m_AllBoneVector.GetNum();++i)
//{
// if(m_AllBoneVector[i]->GetParent() == NULL)
// m_AllBoneVector[i]->EvaluateLocalXForm(l_fUpdateTime);
//}
}