• Announcements

    • khawk

      Download the Game Design and Indie Game Marketing Freebook   07/19/17

      GameDev.net and CRC Press have teamed up to bring a free ebook of content curated from top titles published by CRC Press. The freebook, Practices of Game Design & Indie Game Marketing, includes chapters from The Art of Game Design: A Book of Lenses, A Practical Guide to Indie Game Marketing, and An Architectural Approach to Level Design. The GameDev.net FreeBook is relevant to game designers, developers, and those interested in learning more about the challenges in game development. We know game development can be a tough discipline and business, so we picked several chapters from CRC Press titles that we thought would be of interest to you, the GameDev.net audience, in your journey to design, develop, and market your next game. The free ebook is available through CRC Press by clicking here. The Curated Books The Art of Game Design: A Book of Lenses, Second Edition, by Jesse Schell Presents 100+ sets of questions, or different lenses, for viewing a game’s design, encompassing diverse fields such as psychology, architecture, music, film, software engineering, theme park design, mathematics, anthropology, and more. Written by one of the world's top game designers, this book describes the deepest and most fundamental principles of game design, demonstrating how tactics used in board, card, and athletic games also work in video games. It provides practical instruction on creating world-class games that will be played again and again. View it here. A Practical Guide to Indie Game Marketing, by Joel Dreskin Marketing is an essential but too frequently overlooked or minimized component of the release plan for indie games. A Practical Guide to Indie Game Marketing provides you with the tools needed to build visibility and sell your indie games. With special focus on those developers with small budgets and limited staff and resources, this book is packed with tangible recommendations and techniques that you can put to use immediately. As a seasoned professional of the indie game arena, author Joel Dreskin gives you insight into practical, real-world experiences of marketing numerous successful games and also provides stories of the failures. View it here. An Architectural Approach to Level Design This is one of the first books to integrate architectural and spatial design theory with the field of level design. The book presents architectural techniques and theories for level designers to use in their own work. It connects architecture and level design in different ways that address the practical elements of how designers construct space and the experiential elements of how and why humans interact with this space. Throughout the text, readers learn skills for spatial layout, evoking emotion through gamespaces, and creating better levels through architectural theory. View it here. Learn more and download the ebook by clicking here. Did you know? GameDev.net and CRC Press also recently teamed up to bring GDNet+ Members up to a 20% discount on all CRC Press books. Learn more about this and other benefits here.
Sign in to follow this  
Followers 0
Saad Manzur

Assimp Skeleton Bind Pose

10 posts in this topic

I am trying to render my skeleton's bind pose in DirectX. But when I follow this code I end up having a distorted mesh.

void Bones::UpdateNode(const aiNode *pNode, const XMFLOAT4X4 parentMatrix) //Bone Index, Parent Matrix (Transformation)
{
	const char *name = pNode->mName.C_Str();
	XMFLOAT4X4 temp;
	AItoXM(pNode->mTransformation, temp);
	XMMATRIX NodeTransformation = XMLoadFloat4x4(&temp);

	XMMATRIX finalTransform = NodeTransformation * XMLoadFloat4x4(&parentMatrix);

	if (mBoneInfoMap.find(name) != mBoneInfoMap.end())
	{
		int boneID = mBoneInfoMap[name];
		XMMATRIX temp2 = XMLoadFloat4x4(&m_GlobalInverseTransform) * finalTransform * XMLoadFloat4x4(&mBoneInfo[boneID].toParent);
		XMStoreFloat4x4(&mBoneInfo[boneID].Transform, temp2);
	}

	XMFLOAT4X4 temp3;
	XMStoreFloat4x4(&temp3, finalTransform);

	for (int i = 0; i < pNode->mNumChildren; i++)
	{
		UpdateNode(pNode->mChildren[i], temp3);
	}
} 

What is the offset matrix provided by Assimp. And is the transformation matrix really the transformation with reference to it's parent. Is it necessary to calculate all the way from the root node of the scene ?

0

Share this post


Link to post
Share on other sites

It's been a long time since i looked at my animation code but i found this comment:

 

"Turns out Assimp generates animations relative to the parent joint, NOT the joint itself. So i don't have to multiply the animation transformation by the local transformation. Which i only use if there is no animation for a bone.."

 

