Character animation with 2 body parts

Started by
5 comments, last by Black Knight 13 years, 9 months ago
Hi guys,

Right now my game uses character models that are a single .X model, the mesh is a single enclosed volume and this is somewhat limiting me.

What I want to do is make the characters upper body and lower body seperate models so that they can have different animations from each other. For example the lower body might be walking while the upper body might be attacking or blocking or whatever.

Any ideas on how to accomplish this? Should the lower and upper body be animated separately in 3ds max and then exported as separate x files? My game right now has something like this:

class Entity{//stuff...Vector3 position;Vector3 velocity;// more stuffboost::shared_ptr<Model> model;}


So basically each entity is represented by one model and this model is drawn that position. Instead of that I can have 2 models per entity and draw them at position, this requires the models to be placed correctly in 3ds max which shouldn't be too bad. So it would look like this :
class Entity{//stuff...Vector3 position;Vector3 velocity;// more stuffboost::shared_ptr<Model> upperBody;boost::shared_ptr<Model> lowerBody;//or std::vector<boost::shared_ptr<Model> > bodyParts; //this would require more work though but it maybe better for creatures for more body parts. i would also need a way to define which *.x files make up which entities.}


Any other ideas?
Advertisement
It depends on the purpose of the class... Why not make a base class called "Entity" like you have right now (but let me recommend a better name, like "CreatureBody" or something. Entity is actually way too generic and could mean ANYTHING.), and you can have it store a map of parts keyed by some kind of index (or just a vector and use enumerated labels for the indexes, that works too).

If you want to create different kinds of entities then you can either use a builder to set up your entity to create different kinds of dudes (if you have all the functions you need and your entities are general enough), or you can derive via inheritance and customize (if you need to create or override new functions to get the desired behavior).
_______________________"You're using a screwdriver to nail some glue to a ming vase. " -ToohrVyk
Quote:Original post by Black Knight
Any other ideas?


I don't know the .X format, but if you support skeletal animation you don't need to subdivid your model. Older games have used two models to seperate upper and lower body(quake1/2 ?) with clearly visible seems. But when you are using a bone anmation system, you can keep one model, one skeleton and define bone weights for certain animation overlays.

You can define one overlay 'upper body' where each bone associated with the uppper bone get an alpha value of 1.0 (rest 0.0). Now you can play two different animations, a standard walking animation and an attack animation. The attack animation will be blended over the walking animation by blending the relative bone position and rotation according to the overlay alpha value.

That is the way I do it in my game, thought there're better and more advanced solution for blending animations.


X files have skeletal animation, but I don't know if its possible to do what your saying.

Right now my game loads the models like one of the sdk samples with D3DXLoadMeshHierarchyFromX and builds the matrices for bones and animates them using the AnimationController class. Each specific animation has an animation set like walk,run,idle and I can change the current animation set with something like below. This changes from one set to another gradually instead of a very sudden change.

void AnimInstance::SetAnimationSet(unsigned int index)	{				if (index == m_CurrentAnimationSet)			return;		if (index >= m_Model->m_AnimationSetCount)			index = 0;		m_CurrentTime = 0.0f;		m_AnimationController->ResetTime();				// Remember current animation		m_CurrentAnimationSet = index;		// Get the animation set from the controller		LPD3DXANIMATIONSET set;		m_AnimationController->GetAnimationSet(m_CurrentAnimationSet, &set );			// Alternate tracks		DWORD newTrack = ( m_CurrentTrack == 0 ? 1 : 0 );		// Assign to our track				m_AnimationController->SetTrackAnimationSet( newTrack, set );		set->Release();				// Clear any track events currently assigned to our two tracks		m_AnimationController->UnkeyAllTrackEvents( m_CurrentTrack );		m_AnimationController->UnkeyAllTrackEvents( newTrack );		// Add an event key to disable the currently playing track kMoveTransitionTime seconds in the future		m_AnimationController->KeyTrackEnable( m_CurrentTrack, FALSE, m_CurrentTime + m_MoveTransitionTime );		// Add an event key to change the speed right away so the animation completes in kMoveTransitionTime seconds		m_AnimationController->KeyTrackSpeed( m_CurrentTrack, 0.0f, m_CurrentTime, m_MoveTransitionTime, D3DXTRANSITION_LINEAR );		// Add an event to change the weighting of the current track (the effect it has blended with the secon track)		m_AnimationController->KeyTrackWeight( m_CurrentTrack, 0.0f, m_CurrentTime, m_MoveTransitionTime, D3DXTRANSITION_LINEAR );		// Enable the new track		m_AnimationController->SetTrackEnable( newTrack, TRUE );						// Add an event key to set the speed of the track		m_AnimationController->KeyTrackSpeed( newTrack, 1.0f, m_CurrentTime, m_MoveTransitionTime, D3DXTRANSITION_LINEAR );		// Add an event to change the weighting of the current track (the effect it has blended with the first track)		// As you can see this will go from 0 effect to total effect(1.0f) in kMoveTransitionTime seconds and the first track goes from 		// total to 0.0f in the same time.		m_AnimationController->KeyTrackWeight( newTrack, 1.0f, m_CurrentTime, m_MoveTransitionTime, D3DXTRANSITION_LINEAR );		//m_AnimationController->KeyTrackPosition(newTrack,0.0f,m_CurrentTime + 0.001f);		m_AnimationController->SetTrackPosition(newTrack,0.0f);		// Remember current track		m_CurrentTrack = newTrack;		}


And my system right now is one bone per vertex.

My animations sets are idle,running and attack but I don't have an animation for attacking while running so if you press attack in the game the character plays the attack animation while moving which looks like sliding on the ground.
I don't know how to integrate bone weights in this system to do what I want. Separating the models seems like an easier way to me :/.

So If a character moves ill do;

lowerbody->setAnimationSet(RUN);
upperbody->setAnimationSet(RUN);

if they press attack button while running;

lowerbody->setAnimationSet(RUN);
lowerbody->setAnimationSet(ATTACK);

and so on.

I am still open to suggestions though :)
Are you sure you have one bone per vertex? That seems like a lot.

The ID3DXAnimationController is indeed a tricky beast to use correctly ;)

Try using track blending between run and attack and see if it gives the results you want. If not, you will need to write your own keyframe interpolator that allows you to select which bones (lower-body or upper-body) you actually want the track animation to work with.

Another solution is to have a look at the AnimationSet (either in Notepad by looking at the X file or programmatically by using some of the lesser known accessors of KeyframedAnimationSet). Filter out the keyframes for all the lower-body bones to a separate animation set, thereby creating two AnimationSets, one for Attack Low-Body and Attack High-Body. Do the same with run. Then just use the animation blending as described in the MultiAnimation sample.
@Steve_Segreto:
Quote:Are you sure you have one bone per vertex? That seems like a lot.

You're right. That'd be just a grunch of bones! [smile] I think he means one bone influence per vertex.

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.

Yes you are right I meant one vertex is only influenced by one bone, a bone can control many vertices.

I will probably keep the system intact and copy the animations inside 3ds max and create new animations sets. I will copy the run animation and the attack and make a new animation set. I will probably have the following animation sets.

Idle,Run,Melee Attack,Ranged Attack,Block,Running Melee Attack,Running Ranged Attack,Running Block,Die. It is just less work to copy some key frames in 3ds max in the time line I guess.

This topic is closed to new replies.

Advertisement