Need help calculating surface offset for custom camera to avoid clipping

I’m trying to calculate the minimum surface offset for my custom camera system to avoid clipping on parts/meshes, my current system works to an extent but doesn’t seem to properly avoid all clipping.

This is my code that handles the detection and calculations:

local cameraRaycastParams: RaycastParams = RaycastParams.new()

cameraRaycastParams.FilterType = Enum.RaycastFilterType.Exclude
cameraRaycastParams.FilterDescendantsInstances = { self.character }
cameraRaycastParams:AddToFilter(CollectionService:GetTagged("CameraIgnore"))
	
local hitPosition: Vector3?, hitNormal: Vector3?
	
while true do
	local originPosition: Vector3 = centerPosition
	local direction: Vector3 = newCameraCFrame.Position - originPosition
		
	local raycastResult: RaycastResult? = workspace:Raycast(originPosition, direction, cameraRaycastParams)
		
	if raycastResult then
		if raycastResult.Instance:IsA("Terrain") then
			hitPosition, hitNormal = raycastResult.Position, raycastResult.Normal
				
			break
		else
			if raycastResult.Instance.Transparency >= 0.7 then
				if not table.find(cameraRaycastParams.FilterDescendantsInstances, raycastResult.Instance) then
					cameraRaycastParams:AddToFilter({ raycastResult.Instance })
						
					continue
				end
			end
				
			hitPosition, hitNormal = raycastResult.Position, raycastResult.Normal
				
			break
		end
	end
		
	hitPosition = newCameraCFrame.Position
		
	break
end
	
if hitNormal then
	local nearPlaneZ: number = -currentCamera.NearPlaneZ
	local fieldOfView: number = currentCamera.FieldOfView
	local cameraDistanceToFocus: number = (currentCamera.Focus.Position - hitPosition).Magnitude
		
	local clippingPlaneWidth: number = 2 * nearPlaneZ * math.tan(math.rad(fieldOfView) / 2)
	local minimumDistanceToAvoidClipping: number = nearPlaneZ + clippingPlaneWidth / 2
		
	hitPosition = hitPosition + hitNormal * minimumDistanceToAvoidClipping
end

When the camera gets close to a surface but doesn’t quite touch it yet, it can see through the surface, I’ve tried using other resources from topics similar to mine with no success, you can see the issue below: streamable

External Media

The goal is to avoid this issue as a whole, if anyone has a solution, I’d greatly appreciate the help.

1 Like

I believe you issue here is that you are looking for a ray cast at at the exact camera position that you are at. Here is my suggestion:

Using ROBLOX’s new Shapecast feature. Specifically Spherecast:

What this will essentially allow you to do is locate the distance of the field of view relative to the maximum distance you will need to cast to. using this you can send a Spherecast and perform the needed clipping restrictions.

I would get the radius by calculating the bottom left screen position to the top right screen position and using Pythagorean Theorem to calculate the maximum radius of interest (or just get the magnitude of the UDim2).

You can also use Blockcast to maybe figure out an exact screen resolution and use the side parameter to put it right in front of the player’s Z Plane.

Here is the documentation for that:

Best of luck to your endeavor. I hope I provided you with a sufficiently working resource for your problem.

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.