Sign in to follow this  
skybreaker

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

Recommended Posts

skybreaker    126
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
skybreaker    126
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

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