# Animating quaternion vs euler

## Recommended Posts

Hello again

I'm trying to animate between two rotations (from 0 to 45 degrees).

If I use euler angles, it works fine. If I use quaternions however, it doesn't (it goes to about 20 degrees). See PG below, comment/uncomment lines 44/45.

Any thoughts?

EDIT: Just found out about .rotationQuaternion, seems to work now

Thanks!

##### Share on other sites

Possible fun playground.  You can repeatedly click the x/y/z buttons at the top, setting the mesh rotating via physics applyImpulse twist-thrusting, and watch the mesh rotationQuaternion and its .toEulerAngles() output.  Physics engines LOVE quaternions, and nearly ALWAYS support the Quaternion Party in campaigns/elections.

Quats.  Tumor-causing.  Some webpage somewhere described them as "3 values to aim an arrow, and a 4th value to set the rotation AROUND that arrow".  *shrug*  They are supposed to eliminate something called gimbal lock, which happens to Eulers as values get near the poles.

I could be wrong, though.  I consider myself within the top 10 BabylonJS users... at being wrong.  heh

##### Share on other sites

As usual, you are correct.  Euler angles are generally represented by pitch, roll, and yaw angles/values to set the axis of rotation, as well as an angular vector for translation. Although the order of pitch, roll, and yaw are often ordered differently; these should be re-ordered by the developer when necessary to provide the desired behavior for an object's transforms. Basically every transform applied in most every software application and/or base algorithms for object transforms in most frameworks compute in euler angles, and convert these values to quaternion (x,y,z) values to make these processes simpler for the user - as it is much easier to graphically represent quaternion values in graphic applications for a UI as well as for building function curves and other graphic tools for additional animation control and representation.

