Keyframed ragdoll not perfectly matching to animated skeleton

Keyframed ragdoll not perfectly matching to animated skeleton

I am using the Havok export and ragdoll tutorials to test out the running animation of the given character. When running in Maya or in the game, the actual animated skeleton seems to stand straight up while running, but the radoll skeleton in the debug viewer leans forward a bit. Also if I turn or move the character very quickly, the constraints on the ragdoll seem to break and the bones end up in very strange positions (even though they return to normal within a second or so). Every bone in the ragdoll is set to MOTION_KEYFRAMED and quality at HK_COLLIDABLE_QUALITY_KEYFRAMED_REPORTING. I'm making a fighting game, so the position of the bones should perfectly match up with the bones in the animated skeleton at all times regardless of velocity. How should I go about correcting this?

edit: upon further testing, the bones also take a few frames to line up if the character is running and then instantly put into default position.

26 帖子 / 0 全新

Hi fiction--

Can you check whether you are using hkaRagdollPoweredConstraintController or hkaRagdollRigidBodyController? The behavior you are describing sounds like hkaRagdollPoweredConstraintController, but you will want hkaRagdollRigidBodyController in most situations.

I also recommend taking another look to see if the motion type of your bones is always MOTION_KEYFRAMED because the components of a ragdoll should be MOTION_DYNAMIC. Constraints, such as those in a ragdoll, will do nothing if the bones are keyframed - keyframed bodies effectively have infinite mass, so the constraint cannot move them.

Also, what is your reason for choosing HK_COLLIDABLE_QUALITY_KEYFRAMED_REPORTING for ragdoll? It's very expensive, and is not typcially used for ragdolls.

The ConstraintMatchingDemo is a good reference for ragdoll implementation, so I suggest consulting that as well. Let me know what you discover - thanks!


I am using an hkaRagdollRigidBodyController. I think I may have been misunderstood a bit, but it's probably just my inexperience with Havok showing. What I want: I make an animation in Maya and set up a skeleton. Most of the time, I want the ragdoll/physics skeleton to follow the animation EXACTLY. I want the rigid body of the hand to be exactly where the hand on the animation is at all times, without influencing the animation at all, and regardless of how fast I change animation or hand position. On character death, I want to combine the animation of death with an actual dynamic ragdoll to get a more organic look. When not dying, the character will not be affected by any kind of physics and will directly follow the animation provided by Havok Animation. I had the bone motion type set at MOTION_KEYFRAMED because this seemed like the solution I was looking for. I was using HK_COLLIDABLE_QUALITY_KEYFRAMED_REPORTING to test some collision stuff before, and I actually don't think I need it anymore.

Upon your suggestion I changed the bones to dynamic, but I need to be getting the same issue as I was before. I took some screenshots and labeled them so that it would hopefully explain my issues better. If it helps you think about what I need to do, I am making a fighting game where the animations must be exactly the same each time and completely unaffected by physics (except for the death animation).


下载 ragdollissues.jpg105.9 KB

I believe I solved the issue. I have been using, ragdollInstance::driveToPose when I should have been using ragdollInstance::setPoseModelSpace. There was a warning for using this every frame, but I'm guessing that's just so people don't get confused about how they are driving the ragdoll. The ragdoll now matches the pose of the animation perfectly no matter how quickly I move around or change positions. I'm guessing that in order to make the ragdoll behave according to physics again I would have to begin using driveToPose again? That is my new question :)

Hi fiction--

You probably do not want to call ragdollInstance::setPoseModelSpace() every frame. Quoting from the docs, "setPoseModelSpace() is intended for (re)initialization but not intended to be called continuously during simulation as it can be slow and it will zero all body velocities. To influence (or "drive") the pose of an hkaRagdollInstance over time during simulation, use hkaRagdollRigidBodyController::driveToPose(), or call hkpKeyFrameUtility::applyHardKeyFrame() on each rigid body instead."

It sounds like you only need a ragdoll occasionally, such as when a character dies. If this is the case, you do not need to update the ragdoll at all during regular play. On the frame death occurs, call setPoseModelSpace() once to set the ragdoll's position, apply an appropriate impuse, and then driveToPose() each frame until animation retakes control. If you a need a ragdoll in the course of normal play, however, please let me know what that is and we can discuss solutions.

