Skip to main content
GameDev.net gamedev.net
🔒 Locked

md5 - how to make a character walk according to animation

Started by murderv Jun 30, 2009 at 5:01 AM 4 replies 2.1k views
Original Post
murderv
murderv
hello, i'm in the process of using md5 animations for character animation and i am having problems on getting the characters to walk correctly. i have the distance the root joint travels from the first frame to the last frame. i have subtracted that distance to the animation, that way i can get the character walking always at a specific point.. i've computed the distance it travels between each frame and add that step at every update, but i get some problems. the mesh keeps glitching, because of the interpolations. maybe finding the velocity to travel from one step to the other would work but i'm not getting how to do it? anyone using md5 animations out there? how are you placing them in the world and actually making them walk? thanks in advance
zedz
zedz
IIRC the root node i.e. -1 bone moves about the place right?
well in that case just over ride whats position is the md5 file + replace it with (0,0,0)

this way any walking, jumping etc animation happens on the samespot
during the game just move the -1 bone to where you want the character to walk, this could be along a path for example
murderv
murderv
i have done that. i remove each frame's translation of the root node of every end vertex. i have the models walking on the same point.
the thing is making them walk or run correctly, without making it look like they are sliding on ice.

here's what i've got:

im playing with it, its almost perfect with the code below.. but there is still a moment when the model is moving one foot in front of the other where we usually dont translate. we just push with the back foot to the front..
still in the animation i notice a little translation. which is annoying once you see it =) and im sure johnc wouldn't let that pass.


any ideas ?



CODE FOR ANIMATIO BELOW:

// change frames, indedendently of the app framerate
void updateModelAnimation( float time )
{
currentTime = time;
if( (currentTime-previousTime) > frameTime )
{
previousTime = currentTime;

// update model animation.
updateAnim( 1.0 / animation.getFrameRate() );

// move model along an axis.
// vels holds the distances of the root node at every animation frame.
// which i had to the model world position with every frame change in the animation
modelPos.x += vels[nextFrame].x;
modelPos.y += vels[nextFrame].y;
modelPos.z += vels[nextFrame].z;
}

model.updateAnimation( prevFrame, nextFrame, (currentTime-previousTime) );
}


void updateAnim( float ftime )
{
animTime += ftime;
if( animTime >= frameTimes[nextFrame] )
{
nextFrame++;
prevFrame = nextFrame - 1;
if( nextFrame > frames.length-1 )
{
prevFrame = 0;
nextFrame = prevFrame + 1;

animTime = 0.0f;
}
}
}
zedz
zedz
perhaps youre seeing a skip/jump from when the walking animation ends + it begins again
if so then youre not lerping correctly between the end frame + the start frame

r u lerping between frames?
thus 0.2 time = position = frame0 * 0.8 + frame1 * 0.2
or is it just frame0,1,2,3,4,5,6,0

Ive used md5 before + had no issues with animation (though I wouldnt recommend md5 personally as theres bugger all files available, unlike quake2/3 the user generated contnent never caught on)
bzroom
bzroom
There's 2 parts to it.

1.) making him walk in place. You say you've done this, but does it work flawlessly? This will test your animation interpolation. Does he perfectly moon walk in place? or does he glitch when the animation repeats? If he glitches, fix that at this stage.

2.) Those tranlsation values that you removed from the animation are important and should not be discarded. Every animation update you compute how much translation you extracted from the animation to make him "moon walk" and you make this translation displacement value available to the owner of the animation controller. That object will then request the translation displacement that was extracted and add it to the characters position to make him follow the same translation as the animation would have.

You would introduce physics and turning and any other logic to that last step, when the displacement is integrated into the character.

The final step would be to then look at the characters true velocity, after considering physics and collision, and reconfigure your animation controller to be operating at the correct speed, with the correct animation.
murderv
murderv
bzroom, that is exactly what i've done already.. but im still having problems with it. either it looks jerky or it seems to still do a little bit of the moon walk..

i have taken the distance from frame 0 to last frame. i find out the time it takes to go from one frame to the other and i also save the distances between frames.

so in my loops i then find if nextframe's time was reached. it so, i change to the next frames and i then interpolate the data.. here's my latest animation code..

im trying to get this to animate correctly and still be able to slow or accelerate the animation, hence the speed var.


still it moonwalks, but ofcourse it moves forward a bit..
i think the interpolation t value is correct, it goes from 0 to 1 as possible, no matter how much time it takes to change frames..



CODE:


float speed = frameTime;
float invSpeed = 1.0 / speed;

currentTime = time;
if( (currentTime-previousTime) > speed)
{
previousTime = time - ((time-previousTime) % speed);

// save model's position at this update stage
savedModelPos = modelPos.clone();

// Update animation, frames. also set animation to loop mode
updateAnim( invAnimFrameRate, 1, 1);
}

// interpolate animation from prevFrame to next frame.
model.updateAnimation( prevFrame, nextFrame, (currentTime-previousTime)*invSpeed );

// interpolate position from frame prevFrame to next Frame.
// savedModelPos should hold the position of the model in the last frame update
modelPos.x = savedModelPos.x + (vels[nextFrame].x*(currentTime-previousTime)*invSpeed );
modelPos.y = savedModelPos.y + (vels[nextFrame].y*(currentTime-previousTime)*invSpeed );
modelPos.z = savedModelPos.z + (vels[nextFrame].z*(currentTime-previousTime)*invSpeed );

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.