The reason gimble lock most often occurs when using euler angles/values is that even though no limit exists for euler values, and they can be set to practically any value (ie. +/-10,000 if necessary), most applications "normalize" euler values to be +/- 180 degrees (you'll often find "normalize" as a function used in most graphic applications), which then can cause "gimble lock" and more often "flipping" in an object's rotation, as euler values of -180 and 180 often produce the exact orientation for an object's vector since normalized euler angles produce no euler vector value < -180 and > 180 degrees. So rotating an object on a single euler axis produces the same orientation state at -180 and 180 degrees, depending on the value of the other two angles. So typically there is no way to rotate an object numerically and avoid "flipping" using only euler angles more than one 360 degree rotation - without additional algorithms. And what is often overlooked is that the order in which you apply values to an object's euler angles changes the transformational behavior dramatically. So if you are using euler angles/values in your scene and experience "gimble lock" on a bone object or "flipping" on objects or cameras, then by simply changing the order of rotation - which is the order in which the euler values are applied - can often correct these undesired behaviors

There is certainly allot more to euler and quaternion math, but I hope this provides a basic understanding of behaviors and when and how to use Euler values on a fundamental level. And I agree completely with Wingnut, that I have almost always found it faster to work with animating objects using quaternion values.

DB

##### Share on other sites

Thanks DB!  You should be a trigonometry professor making the big bucks.  That was a sweet explanation.

Just a reminder... DB did it once before, too.  http://www.html5gamedevs.com/topic/3083-spaces-world-parent-pivot-local/?do=findComment&comment=63384

Three posts in a row, there... excellent.  I get .016% better at BJS each time I read them.  Good stuff.  (He's worked-with motion capture/control in major movies, ya know?)

Yuh, DB is a "space cadet".  There's very few people who have such a close working-relationship... with space.    (Wingy swats at minor coordinate points in space, sparkling, colorful, the energy staples holding together the fabric of his reality.)  (or maybe they're faeries!)

##### Share on other sites

If you only knew what a space cadet I really was... Thanks for the props on my last post - I also posted it in the spaces thread, and will get back to sharing more of the little I do know about dimensional space and the math driving it. I was simply lucky enough to work in motion capture at a time before it was easy and there were applications to handle the math - so I had to learn hard core linear algebra to be able to script tracking the first optical systems we built using only crappy security cameras. And I was able to do this, as in all seriousness, NO ONE in the early to mid 90s believed that motion capture would ever be able to produce quality animations - even the game industry, which amazed me at the time.

I've got loads of great stories of where the math has worked fantastic for me, as well as the worst scenarios where for example, a producer ripped me a new "you know what" when I first built the mocap system for the Matrix films - and on the first day of shooting the "math" which allowed the systems to create a very large 3 dimensional volume from multiple smaller volumes completely failed - and the production was spending almost one quarter million dollars a day during the mocap shoots. So that was a very, very bad day - and caused me to take the math allot more seriously than I had ever before.

But there's lots of "tricks" I should provide the community for working with Euler and Quaternion values, and one of the first things I'm going to look into is possibly providing a function allowing Euler values > 180 and < -180, which can solve allot of problems I read on this forum. This would be a function that would permit any value to be set for Euler angles and block the "normalize" function - permitted this is being set in the babylon.js master script. I will also look at the available functions to change the order of Euler angles - so @Deltakosh - if you can let me know if you are normalizing Euler values, or if this is handled in WebGL; and this as well as what functions are available to change the order for both Euler and Quaternion values in babylon.js, this would give me a good head start on providing these or what might be missing to users in the master file. Also I haven't found a function to freeze transforms for either Euler or Quaternion, which would help allot of users - which I'm guessing you have already provided, but if not, these are the types of tools I can provide as well as how such functions can be used to provide additional efficiencies and allow users to avoid "flipping of axis' and "gimble lock" for bones, cameras, and other objects a majority of the time.

Thanks,

DB

##### Share on other sites

Hello @dbawel

Euler values are not normalized. They are transformed into rotation matrices but not normalized.

Regarding freezing, you can freeze a mesh but not individual properties (translation, rotation,scaling)

##### Share on other sites

Hi DK,

Interesting, I'll look closer at the babylon-master.js file to see how you are transforming rotation matrices''. And how ever you are manupulating axis values and/or input values should be interesting, as I appear to see far fewer gimble lock on bones than I might normally expect. I'll also think through what value there might be in calling a freeze matrices' function - as I should evaluate the additional value of freezing transforms in babylon.js, as opposed to Blender or any other 3D application - which is highly recommended and necessary in many cases.

Thanks for the info, as this saves me allot of time parsing through the master BJS file in search of functions which may not exist. Also, FYI - Im truly amazed how easy it is to read through and "mostly" understand the babylon-master.js file after working with the framework for about 2 years now. It truly appeared closer to an alien language to me the first time I tried to read through it, compared to how it appears now.

Cheers,

DB

EDIT - And DK, I see that the order of rotation is Y, X, Z. I cannot find any other functions to change the order of rotation, so am I overlooking any re-order function(s)?

Edited by dbawel

##### Share on other sites

I guess the only one order is Y, X, Z in BJS ... as it feels the most like natural head movements (I mean anatomic "gimballs") like it could be expected in games :  Y == shaking first (to deny), X == nodding then, at last twisting  == Z

I didn't find so far another order in the code so far... maybe is it hidden in the deep mysterious part I didn't explore yet ?

##### Share on other sites

The ManipulationHelpers extension at https://github.com/BabylonJS/Extensions/tree/master/ManipulationHelpers doesn't set a different order, however, it appears to have some good code examples which might provide a head start on setting/changing the order of rotation. Also, thanks for pointing to the function setting the rotation order, as it appears to be a simple change to the function - although I'm thinking about a function similar to how Houdini handles rotation order which can be set on a differently on an individual chain and/or animation, and/or frame range. Not so simple.

As I mentioned previously, I need to evaluate the value currently in babylon.js, however, exporting skeleton animation from Maya and other applications can often cause serious undesired behaviors since there are multiple matrices' driving their IK chains - and this must also be the case with Blender, as all IK requires additional transform behaviors - depending on how they process their IK chains. Not that it matters, but Houdini allows 3 different IK solutions to be set - which used to throw our productions into chaos if the artist wasn't experienced in the software. For me, it's potentially an issue - as I generally use mocap for biped and quadraped animation, and retargetting performance can be assisted/changed dramatically by changing the order of rotation - especially for a specific skeleton animation(s) and not all animations in a move tree, which is why such a function has been incredibly valuable in the past. I don't have a need right now, but it might be fun to build this function and see if anyone else finds it useful. And consider the case of a skeleton such as the Shrek donkey, which has 4 joints (consider the hip) in each leg alone - and an incredibly flexible neck with 9 bones. It required building a whole new IK system for the project, and rotation order was at the top of the list.

As far as freezing transforms, this is a function I believe anyone using mocap or blending animations in move trees would benefit - providing they are working with skeleton animations and didn't have the foresight to freeze all transforms before animating or retargetting. Especially scale, as this can often destroy any hope of saving an animation. However, this would probably be quite a challenge to build in BJS, or any framework where the skeleton already has animation attached. But I should look at the master file, since I'm often amazed by the forethought @Deltakosh, @davrous, and all of the other "Brainiacs" consider when contributing to the babylon-master.js file.

DB

##### Share on other sites

Changing the order of rotation could be easy to integrate to be honest. We can define an enum to specifiy which order to use.

Just wondering: why doing this?

##### Share on other sites
``````Quaternion.prototype.toEulerAnglesToRef = function (result, order) {
if (order === void 0) { order = "YZX"; }
var x = this.x, y = this.y, z = this.z, w = this.w;
switch (order) {
case "YZX":
/* ........*/
default:
throw new Error("Euler order " + order + " not supported yet.");``````

Just a switch case away (btw the documentation says Babylon uses the YXZ order but the code says otherwise )

46 minutes ago, Deltakosh said:

Just wondering: why doing this?

Here is a scenario I ran into last week: slerping quaternions.

Unity uses ZXY. If I bring in a scene from Unity, and want to add rotation to my quaternion without going through the pain of working out matrices, I would need to go from quaternion to euler, add 30 degrees to X, then switch back to quaternions. Currently if you do this you end up with a different quaternion  Same final angle, different quaternion representation. Which when you start slerping, gives you 2 different trajectories hehe.

Pretty specific case I know, but if it's not too hard, that would be a great addition

##### Share on other sites

sounds good to me! please submit a PR

##### Share on other sites

Hey @Deltakosh - I believe @Numa gave a good answer, however, here is a good example of changing the rotation angles in XSI - which is a Y up world orientation aplication, and provides good examples of the difference in performance on skeletal animations:

Quote

Figuring Out the Rotation Order

To help you figure out what the rotation order for a bone should be, it’s best to start with the skeleton in a neutral pose with the bone’s rotation at 0 (see Creating Neutral Poses for Skeletons). Then start posing the skeleton with its most common movements to see where problems can occur.

Mapping the XYZ axes to movement type (such as flexion/extension, medial/lateral, abduction/adduction) can also help to reveal the most useful rotation order. Usually one type of movement will usually be dominant: its axis is the one that you want to be last in the rotation order so that it won’t be affected by the other axes.

For example, let’s compare the XYZ and YZX rotation orders on the humerus bone (biceps) in an arm. With the XYZ order:

• X twists the biceps, which is not that useful in many cases.

• For arms resting at a character’s side, the Z and X approach gimbal lock.

• The back and forth swing of the arm is not easy to animate in FK.

Now by making X the last in the rotation order, the X can be used for animating the back and forth swing an arm has when a character is running or walking. Making it the last also means that the swing axis never changes, which it rarely does because it’s determined by the shoulders.

Meanwhile, Z and Y can still move appropriately:

• Z is natural for medial/lateral movements, like the swing in a punch.

• Y is used for raising and lowering movements. Raising/lowering is usually a much more deliberate movement that comes more from flexing the shoulder muscles. It tends to move along with back and forth or medial/lateral movements, so it makes sense to have it first in the order.

So after analyzing the character’s movements, YZX seems like the best choice for animating the humerus.

Preventing Gimbal Lock

To prevent gimbal lock, there are a few different ways in which you can change a bone’s rotation order.

• When you set up character a rig, you can align the chain’s root with the first bone and set the bone’s rotation order to ZXY or YXZ instead of the default XYZ. Then the middle rotation (X) (which causes gimbal lock) is on the least-used rotation (that is, rotating along the length of the bone).

• If an object needs to rotate only along one axis, change the order of axis to match it; that is, if the object is rotating around the Y axis, change the order of axes to YZX.

• If an object is rotating on two axes, change the order of axes to correspond with the first and last axes; that is, if the object is rotating around the X and Y axes, change the order of axes to XZY.

• In addition to changing the rotation axes order, you can also convert the rotation angles from Euler to quaternion. Quaternion rotation angles produce smooth interpolation to help prevent gimbal lock.

I'm glad I didn't have to write the above. Search/ Copy/ aste is my very favorite function.

Cheers,

DB

##### Share on other sites

please let me know when this change (adding the ability to change the rotation order) because this will need to change also the RotationFromAxis() algorithm, what is a three step decomposition based upon the current order : actually a backward projection of the given axis to compute the angles.

Aaarrggg... not that easy to modify, but still feasable

Unless we assume (until I find the time and the way to improve it) that RotationFromAxis() always returns only a yaw-pitch-roll rotation in the YXZ rotation order ... for now

##### Share on other sites

Just to be sure: regarding bones you don't need this as bones only have a simple transform matrix and no position/rotation/scaling properties

So do you still think it is required? do you plan to animate meshes manually and not through bones?

##### Share on other sites

@Deltakosh hehe sorry I don't know enough about it to write the code myself, we need a quaternion boss to step in

##### Share on other sites

Hi guys!   Sorry to butt-in, but I have a few questions.

I think our 3D Max exporter has a "export rotation as quaternion" check box.  Does our Unity exporter have the same?  Just curious.  It probably doesn't affect the issue.

To try to clarify the issue...

A quat slerp animation done to a model within Unity... has a different animation trajectory... when the same quat slerp is applied to the same model... after it is imported into BJS (and therefore uses a BJS quat afterwards).

Does that sound correct?

Unity model, Unity slerp, Unity quat = one trajectory.
Imported-to-BJS Unity model, same Unity slerp, BJS quat = different trajectory.

Could this be solved with a slerp converter?  Possible?

If the Unity quat slerp could be converted to BJS quat slerp after/during BJS import, then the animation trajectory would be identical for both, yes?

Maybe this is what you guys are already thinking-about.  *shrug*  I'm not at all qualified to speak about ANY of this, but what the heck... I don't mind looking stupid... if it somehow leads to a new idea.  Thx for answers and for patience with my noobness.  Be well, everyone.

## 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.

×   Pasted as rich text.   Paste as plain text instead

Only 75 emoji are allowed.