Sign in to follow this  

Skeletal Animations... It works but still has problems...

This topic is 4396 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

It runs well when I removes all the information of Animation ,AnimationSets. But I haven't load these info at all.Are they loaded by "D3DXLoadSkinMeshFromXof"?? and applied auto during "UpdateSkinnedMesh"? And another problem is Once I changed the FVF of skinedmesh (CloneFVF)the "UpdateSkinnedMesh" will not works....errrr..... /////////////////////////////////////////////////////////////////////////// that's the old info. Hello everyone: I'm tring to write a Skeletal Animation Class.With the help of Jim's book"Advance Animation" I Loaded the frames and skined weight info. After loaded Frames and SkinedWeights,I tried to render a static pose of tiny but something goes wrong,tiny becomes a monster-like thing...... Here is what I did: 1) I Parse the tiny.x file two times. (one time for load frames and another for mesh and it's skinedweights,so I haven't link them together when loading.I'm not quite sure if it's right here.) I use two parser class to load them:cXFrameParser,cXSkinedMeshParser.they are extended from the class cXParser which from Jim's book. Load Frames
bool cXFrameParser::ParseObject(LPD3DXFILEDATA pDataObj,LPD3DXFILEDATA pParentDataObj,DWORD depth,void **Data)
{

	GUID id;
	pDataObj->GetType(&id);	

	if(id==TID_D3DRMFrame&&!pDataObj->IsReference())
	{
	/////////////build frames
D3DXFRAME_EX *pFrame = new D3DXFRAME_EX();
// Get the frame's name (if any)
pFrame->Name = GetObjectName(pDataObj);
// Link frame into hierarchy
	if(Data == NULL) 
	{
	// Link as sibling of root
	pFrame->pFrameSibling = m_RootFrame;
	m_RootFrame = pFrame; pFrame = NULL;
	Data = (void**)&m_RootFrame;
	} 
	else 
	{
	// Link as child of supplied frame
	D3DXFRAME_EX *pFramePtr = (D3DXFRAME_EX*)*Data;
	pFrame->pFrameSibling = pFramePtr->pFrameFirstChild;
	pFramePtr->pFrameFirstChild = pFrame; pFrame = NULL;
	Data = (void**)&pFramePtr->pFrameFirstChild;
	}
	}

	// Set a frame transformation matrix
	if(id == TID_D3DRMFrameTransformMatrix && pDataObj->IsReference() == FALSE && Data) {

		D3DXFRAME_EX *Frame = (D3DXFRAME_EX*)*Data;
		if(Frame) {
			Frame->TransformationMatrix = *(D3DXMATRIX*)GetObjectData(pDataObj,sizeof(D3DXMATRIX));
			Frame->matOriginal = Frame->TransformationMatrix;
			}

	}
	return cXParser::ParseChildObject(pDataObj, depth, Data);
}



Load meshes


bool cXSkinedMeshParser::ParseObject(LPD3DXFILEDATA pDataObj,LPD3DXFILEDATA pParentDataObj,DWORD depth,void **Data)
{

	GUID id;
	pDataObj->GetType(&id);
	if(id == TID_D3DRMMesh) 
	{

		LPSTR name=GetObjectName(pDataObj);
		
			if(!pDataObj->IsReference())
		{
			
			// Load the mesh using the data object load method
			D3DXMESHCONTAINER_EX *pMesh = new D3DXMESHCONTAINER_EX;
            LoadMesh(&pMesh, m_pD3DDevice, pDataObj, NULL,NULL, D3DPOOL_MANAGED)
			// Link mesh to head of list of meshes
		       if(pMesh) 
                        {
			 pMesh->pNextMeshContainer = m_RootMeshContainer;
			 m_RootMeshContainer = pMesh; pMesh = NULL;
          		}
			
		}
	}
	return cXParser::ParseChildObject(pDataObj,  depth, Data);
}



2)Map the meshcontainer with Frames. I itearor the mesh's numofbone and use the pSkinInfo->GetBoneName to find Frame in Frames.
HRESULT RES_Skeletal::MapFramesToMesh()
{
	D3DXMESHCONTAINER_EX *pMesh = m_mesh;
	if(!m_mesh||!m_rootFrame)
		return E_FAIL;
	while(pMesh) {
	// Does this mesh use skinning?
	if(pMesh->pSkinInfo) {
		// Get the number of bones
		DWORD NumBones = pMesh->pSkinInfo->GetNumBones();
		// Allocate the matrix pointers and bone matrices
		pMesh->ppFrameMatrices = new D3DXMATRIX*[NumBones];
		pMesh->pBoneMatrices   = new D3DXMATRIX[NumBones];
		// Match matrix pointers to frames
		for(DWORD i=0;i<NumBones;i++)
                           {
			// Get bone name
         		const char *BoneName = pMesh->pSkinInfo->GetBoneName(i);
			// Find matching name in frames
			D3DXFRAME_EX *pFrame = m_rootFrame->Find(BoneName);
			// Match frame to bone
              			if(pFrame)
				{
			pMesh->ppFrameMatrices[i] = &pFrame->matCombined;
			pFrame->pMeshContainer=pMesh;
				}
				else
				pMesh->ppFrameMatrices[i] = NULL;
			}
		}
	
		// Go to next mesh
		pMesh = (D3DXMESHCONTAINER_EX*)pMesh->pNextMeshContainer;
	} 
	return S_OK;
}


