Getting local transformation from each bone and the world transformation of the hkaRagdollInstance

Getting local transformation from each bone and the world transformation of the hkaRagdollInstance

Good day, Havoker!from the Ragdoll Penetration demo,I have successfully ecreated a havok ragdoll from 3dsMax, and it's totally cool in the visual debuger.animation is cool, as well as collision. And I can move and rotate it without problem.In the graphic side, I have a hierarchy mesh.and I can move and rotate each bones with no problem.but I can't seem to join the two properly.I've played around with functions below and some others.

hkaRagdollInstance::getPoseWorldSpace( ragdollPose.accessUnsyncedPoseModelSpace().begin() );
hkaRagdollInstance::getPoseModelSpace( ragdollPose.accessUnsyncedPoseModelSpace().begin(), hkQsTransform::getIdentity() );
 
hkaSkeletonUtils::findBoneWithName();
 
hkaPose::getBoneLocalSpace(bone_id);
hkaPose::accessBoneLocalSpace(bone_id);
 
hkaSkeletonUtils::transformModelPoseToLocalPose();

so far no good :pCan anyone point me the right scenario and function that I should call?so that I can get the local transformation from each bone and the world transformation of the hkaRagdollInstance?Sincerely, Hiro

10 posts / 0 new
Last post
For more complete information about compiler optimizations, see our Optimization Notice.

Hey Hiro,

What you really need is a Skeleton Mapper.

Typically an animation skeleton will have more bones than a ragdoll.
We want to keep the ragdoll as simple as possible to make the physics efficient, but it leaves us with the problem that there is not a 1-to-1 mapping between ragdoll and animation skeleton bones.

I can't find a demo on this exactly in the demo framework, but have a read of the Animation Manual Chapter 3, Section 8, 'Skeleton Mappers'.

Cormac

Hi Cormac!how's going?I've got the idea of having hi-res and low-res bones. I'll read it again during school.Had a little play around, kept hitting breakponits XDI'll do somemore study when I'm back from school.so in the Ragdoll Penetration Demo.it loads animation data into m_posesLowRes[p] at the begining.then during the stepping, when m_statusFlag == falseit's setting stored animation data into m_ragdollInstance

m_ragdollInstance->setPoseModelSpace(m_posesLowRes[m_poseId]->getSyncedPoseModelSpace().begin(), m_currentTransform);

and I assume m_ragdollInstance stores low-res poses?and what I have to do now is to convert the low-res ragdollPose (retrived from m_ragdollInstance) into hi-res poses?

m_ragdollInstance->getPoseModelSpace( ragdollPose.accessUnsyncedPoseLocalSpace().begin(), hkQsTransform::getIdentity() );

and after I got the hi-res posees (using mapPose function?), I can then populate to my hierarchy mesh?btw, even if I use low-res poses,

vectorbone_maping;
bone_maping.push_back( boneMaping("Ragdoll_HavokBipedRig Pelvis01", "HavokBipedRig Pelvis") );
bone_maping.push_back( boneMaping("Ragdoll_HavokBipedRig Spine01", "HavokBipedRig Spine") );
bone_maping.push_back( boneMaping("Ragdoll_HavokBipedRig Head01", "HavokBipedRig Head") );
bone_maping.push_back( boneMaping("Ragdoll_HavokBipedRig R UpperArm01", "HavokBipedRig R UpperArm") );
bone_maping.push_back( boneMaping("Ragdoll_HavokBipedRig R ForeArm01", "HavokBipedRig R ForeArm") );
bone_maping.push_back( boneMaping("Ragdoll_HavokBipedRig R Hand01", "HavokBipedRig R Hand") );
bone_maping.push_back( boneMaping("Ragdoll_HavokBipedRig R Thigh01", "HavokBipedRig R Thigh") );
bone_maping.push_back( boneMaping("Ragdoll_HavokBipedRig R Calf01", "HavokBipedRig R Calf") );
//bone_maping.push_back( boneMaping("Ragdoll_HavokBipedRig R Foot01", "HavokBipedRig R Foot") );
bone_maping.push_back( boneMaping("Ragdoll_HavokBipedRig L UpperArm01", "HavokBipedRig L UpperArm") );
bone_maping.push_back( boneMaping("Ragdoll_HavokBipedRig L ForeArm01", "HavokBipedRig L ForeArm") );
bone_maping.push_back( boneMaping("Ragdoll_HavokBipedRig L Hand01", "HavokBipedRig L Hand") );
bone_maping.push_back( boneMaping("Ragdoll_HavokBipedRig L Thigh01", "HavokBipedRig L Thigh") );
bone_maping.push_back( boneMaping("Ragdoll_HavokBipedRig L Calf01", "HavokBipedRig L Calf") );
//bone_maping.push_back( boneMaping("Ragdoll_HavokBipedRig L Foot01", "HavokBipedRig L Foot") );