More generally, the purpose of a ragdoll is nearly always to provide a physical representation of an animation, but it will behave unnaturally when trying to match a physically implausible animation. To put it another way, a ragdoll cannot both be physically plausible and also match the animation in all circumstances - what should it do when the animation of two fighting characters force the ragdolls to overlap, and how does it handle cases when the animation forces the ragdoll through fixed world geometry? I realize that fighting games often switch character poses dramatically over a short time frame (such as your example of instantly switching from running to standing still), but a ragdoll is not suited to this kind of motion. Moving objects a long distance over a very short period of time requires massive velocities, and the ragdoll must also maintain the constraints required by the joints.

Let me know if that all makes sense. Thanks!


I was under the impression that moving the ragdoll was how I was supposed to move the physical representation of the character. I thought that I needed the rigid bodies that make up the ragdoll to exist in normal play so that I would be able to do collision detection on the character. If there is a more efficient way of doing this, and I can use the ragdoll only when a character is hit/dying, then I will gladly switch to that method. As a note, the radoll/rigid bodies that make up a character will not actually ever have to worry about velocities and mass when running into dynamic objects. They will only be colliding with static objects or will have forces/impulses applied to them by the game engine (like when a character is hit with an attack).

Edit: I am a bit confused on how to use hkpKeyFrameUtility::applyHardKeyFrame in order to rotate the entire ragdoll/skeleton. I can pose the individual bones, but I'm not sure how to rotate as a whole using the rotation on my character controller (I have no issues while trying to do this with setPoseModelSpace.
Edit2: applyHardKeyFrame seems to have an invDeltaTime parameter that makes the ragdoll match a pose in a time greater than one frame. I can change the invDeltaTime value to change how quickly the change happens, but it doesn't seem to work within a single frame..

Hi fiction--

Using a ragdoll for high-quality collision detection makes sense, but do keep in mind that the capsule associated with a character controller can provide a faster collision check in most situations, albeit with lower quality. To detect collisions but avoid collision response, you should use HK_COLLIDABLE_QUALITY_KEYFRAMED_REPORTING for the ragdoll, update ragdoll bodies with hkpKeyFrameUtility::applyHardKeyFrame(), disable the ragdoll constraints to avoid unnecessary simulation, and employ collision filtering to disable undesirable collisions.

To get your bones to their world-space position, you should be able to multiply the transforms of the ragdoll bones by the character controller's world transform to get the world-space position and orientation and pass this result to applyHardKeyFrame(). Alternately, you can look at hkaKeyFrameHierarchyUtility::applyKeyFrame().

When calling applyHardKeyFrame(), make sure you are passing 1/timestep (rather than the timestep) to invDeltaTime.

Let me know if this works out for you. Thanks!


I solved the problem I was having with applyHardKeyFrame() where it would not snap to position correctly. I was using the correct time value, but I did not have the motion type of the rigid bodies set to MOTION_KEYFRAMED.

My only other issue at this point is that I am not very experienced with these kinds of things and I am a bit confused how to multiply the transforms to achieve the desired result. If you could tell me how it would be much appreciated.

Hi Fiction--

You can multiply two transforms (for example, hkQsTransform) t1 and t2 by simply calling t1.setMulEq(t2); To transform an entire set of bones from local space to world space, you can also use hkaSkeletonUtils::transformLocalPoseToWorldPose(). It takes an array of local transforms (poseLocal), indexes into them using parentIndices, multiplies them by worldFromModel, then writes the result to poseWorldOut.

Let me know if that works for you. Thanks!


I had originally asked a question in this post, but as an edit I'll say that I found the solution. I was doing boneTransform.setMulEq( proxyTransform ), when I should have been doing it the other way around. Problem fixed and everything is working. Thank you so much for your help!

Hi, I now have debug draw working (from my other question thread), and I've noticed that the skeleton still does not perfectly sync with the model at some points. In the original position everything is fine, and while running the lower body matches perfectly. The upper body seems to have some issues, like leaning forward and the left arm being slightly off at certain points ( the right arm is off too but not nearly as much ). Is this just an issue with how the model and ragdoll were set up, or am I still doing something wrong? As a note, I'm using the ragdoll presented in the maya tutorials, as well as the model from the running tutorials.

