How can i find the closest point on a Wedge?

Hello, i’m making a movement system that doesn’t use Roblox’s physic and i need to find the closest point on a Wedge of any size

Here is the code i’m using:

if part:IsA("Part") then
		local shape = part.Shape
		local halfSize = part.Size * 0.5
		local transform = part.CFrame:PointToObjectSpace(HRP.Position)
		
		if shape == Enum.PartType.Wedge then
			local yAxisProgress = (math.clamp(transform.Z, -halfSize.Z, halfSize.Z) / halfSize.Z) * halfSize.Y
			local yClamp = math.clamp(transform.Y, -halfSize.Y, halfSize.Y)
			local localClosest = Vector3.new(
				math.clamp(transform.X, -halfSize.X, halfSize.X),
				(yClamp > yAxisProgress and yAxisProgress) or yClamp,
				math.clamp(transform.Z, -halfSize.Z, halfSize.Z)
			)
			local closestPoint = part.CFrame:PointToWorldSpace(localClosest) 
			
			return closestPoint
			
		else
			-- other part types
		end
	end

And here is the result it gives me:
image

I know that the problem is because of me calculating where the player is on the Z and Y axis but i don’t know how i can calculate the actual closest position.

I saw this function, but for some reason roblox doesn’t let me use it.
And if possible, is there a way of finding the closest point on CornerWedges too?

This is my first post, any help is appreciated!

3 Likes

For any surface of the WedgePart, including the slanted one, you can just project the player location onto the face. First, you get a normal for the face by taking 3 corners of the part that line in the plane of that face, and doing a cross product of two vectors between 2 pairs from the 3 corner points. This gets you a normal for the face. You don’t even have to care about the sign of the normal, as you’ll see it factors out. Then project the vector from one of the corner points ot the player position onto the face by removing the component of this vector that’s along the face normal. The projected point you get is the closest point on the plane of that face to the player’s position.

From there, you just have to do the usual bounds checking or clamping that you’re already doing, to either constrain the point to bounds of the face, or to ignore points that are not on the part (whichever makes sense for your code).

Here is an example, specific to projecting some point onto the slanted face of a WedgePart, exactly as in your screenshot:

local halfSize = 0.5 * wedge.Size
local cf = wedge.CFrame
local v1 = (cf * CFrame.new( halfSize * Vector3.new(1,-1,-1))).p
local v2 = (cf * CFrame.new( halfSize * Vector3.new(-1,-1,-1))).p
local v3 = (cf * CFrame.new( halfSize * Vector3.new(-1,1,1))).p
local n = (v1-v2):Cross(v3-v2).Unit
local projectedPosition = playerPos - ((playerPos -v2):Dot(n) * n)

playerPos is the Player’s position
v1, v2, v3 are 3 part corners that are in the plane of the slanted face of the wedge
n is the calculated normal of the slanted face
projectedPosition is the projection of the player position onto the plane of the slanted face.

The code above is just the projection, I omitted the part size bounds checking since you already know how to do that. The code above would actually generalize to work for any of the 5 sides of the wedge, just by using different permutations of the part’s corners for v1,2,3, but since the other 4 faces of the wedge have normals that are just the part.CFrame.RightVector, LookVector or UpVector (or their opposites), like a normal block part, there’s no need to compute the normal for any face besides the slanted one, so you just do the projection by clamping one of the player position’s coordinates in wedge object space, to half the part size in the relevant direction.

Of course you also need to first identify which face you need to project onto, which is also easy just by converting player position into object space of the part and doing some basic sign and distance checks to see which side of the part it’s on.

For other types of parts, like MeshParts, where there is not necessarily a way to get the face normals from simple geometric calculations, you can still raycast towards the part and get a hit point and normal vector from the raycast result. From that point on, projecting on the the plane defined by the hit point and hit normal works the same as above. For an odd shaped thing, the bounds checks probably also have to be replaced by doing a second raycast towards the projected point.

3 Likes

I actually don’t, i just searched how to find the closest point on a block part and found that

D:

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