Skin binding problem.

Started by
5 comments, last by AntiMoron 9 years, 4 months ago

hello guys .I need your help.
I'v been trying to do skin animation during last 36 hours.but vertices data seems broken.
Using assimp 3.0 to load fbx model.

view the result here http://pasteboard.co/2zixWwMK.png
(for some reason I can't find a good paste image website.)


my project can be download at herel:
https://github.com/AntiMoron/aMazing



the critical code of my problem can be viewd from :

https://github.com/AntiMoron/aMazing/blob/master/aMazing/ModelClass.cpp

https://github.com/AntiMoron/aMazing/blob/master/aMazing/ModelClass.h


my IDE is vs2013
following c++11 standard

what am I doing wrong ?

Advertisement

what am I doing wrong ?

What have you done to find the problem?

Regarding your code: TL;DR as the problem could be any one of several things: bad import technique, wrong winding order, incorrect matrix calcs, bad shader code, incorrect loading of shader resources, etc., all things you can check.

Is your FBX file correct? Do you use assimp correctly to import it? Have you loaded a static model using the same import techniques? I.e., using FBX and assimp, have you created a simple box, imported it, and rendered it sucessfully?

You may want to follow the data to see where the data or the code is incorrect. In particular, note the suggestion to use the simplest data and code possible. Then add another code routine and test it.

Have you read this article on the FBX SDK? You also need to be familiar with the principles of skinned mesh animation.

Please don't PM me with questions. Post them in the forums for everyone's benefit, and I can embarrass myself publicly.

You don't forget how to play when you grow old; you grow old when you forget how to play.


what am I doing wrong ?

What have you done to find the problem?

Regarding your code: TL;DR as the problem could be any one of several things: bad import technique, wrong winding order, incorrect matrix calcs, bad shader code, incorrect loading of shader resources, etc., all things you can check.

Is your FBX file correct? Do you use assimp correctly to import it? Have you loaded a static model using the same import techniques? I.e., using FBX and assimp, have you created a simple box, imported it, and rendered it sucessfully?

You may want to follow the data to see where the data or the code is incorrect. In particular, note the suggestion to use the simplest data and code possible. Then add another code routine and test it.

Have you read this article on the FBX SDK? You also need to be familiar with the principles of skinned mesh animation.

well,thanks for you advise first...

Before starting this thread,I just though that I shouldn't tell what I thought and did for the problem cuz this may effect what others think.

first I though I was setting wrong layout. After rechecking it ,using 'offsetof' instead of calculating offset manualy seems fixed that error.

But I still see artifacts. Broken meshes everywhere.

Sure,I've already rendered a static model.It goes perfectly, really nice.

But I'm not using FBX SDK but assimp 3.0.

Assimp support lots of kinds of models.And users should only consider those interfaces assimp gives.

while importing FBX models,Assimp uses FBX SDK to implement its interfaces. So FBX SDK is not what I should consider.

According to Introduction to 3D game programming

let Pos be position of each vertex,P be the position of this vertex in binding space,M[] be the matrices in world space each bone have,Ind[] be the indices of bones that effect this vertex. W[] be the weights which showing how much is the affect is.

The formula is what I need at last:

Pos = sum(W[Ind] * P * M[Ind]) where i is usually range [0,4)

thus the output of rendering model in static mode(not including skeleton animation) is perfect,the only places where could cause my problem are as follow:

calculation of matrices of each bone.

calculation of vertex positions in binding space.

calculation of indices and weights.

But after checking as what I said still not fixed my problem(Maybe a tiny place but I just can't find).

So I was thinking that anybody experienced could find the bugs to help me.ohmy.png ohmy.png ohmy.png ohmy.png ohmy.png


the only places where could cause my problem are as follow:
calculation of matrices of each bone.
calculation of vertex positions in binding space.
calculation of indices and weights.


In particular, note the suggestion to use the simplest data and code possible.

Are you testing a simple model, perhaps just two cubes with a bone connecting them, perhaps with an animation that doesn't move the bone at all, or moves the bone just a very little bit?

If so, and if you have concluded that those routines are where problems may be, step through the code in debug mode (as suggested in the link) and check if the values are calculated correctly. With such a model, checking the matrix calcs will be very straight forward.

Please don't PM me with questions. Post them in the forums for everyone's benefit, and I can embarrass myself publicly.

You don't forget how to play when you grow old; you grow old when you forget how to play.

Posting a heap of code is a good way to make sure no one helps you.

Plus you didn’t even post your shader.

I am not going to wade through all of that code.

#1: Did you normalize the weights?

#2: Are there at-most 4 weights for each vertex?

#3: How do you know that? Do you print a warning or error when there are more than 4 weights?

#4: How do you handle having only 2 or 3 weights? Do you set the excess values to 0.0f or do you leave them as stack garbage (that would certainly result in the image you showed)?

L. Spiro

I restore Nintendo 64 video-game OST’s into HD! https://www.youtube.com/channel/UCCtX_wedtZ5BoyQBXEhnVZw/playlists?view=1&sort=lad&flow=grid

Posting a heap of code is a good way to make sure no one helps you.

Plus you didn’t even post your shader.

I am not going to wade through all of that code.

#1: Did you normalize the weights?

#2: Are there at-most 4 weights for each vertex?

#3: How do you know that? Do you print a warning or error when there are more than 4 weights?

#4: How do you handle having only 2 or 3 weights? Do you set the excess values to 0.0f or do you leave them as stack garbage (that would certainly result in the image you showed)?

L. Spiro

Sorry for my forgetting pasting the shader url : https://github.com/AntiMoron/aMazing/blob/master/aMazing/Shader/skinAnim/skinAnim.fx

This is included in the project's github url pasted above too.

for InputLayout for this shader :


//this is the data structure that used to save vertex data for skeleton animation.
class SkinVertex 
{
public:
	SkinVertex()
	{
		memset(boneIndices, 0, sizeof(boneIndices));
		weights = { 0, 0, 0, 0 };
	}
	XMFLOAT4 position; //vertex in binding space
	XMFLOAT4 normal; //normals
	XMFLOAT4 texture; //textureCoord (just use the first two element)
	XMFLOAT4 weights; //weights
	unsigned int boneIndices[4]; //bone indices which indicate the bones that influenced the vertex
};
//the layout used for the shader above
D3D11_INPUT_ELEMENT_DESC animLayout[] =
	{
		{ "POSITION", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, offsetof(SkinVertex,position), D3D11_INPUT_PER_VERTEX_DATA, 0 },
		{ "NORMAL", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, offsetof(SkinVertex,normal), D3D11_INPUT_PER_VERTEX_DATA, 0 },
		{ "TEXCOORD", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, offsetof(SkinVertex,texture), D3D11_INPUT_PER_VERTEX_DATA, 0 },
		{ "WEIGHTS", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, offsetof(SkinVertex,wegights), D3D11_INPUT_PER_VERTEX_DATA, 0 },
		{ "BONEINDICES", 0, DXGI_FORMAT_R32G32B32A32_UINT, 0, offsetof(SkinVertex,boneIndices), D3D11_INPUT_PER_VERTEX_DATA, 0 },
	};

A lot of comments has been made in my cpp code to ensure that anybody else can read this code.

for tips #2-#4 you gave me:

I know that there're more than 4 weights

(I've printed debug message before.I thought that those familiar with assimp may know this better than me.)

I've already made it processed like:(save all the weights & sort'em ,cut for the top4 weights & indices,if not enough for 4 couples of index & weight,I made weights all zero for this case)


//the index and weight for each vertex   pair<boneIndex,weight>
	std::unordered_map<std::size_t, std::vector<std::pair<unsigned char,float> > > vindex2Weight;
	//pre-process bone datas
	for (std::size_t cur = 0; cur < bones->size(); ++cur)
	{
		auto& weights = (*bones)[cur]->weights;
		for (std::size_t r = 0; r < weights.size(); ++r)
		{
			std::size_t id = weights[r]->mVertexId;
			if (vindex2Weight.find(id) == vindex2Weight.end())
			{
				vindex2Weight.insert(std::pair<size_t, std::vector<std::pair<unsigned char, float> > >(id, {}));
			}
			//insert weight count
			vindex2Weight[id].push_back(std::pair<unsigned char,float>(cur,weights[r]->mWeight));
		}
	}
	//sort weight data for each vertex.the top4 will be used
	for (auto& entry : vindex2Weight)
	{
		auto& indexAndWeight = entry.second;
		std::sort(indexAndWeight.begin(), indexAndWeight.end(), 
			[](const std::pair<unsigned char, float>& a, const std::pair<unsigned char, float>& b) {
				return a.second > b.second;
		});
	}

For tip #1. I really need to give it a try. Thank you for your advise.

I would reduce pasting code in my future questions.


the only places where could cause my problem are as follow:
calculation of matrices of each bone.
calculation of vertex positions in binding space.
calculation of indices and weights.


In particular, note the suggestion to use the simplest data and code possible.

Are you testing a simple model, perhaps just two cubes with a bone connecting them, perhaps with an animation that doesn't move the bone at all, or moves the bone just a very little bit?

If so, and if you have concluded that those routines are where problems may be, step through the code in debug mode (as suggested in the link) and check if the values are calculated correctly. With such a model, checking the matrix calcs will be very straight forward.

Yes! I should make my test case as simple as possible.

This topic is closed to new replies.

Advertisement