Edit: scratch that part about the lower body. The feet are around the ankles of the model. I am sure I am using the correct scaling.


下载 debugdraw4.png1.56 MB
下载 debugdraw5.png1.43 MB

Hi fiction--

Can you draw the pose that you are using to position your ragdoll as well? Perhaps in a different color? Also, have you used the VDB? Does the animation skeleton match the ragdoll when you look at it in the VDB?


I'm not sure what you mean about drawing the pose that I'm using to position my ragdoll. The ragdoll is keyframed as discussed earlier in this thread. I may be misunderstanding your question. I am passing the same bone values to the model as I am to the ragdoll, so that is a good indication of what the ragdoll should look like. Also I have used the VDB, and it appears exactly as the debug display in-game does (meaning that the VDB does not match the pose of the model either. This was actually my reason for wanting to implement a debug view).
Edit: as a note, the sphere over the right hand in the first picture is not connected with the skeleton and is moved individually, and it matches the animation perfectly, which leads me to believe its a skeleton issue.

Hi fiction--

By drawing the pose, I mean drawing line segments that correspond to the individual bones as defined in the hkaPose generated from your animation. You can use AnimationUtils::DrawPose() to draw such a skeleton in the VDB, or you could modify your code to draw it directly into your game. This would be a more accurate way to judge how well the ragdoll matches, just in case there's an issue with how your skinning positions the vertices.

I'd suggest comparing your implementation to one of the demos. The BlendTest demo is a good candidate - by default, it draws the stress on ragdoll bodies as they animate. Once you launch the demo app, seelct Animation>Api>Ragdoll>BlendTest>A 6 Keyframe.

At first, you will notice that the animated skeleton and ragdoll shapes do not match perfectly. However, you can modify the source code (in BlendTest.cpp) to achieve matching. First, you can modify the demo to achieve keyframed motion yby adding the following line to the constructor (around line 463):

for (hkInt16 i=0; i< m_ragdollInstance->getNumBones(); i++)


	m_ragdollInstance->getRigidBodyOfBone(i)->setCollisionFilterInfo( filter->calcFilterInfo(1, ragdollGroup ) );

	// Add the following line:



You can also get hard keyframes by replacing the call to applyKeyFrame() as follows:

// Replace this line:

//hkaKeyFrameHierarchyUtility::applyKeyFrame( m_timestep, keyFrameData, bodyData, &controlData, output.begin() );
// With this:

for (int i = 0; i < m_ragdollInstance->getNumBones(); ++i)


	const hkVector4& nextPos = ragdollPose.getSyncedPoseModelSpace()[i].m_translation;

	hkQuaternion nextOrient = ragdollPose.getSyncedPoseModelSpace()[i].m_rotation;

	hkpKeyFrameUtility::applyHardKeyFrame( nextPos, nextOrient, 1.0f /m_timestep, m_ragdollInstance->getRigidBodyOfBone(i) );


You should now see that the skeleton and rag doll match as the animation plays. I would suggest you then compare this reference implementation against your own code. Some specific things to try:

1. Check whether you perform various function calls in the same order - animation update, physics tick, etc.
2. Check how you've set up the mapper between animation and ragdoll skeleton
3. If you are manually creating your ragdoll, have you called hkaRagdollUtils::reorderAndAlignForRagdoll properly?
4. If you created your assets in a modeller, can you load your assets with the demo code? If so, do they behave differently?
5. Can you load the demo assets in your framework? Do they behave differently?

I hope that's some help. Let me know how it goes.


Okay, so I've looked through BlendTest and I have all of the same code that should be controlling the ragdoll. There's some stuff from about 517 to 568 in BlendTestDemo.cpp about skeleton mapping that I don't have, but I'm pretty unsure of what it's doing with explicit mappings and stuff. I am doing all of the animation update and physics, etc. in the right order. I did not make my ragdoll from scratch. I am using the ragdoll given in MayaModules/tutorials/RagDollToolbox/havokGirl3.mb and the tutorials/ExportBasics/tutorialEnd_MotionExtracted.mb file with the girl running for the animation. I am having trouble loading the resources between the demo and my framework, but I think it is because my framework is incredibly specific because it is still designed for this specific demo. Here is a video (filmed for another purpose) that will hopefully give you a better idea of what the issue might be.