Along with this code: (It's used for animation rather than getting the bind pose but since the bind pose is usually the first frame of animation, it should be similar to what you're looking for)

// pJoint->mAnimatedTransf is initialized with Assimp's local transform (which you can find like this: g_Scene->mRootNode->FindNode(bone_name)->mTransformation)
	// Then it can be replaced per frame by an interpolated animation transformation for every bone that has an animation
	// pJoint->mOffsetTransf you can find in an aiBone struct
	// DO NOT FORGET TO TRANSPOSE when you load them

	D3DXMATRIX final = pJoint->mAnimatedTransf  *  P;

 	//mFinalTransforms contains the matrices that will be sent to the shader
	mFinalTransforms.push_back( pJoint->mOffsetTransf * final );

From Assimp's documentation:  "Its [bone's] offset matrix declares the transformation needed to transform from mesh space to the local space of this bone."

 

i.e. it's the inverse bind pose.

2

Share this post


Link to post
Share on other sites


// DO NOT FORGET TO TRANSPOSE when you load them

 

So I have to transpose the offset matrix to get the bind pose ?


D3DXMATRIX final = pJoint->mAnimatedTransf * P;

 

Is 'P' the parent's transform matrix ?

0

Share this post


Link to post
Share on other sites

Waaayoff, on 23 Mar 2014 - 10:51 AM, said:

// DO NOT FORGET TO TRANSPOSE when you load them
 
So I have to transpose the offset matrix to get the bind pose ?

 

No. From what i remember, this comment was there to remind me to transpose the offset matrix because of the difference between the matrix order between Assimp and DX. Try it with and without transposing and see which one is correct.

 

 

 



Waaayoff, on 23 Mar 2014 - 10:51 AM, said:

D3DXMATRIX final = pJoint->mAnimatedTransf * P;
 
Is 'P' the parent's transform matrix ?

 

Yes. This is the whole function. It will be called with the skeleton's Root bone and an identity matrix.

