How do I get the world position of a frame in surface gui given object rotation?

I have a script that creates a SurfaceGui with N/A number of frames vertically and horizontally, how do I get their world position?

1 Like

I think you just need this method - Camera | Roblox Creator Documentation

I almost got it by this code:

local Part = self.surface
	local Side = self.gui.Face
	local TopLeft = CFrame.new()
	
	if Side == Enum.NormalId.Front then
		TopLeft = Part.CFrame * CFrame.new(Part.Size.X/2,Part.Size.Y/2,-Part.Size.Z/2)
	elseif Side == Enum.NormalId.Back then
		TopLeft = Part.CFrame * CFrame.new(-Part.Size.X/2,Part.Size.Y/2,Part.Size.Z/2)
	elseif Side == Enum.NormalId.Left then
		TopLeft = Part.CFrame * CFrame.new(-Part.Size.X/2,Part.Size.Y/2,-Part.Size.Z/2)
	elseif Side == Enum.NormalId.Right then
		TopLeft = Part.CFrame * CFrame.new(Part.Size.X/2,Part.Size.Y/2,Part.Size.Z/2)
	end
	
	
	
	local TopLeftPosition = TopLeft.Position
	TopLeftPosition = Vector3.new(TopLeftPosition.x / 2, TopLeftPosition.y / 2, TopLeftPosition.z / 2)
	
	for x=0, self.resolution.x-1 do
		for y=0, self.resolution.y-1 do
			if self.pixels[tostring(x) + tostring(y)] then
				local world_vector = self.pixels[tostring(x) + tostring(y)].world_vector
				local frame = self.pixels[tostring(x) + tostring(y)][tostring(x) + tostring(y)]
				
				world_vector.Value = TopLeftPosition + Vector3.new((self.surface.size.x * x)/2, (self.surface.size.y * y)/2, TopLeftPosition.z)
				
				local p = Instance.new("Part", workspace)
				p.Anchored = true
				p.Size = Vector3.new(0.1, 0.1, 0.1)
				p.Position = world_vector.Value
			end
		end
	end

but it still make it wrong
image

Ah my bad I read SurfaceGui as ScreenGui somehow.

local Part = self.surface
local Side = self.gui.Face
local TopLeft = CFrame.new()
local width = 0
local height = 0

-- Use CFrame.Angles to orient the TopLeft CFrame such that TopLeft.rightVector is in the x direction of the surface gui and -TopLeft.upVector is in the y direction of the surface gui
if Side == Enum.NormalId.Front then
	TopLeft = Part.CFrame * CFrame.new(Part.Size.X/2,Part.Size.Y/2,Part.Size.Z/2) * CFrame.Angles(0, math.rad(180), 0)
	width = Part.Size.X
	height = Part.Size.Y
elseif Side == Enum.NormalId.Back then
	TopLeft = Part.CFrame * CFrame.new(-Part.Size.X/2,Part.Size.Y/2,-Part.Size.Z/2)
	width = Part.Size.X
	height = Part.Size.Y 
elseif Side == Enum.NormalId.Left then
	TopLeft = Part.CFrame * CFrame.new(-Part.Size.X/2,Part.Size.Y/2,Part.Size.Z/2) * CFrame.Angles(0, 0, math.rad(-90) )
	width = Part.Size.Z
	height = Part.Size.Y 
elseif Side == Enum.NormalId.Right then
	TopLeft = Part.CFrame * CFrame.new(Part.Size.X/2,Part.Size.Y/2,Part.Size.Z/2) * CFrame.Angles(0, math.rad(90), 0)
	width = Part.Size.Z
	height = Part.Size.Y 
end

