Beginner question: pose editor - rotation

Hello,
I made a very simple pose editor which is not working yet:
Playground
So with rotation around an axis it is not like expected:
bone.rotation[axis]=value
or
bone.rotate(rotationAxis, value, BABYLON.Space.LOCAL);
What I am doing wrong here?

Another question: does anybody made a better pose editor in Babylon?

Thank you!

The first question, if you set bone.rotation.x/y/z, you should update matrix after setting.If not, babylon will not update it. You can do like this https://playground.babylonjs.com/#CN4KJL#73 (note: because you use Eular Angle to control rotation, the range of X pitch is from -PI/2 to PI/2 , Y yaw/Z roll is from -PI to PI).
image
Pitch and yaw decide the forward of plane, horizon 360°, vertical 180°

2 Likes

The second question, bone.rotate( axis you want, delta value you want to rotate, rotate space ), you should set delta value into this arg, not the current value. https://playground.babylonjs.com/#CN4KJL#69, I think this is a bad way to set (we are not sure whether bone’s value is equal to current value)

3 Likes

thank you very much - this is very helpful.
The second question was about if somebody else made already such an editor?
I mean with sliders it is the easiest solution but dragging things around and having controls everywhere for rotation like in real 3D editing app is way more complicated so inventing everything from scratch if it already exists would be a huge amount of work here.

I try to improve the UI by selection of one body part. But this is only one mesh with bones.
How to get the correct bone by hover/click event here?
Thank you

I found something what I was looking for: https://playground.babylonjs.com/#2101ZD#5
It seems that on sceletonViewer it is not possible to attach a working actionManager. That is what I tried.
Workaround here: add a sphere for each bone. It would be nice having sceletonViewer clickable for each bone - this is not possible?

It would be really hard to do as the skeleton is on big merged mesh only and not a list of separated ones. Also it is defined in a utility layer which is by design not listening to events :frowning:

1 Like

it doesn’t matter because I just want to draw cylinders at bones now and I have another beginner questions here:

  • the height of cylinder should be height of bone but bone.length is undefined here
  • the local orgin of cylinder should be at bottom but it is in middle. I tried to set center of rotation with setPivotPoint but it does nothing here

Thank you!

bones usually have no length as it depends of the skining… and skeleton.

you can only find it by computing the distance with the next one. You can also check how the skeletong viewer is doing :slight_smile:

About the pivot I would recommend to use an intermediate transformnode instead: https://playground.babylonjs.com//#CN4KJL#79

1 Like

ok that transformnode worked - thank you!
But I am still doing baby-steps here - so new questions :slightly_smiling_face:

  • distance: it was a bit confusing because in documentation there is length property. I followed your advice:
    if (bone.children && bone.children[0]) {
    let child=bone.children[0]
    length = BABYLON.Vector3.Distance(bone.position,child.position)
    }
    sometimes the length is correct but most times not.
    UPDATE: I think I have solved this myself
    bone.getAbsolutePositionToRef(mesh,point1)
    child.getAbsolutePositionToRef(mesh,point2)
    length = BABYLON.Vector3.Distance(point1,point2)
    https://playground.babylonjs.com//#CN4KJL#82

  • also I tried to follow the bone-mesh-clone to the original bone by setting the rotation:
    so as setting a pointer to the same data structure I thought it should do it but it does not work:
    tf.rotationQuaternion=bone.rotationQuaternion
    also if I would have position set the same way there is no need for cylinder.attachToBone(bone, tf); in my opinion? but that all doesn’t work for me.

Thank you!

About length, it should be checked in world space I believe https://playground.babylonjs.com//#CN4KJL#83

Also you can find how it is done internally here: Babylon.js/skeletonViewer.ts at master · sebavan/Babylon.js · GitHub

it does the same with length as my version which I got from that file. but yours is shorter - thanks.

I works now. I switched from cylinder to extrusion + path. So no need for rotation :slightly_smiling_face: (https://playground.babylonjs.com//#CN4KJL#86 )

But I have another beginner question now :slightly_smiling_face:
This is same code but instead of using standard Babylon-dummy file I am using a gdb file:

I can see the object and skeleton but my own objects for bones and joints are gone.
UPDATE: variation using translation nodes: https://playground.babylonjs.com//#CN4KJL#92
using .setParent - but also does not work

Any idea how to fix this?

Thank you!

Here is a fixed version, you need the correct scale, and stop animations from interfering. You also need the gizmo displayed in the correct orientation: https://playground.babylonjs.com//#CN4KJL#103

2 Likes

Thank you! This looks good. About scale. In documentation it writes: "When you attach a mesh to a bone in a skeleton, the mesh will be scaled by the same scaling factor as the parent mesh of the skeleton. "

But as I understand your changes you apply a scale which fits to the skeleton. So this is a bug in Babylon or have I understand something wrong here?

It is correct as you can see here without calling attach: https://playground.babylonjs.com//#CN4KJL#106

mesh.scaling shows a 1,1,1 vector so I still do not understand why the huge balls are getting smaller here.

Anyway it works now and this is great :slightly_smiling_face:

For another feature I need to change the bone length. So is it possible to change the length of a bone?
I tried
bone.scaling = new BABYLON.Vector3(…)
but it does not seem to do anything.

Thank you!

Tou should change the position of the connected bone or transformNode of the bone in the case of a gltf.

1 Like

changing it at transform node works great- I would have never find that.
Thank you!

I have another similar question.
I want to store full pose and restore it.
So I made for each bone:

 let lmat=bone.getLocalMatrix()
 lmat.decompose(scale, rotationQ, position)                

and stored scale,rotationQ and position for each bone. I think just storing lmat should do it as well.

for restoring the pose I made (load for each bone the data from an info object):

let lmat = bone.getLocalMatrix()
BABYLON.Matrix.ComposeToRef(info.scale, info.rotationQ, info.position, lmat)
bone.computeAbsoluteTransforms()
bone._markAsDirtyAndDecompose()

This does nothing which makes sense so far because as I understand I have to make it different because of gltf here and using transformNode but .getTransformNode().getLocalMatrix() does not exists. What is the best solution to do this here? Thank you!