How does rotation on CFrames work exactly?

Bed has a Y rotation of 90, but my prints are returning like 1 and 0?

local _, Rotation, _ = Model.PrimaryPart.CFrame:ToEulerAnglesXYZ()
print(Rotation) -- Should print 90?
local Rotation = math.rad(Rotation)
print(Rotation) -- Also 90

I’m trying to get the rotation of the bed on click, so when I move it, it doesn’t revert back to that position (problem asked here Models rotating automatically when clicked on?)

Don’t link me here CFrame I’ve read it all

These are not stored internally in degree measurements; those are radians [-pi, pi]. To get the degree representation, use math.deg on them.

1 Like

That causes it rotate at random, without me rotating it at all :confused:

local _, Rotation, _ = Model.PrimaryPart.CFrame:ToEulerAnglesXYZ()
print(Rotation)
local Rotation = math.deg(Rotation)
print(Rotation)

-- When moving the model
Model:SetPrimaryPartCFrame(
	CFrame.new(NewPos, NewPos + Normal) * 
	CFrame.Angles(-math.rad(90), math.rad(Rotation), 0) *
	CFrame.new(0, (Model.PrimaryPart.Size.Y / 2) - 0.25, 0)
)

Based on your code in the earlier topic and output here, I think this is related to your use of the (pos, lookAt)-constructor. You are using it to make a CFrame that points straight up and then you rotate the created CFrame with CFrame.Angles to make the lookvector horizontal.

I decided to find out where a CFrame created this way would face. First, I didn’t put an y value in the CFrame.Angles. And the resulting CFrame’s lookvector was not the default lookvector (0, 0, -1). Instead, it was almost equal to (-1, 0, 0), which means it’s already rotated without the rotation stored in the Rotation variable being added. Here’s a print statement that shows the lookvector.

print((CFrame.new(Vector3.new(), Vector3.new(0, 1, 0))*CFrame.Angles(-math.pi/2, 0, 0)):ToEulerAnglesXYZ().LookVector)

The output shows that before you start moving the sofa for the first time, its primarypart’s CFrame is rotated. The rotation, 90 degrees, is stored to the variable. And when the y rotation is given to CFrame.Angles, the y orientation actually doesn’t become 90 degrees higher than it was. Instead, it’s reduced by 90 degrees, so it becomes 0 and 0 will be the value of the rotation variable next time you start moving. The lookvector still isn’t the default one, it’s the default’s opposite direction (0, 0, 1).

print((CFrame.new(Vector3.new(), Vector3.new(0, 1, 0))*CFrame.Angles(-math.pi/2, math.pi/2, 0)).LookVector)

ToEulerAnglesXYZgives(180, 0, 180)` in radians. The y rotation is the relevant thing here.

Here’s what I believe is happening when you move it:

First time moving it:

  1. The y orientation angle of the primarypart is 90 degrees.
  2. The new CFrame is created and rotated so that it’s y rotation becomes 0.

Second time moving it:

  1. The y orientation of the primarypart is 0 degrees.
  2. Because the value of the Rotation variable is 0, the model’s rotation isn’t changed from the rotation of
CFrame.new(NewPos, NewPos+Normal)*CFrame.Angles(-math.rad(90), math.rad(Rotation), 0)

The y orientation of the CFrame created that way is 90 degrees, so the rotation is the same as it was before than the model was moved for the first time. So the rotation is resetted.

Then, a possible solution. I believe you could do this

local NewCf
if Normal:Dot(Vector3.new(0, 1, 0)) < 1e-5 then
    NewCf = CFrame.new(NewPos+Vector3.new(0, model.PrimaryPart.Size.Y/2-.25, 0))*CFrame.Angles(0, -math.rad(rotation), 0)
else NewCf = CFrame.new(NewPos, NewPos + Normal) * 
	CFrame.Angles(-math.rad(90), math.rad(Rotation), 0) *
	CFrame.new(0, (Model.PrimaryPart.Size.Y / 2) - 0.25, 0)
end
Model:SetPrimaryPartCFrame(NewCf)
1 Like

Didn’t seem to fix anything :confused: Also made items not rotate along walls :confused:

When it comes to walls, I want the ‘Bottom’ surface of the PrimaryPart to always be touching the surface (floor/walls/roof) so the model needs to rotate along that surface

I had forgot the CFrame.Angles from the line below the if-line. I now added it. With it, I think the sofa should be able to rotate correctly on the floor. I don’t know how to fix the wall thing, though.

Still did the same thing as the video :confused:

Actually, I didn’t realise one thing. The y orientation is always between -90 and 90 degrees. So the angle for CFrame.Angles needs to be calculated in a different way. I don’t know how to do the calculation correctly for any surface, but this might work for the floor.

local LV = Model.PrimaryPart.CFrame.LookVector
local Rotation = math.atan2(LV.X, -LV.Z) -- this is the y rotation in radians