I have also included a photo of a closeup of the feet. I have a feeling that the fact that the feet do not match up, even given the reference pose, is probably heavily connected to the issue here. I'm guessing the issue is with mapping somewhere, but I'm still looking for what the problem could be. Any additional help you may be able to give to point me in the right direction would be very appreciated. This is quite frustrating.

Edit: I've been playing around with the mapping and I've figured out a few things. I changed the Unlocked Bones choice to "All" instead of "Auto", and even though I got 2 warnings, the arms and head were now in place perfectly! I think it just has something to do with the fact that the collarbones are not mapped, and the rig isn't prepared to do movements with locked bones or something. I don't have much knowledge here so many you could illuminate it for me a bit. It was improved, but the torso was still swaying forward. In the original mapping there is a chain mapping from HavokRig_c_back_1 to HavokRig_r_u_up_arm. This is what causes the torso to sway forward, although I'm not sure exactly why. I changed Mapping Source to manual and removed this, and everything seems to work now with the exception of the feet. For some reason the upper length joint is higher up than it is in maya, and the ankle joint is more in the middle of the foot. I'm not sure how to fix this still. Here are a couple screenshots of what it looks like now. (002 and 003). Really not sure if I'm even going in the right direction on this but assuming that the more data I have for you the easier it will be to help me out.


Hi fiction--

The purpose of a hkaSkeletonMapper is to tell the simulation how to match up various parts of the high resolution animation skeleton with the low resolution ragdoll. For example, the three bones of an animated skeleton's spine might be mapped to a single body in the ragdoll. You could definitely see extreme difference between the ragdoll and animation with a bad mapping - the behavior you are seeing with the feet could come from attempting to map the feet of the ragdoll to the ankles of the animation, for example. It sounds like you are creating the mapping in Maya, rather than in code. Have you examined the exported assets in the Havok Content tools Preview application? Does the ragdoll match the skinned skeleton at that point? I've attached an image of how this model looks after I've exported it (ragdollMapping.png). You can hover over a ragdoll body with your mouse, hold space and drag to manipulate the ragdoll with the preview application. Does it respond as you'd expect?

It also looks possible that the pivot of the foot is centered in the box which constitutes the foot, rather than at the joint - notice how the foreleg seems to be attached to the middle of the foot. Did you change the pivot or move the bones before exporting? The pivot should be placed as in the screenshot I've attached (ragdollpivot.png).

Assuming the asset looks fine in the preview tool, are you loading the mapper and applying it by calling mapPose() after calling sampleAndCombineAnimations()? Also, is it possible you are applying some sort of scaling factor to your skeleton, skin, or the skeleton mapper? You said you are having trouble loading the resources in your application - what kind of issues are you encountering, specifically?

Also, it might be helpful if you uploaded your exported asset. Thanks,



下载 ragdollpivot.png107.52 KB
下载 ragdollmapping.png137.39 KB

The asset looks fine in the preview tool. Everything matches just fine. I didn't change anything when exporting. Just grabbed the finished ragdoll from the tutorial and exported. The preview that you showed looks similar to the one I can see and the pivot is in the right position. I am loading the mapper and applying it by calling mapPose() after calling sampleAndCombineAnimations(). For some reason I can't seem to find the .hkx files used by the demo, even though I'm looking in the folders they should be in. I have my animation/rig file and my ragdoll file in the zip file I uploaded. I will continue reviewing my code to try to understand what I could be doing wrong.


下载 havokfiles.zip337.67 KB

Hi fiction--

I was unable to open animationtest2.hkx - it raises an error message when I try to open it in the standalone tools that reads "Wrong platform for packfile." I was able to load the other file, and I agree that it looks right. Perhaps corrupt data is at the root of your problem?

As you continue to look at your code for the problem, it may be worth double-checking your rendering code as well - it is possible that the issue is in the skinned mesh, rather than in the ragdoll. If you are willing and able to provide some minimal set of source code that reproduces the problem, I am also wiling to help you dig into the issue at the code level - though I realize this may not be feasible for you.

Also, all of the demo assets should reside in /Demo/Demos/Resources. What is the name of the resource you are trying to load?