this is what I use to retrive the bone_id and the rotations.if I can get the correct bone_id from hkaSkeletonUtils::findBoneWithNamewouldn't it contains the same quaternion rotations as the hi-res?

Hi, people.This is my test 2.The test code is pretty much identical to the PenetrationDemo.And here's the code I tried after the m_statusFlag switching in the stepDemo function.First I tried to get the low-res poses

hkLocalBufferhkQsTransform ragdollModelSpace( m_ragdollInstance-getSkeleton()-m_bones.getSize() );
m_ragdollInstance-getPoseModelSpace( ragdollModelSpace.begin(), hkQsTransform::getIdentity() );

then map low-res(ragdollModelSpace) to hi-res(modelBOut)

const hkQsTransform* localBIn  = poseHighRes-getSyncedPoseLocalSpace().begin();
hkQsTransform* modelBOut = poseHighRes-accessSyncedPoseModelSpace().begin();
ragdollToHighResMapper-mapPose( ragdollModelSpace.begin(), localBIn, modelBOut, hkaSkeletonMapper::CURRENT_POSE );

assumed modelBOut is world translations, need to transform hi-res world space to local space

hkArrayhkQsTransform hires_local( poseHighRes-getSkeleton()-m_bones.getSize() );
hkaSkeletonUtils::transformWorldPoseToModelPose( poseHighRes-getSkeleton()-m_bones.getSize(), hkQsTransform::getIdentity(), modelBOut, hires_local.begin() );

and after we've got the hi-res local transformations,search for the bone we want, retrive its transformation and apply to our hierarchy mesh.

hkaSkeleton* animationSkeleton = const_casthkaSkeleton*(poseHighRes-getSkeleton());
 
vectorboneMaping::iterator it = bone_maping.begin();
while ( it!= bone_maping.end() ){
   bone_id = hkaSkeletonUtils::findBoneWithName( *animationSkeleton, (*it).bone_name.c_str() );
   if( bone_id != -1 ) {
      hkQsTransform trans = hires_local[bone_id];
      Ogre::Quaternion quat = ogreHavokTool::hkQuatToOgre( trans.getRotation() );
      Ogre::Vector3 pos = ogreHavokTool::hkVector4ToOgre( trans.getTranslation() );
      objectTool::setBoneRotation( "ef_ragdoll", (*it).bone_name, quat );
      objectTool::setBonePosition( "ef_ragdoll", (*it).bone_name, Vec3::ogreVec3ToVec3(pos) );
   }
   it = bone_maping.erase(it);
};

so far, the hierarchy meshs are still falling apart...still unsure what steps I should take in order to get the local transformation for each bone.Regards, Hiro

this is testing 3I'm starting to think maybe the havok's and ogre's ragdoll initial rotation doesn't match in the first place.like If I set both the ogre's and havok's particular bone (lets say, shoulder) rotation to IDENTITY.They actually don't match in the virual debuger and the rendering.here's what I tried but not sure if this is how it is done.in the function doRagdollFeedback,before the animation codes

m_ragdollInstance-setPoseModelSpace(m_posesLowRes[m_poseId]-getSyncedPoseModelSpace().begin(), m_currentTransform);
 
for ( int i = 0; i  m_ragdollInstance-getNumBones(); i++)
{
   hkpRigidBody* rb = m_ragdollInstance-getRigidBodyOfBone(i);
 
   // Initialize with quality type and collision filter
   if (rb != HK_NULL)
   {
      _setBodyKeyframed( rb );
   }
}

I did this to just rotate havok's ragdoll shoulder

const hkaSkeleton* animationSkeleton = m_posesLowRes[m_poseId]-getSkeleton();
for( int i = 0; i  animationSkeleton-m_bones.getSize(); i++ ) {
   if( hc::compare( animationSkeleton-m_bones[i].m_name.cString(), "Ragdoll_HavokBipedRig R UpperArm01" ) ) {
      hkQsTransform t = m_posesLowRes[m_poseId]-getBoneLocalSpace(i);
      t.m_rotation = hkQuaternion( hkVector4(0,1,0), 3.146f/2.f );
      m_posesLowRes[m_poseId]-setBoneLocalSpace(i, t);
   }
}

here's thescreenshotand the comparison between havok and ogre.and here's the code I used to rotate ogre's shoulder

objectTool::setBoneRotation( "HavokBipedRig R UpperArm", Ogre::Quaternion(Ogre::Radian(0.f), Ogre::Vector3(0,0,1) ) );

