#### I’d like to make an imagelabel on a part, on a specific position, I have the position from a raycast, but of course, SurfaceGUIs dont work with that.

Does anyone have any Idea how could I achieve this?

Does anyone have any Idea how could I achieve this?

How are you raycasting? Because particles don’t have collisions so not sure how you’re getting that position

2 Likes

**edit: previous version of module didn’t calculate the x,y values correctly, heres the fixed one**

**i’d also like to add that this works optimally when the part isn’t rotated, which in your case, it isn’t**

```
local WorldToVector2 = {}
function WorldToVector2:Vector2FromRay(result : RaycastResult) : (number,number,Enum.NormalId)
-- the following will be done:
-- convert to object space for easier cacluations
-- use the normal values to determine which face the ray hit and cacluate the normalized distances between the corners
-- of the hit face
local hit_part : BasePart = result.Instance :: BasePart
local pos : CFrame = hit_part.CFrame:ToObjectSpace(CFrame.new(result.Position + Vector3.new(0.5,0.5)))
local norm_x = result.Normal.X
local norm_y = result.Normal.Y
local norm_z = result.Normal.Z
if math.abs(norm_x) == 1 then
local x = (pos.Z * -norm_x) + (hit_part.Size.Z/2)
local y = (-pos.Y) + (hit_part.Size.Y/2)
x /= hit_part.Size.Z
y /= hit_part.Size.Y
return x,y, norm_x < 0 and Enum.NormalId.Left or Enum.NormalId.Right
end
if math.abs(result.Normal.Y) == 1 then
local x = (-pos.X * -norm_y) + (hit_part.Size.X/2)
local y = (-pos.Z) + (hit_part.Size.Z/2)
x /= hit_part.Size.X
y /= hit_part.Size.Z
return y,x, norm_y < 0 and Enum.NormalId.Bottom or Enum.NormalId.Top
end
if math.abs(result.Normal.Z) == 1 then
local x = (pos.X * norm_z) + (hit_part.Size.X/2)
local y = (-pos.Y) + (hit_part.Size.Y/2)
x /= hit_part.Size.X
y /= hit_part.Size.Y
return x,y, norm_z < 0 and Enum.NormalId.Front or Enum.NormalId.Back
end
end
```

i’ve created this short module to determine the normalized distances between the corners of the raycast’s hit face

to get the 2d position:

```
local nx,ny,face = WorldToVector2:Vector2FromRay(raycast)
local x,y = SurfaceGui.CanvasSize.X * nx, SurfaceGui.CanvasSize.Y * ny
```

1 Like

It is not a particle. just a sphere controlled through a script.

2 Likes

Holy crap, well first of all, how would I use this?

And by any chance could you explain some of the math you’re doing here? My brain is fried just from reading that.

Edit: I’m using the normal of the raycast to find the face of the part, is there any way to use this in the function? Because I had intended the surfaceGUI to also go on other player’s bodyparts, so normally they’d be rotated.

1 Like

```
local WorldToVector2 = {}
function WorldToVector2:Vector2FromRay(result : RaycastResult) : (number,number,Enum.NormalId)
-- the following will be done:
-- convert to object space for easier cacluations
-- use the normal values to determine which face the ray hit and cacluate the normalized distances between the corners
-- of the hit face
local hit_part : BasePart = result.Instance :: BasePart
local pos : CFrame = hit_part.CFrame:ToObjectSpace(CFrame.new(result.Position))
local local_normal : Vector3 = hit_part.CFrame:VectorToObjectSpace(result.Normal)
local norm_x = math.round(local_normal.X)
local norm_y = math.round(local_normal.Y)
local norm_z = math.round(local_normal.Z)
if math.abs(norm_x) == 1 then
local x = (-pos.Z * norm_x) + (hit_part.Size.Z/2)
local y = (-pos.Y) + (hit_part.Size.Y/2)
x /= hit_part.Size.Z
y /= hit_part.Size.Y
return x,y, norm_x < 0 and Enum.NormalId.Left or Enum.NormalId.Right
end
if math.abs(norm_y) == 1 then
local x = (-pos.X * -norm_y) + (hit_part.Size.X/2)
local y = (-pos.Z) + (hit_part.Size.Z/2)
x /= hit_part.Size.X
y /= hit_part.Size.Z
return y,x, norm_y < 0 and Enum.NormalId.Bottom or Enum.NormalId.Top
end
if math.abs(norm_z) == 1 then
local x = (-pos.X * -norm_z) + (hit_part.Size.X/2)
local y = (-pos.Y) + (hit_part.Size.Y/2)
x /= hit_part.Size.X
y /= hit_part.Size.Y
return x,y, norm_z < 0 and Enum.NormalId.Front or Enum.NormalId.Back
end
end
```

i forgot to use `VectorToObjectSpace`

for the raycast’s normal which pretty much fixes the rotation problem

the module already returns the face of the part for you

Wow, it works, It’s gonna take me a while to understand all this witchery.

One last question tho, any way to keep the texture a fixed size? the image label im using uses offset instead of scale for size yet it still changes depending on the size of the part its parented to.

you can try changing the `CanvasSize`

to see if that helps

```
Gui.CanvasSize *= ray.Instance.Size.Magnitude * 0.025
```

Seems to have worked, thanks!