Editing ViewportFrame?

I’m attempting to edit an existing “Window” / “Portal” script provided by @EmilyBendsSpace -
Currently the way the system works is by Rendering the objects directly around the area of the “Portal” - I’m looking to adjust this to render the objects from around another “Portal” rather than the origin.





Original Code:
--[[

ViewportFrame crude portal

EmilyBendsSpace 9.15.2019

--]]

local RunService = game:GetService("RunService")

local PlayerGui = game.Players.LocalPlayer:WaitForChild("PlayerGui")

local UNIT_Y = Vector3.new(0,1,0)

local UNIT_ZM = Vector3.new(0,0,-1)

local XZ = Vector3.new(1,0,1)

local YZ = Vector3.new(0,1,1)

local camera = game.Workspace.CurrentCamera

-- Setup viewport frame and camera

local surfaceGui = PlayerGui:WaitForChild("SurfaceGui")

local vpf = surfaceGui:WaitForChild("ViewportFrame")

local vpfCam = camera:Clone()

vpfCam.Parent = surfaceGui

vpf.CurrentCamera = vpfCam

-- Folder of portal parts we don't copy into the VPF

local portalFolder = game.Workspace:WaitForChild("Portal_NO_COPY")

-- Portal location, corners, edge centers, face center

local portal = portalFolder:WaitForChild("Portal")

local tc = portal.CFrame.p + 0.5 * portal.Size * YZ

local bc = portal.CFrame.p + 0.5 * portal.Size * Vector3.new(0,-1,1)

local p = portal.CFrame.p - portal.Size.Z * 0.5 * portal.CFrame.LookVector -- Portal face center, not part center (SurfaceGui is on Back face)

-- Unoptimized render loop. Much redundant calcs, wow.

RunService.RenderStepped:Connect(function(dt)

local camCF = camera.CFrame

local c2p = p - camCF.p

local c2pXZ = (c2p * XZ)

local c2pYZ = (c2p * YZ)

local levelCamCF = CFrame.fromMatrix(camCF.p, camCF.RightVector, Vector3.new(0,1,0), camCF.RightVector:Cross(Vector3.new(0,1,0)))

local csbc = levelCamCF:Inverse() * bc

local cstc = levelCamCF:Inverse() * tc

local v1 = (csbc*YZ).Unit

local v2 = (cstc*YZ).Unit

local alpha = math.sign(v1.Y) * math.acos( v1:Dot(UNIT_ZM))

local beta = math.sign(v2.Y) * math.acos( v2:Dot(UNIT_ZM))

local fh = 2.0 * math.tan(math.rad(camera.FieldOfView) * 0.5)

local hPrime = math.tan(beta) - math.tan(alpha)

local refHeight = hPrime / fh

local dpX = c2pXZ.Unit:Dot(-portal.CFrame.LookVector)

local camXZ = (camCF.LookVector * XZ)

local scale = math.abs(camXZ.Unit:Dot(c2pXZ.Unit)) / (math.abs(portal.CFrame.LookVector:Dot(c2pXZ.Unit)))

local tanarccos = math.sqrt(1-dpX*dpX)/dpX

local sc = scale * refHeight

local w = 1

local h = 1

local dx = math.sign(c2p.X * c2p.Z)*tanarccos

local dy = -c2pYZ.Y/c2pYZ.Z

local d = sc

-- Camera CFrame won't take values too much larger than 1, so normalizing the unprojection matrix by the largest component

local max = math.max(w,h,math.abs(dx),math.abs(dy),d)

w, h, dx, dy, d = w / max, h / max, dx / max, dy / max, d / max

vpfCam.CFrame = CFrame.new(0,0,0, w, 0, 0, 0, h, 0, dx, dy, d) + camCF.p

end)




Edited Code:
local RunService = game:GetService("RunService")

local PlayerGui = game.Players.LocalPlayer:WaitForChild("PlayerGui")

local UNIT_Y = Vector3.new(0,1,0)

local UNIT_ZM = Vector3.new(0,0,-1)

local XZ = Vector3.new(1,0,1)

local YZ = Vector3.new(0,1,1)

local camera = game.Workspace.CurrentCamera

-- Setup viewport frame and camera

local surfaceGui = PlayerGui:WaitForChild("SurfaceGui")

local vpf = surfaceGui:WaitForChild("ViewportFrame")

local vpfCam = camera:Clone()

vpfCam.Parent = surfaceGui

vpf.CurrentCamera = vpfCam

-- Folder of portal parts we don't copy into the VPF

local portalFolder = game.Workspace:WaitForChild("Portal_NO_COPY")

-- Portal location, corners, edge centers, face center

local portal = portalFolder:WaitForChild("Portal")

local portal2 = portalFolder:WaitForChild("Portal2")

local tc = portal2.CFrame.p + 0.5 * portal2.Size * YZ

local bc = portal2.CFrame.p + 0.5 * portal2.Size * Vector3.new(0,-1,1)

local p = portal2.CFrame.p - portal2.Size.Z * 0.5 * portal2.CFrame.LookVector -- Portal face center, not part center (SurfaceGui is on Back face)

-- Unoptimized render loop. Much redundant calcs, wow.

RunService.RenderStepped:Connect(function(dt)

local camCF = camera.CFrame

local c2p = p - camCF.p

local c2pXZ = (c2p * XZ)

local c2pYZ = (c2p * YZ)

local levelCamCF = CFrame.fromMatrix(camCF.p, camCF.RightVector, Vector3.new(0,1,0), camCF.RightVector:Cross(Vector3.new(0,1,0)))

local csbc = levelCamCF:Inverse() * bc

local cstc = levelCamCF:Inverse() * tc

local v1 = (csbc*YZ).Unit

local v2 = (cstc*YZ).Unit

local alpha = math.sign(v1.Y) * math.acos( v1:Dot(UNIT_ZM))

local beta = math.sign(v2.Y) * math.acos( v2:Dot(UNIT_ZM))

local fh = 2.0 * math.tan(math.rad(camera.FieldOfView) * 0.5)

local hPrime = math.tan(beta) - math.tan(alpha)

local refHeight = hPrime / fh

local dpX = c2pXZ.Unit:Dot(-portal.CFrame.LookVector)

local camXZ = (camCF.LookVector * XZ)

local scale = math.abs(camXZ.Unit:Dot(c2pXZ.Unit)) / (math.abs(portal.CFrame.LookVector:Dot(c2pXZ.Unit)))

local tanarccos = math.sqrt(1-dpX*dpX)/dpX

local sc = scale * refHeight

local w = 1

local h = 1

local dx = math.sign(c2p.X * c2p.Z)*tanarccos

local dy = -c2pYZ.Y/c2pYZ.Z

local d = sc

-- Camera CFrame won't take values too much larger than 1, so normalizing the unprojection matrix by the largest component

local max = math.max(w,h,math.abs(dx),math.abs(dy),d)

w, h, dx, dy, d = w / max, h / max, dx / max, dy / max, d / max

vpfCam.CFrame = CFrame.new(0,0,0, w, 0, 0, 0, h, 0, dx, dy, d) + camCF.p

end)


As you can tell from the snippets provided - My edited version doesn’t behave at all how I’d like it to.
Does anyone have ideas on how I can adjust this?
Thank you.

1 Like