Notifications
Clear all

[Closed] Find shortest distance between point and a mesh?

Is there a way to find the distance between a point and a seperate mesh without using a normal/direction?

I have the point3 position and a mesh. I would like to find the closest point on the mesh as a point3 value.

Unfortunatley both
intersectRay <node> <ray>
intersectRayEx <node> <ray>

require a direction ray…

Cheers

18 Replies
1 Reply
(@f97ao)
Joined: 10 months ago

Posts: 0

I think you would have to look through all the points in the mesh and check each of them if they are the closest.
It’s not gonna be that fast I’m afriad
/Andreas

Well, I know this won’t work with non-convex meshes, but if it’s a convex mesh, could you use the vector that goes from the point to the center of the object as direction ray and then use distance between the point in the surface and the first point?.
it’s a quick and dirty method, I know.

I think what andreas was saying was to loop through the mesh and get the position of each vert in the mesh then do a distance calculation between the point and each of the verts. If you save each of these test values into an array you can use amin(arrayname) to find out the smallest value so it’d return the shortest distance between the point and any of the verts in the mesh.

Something like this, I guess:

fn closestDistanceToObject pt obj = (
	local msh = snapshotAsMesh obj

	local closestDist = distance pt (getVert msh 1)
	
	for i = 2 to msh.numVerts do (
		local dist = distance pt (getVert msh i)
		if dist < closestDist do closestDist = dist
	)
	
	delete msh
	
	return closestDist
)
2 Replies
(@bobo)
Joined: 10 months ago

Posts: 0

In addition, record the index of the vertex that returned the closest distance. Then get all faces shared by that vertex and project the point onto the surface of each face along the negative face normal using IntersectRay(). Chances are the closest point on the surface lies inside one of these faces and not on the vertex…

(@halfvector)
Joined: 10 months ago

Posts: 0

That’s right!.

fn closestDistanceToObject pt obj = (
	local msh = snapshotAsMesh obj

	local closestVert = 1
	local closestDist = distance pt (getVert msh 1)
	
	for i = 2 to msh.numVerts do (
		local dist = distance pt (getVert msh i)
		if dist < closestDist do (
			closestDist = dist
			closestVert = i
		)
	)
	
	local faces = meshOp.getFacesUsingVert msh #{closestVert}
	
	if faces != undefined do (
		for f in faces do (
			local rayDir = -(getFaceNormal msh f)
			local intInfo = intersectRay obj (Ray pt rayDir)

			if intInfo != undefined do (
				local dist = distance pt intInfo.pos
				if dist < closestDist do
					closestDist = dist
			)
		)
	)
	
	delete msh
	
	return closestDist
)

I think it’s right… :hmm:

By the way. Exists an obvious optimization. We can avoid the square root used by the distance function by comparing squared distances.

-- Returns the squared distance between two points
fn distanceSq pt1 pt2 = (
	return ( (pt2.x - pt1.x)^2 + (pt2.y - pt1.y)^2 + (pt2.z - pt1.z)^2 )
)

-- Returns the closest distance to an object
fn closestDistanceToObject pt obj = (
	local msh = snapshotAsMesh obj

	local closestVert = 1
	local closestDistSq = distanceSq pt (getVert msh 1)
	
	for i = 2 to msh.numVerts do (
		local distSq = distanceSq pt (getVert msh i)
		if distSq < closestDistSq do (
			closestDistSq = distSq
			closestVert = i
		)
	)
	
	local faces = meshOp.getFacesUsingVert msh #{closestVert}
	
	if faces != undefined do (
		for f in faces do (
			local rayDir = -(getFaceNormal msh f)
			local intInfo = intersectRay obj (Ray pt rayDir)

			if intInfo != undefined do (
				local distSq = distanceSq pt intInfo.pos
				if distSq < closestDistSq do
					closestDistSq = distSq
			)
		)
	)
	
	delete msh
	
	return (sqrt closestDistSq)
)

Obviously, at the end we return the real distance.

Greets.

This is basically what im doing in my script currently(tho unoptimised).

Problem is if u use the inverse normal of the faces to case a ray from my original position it does not hit the target object due to the shape im working with.

Eg.


 
 |  | 
 |  |
 |  |____  <-target mesh
  \.______   <- first vert here is my example(marked as a dot)
 
 
 

Ok now if we use the fist vert ive listed in the example. The normals from the target mesh are down, and left(so we invert these).
Problem here is if we cast a ray from the vert using the face normals from the low poly target mesh, we get not “hit”.

Any ideas on this problem?

Edit: im trying to get the target position on the tragetmesh.(ie where the shortest distance meets the other mesh). So i need either the position and the face, or a direction so I can use a raycast to test for the face/position.

1 Reply
(@bobo)
Joined: 10 months ago

Posts: 0

I don’t see the problem. The ray casting we added is IN ADDITION to measuring the distance to the vertices. If no ray hits, the closest distance to a vertex IS the closest distance to the mesh. If the point happens to be closer to a surface than to a vertex, then we overrule the closest vertex distance.
But in your example the intersectRay() would return undefined because your point IS closer to the corner vertex than to any of the faces, and we ignore the intersection attempts…

Ok thats fair. What if the example both of those were extruded towards the camera, but my point had no matching point on the low poly mesh, the closest point would then be on the line of the low poly mesh, not on the actual vertex itself…Correct?

Hey guys

I think I’m having similar problems with this as Gibbz. I’m relatively new to maxscript but I’m pretty sure I understand everything that is going on in this function.

I’m rotating helper 1 around a cube and positioning the helper 2 at the closest point on the surface. As helper 1 passes over an edge of the cube intersectRay returns undefined so it places helper 2 at closest vertex which isn’t the closest point on the surface. This causes helper 2 to jump all over the place.

Is their a better way? Do I need to also some how check the closest point on an edge?

Not necessarily. The further away the point is from the mesh, the more likely a vert will be closest. Also, the rougher the surface, the more likely a vert is closest. Depending on how accurate this distance measurement needs to be, you might just want to skip the face detection altogether.

I just thought I would post an image to illustrate my problem. I want to find the point on the cube that is closest to the white helper. The yellow helper is the position the above solution finds. Obviously the blue end of the tape helper is where the yellow helper should be.

Page 1 / 2