Is the name "Euler Angles" used in GODOT correct?

If what I am going to say below is wrong, I would appreciate being corrected, since at the moment I have not seen any literature that would make me think otherwise.

REFERENCE: Euler angles - Wikipedia
When the orientation of a body is defined from three rotations, in some order, with respect to each axis of a system of fixed global axes, it is said that this orientation is being expressed with “extrinsic rotations.” The orientation can also be defined in terms of three intrinsic rotations, that is, in each step a rotation is considered referring to the initial position (in that step) of a system of axes rigidly attached to the object (whose orientation changes in each step). It is possible to relate the angles of intrinsic rotations with those of extrinsic rotations; working with one or the other is a matter of convenience. Two types of intrinsic rotations are commonly considered. One is given by Euler angles, which are made with respect to only two axes (where the first and third rotation repeat same axis). The other is the rotations given by Tait–Bryan angles, one for each axis. The latter are several, depending on the order of the rotations.

By default the orientation encoded in the INSPECTOR is expressed through a specific sequence of EXTRINSIC rotations. That is, the angles associated with each rotation around a fixed axis in general are neither Euler nor Tait-Bryan angles, because these are defined in INTRINSIC rotations.

REFERENCE: Using 3D transforms — Godot Engine (stable) documentation in English
However, the documentation calls Euler angles those used for extrinsic rotations in the INSPECTOR. Furthermore, in GODOT’s INSPECTOR there is a configuration called “Rotation Edit Mode”, which by default is precisely “Euler”.

So why does GODOT use the name “Euler Angle”? Additionally, I have seen other engines using the same designation in the same sense as GODOT, which I suspect is not a coincidence. What’s going on here?

1 Like

From the Wiki page you’ve quoted (have you missed that part?):

  • Proper Euler angles (z-x-z, x-y-x, y-z-y, z-y-z, x-z-x, y-x-y)
  • Tait–Bryan angles (x-y-z, y-z-x, z-x-y, x-z-y, z-y-x, y-x-z).

Tait–Bryan angles are also called Cardan angles; nautical angles; heading, elevation, and bank; or yaw, pitch, and roll. Sometimes, both kinds of sequences are called “Euler angles”. In that case, the sequences of the first group are called proper or classic Euler angles.

So yes, Godot seems to simply call the Tait–Bryan angles as Euler angles, according to the note in the last quoted sentence. AFAICT such convention is not uncommon. But I guess the relevant docs could be improved/clarified to mention Tait–Bryan angles as well.


That’s not really true that what’s presented in the inspector are extrinsic rotations. Let’s read the docs:

Specify the axis rotation order of the rotation property. The final orientation is constructed by rotating the Euler angles in the order specified by this property.

  • From EulerOrder enum, e.g. description for EULER_ORDER_XYZ:

Specifies that Euler angles should be in XYZ order. When composing, the order is X, Y, Z. When decomposing, the order is reversed, first Z, then Y, and X last.

Ok, so it’s saying that rotation order XYZ is rotating firstly around X, then around Y, then around Z. But around what X/Y/Z? Local? Global/fixed? Let’s check it in action!

Let’s create a Node3D, select it, and enable local space for the gizmo so we’ll see the local axes during the rotations (the global axes are drawn anyway):
Godot_v4.3-dev5_win64_6nWGw4VaGm

Firstly rotate around X:
mfwJu6heoi
Then around Y:
3pAi9iwfIW
Then around Z:
pDMafsyRyk

As you can see the rotations are around the local axes, these are intrinsic rotations!
(for the first rotation the global/local axes match each other of course)

But why could you think/conclude that these are extrinsic rotations? Because such sequence of intrinsic rotations can be seen as a reversed sequence of extrinsic rotations, the result will be the same. So e.g. the XYZ intrinsic order gives the same result as ZYX extrinsic order. You can observe in the inspector that when applying the rotations in the reversed axis order these are rotations around the global/fixed axes:

Firstly rotate around Z:
55wExKzaL8
Then around Y:
hLXnCsXnYU
Then around X:
eaRuYQw50T

I think you can see above that these are rotations around global Z, Y, X axes.