note that the orientation is also different.Havok uses hkVector4(0,1,0) and Ogre uses Vector3(0,0,1);is there anything built-in in the mapping utility that I can use?or maybe some setting in the 3ds exporter?or I'll have to manully code the offsets function?Regards, Hiro

Hi Hiro,

This can be a tricky one to sort out.
Axis conventions may differ. I think typically Ogre uses y-up and 3dsMax uses z-up, and Havok can use any orientation depending on how you've set it up.
The reference pose of the skeleton may be different in the Ogre and Havok representations too.

If the problem is at runtime (setting corresponding orientations between Havok and Ogre) then you'll probably have to make your own debug-drawing tools to visualize the bone orientations to see if they're matching up.

Cormac

Hi, Cormac!some breakthrough!!followed by getting the low-res model poese then convert it to the hi-res model poses.I then tried the following to get the local poses.

hkArrayhkQsTransform renderPose( poseHighRes-getSkeleton()-m_bones.getSize() );
hkaSkeletonUtils::transformModelPoseToLocalPose( poseHighRes-getSkeleton()-m_bones.getSize(), poseHighRes-getSkeleton()-m_parentIndices.begin(), modelBOut, renderPose.begin() );

the meshs are in place but with an additional twist...imageand the weird thing is,the shoulder and head will slowly get pulled towards the body then disappeared.the ragdoll's action in the visual debuger remains the same lo.and here's the trace

quat HavokBipedRig R UpperArm: 0.05, 0.02 -0.05 -1.00
pos HavokBipedRig R UpperArm: 1.53, -0.00 0.00
 
quat HavokBipedRig R UpperArm: 0.05, 0.02 -0.05 -1.00
pos HavokBipedRig R UpperArm: 1.53, -0.00 0.00
 
quat HavokBipedRig R UpperArm: 0.05, 0.02 -0.05 -0.99
pos HavokBipedRig R UpperArm: 1.49, -0.02 0.03
 
quat HavokBipedRig R UpperArm: 0.05, 0.02 -0.05 -0.98
pos HavokBipedRig R UpperArm: 1.25, -0.14 0.17
 
quat HavokBipedRig R UpperArm: 0.05, 0.02 -0.05 -0.97
pos HavokBipedRig R UpperArm: 1.11, -0.20 0.24
 
quat HavokBipedRig R UpperArm: 0.05, 0.02 -0.05 -0.96
pos HavokBipedRig R UpperArm: 0.87, -0.27 0.32
 
quat HavokBipedRig R UpperArm: 0.05, 0.02 -0.05 -0.91
pos HavokBipedRig R UpperArm: 0.52, -0.23 0.28
 
quat HavokBipedRig R UpperArm: 0.05, 0.02 -0.04 -0.82
pos HavokBipedRig R UpperArm: 0.22, -0.10 0.12
 
..............
 
quat HavokBipedRig R UpperArm: 0.00, 0.00 -0.00 -0.00
pos HavokBipedRig R UpperArm: 0.01, -0.00 0.01

First guess is that, maybe because I'm not using the Clavicle and Neck bone? And the mapPose has somehow correct the transformation?(I've tried to set m_bones[i].m_lockTranslation to true, but the m_bones[i] is a const...)Second guess, maybe the ragdoll is smaller?So I tried to increase the scale factor by doing the following.

hkArrayhkQsTransform renderPose( poseHighRes-getSkeleton()-m_bones.getSize() );
hkArrayhkQsTransform worldPose( poseHighRes-getSkeleton()-m_bones.getSize() );
 
hkRotation r;
r.getColumn(0).set(1,0,0);
r.getColumn(1).set(0,0,-1);
r.getColumn(2).set(0,1,0);
 
hkQsTransform t;
t.m_translation.setZero4();
//t.m_rotation.set;
t.m_rotation.setIdentity();
t.m_scale.setAll( 3.f );
 
hkaSkeletonUtils::transformModelPoseToWorldPose( poseHighRes-getSkeleton()-m_bones.getSize(), t, modelBOut, worldPose.begin() );
hkaSkeletonUtils::transformWorldPoseToLocalPose( poseHighRes-getSkeleton()-m_bones.getSize(), poseHighRes-getSkeleton()-m_parentIndices.begin(), hkQsTransform::getIdentity(), worldPose.begin(), renderPose.begin() );

no changes no matter how I set the m_scale...
UPDATE :I've change the transformation matrix from
1 0 0
0 1 0
0 0 1
to
1 0 0
0 0 -1
0 1 0
intheTransform Scene setting. and it fixed the additional twist.
but the disappearing still happens.
Regards, Hiro

