How would I get an instance's rotation from its CFrame

Hello There! I’m trying to get more involved in CFrame animation/movement.

My question is:
How would I get the rotation of a part using its CFrame?

The only other thing that I would be able to use is Orientation, but when working with the camera I can’t do that.

4 Likes

I have a solution, but it’s a little hacky.

Typically in this case what I’d do is make a dummy part and put it in one of the storage services. Then I would take the current CFrame of the thing I’m editing (like a Camera) and change the dummy part’s CFrame to that, and then take the Orientation after the change is made.

If you’d wanna go in reverse, say get a CFrame from a change in orientation only, change the part’s orientation to whatever you want, then take the CFrame of the part. Change the other object’s CFrame. Nice and easy. I tested this in a plugin I made a little bit ago used to configure cameras in ViewportFrames. It works nicely in my opinion:


Maybe not the most elegant of solutions, but it works nonetheless if you want something nice and simple.

Maybe someone else will post a better solution.

You can use CFrame:ToOrientation, CFrame:ToEulerAnglesXYZ, or CFrame:ToEulerAnglesYXZ. Alternatively, you can calculate it using components of the cframe, for example: You can get the Y axis value by using: math.asin(R02). R02 is also called m31, but calculating the y axis value is the only one I’m aware of when dealing with the components.

FYI: You can get the R02 using CFrame:components()

EDIT: After a bit of research, the other axes values are calculated as follows:

x = math.atan2(-r12, r22)
z = math.atan2(-r11, r00)
2 Likes

The “rotation” component of a cframe can be defined as:

local cf = part.CFrame
local rotation =  (cf - cf.Position)
Here is the expanded version
local cf = script.Parent.CFrame
local UpVec = cf.UpVector
local RightVec = cf.RightVector 
local BackVec = -cf.LookVector

local rotation = CFrame.new(0,0,0,RightVec.X, UpVec.X, BackVec.X,RightVec.Y,  UpVec.Y, BackVec.Y,RightVec.Z ,UpVec.Z,BackVec.Z)

Now that’s just “CFrame rotation” without the position applied , which means that to apply this to another CFrame, in case you wanted to mimic rotation across parts, we must multiply our rotation by the part’s position that we are dealing with first:

local NewCFrame = CFrame.new(pos) * rotation

However this isn’t the same thing as “changing a part’s Orientation”, because Orientation is applied in ZXY order, so the CFrame equivalent of orientation is a bit different:

local cf = part.CFrame
local rotation =  (cf - cf.Position)
local rx, ry, rz = rotation:ToOrientation()
local orientation = Vector3.new(math.deg(rx), math.deg(ry),math.deg(rz))

And because the position component of a CFrame doesn’t make a difference whether it’s left in or out of the equation when using ToOrientation or really “anything dealing with rotation” in that matter we can take out the (cf - cf.Position) and just use the full CFrame, so that our final simplified version becomes:

local cf = script.Parent.CFrame
local rx, ry, rz =  cf:ToOrientation()
local orientation = Vector3.new(math.deg(rx), math.deg(ry),math.deg(rz))

Also here are some links to some useful wiki pages:

14 Likes

I haven’t finished reading your post yet. But is this genuinely the ONLY way to get a model’s rotation?

This is looking like some mega annoyingly complicated fluff that Roblox could’ve done better for those who want to grab JUST an object orientation…

Edit: You code worked for me, but my gripe still stands. Why is something like grabbing an object orientation as complicated as that?

I’m new to using CFrames, and ended up needing to use them for a build system I’m working on. Everything is working up until the orientation.

1 Like