Edit: note that in the presented example the Node3D has no parent, hence the global coordinate space is the same as its parent coordinate space. But in general case the fixed coordinate space in which the mentioned extrinsic rotations happen is the parent coordinate space of such Node3D, not the global coordinate space (in the inspector we’re editing the rotation part of this node’s transform, not its global_transform).

So to sum up the XYZ (same for its permutations) Euler rotation order presented in the inspector represents:

  • An intrinsic rotations (around local axes) in order: X, Y, Z.
  • An extrinsic rotations (around fixed, parent-space axes) in order: Z, Y, X.
5 Likes

How clarifying! You are right!

I have the YXZ order by default… and I was reading it from right to left because I thought of Z, X and Y as rotation matrices acting successively. For me it was natural to rotate first Z, then X and finally Y. For this reason, when I did the verification in the Global axis system (or the parent node, as you clarify), I only saw extrinsic rotations.

The truth is, I had seen the topic in another source, but I used the Wikipedia link to be able to share a reference. Shamefully, I had only read the first section, which reproduced what I already knew. I overlooked the equivalence between extrinsic and intrinsic rotations of (Tait–Bryan), which was explained later.

In conclusion:
–The Tait–Bryan angles are not the classic Euler angles but due to use and habit they are called “Euler Angles”.
–The sequence of Tait–Bryan rotations (which are intrinsic rotations) have the equivalent effect of the inverse application of extrinsic rotations.
–It is for this reason that the rotations in the INSPECTOR seem to be applied with respect to “fixed” axes if only one of them or all three are considered in the inverse order of the “fake” Euler angles.

Thank you @kleonc for the detailed response

EDIT: A completely unrelated question: How did you generate all those .gif files?.. I would only know how to do it by capturing video with OBS and with a tedious subsequent process using GIMP

1 Like

Indeed, this can be a little confusing for someone used to matrix multiplication, as YXZ order here refers to Z * X * Y matrix multiplication (assuming basis vectors stored in matrix columns; that’s how it is in Godot). Although the docs clarify a little the order of composition/decomposition, it definitely could be clearer. Plus the tooltips don’t help here:

Godot_v4.3-dev5_win64_T5MIoRMSNu

Godot_v4.3-dev5_win64_f1ptaGSHVS

And a small digression showing that in code you also need to be aware of the ordering: if you’d want to manually compose a Basis for the given euler: Vector3 angles then e.g. for YXZ order you could use:

  • Basis.IDENTITY.rotated(Vector3(0, 1, 0), euler.y).rotated(Vector3(1, 0, 0), euler.x).rotated(Vector3(0, 0, 1), euler.z)
    Note that the order of composing is according to the call order (Y then X then Z).

  • Basis(Vector3(0, 0, 1), euler.z) * Basis(Vector3(1, 0, 0), euler.x) * Basis(Vector3(0, 1, 0), euler.y)
    Note that the order of (intrinsic) composing is according to the right-to-left matrix multiplication (Y then X then Z).

Anyway, no need to use any of the above in code, there’s a static Basis.from_euler method for this.

Oh, I also haven’t reached that part mentioning the extrinsic/intrinsic equivalence. Otherwise I’d probably just link such section. I’ve only searched if there’s a note mentioning that Euler is used for both Tait-Bryan / proper Euler. :upside_down_face:

I use ShareX for that.

Indeed, this can be a little confusing for someone used to matrix multiplication, as YXZ order here refers to Z * X * Y matrix multiplication (assuming basis vectors stored in matrix columns; that’s how it is in Godot). Although the docs clarify a little the order of composition/decomposition, it definitely could be clearer.

I was thinking about
Y * X * Z * vector = Y (X (Z(vector)))
But being the rotation matrices with respect to the system of fixed axes of the parent node (or “global system”)

I use ShareX for that.

ok, I see it’s for windows… I use linux (maybe wine will help)

Is there any way to mark that the question was answered?

2 Likes

I’m not familiar with the forum functionalities myself but looking at the other topics it seems like you should be able to mark some specific post as a solution:

Tk2USbffel

DgBBSdsDYC

It seems that in the “General” section there is no such possibility. I assume that this section is not intended for specific questions but for comments.