How to reposition multiple bones in skeleton

trying to manually reposition some bones in skeleton, with something like this:

function reposition(position: BABYLON.Vector3, bone: BABYLON.Bone) {
  // same issue is using bone.setPosition or just bone.position
  bone.setAbsolutePosition(position); 
  // this should always be 0!
  const errorOffset = Vector3.Distance(position, bone.getAbsolutePosition()); 
}

and that works fine while repositioning a single bone at the time

but when trying to manipulate multiple bones which have hierarchical relationship, it works for first bone (e.g. Hips as that is the root bone of a skeleton)

but if trying to reposition any of the child bones in the same pass results in some offsetError
(which can be quite large and causes visual artifacts and overall skeleton tearing)

and running reposition again immediately doesn’t change it at all
only solution is to let scene render and repeat the same operation several times
(each time errorOffset gets smaller until it hits zero)

how can i force recalculation so multiple bones can be repositioned in the single pass?

or alternatively, how can i even know that i shouldn’t touch a specific bone since some of its parents have not yet updated rendering?

i’ve tried checking isDirty for all bones and it doesn’t do much

i’ll try to create a playground reproduction, but i hope you get the idea from the description

Hey! you need to force the bone system to update all its value based on the hierarchy

This is done when you call skeleton.prepare() (this is a late call mechanism to avoid computing all the values if not necessary)

It seems that just calling computeAbsoluteTransforms() on the bone after calling setAbsolutePosition() on it positions the bones correctly and reduces the calculated error to 0 (or basically 0, like 1e-21).

2 Likes

I just tried skeleton.prepare, doesn’t help…

setOrigin = (name: string, kpt: Point) => {
  const pos = new Vector3(kpt[0], kpt[1], kpt[2]);
  this.bone[name].setPosition(pos, Space.BONE);
  this.person.skeleton.prepare();
  const error = Vector3.Distance(pos, this.bone[name].getAbsolutePosition());
  console.log(name, error);
};

for example, settings Hips, Neck and Head which are all parts of the same hierarchy of bones - on each frame render error gets smaller and smaller

(actuall position values do not change between frame here, so its really error compared to what position should be):

frame 1 - none of results are good
Hips 0.9503423103910856
Neck 1.0602815252350177
Head 1.0619467861520084

frame 2 - hips are now correct, neck and head are even worse
Hips 2.7157857815200453e-9
Neck 3.9674858221825517
Head 5.030965903722281

frame 3 - hips and neck are ok, but head not yet
Hips 2.7157857815200453e-9
Neck 6.986741067166878e-8
Head 0.9267481806160107

frame 4 - finally all results are good
Hips 2.7157857815200453e-9
Neck 6.986741067166878e-8
Head 8.538947971500482e-8

And I just tried bone.computeAbsoluteTransforms() - that solves it completely
Thank you!

1 Like

My bad, I was on my phone :slight_smile: skeleton.computeAbsoluteTransforms() was what I meant but actually @blake suggestion to do it on the bone is event better!

2 Likes