Jump to content

Composition of rotations on bone


yorke
 Share

Recommended Posts

Hi all, I lurked some topics related to bones and their rotation but didn't find a clear solution to my problem, so I try to expose it.

I'm trying to find the best way to compose rotation of bone on all 3 local axes.
In my simulation, i rotate manually the bones of a human rigged model to match desired poses. Everything works fine when a bone rotates only around one local axis (x, y or z), but if I have to compose rotations and rotate, by example, a bone 90° around original x axis and 90° around original z axis, the results are not the ones I  expected.

E.g:

bone.rotate(BABYLON.Axis.X,Math.PI/2, BABYLON.Space.LOCAL); bone.rotate(BABYLON.Axis.Z,Math.PI/2, BABYLON.Space.LOCAL);

gives different results than

bone.rotate(BABYLON.Axis.Z,Math.PI/2, BABYLON.Space.LOCAL); bone.rotate(BABYLON.Axis.X,Math.PI/2, BABYLON.Space.LOCAL); 

So what's the best way to compose rotations on 3 bone axes? Using quaternions and multiplying 3 rotation matrixes with the initial quaternion?

Thus I'd like to write a sort of function rotateBone(bone, x, y, z) that rotates a bone of x degrees around its original X axis, y axis and z axis, where x, y, and z are expressed in radians [0 - 6.28] (or degrees [0 - 360])

Link to comment
Share on other sites

Many thanks to both of you for your good hints.

I'm taking a look at the second PG posted by adam.

After some tests on that PG, it seems to me that calling three times bone.rotate() on local axes and ZXY order is equivalent to setYawPitchRoll(Y,X,Z), which is also equivalent to multiplying quaternions (no order needed in this case). Am i wrong?

Maybe the problems I noticed could be caused by the fact that I was calling bone.rotate() in YXZ order, I'm just verifying

Link to comment
Share on other sites

23 minutes ago, yorke said:

which is also equivalent to multiplying quaternions (no order needed in this case).

Changing the order of quaternion multiplication changes the rotation order.

Note that bone.rotate() accumulates rotation.  It will act differently than the other rotation functions if you are calling it on each frame without resetting the rotation at the beginning of each frame.

http://www.babylonjs-playground.com/#E49AL#5

resetting rotation before using rotate:

http://www.babylonjs-playground.com/#E49AL#6

Link to comment
Share on other sites

Woah just what I needed :D

Awesome adam, the latter PG made things very more clear to me with your explanation about resetting bone and re-applying rotations vs rotating by deltas on previous frame.

Also I was totally missing rotations' order. Putting it at work: still many thanks, you saved me a huge waste of time!

Link to comment
Share on other sites

  • 4 weeks later...

Up.

I'm achieving nice results using bone quaternions, but now i've the problem to let bone rotation not be affected by mesh rotation (or translation)

Thus I can successfully work on bone rotations retrieving bone quaternion, interpolating it with the quaternion of the final pose and reapplying il to the bone:

var quat = mesh.skeleton.bones[i].getRotationQuaternion(BABYLON.Space.WORLD, mesh);
[...] modify quaternion
mesh.skeleton.bones[i].setRotationQuaternion(quat,BABYLON.Space.WORLD,mesh);

but if I rotate the mesh, the poses become wrong because I use world coordinates (e.g. mesh rotates but bone stays in the same place and does not rotate with the mesh).

I tried to substitute Space.WORLD with Space.LOCAL but it gives odd results, e.g if I simply get the bone quaternion in local space and reapply it to the bone without changing it:

var quat = mesh.skeleton.bones[i].getRotationQuaternion(BABYLON.Space.LOCAL, mesh);
mesh.skeleton.bones[i].setRotationQuaternion(quat, BABYLON.Space.LOCAL,mesh);

bone rotation changes, while I'd expect it to stay the same not having changed its local quaternion...

How to let bone quaternion independent from mesh position/rotation?

 

Link to comment
Share on other sites

Thanks raggar and adam for your kind replys

40 minutes ago, adam said:

Don't pass the mesh to the rotation function.

That seems to have done the trick, awesome as usual adam! Passed Space.WORLD with no mesh and everything seems working fine now, doing more tests however.

On the opposite Space.LOCAL continues to give me strange results also with no mesh passed, althought if I saw it's working fine in the PG posted by raggar... But I'm working on models created and imported from blender, don't know if the problem can depend on that.

I'm still on v2.5: I'm planning to move to BJS3 but i'm afraid with compatibility issues - and long, long debug sessions -, I had bad experiences with three.js (although that's a great framework, don't misunderstand me... maybe only a little bit "dynamic")

Link to comment
Share on other sites

Sorry I've still another question on this topic, I couldn't find an answer to this on the forum and official docs on rotations didn't help me.

The question is: is there a way to get yaw, roll and pitch of a bone?

Let me explain: I can rotate a bone using eulers: mesh.skeleton.bone.setYawPitchRoll(y,x,z)

But how do I read those Eulers from the bone? if I try to read them using mesh.skeleton.bones.getRotation() I would have expected to obtain exactly x,y and z passed to setYawPitchRoll() function, but results are quite different. Lurking BJ'S code, I saw that getRotation() gets bone's RotQuaternion and calculates toEulers() on it, so I can't understand why results are different.

By example: getRotation() output (x,y,z) coincide with values passed to setYawPitchRoll(y,x,z) only if x=z=0 and y in [0 , 3.14].

I tried both in local and world spaces but with no result, also tryed with quaternions but didn't arrive to anything...

Am I missing something or babylon uses different euler conventions in those two functions?

Link to comment
Share on other sites

23 hours ago, yorke said:

I'm still on v2.5: I'm planning to move to BJS3 but i'm afraid with compatibility issues - and long, long debug sessions -, I had bad experiences with three.js (although that's a great framework, don't misunderstand me... maybe only a little bit "dynamic")

It will only get worse the longer you wait.

I don't believe you'll face any major issues. Why not give the newest release or preview version a test run, just to see whether or not you've been affected by breaking changes?

Link to comment
Share on other sites

38 minutes ago, yorke said:

Sorry I've still another question on this topic, I couldn't find an answer to this on the forum and official docs on rotations didn't help me.

The question is: is there a way to get yaw, roll and pitch of a bone?

Let me explain: I can rotate a bone using eulers: mesh.skeleton.bone.setYawPitchRoll(y,x,z)

But how do I read those Eulers from the bone? if I try to read them using mesh.skeleton.bones.getRotation() I would have expected to obtain exactly x,y and z passed to setYawPitchRoll() function, but results are quite different. Lurking BJ'S code, I saw that getRotation() gets bone's RotQuaternion and calculates toEulers() on it, so I can't understand why results are different.

By example: getRotation() output (x,y,z) coincide with values passed to setYawPitchRoll(y,x,z) only if x=z=0 and y in [0 , 3.14].

I tried both in local and world spaces but with no result, also tryed with quaternions but didn't arrive to anything...

Am I missing something or babylon uses different euler conventions in those two functions?

http://www.babylonjs-playground.com/#1EVNNB#91

Try updating to the latest Babylon.js version.

Link to comment
Share on other sites

Thanks raggar, I saw your PG and I'm investigating what's wrong in my scene or models, that's really strange. At least you confirmed me that both functions use the same conventions for eulers, that's a good starting point. In previous PGs there was the option to run the PG on an older version of BJS, was this feature removed on PGs from BJS3? I can't see that option.

For what concerns upgrading to v3, you're right but I saw that v3 is not marked as stable yet. 

I'm surely planning to upgrade and wasting some time to let my code compatible with it, but I'll first wait for the stable version

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...