I’m making a game with a viewmodel and I need to move it to the camera’s position and rotation, but without the vertical rotation of the camera (so it stays in place as I look up and down). Currently I have this code, but it makes the viewmodel rotate in weird directions when I rotate the camera. Does anyone know how to achieve this?
local xc,yc,zc = cam.CFrame:ToEulerAnglesXYZ()
viewmodel.Root.CFrame = CFrame.new(cam.CFrame.Position) * CFrame.Angles(xc,0,zc)
This function was given to me many years ago when I had a similar issue, and now I pass it along to you.
local function removePitch(cframe: CFrame): CFrame
local xVector: Vector3 = cframe.XVector
local yVector: Vector3 = Vector3.yAxis
local zVector: Vector3 = xVector:Cross(yVector)
return CFrame.fromMatrix(cframe.Position, xVector, yVector, zVector)
end
If I understood correctly, you want the model to only rotate in the XZ plane direction. This means rotation around y axis. So the angle you removed and the ones you left were the exact opposite of what you should have removed and left. This should work.
local xc,yc,zc = cam.CFrame:ToEulerAnglesXYZ()
viewmodel.Root.CFrame = CFrame.new(cam.CFrame.Position) * CFrame.Angles(0,yc,0)
The function @Rocky28447 gave works too, since the RightVector should stay the same (assuming it’s already parallel to the XZ plane) and you know the desired UpVector. These two vectors are enough information to calculate the last vector in the CFrame, the back vector.
Rocky’s function can be simplified because CFrame.fromMatrix can calculate the back vector given the other two rotation vectors so you don’t need to calculate the back vector yourself.
local function removePitch(cframe: CFrame): CFrame
local xVector: Vector3 = cframe.RightVector
local yVector: Vector3 = Vector3.yAxis
return CFrame.FromMatrix(cframe.Position, xVector, yVector)
end