Notice that when you rotate a catalog item along the X axis with your mouse, no matter which way up or down the object is tilted, it rotates the same way relative to itself. However, when you move your mouse along the Y axis, the object does not tilt up or down relative to itself but relative to your "camera."
Just play around with it and you'll see what I mean. I'm wondering how I'd simulate the latter type of rotation with coordinate frames. Can anyone point me in the right direction?
Call the camera's position "focus"
Call the zoom distance "zoom"
Call the X rotation "pitch"
Call the Y rotation "bearing"
Track the change in the mouse's position, subtract the x delta from the bearing, add the y delta to the pitch. Divide the delta by some number like 100 first so it doesn't move too quickly.
Constrain the pitch. To avoid gimbal lock, the absolute value of the pitch should be less than or equal to math.pi/2-.14154
.
camera.CoordinateFrame = CFrame.new(focus) * CFrame.Angles(0,bearing,0) * CFrame.Angles(pitch,0,0) * CFrame.new(0,0,-zoom)
Here's a demo:
set CharacterAutoLoads to false
use a LocalScript in StarterPlayerScripts
local focus=Vector3.new(0,10,0) local pitch,bearing=0,0 local maxPitch=math.pi/2-.14154 local camera=workspace.CurrentCamera camera.CameraType=Enum.CameraType.Scriptable local down=false local posx,posy=0,0 local zoom=10 game:GetService('UserInputService').InputBegan:connect(function(input) if input.UserInputType.Name=="MouseButton1"then down=true local pos=input.Position posx,posy=pos.x,pos.y end end) game:GetService('UserInputService').InputEnded:connect(function(input) if input.UserInputType.Name=="MouseButton1"then down=false end end) game:GetService('UserInputService').InputChanged:connect(function(input) if input.UserInputType.Name=="MouseWheel"then zoom=math.min(math.max(zoom-input.Position.z,1),100) camera.CoordinateFrame=CFrame.new((CFrame.new(focus)*CFrame.Angles(0,bearing,0)*CFrame.Angles(pitch,0,0)*CFrame.new(0,0,-zoom)).p,focus) end if down then local pos=input.Position local x,y=pos.x-posx,pos.y-posy posx,posy=pos.x,pos.y pitch=math.min(math.max(pitch+y/100,-maxPitch),maxPitch) bearing=bearing-x/100 camera.CoordinateFrame=CFrame.new((CFrame.new(focus)*CFrame.Angles(0,bearing,0)*CFrame.Angles(pitch,0,0)*CFrame.new(0,0,-zoom)).p,focus) end end)