Hey Hiro,

Glad to see you won't give up and keep working at this - it'll come right eventually!

- How have you defined your skeleton mappers?
Are you using the filter in the Havok content tools?

- Are the meshes of the body parts defined in the same coordinate system as the bones?
(i.e. if you line up the XYZ axes of the mesh with the axes of the bone, is it in the correct orientation?)

- The same question regarding the bones of the hi-res skeleton and the low-res skeleton (ragdoll)

Consider writing a debug display tool for Ogre, to compare your skeleton axes.
It'll come in useful every time you make a character, because these kinds of issues will keep arising.
And also, just writing it may give you ideas as to what could be going wrong.

Cormac

Thanks for the help Cormac!for now, it's all good!! yeah!!!after I added the Clavicle and Neck bone to the ragdoll, the shoulder and head now stays where they should be.I didn't include them in the first place because penetration_rig.max didn't use it too.guess maybe the Clavicle and Neck didn't get poseMapped, but still taking effects from gravity? and then Ogre did its culling thingy when the bone's translation went wrong... or something.the good thing is,now I don't have to search for the bones, cause the poseHighRes-getSkeleton()-m_bones[i].m_name IS the name of the bone's name of the Ogre hierarchy mesh.I'll just have to loop from 0 till poseHighRes-getSkeleton()-m_bones.getSize()the only issue I'm getting is the pelvis transformation.if I apply the pelvis' translation direct to the pelvis' skeleton. the x and z seemed flipped.when I move towards x+ it's acturally z+, and so do the rotation.if I apply the same translation to the object itself (or the debug display draws), I got the right position but the wrong rotation...it's like an additional 90 degree's roll has applied.here's the work around.

hkQsTransform trans = renderPose[i];
Ogre::Quaternion quat = ogreHavokTool::hkQuatToOgre( trans.getRotation() );
Ogre::Vector3 pos = ogreHavokTool::hkVector4ToOgre( trans.getTranslation() );
 
if( hc::compare( poseHighRes-getSkeleton()-m_bones[i].m_name.cString(), "HavokBipedRig Pelvis" ) ) {
	quat = quat * Ogre::Quaternion( Ogre::Radian(-3.146f/2.f), Ogre::Vector3(0,0,1) ) * Ogre::Quaternion( Ogre::Radian(-3.146f), Ogre::Vector3(0,1,0) );
	objectTool::setObjectRotation( "ef_ragdoll", quat );
	objectTool::setObjectPosition( "ef_ragdoll", pos );
} else {
	objectTool::setBoneRotation( "ef_ragdoll", poseHighRes-getSkeleton()-m_bones[i].m_name.cString(), quat );
	objectTool::setBonePosition( "ef_ragdoll", poseHighRes-getSkeleton()-m_bones[i].m_name.cString(), pos );
}

though everything worked.but not satisfying... :p don't feel comfortable with the extra rotation work.- q1I tried mimicing the setting in the penetration_rig.maxin the step "Create Ragdoll", if I choose "Use Skeleton"I dont get the option for "Ragdoll_HavokBipedRig Pelvis01" in "Skeleton B" in the step "Create Mapping"and I still can't find out why...therefore, I choose "Use Physics System".so I got my sweet "HavokBipedRig Pelvis" for "Skeleton A" and "Ragdoll_HavokBipedRig Pelvis01" for "Skeleton B"in the "Define Mappings". I use "Auto Pos" and "Auto". I tried setting it manually... couldn't figure out what i was doing XD- q2are you refering to the max file's mesh and biped skeleton?ouuuuu.... not sure where to look.if I switch the rotation reference to "Local" in 3ds and clicking on an object.the biped skeletons and havok rigid bodies have all different orientations.but all my mesh parts are z up, x right and y going into the screen.which means... they are not lined-up?- q3ah yes, I've done tracing the values from low-res to hi-res and vice versa (also world).most of the bones are identical except Spine - Spine + Spine01 + Spine02.guess this is how it is :)Regards, Hiro

Hey Hiro,

It's hard to visualize since there are really 3 systems here - 3dsMax, Havok and Ogre, and all of them could be making different assumptions about the coordinate systems.

Sounds like you're doing ok with the exporter, or at least not going too far wrong.

As for the root translation issue - take a look at the Ogre nodes at the root.
I seem to remember there might be an extra node that's the parent of the Ogre skeleton that might have some rotation on it. Or the Ogre skeleton root is rotated relative to that parent. Either way, when you apply translation to the skeleton root node it might go wrong.

Cormac

PS Do some debug drawing! :)

Login to leave a comment.