Clamp rotation on one axis?

I’m back with stupid maths questions :joy:
How would I clamp the rotation of a part on one axis so it cannot rotate beyond 80 degrees? I’ve already attempted to do this and it works nicely when the part is facing forward, but once its rotation changes on other axis it freaks out.

local x, y, z = workspace.Part.CFrame:toEulerAnglesXYZ()
local newX = math.clamp(math.deg(x),-80,80)
workspace.Part.CFrame = CFrame.new(workspace.Part.CFrame.p)*CFrame.Angles(math.rad(newX), y, z)

2 Likes

Rotations in 3D aren’t very straightforward at all and Euler angles definitely do not do a good job at describing them for general purpose use cases. I don’t completely understand what you want to clamp because there are so many ways of interpreting that kind of clamp behavior based on how the object has rotated. Are you trying to prevent the part from flipping upside down? If you can, please describe the exact behavior you want in multiple cases like when the part is yawed 50 degrees, then rotated, or rotated to the clamp seen in the gif, yawed, then rotated against the clamp again.

1 Like

It’s meant to be for a new camera feature I’m working on, but to make it easier to explain and visualize I’m doing it on a part first. Basically, what I want to do is so when the camera looks up, it can only look up to a certain point, but to do this I need to clamp the vertical rotation. My code works fine as long as the part is facing forward, if it’s looking in any other direction the whole CFrame gets messed up.

Nevermind, I found a solution made by @Xan_TheDragon which is pretty much the exact same thing, except it uses “toOrientation()” instead of “toEulerAnglesXYZ()”.

--Local variable your_cf is your CFrame
local RX, RY, RZ = your_cf:toOrientation() --These values are in radians.
local LimX = math.clamp(math.deg(RX), -45, 45)
--(continue for Y and Z)
whatever_is_using_your_cf.CFrame = CFrame.new(whatever_is_using_your_cf.CFrame.p) * CFrame.fromOrientation(math.rad(LimX), ...) --So on for the rest of the rotations.
8 Likes

Oh, yeah. Euler angles can do that, but the axis need to be in a different order. Roblox does pitch, yaw, roll by default, but if you do yaw, pitch, roll, then you can get the effect you want as well. You would need to store the pitch and yaw values by variable though, but that isn’t really a problem with camera code. Glad to see you found a solution though!

If you want to take a look at the Euler angles solution too then it would use CFrame.fromEulerAnglesYXZ instead of XYZ.

1 Like

Just so you know, the main reason for orientation is the way it works. It is applied to / extracted from the transformation matrix in such a way that it makes each axis’s value what you would expect it to be if you were only looking at that axis and none of the other ones. I’m glad they added it to the API, because you had to do a lot of math before.

How would you set the script up so it works for the camera instead of the basepart?