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.