Help with camera centered cframe math

Previous devforum posts havent been much help, and Im concerned that what I want to do might be restricted by robloxs capabilities, which would be frustrating. But Ill still ask.

I’m trying to create an onscreen effect using a beam, and with that comes some immediate restrictions that I’m trying to work around. and viewports are not an option. Ive tried using

camera:GetRenderCFrame():ToWorldSpace(blah blah cframe math)

which somewhat works and allows me to manipulate it. However, moving it left to right according to my viewportsize in order to find the screen’s edge, but doesn’t seem possible to my knowledge. Please let me know if you know a way. :pray:

I believe this is the correct equation for this:

local camera = workspace.Camera

local screenRatio = camera.ViewportSize.X / camera.ViewportSize.Y
local verticalFOV = camera.FieldOfView
local horizontalFOV = screenRatio * verticalFOV

-- Gets the horizontal offset of a plane facing the camera at a distance of `distance`
local function getHorizontalOffsetAtDistance(distance)
    -- This is the distance from the camera ray (center of the screen) to the horizontal edge of the viewing plane
    return math.tan(math.rad(horizontalFOV) / 2) * distance
end

This is more of a math problem, so it’s definitely possible on the platform.

This somewhat works but not entirely, i have the issue of my part moving out of bounds of view

https://gyazo.com/0f57cd0c63d120642881aa53a2ded6a7

here is my current code


local function getHorizontalOffsetAtDistance(distance)
	local screenRatio = camera.ViewportSize.X / camera.ViewportSize.Y
	local verticalFOV = camera.FieldOfView
	local horizontalFOV = screenRatio * verticalFOV
	return math.tan(math.rad(horizontalFOV) / 2) * distance
end

local Part = script.Parent.Part
Part.Parent = workspace

game:GetService("RunService").RenderStepped:connect(function()
	Part.CFrame = workspace.CurrentCamera:GetRenderCFrame():ToWorldSpace(
	CFrame.new(
		getHorizontalOffsetAtDistance(1),
		-3,
		-3) 
	*  
	CFrame.Angles(
			math.rad(0),
			math.rad(0),
			math.rad(-15)
		)
	)
end)

Whoops, I didn’t fully think through calculating the horizontal FoV based on the aspect ratio.

The actual equation should be:

local horizontalFOVRad = math.deg(math.atan(math.tan(math.rad(verticalFOV) * 0.5) * screenRatio) * 2)

I tested it using the code below and it the part always stayed at the same spot on the right edge in the middle now.

-- A client code with a small sphere named "Part" in workspace
local camera = workspace.CurrentCamera

local function getHorizontalOffsetAtDistance(distance)
	local screenRatio = camera.ViewportSize.X / camera.ViewportSize.Y
	local verticalFOV = camera.FieldOfView
	local horizontalFOV = math.deg(math.atan(math.tan(math.rad(verticalFOV) * 0.5) * screenRatio) * 2)
	return math.tan(math.rad(horizontalFOV) / 2) * distance
end

local part = workspace:WaitForChild("Part")

game:GetService("RunService").RenderStepped:connect(function()
	local distance = 1
	local cameraOffsetRelative = Vector3.new(getHorizontalOffsetAtDistance(distance), 0, -1*distance)
	
	local cframe = CFrame.new(workspace.CurrentCamera:GetRenderCFrame():PointToWorldSpace(cameraOffsetRelative))
	
	part.CFrame = cframe
end)

Hope this helps!

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