function Portal.AddToWorld(e,s)s.Parent=e.ViewportFrame end function Portal.ClipModel(e,s)local n,T=e:GetSurfaceInfo()local G=s:GetDescendants()for s=1,#G,1 do local e=G[s]if e:IsA("\066\097\115\101\080\097\114\116")then local s=getCorners(e)table.insert(s,1,e.Position)local T=false for e=1,#s,1 do if(n:PointToObjectSpace(s[e])).z<=0 then T=true break end end if not T then e:Destroy()end end end return s end function Portal.GetPart(s)return s.SurfaceGUI.Adornee end function Portal.GetSurfaceInfo(s)local e=s.SurfaceGUI.Adornee local n,T=e.CFrame,e.Size local G=-Vector3.FromNormalId(s.SurfaceGUI.Face)local X=math.abs(G.y)==1 and Vector3.new(G.y,0,0)or UP local d=CFrame.fromAxisAngle(X,PI2)*G local t=(G:Cross(d)).Unit local l=n*CFrame.fromMatrix((-G*T)/2,d,t,G)local Q=Vector3.new((T*d).Magnitude,(T*t).Magnitude,(T*G).Magnitude)return l,Q end function Portal.RenderFrame(T,s,e,n)local G=T.ViewportFrame local X=T.SurfaceGUI local d=game.Workspace.CurrentCamera local t=T.Camera local l=s or d.CFrame if not(e and n)then e,n=T:GetSurfaceInfo()end local Q=e:PointToObjectSpace(l.p)local g,Y=Q.x/n.x,Q.y/n.y local c=1+math.max(n.y/n.x,n.x/n.y,math.max(math.abs(g),math.abs(Y))*2)local a=n.y/2 local b=(l.p-e.p):Dot(e.LookVector)local B=2*math.atan2(a,b)local O=math.clamp(math.deg(B),1,120)local D=a/math.tan(math.rad(O)/2)local h=b/D local u=(B>FOV120 and h or 1)/c local H=CFrame.new(0,0,0,u,0,0,0,u,0,0,0,1)G.Position=UDim2.new(G.AnchorPoint.x-g,0,G.AnchorPoint.y-Y,0)G.Size=UDim2.new(c,0,c,0)G.BackgroundColor3=X.Adornee.Color local A=d.ViewportSize.y X.CanvasSize=Vector2.new(A*(n.x/n.y),A)t.FieldOfView=O t.CFrame=((CFrame.new(l.p)*(e-e.p))*CFrame.Angles(0,math.pi,0))*H end
--

function Portal:AddToWorld(item)
	item.Parent = self.ViewportFrame
end

function Portal:ClipModel(model)
	local cf, size = self:GetSurfaceInfo()
	local descendants = model:GetDescendants()
	for i = 1, #descendants do
		local part = descendants[i]
		if part:IsA("BasePart") then
			local corners = getCorners(part)
			table.insert(corners, 1, part.Position)

			local pass = false
			for j = 1, #corners do
				if cf:PointToObjectSpace(corners[j]).z <= 0 then
					pass = true
					break
				end
			end

			if not pass then
				part:Destroy()
			end
		end
	end
	return model
end

function Portal:GetPart()
	return self.SurfaceGUI.Adornee
end

function Portal:GetSurfaceInfo()
	local part = self.SurfaceGUI.Adornee
	local partCF, partSize = part.CFrame, part.Size

	local back = -Vector3.FromNormalId(self.SurfaceGUI.Face)
	local axis = (math.abs(back.y) == 1) and Vector3.new(back.y, 0, 0) or UP
	local right = CFrame.fromAxisAngle(axis, PI2) * back
	local top = back:Cross(right).Unit

	local cf = partCF * CFrame.fromMatrix(-back * partSize / 2, right, top, back)
	local size = Vector3.new((partSize * right).Magnitude, (partSize * top).Magnitude, (partSize * back).Magnitude)

	return cf, size
end

function Portal:RenderFrame(camCF, surfaceCF, surfaceSize)
	local vpf = self.ViewportFrame
	local surfaceGUI = self.SurfaceGUI
	local camera = game.Workspace.CurrentCamera
	local nCamera = self.Camera

	local camCF = camCF or camera.CFrame
	if not (surfaceCF and surfaceSize) then
		surfaceCF, surfaceSize = self:GetSurfaceInfo()
	end

	local rPoint = surfaceCF:PointToObjectSpace(camCF.p)
	local sX, sY = rPoint.x / surfaceSize.x, rPoint.y / surfaceSize.y

	local scale = 1
		+ math.max(
			surfaceSize.y / surfaceSize.x,
			surfaceSize.x / surfaceSize.y,
			math.max(math.abs(sX), math.abs(sY)) * 2
		)

	local height = surfaceSize.y / 2
	local rDist = (camCF.p - surfaceCF.p):Dot(surfaceCF.LookVector)
	local newFov = 2 * math.atan2(height, rDist)
	local clampedFov = math.clamp(math.deg(newFov), 1, 120)
	local pDist = height / math.tan(math.rad(clampedFov) / 2)
	local adjust = rDist / pDist

	local factor = (newFov > FOV120 and adjust or 1) / scale
	local scaleCF = CFrame.new(0, 0, 0, factor, 0, 0, 0, factor, 0, 0, 0, 1)

	vpf.Position = UDim2.new(vpf.AnchorPoint.x - sX, 0, vpf.AnchorPoint.y - sY, 0)
	vpf.Size = UDim2.new(scale, 0, scale, 0)
	vpf.BackgroundColor3 = surfaceGUI.Adornee.Color

	local viewportSizeY = camera.ViewportSize.y
	surfaceGUI.CanvasSize = Vector2.new(viewportSizeY * (surfaceSize.x / surfaceSize.y), viewportSizeY)

	nCamera.FieldOfView = clampedFov
	nCamera.CFrame = CFrame.new(camCF.p) * (surfaceCF - surfaceCF.p) * CFrame.Angles(0, math.pi, 0) * scaleCF
end
