How can I get the position of the surface that's always facing up?

These are a bunch of random parts that are rotated randomly.

Above is the same image, but the red points are what I want to get. Since I rotated the object with the blue dash on it to its side, it doesn’t get the red surface position anymore. It instead gets the position of the blue dot.

To be as simple as possible, I want to get the top surface position (the red marks) of all the parts regardless of the parts orientation. I know this is possible with UpVector but I don’t understand CFrame in the slightest.

This is the math I currently have for getting the surface position. It works perfectly for parts until they’re rotated.

local TopSurfaceYAxis = (BasePart.CFrame * CFrame.new(0, BasePart.Size.Y / 2, 0))
1 Like

I think probably the easiest way to do this would be to loop through each face and track which one had the highest y-value.

--TopSurfaceYAxis's y-value must be set to -math.huge so rotated normals under 0 work
local TopSurfaceYAxis, CFHold = CFrame.new(0, -math.huge, 0), CFrame.new()

for _, face in pairs(Enum.NormalId:GetEnumItems()) do
	--get the rotated normal 
	CFHold = BasePart.CFrame * CFrame.new(Vector3.fromNormalId(face) * BasePart.Size / 2)
	--compare the rotated normal's y-value to current y-value
	if CFHold.p.Y > TopSurfaceYAxis.p.Y then
		TopSurfaceYAxis = CFHold
	end
end

This could be improved, i.e. using a direction Vector and getting the angle between that and each normal, but for simplicity’s sake I think this is fine.

3 Likes

Do you know if there’s a simpler way to do this using UpVector? I heard it was a way but wasn’t given a good explanation on the how.

1 Like

From my knowledge, no. CFrame.UpVector returns the up-facing direction of the CFrame, which accounts for rotation. In a problem like this where the CFrame is arbitrarily rotated, UpVector doesn’t give any useful information.

1 Like

You can do a couple of things:

Make sure all your parts are rotated the correct way(easiest and simplist to do)

Raycast above the part downwards then find the matching face by comparing it with the CFrame of the part(relatively simple but not really effective and not recommended for a task like this)

Use maths. Get the DotProduct of every Vector to the world’s up vector( which is (0,1,0) then the Smallest product will be the one that faces upwards the most.

Or you can do the other method @ranto828 said, testing to see which side of the part is higher although it will not work for long and flat parts.

(You will need a map for getting the normal corresponding to each face.)

1 Like

Thank you both for the information. I’ve decided to use ranto’s method as well as incorporate a small amount of raycasting just for double checking to get long and flat parts.

1 Like