Take out pitch from rotation matrix while preserving yaw and roll

I want to experiment with having my camera attached to an object so that it looks in the direction of where the object is facing but only it’s yaw and roll, and not it’s pitch. So far messing with the rotation matrix to try to get what I want has yielded nothing but corrupted results and I don’t have much to go on since it doesn’t seem like anyone has attempted something like this that i know of (at least not publicly).

Judging from this picture…

You should be able to do this.

object.CFrame = object.CFrame * CFrame.Angles(1, 0, 1)

2 Likes

I’ll be a bit more specific, I want to get a CFrame and change just the pitch of the rotation matrix to 0 while preserving the yaw and roll. So that the pitch is constantly the same but the yaw and roll update accordingly.

If you’re referring to the rotations as pitch, roll, and yaw, then you’re probably using euler angles. The simplest way of removing the pitch would then be:

local function removePitch(cf)
    local _, roll, yaw = cf:toEulerAnglesXYZ()
    return CFrame.new(cf.p) * CFrame.fromEulerAnglesXYZ(0, roll, yaw)
end

EDIT: I haven’t tested this one out, but if you’re using axis-angles, then just remove the EDIT2: x-component of the axis. Not working.

Summary
local function removePitchAxisAngles(cf)
    local axis, angles = cf:toAxisAngle()
    axis = (axis * Vector3.new(0, 1, 1))
    if axis.magnitude > 0 then
        return CFrame.new(cf.p) * CFrame.fromAxisAngle(axis, angles)
    else
        return CFrame.new(cf.p)
    end
end

I got:

local part = workspace.Part

local axis = Vector3.new(0,0,1)
local pitch = part.Orientation.Z

part.CFrame = part.CFrame*CFrame.fromAxisAngle(axis,math.rad(-pitch))

But it literally sets the part’s Z Orientation to 0 so you could do that too? (unless I’m completely missing the question)

Hmm the AxisAngles approach doesn’t work, but the first approach almost works. The removePitch function works only when facing certain directions, if I spin the object the camera is tied to on it’s yaw then the camera flips upside down when it get’s to certain degrees.

yxz is for working with yaw/pitch/roll

local function removePitch(cf)
    local pitch, yaw, roll = cf:toEulerAnglesYXZ()
    return CFrame.fromEulerAnglesYXZ(0, yaw, roll) + cf.p
end
1 Like

That’s really close, but the camera flips upside down when the pitch goes to around 180 degrees

Gyro point of view

              0
 -90                        90

         -180 | 180

so you could use some math that that says

if pitch >= NearPointOfFlip then
 pitch = BeforePointOfFlipValue -- basically the value before the camera flips upside down
end

Just came up with it at the spot, so may be wrong.

(I know you still have the pitch, but perhaps this could help you in some way)

See if this offers any improvement

function lookAtPart(cframe)
local right = cframe.rightVector
local front = (cframe.lookVector * Vector3.new(1,0,1)).Unit
local back = -front
local top = back:Cross(right)

return CFrame.new(cframe.X, cframe.Y, cframe.Z, right.X, top.X, back.X, right.Y, top.Y, back.Y, right.Z, top.Z, back.Z)
end

You still won’t be able to stop the camera flipping upside down when the angle is equal to or more than 180 degrees, because the direction you are looking has itself flipped upside down (like doing a forward roll with the camera). It feels erroneous because we’ve been ignoring the pitch previously, but are now in a ‘legal’ orientation that is read as having rotated the camera yaw 180 degrees, and then rolled upside down.

The only way to prevent this is to constrain the position of the part to not allow the camera to do a full 360 degree pitch revolution - Roblox does this with the camera by locking your camera’s max pitch to 170 degrees and min pitch to 10 degrees (i.e. you can never look vertically up or vertically down - your camera will stop just before this point)

I can’t come up with any way of clamping the camera so that it doesn’t roll. I want the camera attached to my car to be able to attached to it so that it keeps up with the car’s yaw and roll but, whenever it does a front flip for example, it doesn’t follow that. Everything I’ve tried so far ends up having the camera flip upside down when I do a front flip at 180 degrees and I can’t think of any possible way of preventing it. I tried the built in camera types and they pretty much flip upside down whenever I do a flip as well.

The issue with this is to do with trying to ignore rotation along one axis, while maintaining the rotation around the other two axes. This means that some angles created from changing the pitch (your front flip) can still be constructed using yaw and roll alone, and our code can’t differentiate between the two. We’re basically giving the ‘best guess’ of what’s going on based on the current orientation and the assumption that you can only change yaw and roll.

The only way I can think of doing this is to detect if we have flipped from rotation along the x axis, and then maintain the camera under assumption we are upright until the car comes to rest