//=====================================================================================================
// Recursively calculate the joints' combined transformations
//=====================================================================================================
void AnimationController::CombineTransforms(Joint* pJoint, const D3DXMATRIX& P)
{
	  D3DXMATRIX final = pJoint->mAnimatedTransf  *  P;

	  mFinalTransforms.push_back( pJoint->mOffsetTransf * final );

	  for (unsigned i = 0; i < pJoint->mChildren.size(); i++)
	  {
			 CombineTransforms(pJoint->mChildren[i], final);
	  }

Where, like i mentioned above, pJoint->mAnimatedTransf should contain the local transformation if you want to get the bind pose.

Edited by Waaayoff
1

Share this post


Link to post
Share on other sites

Thanks to you, I have gotten this far.. But the mesh is still distorted..

 

distorted2_zps46dc1a32.png

 

Here is my code :

 

void Bones::UpdateNode(const aiNode *pNode, const XMFLOAT4X4 parentMatrix) //Bone Index, Parent Matrix (Transformation)
{
	const char *name = pNode->mName.C_Str();
	XMFLOAT4X4 temp;
	AItoXM(pNode->mTransformation, temp);
	XMMATRIX NodeTransformation = XMLoadFloat4x4(&temp);

	XMMATRIX finalTransform = XMLoadFloat4x4(&parentMatrix) * NodeTransformation;

	if (mBoneInfoMap.find(name) != mBoneInfoMap.end())
	{
		int boneID = mBoneInfoMap[name];
		if (mBoneInfo[boneID].meshdata)
		{
			XMMATRIX temp2 = finalTransform * XMLoadFloat4x4(&mBoneInfo[boneID].offsetMatrix);
			XMStoreFloat4x4(&mBoneInfo[boneID].Transform, temp2);
		}
		else
		{
			XMStoreFloat4x4(&mBoneInfo[boneID].Transform, XMMatrixIdentity());
		}
	}

	XMFLOAT4X4 temp3;
	XMStoreFloat4x4(&temp3, finalTransform);

	for (int i = 0; i < pNode->mNumChildren; i++)
	{
		UpdateNode(pNode->mChildren[i], temp3);
	}
}

aiNode->mTransformation is the local transform right ? And transpose does not work for me. This is the closest to what I got. I am passing the scene's root node. Your help is greatly appreciated. 

0

Share this post


Link to post
Share on other sites

First: I'm not sure what "meshdata" is, so I don't know if it makes a difference.

 

However, if a bone is found in mBoneInfoMap, is it an error condition if that bone's meshdata is NULL or FALSE?

 

Also, the code you posted is apparently for some class or object Bones::. Does that function, in fact, iterate the entire node structure? That is, do you calculate the final transform for every node in the hierarchy?

1

Share this post


Link to post
Share on other sites

First: I'm not sure what "meshdata" is, so I don't know if it makes a difference.

 

It's just a flag if the bone has a mesh around it or not. Because in my model, not every bone is used for the mesh (Like Bind_HeadTopEnd) this bone is not used , I guess this bone is given to bind some helmet or other static meshes with it. 
 


Does that function, in fact, iterate the entire node structure?

 

I guess so, because I provide the root node as paremeter's to the funtion. It should visit each node in the SCENE not in the FRAME only, I guess. 

 

Help me understand this multiplications:(Thinking out loud)

 

 


XMMATRIX finalTransform = XMLoadFloat4x4(&parentMatrix) * NodeTransformation;

 

This transforms the child bone's position with respect to it's parent locally.

 

 

 


XMMATRIX temp2 = finalTransform * XMLoadFloat4x4(&mBoneInfo[boneID].offsetMatrix)

 

And this transforms the previous local transform into bind pose . (where offset matrix is said to be inverse bind pose matrix)

I am wrong right ?

 

Edit : If you observe the screen shot you will see that the hand is not the only thing that is distorted. The hip too.

Edited by Saad Manzur
0

Share this post


Link to post
Share on other sites

Ok , thanks guys I have solved it . Buck, Waaayoff and IceBreaker all of you , thanks for feedback. The thing is that I had to transpose the finalTransfromation matrix . It is still slightly distorted. It was even when I fed the identity matrices. Now for the animation part. Does it get easier or harder from here ?

bindPose_zps64675505.png

0

Share this post


Link to post
Share on other sites

Saad Manzur, on 24 Mar 2014 - 10:14 AM, said:


XMMATRIX finalTransform = XMLoadFloat4x4(&parentMatrix) * NodeTransformation;


This transforms the child bone's position with respect to it's parent locally.

Well, sort of. In that particular function, because you start at the root and work through the hierarchy, each node passes on its mesh-space transform to its children. So when a child multiplies it's local "to parent" transform times it's parent's mesh-space transform, that forms the bone's bone-space-to-mesh-space transform.

 

 

 


Saad Manzur, on 24 Mar 2014 - 10:14 AM, said:

XMMATRIX temp2 = finalTransform * XMLoadFloat4x4(&mBoneInfo[boneID].offsetMatrix)


And this transforms the previous local transform into bind pose . (where offset matrix is said to be inverse bind pose matrix)

Nope. The final transform is not a "local" transform. It transforms from bone-space to mesh-space. The offset matrix transforms from mesh-space to bone-space. As mentioned in my article (you really should read through it, it may help), when a vertex is multiplied by temp2 (as you have it above) the vertex (which is in mesh-space) is transformed to bone-space (by the offset matrix), and then transformed from bone-space to mesh-space by the final transform part of it. When you use the pose mode locat transforms to do all that, the temp2 matrix you have above should end up as an identity matrix.

 

 

 


The thing is that I had to transpose the finalTransfromation matrix

 

That's likely because all your frame transforms appear to be column-major, judging by the order of the matrix multiplications. The shader likely expects row-major matrices which is accomplished by transposing.

Edited by Buckeye
1

Share this post


Link to post
Share on other sites

Thanks for your feedback. But the mesh is still distorted. I guess a vertex in the hand region does not have weight and bone index attached to it. I have to check it.

Do you know how to export complex animations from maya in dae format ? 

0

Share this post


Link to post
Share on other sites


Do you know how to export complex animations from maya in dae format ?

I personally don't. Anyone else?

0

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  
Followers 0