skinning implement problem

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 :slight_smile:

==============================================================
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);
	//}
}

sorry…after I clicked submit…I saw a choose file button…
so I upload the file :smiley:

it seems no anybody here :(,but I still keep doing my project,now I got a new problem…
I have render skeleton correctly,but the mesh is wrong,the attach images show the result, it looks like setup wrong influence joints or somethings…Could anybody just take a glance and tell me what possible wrong it is.

thanks for all

Sorry that no one can take the time to debug your code for you. There is plenty of existing COLLADA skinning and animation code in the open source community that you can examine to learn where your code is going wrong.

Hi marcus
thanks for replay,I know it’s hard to ask someone who would like to spend lots time to debug for me,I will finish it one day,and write a tutorial for all guys who need use it.

All the open source tutorial are using different way to implement Collada,some of them choice third party library to get all Collada data(FCollada),or Skinning demo in XNA or ColladaDOM,the XNA demo seems simple enough to me, but it still is not simple enough to the people who first time to learn Collada,if you got time please go check my data structure,it is quite stupid but easy,I hope one day I could share a tutorial which use such stupid way to implement Collada :slight_smile:

Have you read all the forum threads on skinning?

Like this one? viewtopic.php?f=12&t=1485

Thanks Marcus!!

I have read all thread about skinning,and finally it seems work for some model…

I will post it and share the code and my XML tool,but it does’t parse well for all Collada files,I will keep maintain it and post in my blog :slight_smile:

here is the link

http://fatmingwang.spaces.live.com/default.aspx