Drawing blips on viewport

I am trying to make waypoints on a viewport.

I can’t get it to work, I’ve found nothing that works.

I’ve tried Plum’s Minimap but that doesn’t work as I am trying to draw it on a surface GUI (Trying to make a Satellite system)

Current code:

local MainFrame = script.Parent.MainFrame
local viewPort = MainFrame:WaitForChild("ViewportFrame")
local charPart = viewPort:WaitForChild("Character")
local height = 5000

local map = workspace.RipOffWorkspace_Because_Yes

map:Clone().Parent = viewPort

local x, z = 0, 0

local Icons = {
	["SOC"] = {  }
}

local Waypoints = workspace.Waypoints

function Change_Position(step, change)
	if change == "Height" then
		height = height - step
	elseif change == "X" then
		x = x - step
	elseif change == "Z" then
		z = z - step
	end
end

local WaypointPositions = {}

local function SetUpWaypoints()
	for _, v in pairs(Waypoints:GetChildren()) do
		local Clone = MainFrame.IconTemplate:Clone()
		Clone.Name = v.Name
		Clone.Visible = true
		Clone.Parent = MainFrame

		WaypointPositions[Clone] = v.Position
	end
end

local function GetPosGround(Position)
	return Vector3.new(Position.X, 0, Position.Z)
end

local function PositionIcons()
	for i, v in pairs(WaypointPositions) do
		local Mag = (GetPosGround(Vector3.new(x, height, z)) - GetPosGround(v)).Magnitude

		local PositionX = ((v.X - x)/(height))
		local PositionY = ((v.Z - z)/(height))

		i.Position = UDim2.new(PositionX, 0, PositionY, 0)
	end
end

local camera = Instance.new("Camera", workspace)
camera.CameraType = "Scriptable"

local player = game.Players.LocalPlayer
repeat wait() until player.Character

viewPort.CurrentCamera = camera
local position = player.Character.HumanoidRootPart.Position
camera.CFrame = CFrame.new(Vector3.new(position.X,height,position.Z), position)

SetUpWaypoints()

game:GetService("RunService").RenderStepped:Connect(function ()
	camera.CFrame = CFrame.new(Vector3.new(x,height,z), position)
	charPart.CFrame = player.Character.HumanoidRootPart.CFrame
	PositionIcons()
end)
local function calculatePosition(BasePartPosition, camera)

    -- calculate the position of the blip on the screen

    -- end result is a udim2

    -- these calculations are almost right

    -- the only thing that is wrong is calculating the si

    local viewport = script.Parent

    local viewportSize = viewport.AbsoluteSize

    local viewportPosition = viewport.AbsolutePosition

    local viewportCenter = Vector2.new(viewportPosition.X + viewportSize.X / 2, viewportPosition.Y + viewportSize.Y / 2)

    local viewportCenter3D = camera:ScreenPointToRay(viewportCenter.X, viewportCenter.Y)

    viewportCenter3D = viewportCenter3D.Origin + viewportCenter3D.Direction * 300

    local viewportCenter2D = camera:WorldToScreenPoint(viewportCenter3D)

    local blipPosition3D = camera:ScreenPointToRay(BasePartPosition.X, BasePartPosition.Y)

    blipPosition3D = blipPosition3D.Origin + blipPosition3D.Direction * 300

    local blipPosition2D = camera:WorldToScreenPoint(blipPosition3D)

    local blipPosition = UDim2.new(0, math.abs(blipPosition2D.X - viewportCenter2D.X), 0, math.abs(blipPosition2D.Y - viewportCenter2D.Y))

    return blipPosition

end

It almost has the right calcs, except a little mismatch.