PcoWSkbVqDnWTu_dm2ix
We use cookies on this site to enhance your user experience

Jul 02 2018, 5:54 PM PST 5 min

Euler angles are a way to represent the rotational orientation of an object in 3-dimensional space, using three angles. The order in which these angles are applied is important, as different orders of these rotations lead to different final orientations.

Roblox uses “intrinsic XYZ” Euler angles (equivalent to “extrinsic ZYX”), meaning that the rotations happen in object space, in the order XYZ, for CFrame rotations. The BasePart/RotVelocity property uses extrinsic XYZ angles instead.

Understanding Euler angles

Euler angles represent a series of rotations in different axes. Let’s assume we apply the euler angles 30°, 60°, and 45° to a brick. We can visualize this as a sequence of simple rotations:

  • Rotate the brick in its X axis by 30°
  • Rotate the brick in its Y axis by 60°
  • Rotate the brick in its Z axis by 45°

An important thing to note here is that rotations are done relative to the bricks position at each step. At step two, the brick is tilted - the Y axis is no longer vertical.

If we reverse the order, we can use absolute axes

  • Rotate the brick in the world Z axis by 45°
  • Rotate the brick in the world Y axis by 60°
  • Rotate the brick in the world X axis by 30°

Converting Euler angles to a CFrame

To actually do this rotation in roblox, you would use math.rad to convert your angles to radians, and CFrame.Angles to create the CFrame.

part.CFrame = CFrame.Angles(math.rad(30), math.rad(60), math.rad(45))

It’s worth noting that in general:

CFrame.Angles(x, y, z) == CFrame.Angles(x, 0, 0)
                        * CFrame.Angles(0, y, 0)
                        * CFrame.Angles(0, 0, z)

Converting a CFrame to Euler angles

Roblox provides a method to convert a CFrame to Euler angles, CFrame:toEulerAnglesXYZ()

local x, y, z = part.CFrame:toEulerAnglesXYZ()

However, this is generally not the right solution to the problem you are trying to solve. Some common cases for which this is the wrong solution:

Getting only the rotational part of a CFrame

Sometimes, you might want to copy the rotation of one brick, and apply it to another, without moving the second brick. An obvious approach is

local x, y, z = part1.CFrame:toEulerAnglesXYZ()
local rotation = CFrame.Angles(x, y, z)
part2.CFrame = rotation + part2.Position

While this method works, it is terribly inefficient, and prone to rounding errors. A much better approach is

local rotation = part1.CFrame - part1.Position
part2.CFrame = rotation + part2.Position

To get only the rotational part, you can just subtract the position!

Finding the heading of a part

You might want to show the angle the player is driving a vehicle at (0 - 360°) in a GUI.

local direction = part1.CFrame.lookVector
local heading = math.atan2(direction.x, direction.z)
heading = math.deg(heading)

Extracting Euler Angles

Given CFrame matrix, the Euler angles can be extracted from the CFrame like the following demonstrates.

local sx, sy, sz, m00, m01, m02, m10, m11, m12, m20, m21, m22 = matrix:components()
--            m12 = −cos Y sin X
--            m22 = cos X cos Y
--  => -m12 / m22 = sin X / cos X ]]
local X = math.atan2(-m12, m22)

--  m02 = sin Y
local Y = math.asin(m02)

--            m01 = −cos Y sin Z
--            m00 = cos Y cos Z
--  => -m01 / m00 = sin X / cos X ]]
local Z = math.atan2(-m01, m00)

See Also

  • DataType/CFrame
  • DataType/Vector3
  • Tait–Bryan angles, the technical name for the class of Euler angles used by Roblox
Tags:
  • movement
  • math
  • animation
  • coding