How can I get the BoneIKController to work?

Hello!

I have during the last weeks been trying out Babylon and it is quite fun. I have managed to do a few simple scenes and also imported stuff from Blender, including Animations.

My latest project is to try to get the BoneIKController to work but can´t get it to work.

I have made a simple model in Blender consisting of two meshes and a two bones in a armature. Each mesh is parented to a bone using Automatic Weights.
I have also applied all transformations on my objects.

The model was then exported as .babylon format.

In Babylon I then import the model as well as adding two new meshes, a target and a poletarget, for my IKController.

The Cube on top is called Cube2 and the lower cube is called Cube1.
They are not parented to the corresponding Bone, I don´t understand how to do it. I saw the function attachToBone but it takes two arguments, the bone and a Mesh. I have only one mesh per bone so the code would be something like Cube1.attachToBone(Bone, Cube1), this of course does not work…
Is there a better way to to this?

My IK controller looks accordingly,

ikCtrl = new BABYLON.BoneIKController(Cube2, SecondBone, { targetMesh: target, poleTargetMesh: poleTarget, poleAngle: Math.PI });

This does not work at all. It looks like the Bone is tracking the target without bending any bones.
If i look in the documentation the “characterMesh” seems to be one big mesh with several bones so i am guessing I need to do some adjustment in some way.

What is wrong here? I have tested many different variations of this can´t get it to work.

As a total beginner with everything regarding 3D stuff, I feel a bit lost at the moment. If anyone have any suggestions I would appreciate it =)

Best regards
Nessie

let me invite our BoneIK creator: @adam

You kind of need more than 2 bones to do something meaningful with IK.

Here is an IK PG to look at https://www.babylonjs-playground.com/#VSURBJ#2. Just drag either of the 2 control meshes. This mesh did not come from Blender.

I also just got it working from one I got from Blender. There is an option I had to change to get it to work right, that was the bendAxis option. Default is BABYLON.Vector3.Right(). I had to change it to Left(). Otherwise, things bent the wrong way. Not sure you need to do this, but if it looks like the picture you do.

I am not sure how you could even tell though with only 2 bones. There also is different logic in the ikBoneController when the parent bone itself does not have a parent. Not sure I would want to start out with a scenario like that.

Also, the poleAngle is best set by looking at things without turning on update(). PoleAngle is set correctly when after you turn on update(), but before doing anything, it still looks like update() was not run.

Those are the only tips I’ve got.

1 Like

Hello again,

Thank you for your quick response =)

I have looked on the playground and this is exactly what I want to do.
Did not realize that you needed a few more bones, so I added two more Cubes and two more Bones, but still it is not working.

The code I have now looks like this,

let target = BABYLON.MeshBuilder.CreateBox('', { diameter: 1 }, scene);
let poleTarget = BABYLON.MeshBuilder.CreateSphere('', { diameter: 0.5 }, scene);

BABYLON.SceneLoader.LoadAssetContainer("./", "Ik_Testing.babylon", scene, function (container) {
          
          Cube1 = container.meshes[0]
          Cube2 = container.meshes[1]
          Cube3 = container.meshes[2]
          Cube4 = container.meshes[3]
     

          FirstBone = container.skeletons[0].bones[0]
          SecondBone = container.skeletons[0].bones[1]
          ThirdBone = container.skeletons[0].bones[2]
          ForthBone = container.skeletons[0].bones[3]


          target.position = new BABYLON.Vector3(2, 2, 0);
          target.addBehavior(new BABYLON.PointerDragBehavior());

          poleTarget.position = new BABYLON.Vector3(2, 2, 0);
          poleTarget.addBehavior(new BABYLON.PointerDragBehavior());

          target.parent = Cube4
          poleTarget.parent = Cube4


        ikCtrl = new BABYLON.BoneIKController(Cube4, ThirdBone, 
        { targetMesh: target, poleTargetMesh: poleTarget, poleAngle: Math.PI/2 });


        console.log(container)
        container.addAllToScene()


          scene.registerBeforeRender(function () {
            ikCtrl.update();
        })
  })

This seems to be somewhat close to the playground but with the differens that i have 4 meshes instead of one. In the IKController I have tested with both Cube3 and 4 as target mesh and i have also tested with different bones but still nothing that works.
Can you see any obvious errors I am doing here?

Once again, thank you for the help!

BR
Nessie

I think it would be better with anatomic names for your imports:

// for bones
let skeleton = container.skeletons[0];
let spine    = skeleton .bones[0];
let shoulder = skeleton .bones[1]
let upperArm = skeleton .bones[2]
let lowerArm = skeleton .bones[3] 

// if you give your bones meaningful names in Blender (important once you add many more),
// then ref like this
let spine = skeleton.bones[skeleton.getBoneIndexByName('spine')];
...

// for meshes given meaningful names in Blender
let bodyMesh     = scene.getMeshByName('body'); // formerly index 0, maybe
let shoulderMesh = scene.getMeshByName('shoulder'); // formerly index 1, maybe
let uArmMesh     = scene.getMeshByName('upperArm'); // formerly index 2, maybe
let lArmMesh     = scene.getMeshByName('lowerArm'); // formerly index 3, maybe

This is more than cosmetic. Unlike skeletons, which always has bones in a specific order, you cannot rely on what order Blender will export. This is a bug. Also, a skeleton with 50 bones, exported without meaningful names is a disaster. Better to correct this now. It also helps write / explain code here.

Your controller has the wrong arguments. The first arg is the mesh anchoring everything. That would be ‘bodyMesh’. The 2nd argument is also wrong. It should be ‘lowerArm’, not ‘upperArm’.

I am sure there still will be issues on correction, but these are fatal.

True, the naming in this example is not good. In a “real” model i would for sure use better names.
I was not aware about the order issue in Blender exports, I will take not of this in the future.

I continued with my little project and made the changes you pointed out. Now the bodyMesh is the first argument and the “Lowerarm” is the bone. I also added a Skeleton viewer to see what´s happening with the bones.

If i run the scene WITHOUT the IKController, this is what i have.

The cubes, the skeleton, target and poleTarget are all shown as it should.

However, when I turn the IKController back on again I get some strange results, as per below.

image

When the IKControler is on the “Arm meshes” can no longer be seen, and this is also true for the two “Arm bones”.

Is this a problem with my export from Blender?

I read that when the GPU is computing the bones, the CPU don´t know where the meshes vertices are and to do a .refreshBoundingInfo(true) would update the info. This was however noted when you wanted to pick a mesh with the scene.pick(). Did not seem to do any difference.

I will include my .babylon file, if you might suspect that something is weird with it.

Ik_Testing.zip (1.3 KB)

Thanks once again for you kind support!

BR
Nessie