There is no mention of the fromEulerAngles constructor
Page URL: https://create.roblox.com/docs/en-us/reference/engine/datatypes/CFrame
There is no mention of the fromEulerAngles constructor
Page URL: https://create.roblox.com/docs/en-us/reference/engine/datatypes/CFrame
No, there is a constructor named fromEulerAngles
that takes 3 numbers and an optional RotationOrder
.
Thanks for the report! We’ll follow up when we have an update for you.
Thanks so much for calling this out. I’ve added the missing constructor here: CFrame | Documentation - Roblox Creator Hub
Thank you for adding this to the documentation, though it seems the rotation order described doesn’t align with the rotation orders described for fromEulerAnglesXYZ and fromEulerAnglesYXZ.
On the rotation order page it says Enum.RotationOrder.ZYX
applies rotation orders in the order Z,Y,X which is the same as described in the fromEulerAnglesXYZ constructor.
print(
CFrame.fromEulerAngles(1,2,3,Enum.RotationOrder.ZYX)
==
CFrame.fromEulerAnglesXYZ(1,2,3)
) -- false
print(
CFrame.fromEulerAngles(1,2,3,Enum.RotationOrder.XYZ)
==
CFrame.fromEulerAnglesXYZ(1,2,3)
) -- true
print(
-- X,Y,Z order
CFrame.Angles(0,0,3)*CFrame.Angles(0,2,0)*CFrame.Angles(1,0,0)
==
CFrame.fromEulerAngles(1,2,3,Enum.RotationOrder.ZYX)
) -- true
From these tests it seems that Enum.RotationOrder.XYZ
is doing Z,Y,X order not Enum.RotationOrder.ZYX
, and that Enum.RotationOrder.ZYX
is actually doing X,Y,Z order. The rotation orders described on the documentation for RotationOrder and fromEulerAngles should be reversed to match the orders described on fromEulerAnglesXYZ and fromEulerAnglesYXZ.
Also, I just noticed that there is a method ToEulerAngles
that takes an optional RotationOrder (default Enum.RotationOrder.XYZ
) to complement fromEulerAngles
.
local x,y,z = CFrame.fromEulerAngles(.5,.6,.7):ToEulerAngles(Enum.RotationOrder.XYZ)
print(
CFrame.fromEulerAngles(x,y,z,Enum.RotationOrder.XYZ)
==
CFrame.fromEulerAngles(.5,.6,.7,Enum.RotationOrder.XYZ)
) -- true
Hi FindFirstChild, thanks for the response and the sample code – – it’s been helpful in trying to get this all sorted out. My takeaway isn’t quite the same as yours, though. My understanding is that the rotation order descriptions on the CFrame
page are incorrect and that the ones on RotationOrder
are accurate, as one would intuitively hope based on their names.
A variation on your last code sample, where you manually force a particular rotation order, seems to demonstrate this point, but maybe I’m missing something:
local cframe4 = CFrame.fromEulerAnglesXYZ(1, 2, 3)
local cframe5 = CFrame.fromEulerAnglesYXZ(1, 2, 3)
local cframe6 = CFrame.fromEulerAngles(0, 2, 0) *
CFrame.fromEulerAngles(1, 0, 0) *
CFrame.fromEulerAngles(0, 0, 3)
print(cframe4 == cframe6) -- false
print(cframe5 == cframe6) -- true
For the fromEulerAngles()
calls, we can actually specify any Enum.RotationOrder
and get the same result, because of the zeroes and how we’re forcing Y, X, Z order in the multiplication/composition statements.
local cframe4 = CFrame.fromEulerAnglesXYZ(1, 2, 3)
local cframe5 = CFrame.fromEulerAnglesYXZ(1, 2, 3)
local cframe6 = CFrame.fromEulerAngles(0, 2, 0, Enum.RotationOrder.ZYX) *
CFrame.fromEulerAngles(1, 0, 0, Enum.RotationOrder.YZX) *
CFrame.fromEulerAngles(0, 0, 3, Enum.RotationOrder.ZXY)
print(cframe4 == cframe6) -- false
print(cframe5 == cframe6) -- still true, even with the random enums
Am I misunderstanding something important here? My current plan is to run through the CFrame
page, un-reverse all the rotation orders, and add the missing method that you pointed out, but I wanted to check in first and see what you thought. Thanks again!
See Contradictory fromEulerAnglesYXZ Documentation - #3 by NPh_rd
It appearing backwards is the result of the different ordering between roll pitch yaw and euler angles if I remember correctly.
Thanks for the extra context. I did… perhaps too much digging into this and basically came to the conclusion that the technical, mathematical way of approaching rotation order isn’t especially helpful and obscures the information we want to present, which is just, “What does this function do?” I added a bunch of examples that demonstrate equivalency and the behavior of the functions and removed a lot of the “applies the rotations in a given order” statements that were so rooted in matrix math.