ViewportFrame to 3D Space?

I’m attempting to find a way to allow players to place markers on my in-game map that also reflect it’s position in 3D space, but I’m having a hard time coming up with ways to accurately convert that click inside the ViewportFrame to the actual game world.

Has this been done before? If not, does anyone have some ideas on how I could accomplish this?

this is very difficult to do because the roblox api to get the world position does not work on viewportframes, but i have a somewhat-usable method that gets a mostly accurate 3d position from user input on a viewportframe below:

local GUIService = game:GetService("GuiService")
local Cam = your viewport camera
local HRP = humanoidrootpart of local player or current character
local MinimapSize = ViewportFrame.AbsoluteSize -- add variable ref
local MinimapPos = ViewportFrame.AbsolutePosition
local WorldModel = ViewportFrame:FindFirstChildOfClass("WorldModel") -- for raycasting
local MinimapRotation = 0 -- in degrees, not radians
local YOffset = 0 -- custom y offset for camera position, this was in our code so i just included it

local CamCF = Cam.CFrame
local RootPos = HRP.Position
local PixelDiff = Cam:WorldToViewportPoint(RootPos) :: Vector3 
local Point2 = Cam:WorldToViewportPoint(RootPos + Vector3.new(1,0,1)) :: Vector3
PixelDiff = Point2-PixelDiff -- scale difference, always positive
PixelDiff = Vector2.new(PixelDiff.X,PixelDiff.Y)*MinimapSize -- amount of pixels in one stud

local MiddleOfUI = (MinimapPos + Vector2.yAxis*GUIService.TopbarInset.Height) + MinimapSize/2
local LocDifference = InputPos - MiddleOfUI -- positive x/y when the mousepos is to the right or down past the MiddleOfUI
local OffsetFromCamera = LocDifference/PixelDiff -- get the X&Z stud offset from the middle of the minimap

local NewPosition = CamCF*CamCF.Rotation:Inverse()*CFrame.Angles(0,math.rad(MinimapRotation),0)*CFrame.new(OffsetFromCamera.X,0,OffsetFromCamera.Y)
--print(PixelDiff,"\n",LocDifference,"\n",OffsetFromCamera,"\n",NewPosition.Position)

local HitPart = WorldModel:Raycast(NewPosition.Position + Vector3.yAxis*YOffset, -Vector3.yAxis * 2000)

 -- debug part
--local p = Instance.new("Part")
--p.Position = Vector3.new(CamPoint.X,PositionCam.CFrame.Position.Y+10,CamPoint.Z)
--p.Anchored = true
--p.Color = Color3.fromRGB(0, 255, 81)
--p.Size = Vector3.new(10,0,10)
--p.Parent = workspace
--task.delay(2,game.Destroy,p)

if HitPart then
-- you got your position
end

even if the client can correctly get the 3d position, you should still do raycast validation on the server and such to make sure they arent sending bad positions. if you were to only raycast with the workspace camera, you may want to use ViewportPointToRay as it only works on workspace.CurrentCamera, not viewport cameras

1 Like

This is actually such a rare pull, thank you. I’ll review this and see if it gets the desired outcome. I’ll keep you updated!

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