Cloned skinned mesh picking gets broken on original mesh skeleton transform

Hi everybody,

There is an issue with picking a mesh cloned with:
mesh.instantiateHierarchy(null, {doNotInstantiate: true})
If an original mesh is skinned.

Here is a PG to demonstrate that.
Dude’s skeleton root bone is moved to (0, 0, -10).
You can select the original dude just fine. Meshes are highlighted on click.
Cloned dude on the other hand is not selected properly after that.

I’m aware of how GPU skinning works so I added the following picking predicate to recalculate CPU data for every mesh right before picking:

    scene.pointerDownPredicate = (m) => {
        m.refreshBoundingInfo(true);
        return true;
    }

The problem is that the two meshes (original + cloned one) use the same position (and other) buffers and CPU data is recalculated only for the mesh with mesh.skeleton !== null. That happens right here. The cloned mesh just skips this code.

Would be good to have a way to force _getPositionData to recalculate data anyway. Maybe there are more robust solutions.

I ll summon @Evgeni_Popov 's genius here :slight_smile:

It seems you need to make the geometry of the clones unique for picking to work:
https://playground.babylonjs.com/#4I42CF#20

I think the geometry is reused/modified in some way when you compute the bounding boxes by applying the skeleton: if you set false instead of true line 24, you can comment line 20 and picking the cloned mesh does work, but obviously picking the initial mesh does not work as expected because the skeleton is not applied when computing the bounding boxes.

1 Like

@Evgeni_Popov Thanks for the proposal. Yeah, this works with unique geometry because abstractMesh._getPositionData is not called with a skeleton !== null for the copied mesh and positions buffer stays intact as you’ve mentioned.

Unfortunately, my intention is to make it work with a cloned geometry. It is kind of a requirement in my project. This is only possible if for the cloned mesh I would be able to restore the original positions buffer. I’m thinking of hacks like temporary applyting a one-bone skeleton and calling mesh.applySkeleton but that is too hacky.

I think this still should be considered a bug. Right now it is not possible to get correct results by calling mesh.refreshBoundingInfo for cloned skinned meshes. What do you think?

I’m on it actually. The PR will be available soon

Here we are: Fix getPositionData issue by deltakosh · Pull Request #10667 · BabylonJS/Babylon.js (github.com)

3 Likes

Nightly on its way nightly by sebavan · Pull Request #10670 · BabylonJS/Babylon.js · GitHub

1 Like

Awesome stuff! Thanks a lot for the super quick reaction guys. You rock!

So you d need a version of the playground like this: https://playground.babylonjs.com/#4I42CF#21 I am fixing a last issue in the nightly and you ll have it in a couple hours.

2 Likes