3)UpdateHierarchy by root frame, same as the book
void UpdateHierarchy(D3DXMATRIX *matTransformation = NULL)
	{
		D3DXFRAME_EX *pFramePtr;
		D3DXMATRIX matIdentity;

		// Use an identity matrix if none passed
		if(!matTransformation) {
			D3DXMatrixIdentity(&matIdentity);
			matTransformation = &matIdentity;
		}

		// Combine matrices w/supplied transformation matrix
		matCombined = TransformationMatrix * (*matTransformation);

		// Combine w/sibling frames
		if((pFramePtr = (D3DXFRAME_EX*)pFrameSibling))
			pFramePtr->UpdateHierarchy(matTransformation);

		// Combine w/child frames
		if((pFramePtr = (D3DXFRAME_EX*)pFrameFirstChild))
			pFramePtr->UpdateHierarchy(&matCombined);
	}


4)UpdateMesh() using pSkinInfo->UpdateSkinnedMesh() function. And it returned true;
RES_Skeletal::UpdateMesh()
{	// Error checking
	HRESULT result;

	if(!m_mesh)
		return E_FAIL;
	if(!m_mesh->MeshData.pMesh || !m_mesh->pSkinMesh || !m_mesh->pSkinInfo)
		return E_FAIL;
	if(!m_mesh->pBoneMatrices || !m_mesh->ppFrameMatrices)
		return E_FAIL;
  
// Copy the bone matrices over (must have been combined before call DrawMesh)
	for(DWORD i=0;i<m_mesh->pSkinInfo->GetNumBones();i++) 
        {
	// Start with bone offset matrix
	m_mesh->pBoneMatrices[i] =(*m_mesh->pSkinInfo->GetBoneOffsetMatrix(i));
	// Apply frame transformation
	if(m_mesh->ppFrameMatrices[i])
        	m_mesh->pBoneMatrices[i] *= (*m_mesh->ppFrameMatrices[i]);
	}

	// Lock the meshes' vertex buffers
	void *SrcPtr, *DestPtr;
        m_mesh->MeshData.pMesh->LockVertexBuffer(D3DLOCK_READONLY, (void**)   &SrcPtr);
        m_mesh->pSkinMesh->LockVertexBuffer(0, (void**)&DestPtr);
	// Update the skinned mesh using provided transformations
  result=m_mesh->pSkinInfo->UpdateSkinnedMesh(m_mesh->pBoneMatrices,NULL, SrcPtr, DestPtr);

	// Unlock the meshes vertex buffers
	m_mesh->pSkinMesh->UnlockVertexBuffer();
	m_mesh->MeshData.pMesh->UnlockVertexBuffer();

	// Return success
	return result;
}


5)render it...
 RES_Skeletal::DrawPart(int index)
{
	if(m_rootFrame)
        	m_rootFrame->UpdateHierarchy();
	MapFramesToMesh();
	UpdateMesh();

for(int i=0;i<m_mesh->NumMaterials;i++)
m_mesh->pSkinMesh->DrawSubset(i);
	

}


I'm almost crazy for this,still can't find where was wrong... oh...thank you so much for reading so much...thanks. [Edited by - skybreaker on November 30, 2005 2:08:17 AM]

Share this post


Link to post
Share on other sites
I still have something not clear,can someone simply answer these question please?
1)I found some mesh is a child of a frame in .x file like this:
Frame a {
....
Mesh b{....}
...
}

But I don't understand the meaning of it.Doesn't the mesh's SkinedWeight Template already has the name of bone which is as same as the name of frames?
So I ignoned it and simpley loaded mesh and frames separatly and use their name to map them .But it doesn't work...

2) I found another strange problem. One mesh has been loaded for 3 times.I thought It was cause of some referenced data has been loaded more than one time.
but I have already checked if the data is a referenced by ID3DXFileData::IsReferenced().
like this:

if(id == TID_D3DRMMesh & pDataObj->IsReference()==FALSE)
{
LPSTR name=GetObjectName(pDataObj);
// Load the mesh using the data object load method
D3DXMESHCONTAINER_EX *pMesh = new D3DXMESHCONTAINER_EX;
LoadMesh(&pMesh, m_pD3DDevice, pDataObj, NULL,NULL, D3DPOOL_MANAGED));
// Link mesh to head of list of meshes
if(pMesh) {
pMesh->pNextMeshContainer = m_RootMeshContainer;
m_RootMeshContainer = pMesh; pMesh = NULL;
}

}


It troubles me in a long time ....someone help....help...help

Share this post


Link to post
Share on other sites

This topic is 4396 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