Skinned Animation System acting funny! Help

Started by
5 comments, last by LWard 7 years, 6 months ago

Hey Guys!

So i am building a custom c++ engine for my game but the skinned animation system is acting funny the animation is not acting correctly
I am thinking it has to do with the Joint Hierarchy maybe not been applied correctly during the skinned animation process and the joint poses are not set to the correct space, but at first glance what do you guys think the problem could be and what should i look at to fix it?

This would be the way its suppose to work (This are GIFs so click them so they can animate)

[attachment=33840:Animation_Walk.gif]

This is the way it actually shows up in game (This are GIFs so click them so they can animate)

[attachment=33841:Wrong_Walk_Animation.gif]

Here is some of the animation code


Animation* Current_Animation = _Model->GetAnimation(_AnimName);

	Mesh* TempMesh = _Model->GetMesh();

	//Final Vector with animation Updated Vertex Positions
	vector<FLOAT4X4> CurrentPoses = ProcessChannels(Current_Animation,_DT);
	vector<Vector_Struct> FinalVertexs;
	for (unsigned int i = 0; i < _Model->GetOrgVertexs().size(); i++)
	{
		Vector_Struct vSum = {};

		for (unsigned int x = 0; x < TempMesh->The_Influences[i].size(); x++)
		{
			int JointIndex = TempMesh->The_Influences[i][x].joint_index;
			float Weight = TempMesh->The_Influences[i][x].weight;

			FLOAT4 CurrentVertexOffset = {};
			FLOAT4 Result = {};
			FLOAT4X4 BindPoseInverse = {};

			//Get the inverse bind pose to but the vertex into the correct space
			FLOAT4X4 Bind_Pose = TempMesh->The_Joints[JointIndex].bind_pose_transform;
			BindPoseInverse = Math::GetInstance()->FLOAT4X4Inverse(Bind_Pose);
			//Put the Original Vertex into the correct space
			CurrentVertexOffset = _Model->GetOrgVertexs()[i].Position * BindPoseInverse;
			//Get the pose for the current animation frame
			FLOAT4X4 pose = CurrentPoses[JointIndex];// Current_Animation->channels[JointIndex].keys[CurrentKey].node;
			//apply the pose to the updated vertex
			Result = CurrentVertexOffset * pose;

			//affect the Vertex by the correct weight and apply the result affected by the weight into the complete vertex for the final version
			Result *= Weight;
			vSum.Position += Result;
		}
		//add it into the vector
		FinalVertexs.push_back(vSum);
	}


	for (unsigned int i = 0; i < FinalVertexs.size(); i++)
	{
		_Model->GetVertexs()[i].Position = FinalVertexs[i].Position;
	}

	UpdateVertexBuffer = false;
	_Model->SetAnimated(true);
Advertisement

It looks like the joints are upside down as if the shoulders are by the feet and the hip joint is between the feet rather than above them, but it does look like they are doing the correct rotations just around joints in the wrong positions.

Can you confirm if the joints are in the correct(ish) position? Should be easy to see if the shoulders are where they should be rather than by the feet, once you have updated your vertex positions. If they are we then know we should be looking at if the rights joints are being used with/to create the right rotations.

Your right! :D

the joints are in incorrect positions also i decided to make a shoulder shrug animation and once imported into the engine nothing happens meaning the model doesn't animate at all

which makes me think that the hand joints are not taking the shoulder joints into account at all

i also found out that the shoulders are actually by the feet in the engine version of the model.

Do you think this mean i am not taking the joint hierarchy correctly? or that maybe the model was rigged incorrectly?

thanks for the help btw

Its not the model or rigging since i check if it works correctly in unreal and it does which means that the problem is without a doubt in my engine

which was actually what i was kinda dreading :/.

So the first thing you need to look at is why are the positions incorrect in your engine, once you found that out it should be easier to work out why the hand joints are not taking the shoulder joints into account.

the joints are in incorrect positions

The first thing I would do is check that when you load your model that the positions are correct?

If so, look at anything that updated/modifies those positions - for example does 'BindPoseInverse = Math::GetInstance()->FLOAT4X4Inverse(Bind_Pose);' or other functions return what your expecting?

If that all looks fine, check how your uploading that data to the GPU. Are the buffers being created and filled correctly?

If that looks correct, check your shaders. Although if it is the vertex shader I would have thought the whole model would be inverted.

which makes me think that the hand joints are not taking the shoulder joints into account at all

For this, you need to get the parent joint (I'm guessing you're storing it as a matrix) and include (multiplication) that when you are translating or rotating a child joint. For example, the shoulders move so the hands need to know where the shoulders are now when they are moving.

FIXED IT!

Thanks for the help LWard! :D

The problem was that i was using the wrong math operation here


CurrentVertexOffset = _Model->GetOrgVertexs()[i].Position * BindPoseInverse;

were this is taking into account the FLOAT4 w value which isnt needed which therefore messed up all of the other values all i had to do was

do the operation as if it was a FLOAT3


CurrentVertexOffset = Math::GetInstance()->FLOAT3Transform(_Model->GetOrgVertexs()[i].Position, BindPoseInverse);

and everything started working great! :D

Glad you were able to get it working :)

This topic is closed to new replies.

Advertisement