What kind of standalone tools were you using to attempt to open the file? If i can reproduce the error you are getting then maybe I can figure out a way to reproduce and fix the error. The issue isn't with the rendering. I know because of the red sphere around the character's hand and because it visually matches the animation in Maya. (the red sphere was manually animated in maya to follow the character's hand, which it does in the game perfectly). I was looking for hkRig.hkx, but it does not seem to exist in the resource folders. All I have are hkRig.max and hkRig_L4101.hkx, but that hkRig file would not open in my code so I'm not sure what's going on.

It's called "ToolStandAlone.exe" - it should be in the directory where you installed the Havok Content tools. It's the same application that's launched when you add a preview filter in 3DS Max or Maya.


I had accidentally saved as a packfile instead of a tagfile. I have corrected it and exported again. This should open correctly in ToolStandAlone.exe. It still runs the same in my code. I apologize if the code is poorly written, I'm planning cleaning it up more once I have this working.

Loading the ragdoll and mappers file:

hkObjectResource *loadedRagdoll = hkSerializeUtil::loadOnHeap( "HavokResources/savetest4.hkx" );

hkRootLevelContainer *container3 = loadedRagdoll->stealContents();

delete loadedRagdoll;

Initializing the bones.

for( int b = 0; b < m_doll->getNumBones(); ++b )


	hkpRigidBody *rb = m_doll->getRigidBodyOfBone( b );

	const hkUint32 fi = hkpGroupFilter::calcFilterInfo( CollisionLayers::Hurt,

		GetID() );

	rb->setUserData( (hkLong)this );




	rb->setLinearVelocity( hkVector4::getZero() );


Extracting the mappers from the file.

const hkaSkeleton *ragdollSkeleton = m_doll->getSkeleton();

void *objectFound = container3->findObjectByType( hkaSkeletonMapperClass.getName() );

while( objectFound )


	hkaSkeletonMapper *mapperFound = (hkaSkeletonMapper*)objectFound;

	if( mapperFound->m_mapping.m_skeletonA == ragdollSkeleton )

		m_ragdollToHighResMapper = mapperFound;


		m_highResToRagdollMapper = mapperFound;

		objectFound = container3->findObjectByType( hkaSkeletonMapperClass.getName(), objectFound );


if( m_highResToRagdollMapper == NULL || m_ragdollToHighResMapper == NULL )

	assert( 0 && "Error loading mappers" );

Stepping the animation and sampling animations

m_animatedSkeleton->stepDeltaTime( TIMESTEP );

hkaPose pose( m_animatedSkeleton->getSkeleton() );

m_animatedSkeleton->sampleAndCombineAnimations( pose.accessUnsyncedPoseLocalSpace().begin(),

	pose.getFloatSlotValues().begin() );

Mapping the hi-res (pose) to low-res (pose2), sorry for the bad naming.

hkaPose pose2( m_doll->getSkeleton() );


m_highResToRagdollMapper->mapPose( pose, pose2, hkaSkeletonMapper::CURRENT_POSE );

const int numBodies = m_doll->getRigidBodyArray().getSize();

Keyframing the bones

hkQsTransform boneWorldTransform;

for( int b = 0; b < m_doll->getNumBones(); ++b )


	hkpRigidBody *rb = m_doll->getRigidBodyOfBone( b );

	hkQsTransform boneTransform = pose2.accessBoneModelSpace( b );

	boneWorldTransform.setMul( proxyTransform, boneTransform );

	hkpKeyFrameUtility::applyHardKeyFrame( boneWorldTransform.m_translation,

		boneWorldTransform.m_rotation, 1/TIMESTEP, rb );



下载 animationtest3.zip175.9 KB

Hi fiction--

I think the problem is with your assets. From what file did you get your animation data? Is it one of the resources we provided, or did you create it?

I made a simple example app using Resources/Animation/Ragdoll/dismemberment_ragdoll.hkx for my ragdoll, Resources/Animation/HavokGirl/hkRunLoop.hkx for my animation, and Resources/Animation/Ragdoll/dismemberment_skin.hkx for my skin, and with this data I got proper ragdoll matching. I then replaced those assets with savetest4 for ragdoll, and animationtest3 for the animation and skin data. Using this data with my code otherwise unchanged, I saw the same mismatched behavior you observed. My working theory is that the animation data in animationtest3 is based on a different skeleton topology than the skeleton in savetest4. Can you try using the same assets I used and see what behavior you get?


Is there some way for me to get the file of the dismemberment_skin.hkx for Maya? I'm using Ogre for rendering and am exporting the skin to Ogre separately from Maya. Also I got the animation data from the Export and Animation Basics tutorial for the Maya content tools (the motion extracted one). The ragdoll was from the Ragdoll Toolbox tutorial. Also, all of the .hkx files in the demo resources seem to have an extra _L4101 on my computer. For instance, I have hkRunLoop.max and hkRunLoop_L4101.hkx. I do not have a file for hkRunLoop.hkx in my demo resources. When I try to use the files that have _L4101 appended to them using hkSerializeUtil::loadOnHeap(), my hkObjectResource pointer ends up as NULL. The demos seem to run correctly when running with the files names hkRunLoop.hkx and the like. When I tried to look at hkRunLoop_L4101.hkx, dismemberment_ragdoll_L4101.hkx, and dismemberment_skin_L4101.hkx in the standalone tool, they all gave the error "wrong platform for packfiles."

EDIT: As a piggyback question, when using the Create Skeletons filter, I'd like to custom order some bones on a skeleton. However, when I save/load from a file the ordering works but the hierarchy is completely flat. How do I save/load the bone order with the hierarchy intact so I can order the bones differently? (the spine and the right hip are both at the same level in the hierarchy and need to be swapped so I can render with them in Ogre)

EDIT 2: Upon trying to make my own mapping by looking at the Maya tutorial again, I realized that my HavokGirl3.mb demo file had the only Chain Mapping as HavokRig_c_back_1 -> HavokRig_r_u_up_arm. In the tutorial the only chain mapping is HavokRig_c_back_1 -> HavokRig_c_head_0. Not sure how this bug got into my demo, but this fixes at least issues with the back/head on the demo ragdoll. Does not solve the disconnect of arms/feet but may be a slight error in the demo.

Hi fiction--

Unfortunately, the dismemberment_skin assets were created in 3DS Max; no Maya version exists.

The filename suffix on the end of each file is how the demos distinguish between platform-specific files. hkAssetManagementUtil::getFilePath() converts a base path (such as hkRunLoop) into the appropriate path for the platform (such as hkRunLoop_L4101.hkx). The first digit is the number ofbytes in a pointer, the second specifies big or little endian (1 or 0), and the last two some packing optimization flags (reusing padding and empty base classes). Thus, your files are compatible with x86. If you installed x64 tools, then the preview tool would raise the warning you are seeing because you are trying to view x86 data.

In any case, the two assets you are trying to combine are incompatible, which is almost certainly why you are seeing issues in ragdoll mapping. You could use the retargetting functionality to map between the two different skeletons you're currently trying to work with (see BasicPoseRetargetingDemo.cpp for an example), but it would be much simpler to just create your ragdoll from the same skeleton that drives your animation. You should be able to do this by completing the ragdoll tutorial, but starting from the file that contains your animation.

Whn you use the Create Skeletons filter with file ordering, which hierarchy is flat? It might be helpful to see the assets for this case.


Hi, sorry for the slow response. I hope you had a good Thanksgiving. I am making my own ragdoll in Maya and Content Tools, and I seem to have an issue with this:

" [0xabba873d] Warning : Degenerate Capsule (ragdoll_COG): Using Sphere Shape Instead"

on a lot of my bones. I am not doing any odd sort of scaling on them and am using the attribute editor as recommended in the tutorial. For the bones (including some that I do not get the warning on), I get something like
'ragdoll_COG' - Shape shrinking not supported for sphere shapes.

Any idea what could be going wrong here?

Edit: Actually it seems like it was some kind of scaling issue between what the artist had done and Havok. For some reason removing Transform Scene solved the problem. The ragdoll now works perfectly when keyframed. However, the constraints in Maya are turned around a bit, so a dynamic ragdoll isn't perfect. According to the Havok documentation, this is a known issue. The "override joint spaces" option is already on, and everything is still turned around. Will I have to go in and manually adjust each joint template?
Also, I attached a screenshot of the rig working perfectly while keyframed :)


下载 ellseerig.png1.39 MB

Hi fiction--

I'm not sure I fully follow your description of the problem you're seeing in dynamic ragdolls, but manual tweaking often is necessary to get ragdolls behaving properly. If you can give a more specific example of the issues you're seeing, I'll try to help.