Since Camera:GetLargestCutoffDistance is deprecated (Camera | Roblox Creator Documentation), I have to create my own method to get the “Largest Cutoff Distance”.
For some reason even though I managed to achieve identical results there seems to be some imprecision on the x-axis. If somebody has the source of the original camera method or has achieved 100% identical results please share it with me.
function SCamera:GetLargestCutOffDistance(CameraCFrame: CFrame,Focus: CFrame)
local Origin = Focus.Position
local Direction = CameraCFrame.Position - Focus.Position
local RaycastResult: RaycastResult = workspace:Raycast(Origin,Direction,self.RayParams)
if RaycastResult then
return (RaycastResult.Position - CameraCFrame.Position).Magnitude
else
return 0
end
end
I just found this post from searching up this topic myself while trying to implement my own occulsion
Quote from the GetLargestCutoffDistance() documentation,
This function is used by ‘PopperCam’ in the default camera scripts to ensure obstructions do not come between the Camera and the Camera’s subject.
The replacement for this deprecated method seems to be implemented in the Roblox default camera modules as a function.
The new function can be found in PlayerModule.CameraModule.ZoomControler.Popper
Make a copy of the PlayerModule during runtime and paste it back into StarterPlayerScripts ,
then from there you can access the Popper by requiring the module.
From my limited testing, the Popper() function seems to returns the same as GetLargestCutoffDistance().
i.e. “the distance that the Camera needs to be pushed towards its Camera.Focus to ensure there are no obstructions between the Camera.Focus and Camera.CFrame of the Camera.”
Thank you for taking the time to share this with me. I took a quick look at the Popper module it seems to serve the same purpose. I will test to confirm as soon I can and mark your reply as the solution.
Apologies for the very late response but it seems the Popper function returns another kind of distance. If somebody has found the GetLargestCutoffDistance source feel free to enlighten me.
Edit: It seems like the Popper returns the maximum distance from the focus point. (while factoring occlusion)
Hey there, this is going to be a late reply (one year!) but I’ve just made a version that seems to replicate the functionality of :GetLargestCutoffDistance() quite well!
The issue I found with your above implementation is that it fails to account for the collision radius of the camera. I’ve made a version of your function that accounts for the collision radius and returns a proper magnitude to avoid that X-axis inaccuracy/clipping:
local function getLargestCutoffDistance(currentFocus: CFrame, goalCFrame: CFrame, collisionRadius: number, ignoreList: { any }?): number
local origin = currentFocus.Position
local params = RaycastParams.new()
params.FilterDescendantsInstances = ignoreList or {}
params.FilterType = Enum.RaycastFilterType.Exclude
-- Camera bounds
local cameraOffsets = {
Vector3.new(0, 0, 0), -- camera center
Vector3.new(collisionRadius, 0, 0), -- right of the camera
Vector3.new(-collisionRadius, 0, 0), -- left of the camera
}
local largestCutoffDistance = 0
for _, offset in ipairs(cameraOffsets) do
local correctedGoalCFrame = goalCFrame * CFrame.new(offset)
local direction = ((correctedGoalCFrame.Position) - currentFocus.Position)
local result: RaycastResult = workspace:Raycast(origin, direction, params)
if not result then
continue
end
local distance = (result.Position - correctedGoalCFrame.Position).Magnitude
if distance > largestCutoffDistance then
largestCutoffDistance = distance
end
end
return largestCutoffDistance
end
The next question is:
“How do we calculate the collision radius of the camera?”
This function below will do it for you. I’m not going to act like I understand the math of how it fully works lol.
local function getCollisionRadius(): number
local camera = workspace.CurrentCamera
local viewportSize = camera.ViewportSize
local aspectRatio = viewportSize.X / viewportSize.Y
local fovRads = math.rad(camera.FieldOfView)
local imageHeight = math.tan(fovRads) * math.abs(camera.NearPlaneZ)
local imageWidth = imageHeight * aspectRatio
local cornerPos = Vector3.new(imageWidth, imageHeight, camera.NearPlaneZ)
return cornerPos.Magnitude
end
Hopefully this helps you if you still need it or it helps anyone else who stumbles across this DevForum post!
Thanks for the reply! I have since figured out a way to replicate the functionality and have implemented a very similar implementation (no pun intended) for my camera resource.
function SUCamera._GetCollisionRadius(self: SUCamera)
if self._CurrentCamera == nil then
return 0
end
local ViewportSize: Vector2 = self._CurrentCamera.ViewportSize
local AspectRatio = ViewportSize.X / ViewportSize.Y
local FovRads = math.rad(self.FOV)
local ImageHeight = math.tan(FovRads) * math.abs(self._CurrentCamera.NearPlaneZ)
local ImageWidth = ImageHeight * AspectRatio
local CornerPos = Vector3.new(ImageWidth, ImageHeight, self._CurrentCamera.NearPlaneZ)
return CornerPos.Magnitude
end