for x=0, self.resolution.x-1 do
	for y=0, self.resolution.y-1 do
		if self.pixels[tostring(x) + tostring(y)] then
			local world_vector = self.pixels[tostring(x) + tostring(y)].world_vector
			local frame = self.pixels[tostring(x) + tostring(y)][tostring(x) + tostring(y)]
			
			-- Use the TopLeft CFrame to get the world position
			world_vector.Value = TopLeft.Position + ( TopLeft.RightVector * x / self.resolution.x * width - TopLeft.UpVector * y / self.resolution.y * height)
			
			local p = Instance.new("Part", workspace)
			p.Anchored = true
			p.Size = Vector3.new(0.1, 0.1, 0.1)
			p.Position = world_vector.Value
		end
	end
end
1 Like

This works but it’s on the wrong side when it should be on NormalId Front it’s on Back

Like this: Frames on front, and the points on back
image

image
works perfectly, swapped back and front

1 Like

Ah I must have got the Enums mixed up but it seems like you’ve fixed it now

yep, thanks, you just helped me alot < 3

1 Like

Im sorry but can you help me with coe again? I make it to use pixel by pixel and now i using

function pixel:update(surface, face, resolution)
	local Part = surface
	local Side = face
	local TopLeft = CFrame.new()
	local width = 0
	local height = 0

	-- Use CFrame.Angles to orient the TopLeft CFrame such that TopLeft.rightVector is in the x direction of the surface gui and -TopLeft.upVector is in the y direction of the surface gui
	if Side == Enum.NormalId.Front then
		TopLeft = Part.CFrame * CFrame.new(-Part.Size.X/2,Part.Size.Y/2,-Part.Size.Z/2)
		width = Part.Size.X
		height = Part.Size.Y
	elseif Side == Enum.NormalId.Back then
		TopLeft = Part.CFrame * CFrame.new(Part.Size.X/2,Part.Size.Y/2,Part.Size.Z/2) * CFrame.Angles(0, math.rad(180), 0)
		width = Part.Size.X
		height = Part.Size.Y
	elseif Side == Enum.NormalId.Left then
		TopLeft = Part.CFrame * CFrame.new(-Part.Size.X/2,Part.Size.Y/2,Part.Size.Z/2) * CFrame.Angles(0, 0, math.rad(-90) )
		width = Part.Size.Z
		height = Part.Size.Y 
	elseif Side == Enum.NormalId.Right then
		TopLeft = Part.CFrame * CFrame.new(Part.Size.X/2,Part.Size.Y/2,Part.Size.Z/2) * CFrame.Angles(0, math.rad(90), 0)
		width = Part.Size.Z
		height = Part.Size.Y 
	end
	
	local position = self.instance.AbsolutePosition
	print(position)
	
	self.world_position = TopLeft.Position + ( TopLeft.RightVector * position.x / resolution.x * width - TopLeft.UpVector * position.y / resolution.y * height)
	
	local p = Instance.new("Part", workspace)
	p.Anchored = true
	p.Size = Vector3.new(0.1, 0.1, 0.1)
	p.Position = self.world_position
end

but that doesn’t work, pls help if you can

What is wrong with it/ what issue are you having?

It arranges the vectors incorrectly, most likely this is due to the lack of a for loop, because I am addressing the pixel directly

Is this something like a frame directly parented to the surface gui then?

yep, thats it, i need three characters
to reply

I think the rearrangement of front to back hasn’t been done properly maybe then. I reckon it should be this

if Side == Enum.NormalId.Front then
	TopLeft = Part.CFrame * CFrame.new(Part.Size.X/2,Part.Size.Y/2,-Part.Size.Z/2) * CFrame.Angles(0, math.rad(180), 0)
	width = Part.Size.X
	height = Part.Size.Y
elseif Side == Enum.NormalId.Back then
	TopLeft = Part.CFrame * CFrame.new(-Part.Size.X/2,Part.Size.Y/2,Part.Size.Z/2) 
	width = Part.Size.X
	height = Part.Size.Y
1 Like

that doesn’t helped, yet, it still very big distance…

What are you passing in for the resolution?

literally nothing because the method is in pixel

You need to pass in the resolution (in pixels) of the surface gui in order for it to work.