3
$\begingroup$

I am working with Blender 3.6.4.

I seek to have points inside a concave object be taken to its surface. I have set up the node tree in the photo, which does the following: the input geometry at the left is a point cloud surrounding the object "Sphere". I set the position of those points based on a "Switch" node, which would hopefully evaluate as "False" for points not inside the sphere and "True" for points inside it. Right now, the "Switch" entry is effectively void; I have tried some solutions I will discuss later, but they didn't work.

If "False", then the Switch simply repeats the point's position. If "True", then gives the closest position on the sphere (outputted from Geometry Proximity).

enter image description here

The "False" and "True" inputs are working as expected; I just can't have the "Switch" correctly select which points should move and which should stay in place. If all selected are true/false, the following results are obtained:

enter image description here

(False)

enter image description here

(True)

What I was trying to do is, I was trying to check whether the vector going from the closest position on the sphere to the point's position goes roughly in the same direction as the normal at that point of the sphere by checking the sign of their dot product. Hence, a positive dot product signals the point is outside the object, because the normal at the closest position of the sphere would point at it (roughly).

The problem is: I don't know how to retrieve the normal at the closest position on the sphere. The closest node I know for that would be "Evaluate at Index", but I don't have the index, only the position. I have tried different combinations of nodes, but they didn't work.

$\endgroup$
2
  • 2
    $\begingroup$ It seems a better title would be: "Move points outside of an object to its surface"? $\endgroup$ Commented Oct 6, 2023 at 12:33
  • $\begingroup$ You are correct and I have edited the title. However, I think I may have miswritten somewhere in the post, but the goal was actually to get points inside to the surface, not those that are outside... $\endgroup$ Commented Oct 7, 2023 at 13:10

1 Answer 1

5
$\begingroup$

You probably became a victim of sharp edges… Imagine a 2D world, where you find the nearest point on a surface circumference:

problem is, it's ambiguous which line is the nearest. Yellow or cyan?

I don't know what is the tie-breaker, I'd guess the lowest index of a face wins. So if the yellow line had the lower index, its normal would suggest you're inside the shape!

($α > 90°$)

Here's a simple way that is 100% reliable with convex and concave hulls (objects), as long as they are manifold (here the important part is that hulls don't overlap - if they do, you will want to use Hulifier's solution)

The way it works is that for each point it shoots a ray directly down $<0, 0, 1>$, and it can't possibly hit a vertical face (parallel to the ray), so each face hit has to be at least slightly tilted from the vertical. Interpretation if it's tilted down or up depends on the face's normal - starting inside a hull, all faces hit must have a normal $90°$ within the same direction as the ray - see how the arrow going down can't possibly hit a red line (face in 3D) from inside:

I added a triangulation because I'm not sure if maybe discrepancy between a triangle and face normal (or geometry) could cause an issue. See the comments and edit history for more information on that.

And here's the result:

I initially misunderstood what OP wanted and selected points outside, whereas OP wanted to select points inside - to get the latter, simply pass the Selection through Boolean Math: NOT - or, since I'm already NOTting within the NOT AND, just resign from that NOT (two NOTs cancel out just like two minuses):

Also notice how I flattened the spawning box, so that we can see the result works:

$\endgroup$
6
  • $\begingroup$ This solution works very well – Raycast is a great solution to the problem. The issue I had wasn't with the mapping to the surface as in the drawings (that is handled by Geometry Proximity), it was with the selection, which you did with Raycast. Also, you had to increase the threshold because the Raycast axis has a forgotten 0.100 that seems like it should be a 0.000. $\endgroup$ Commented Oct 7, 2023 at 13:12
  • $\begingroup$ @ÉricoPatto I understood the issue is with the selection, but while you didn't actually present the failing solution, it seemed from the description you first found the index of the nearest face, and then read the normal of that face (or in one step directly using "Sample Nearest Surface) to compare with the offset from that face - and so I explained why that was unreliable (not sure, but maybe you could make it work: after finding the nearest position on a face, check if the distance from there to the nearest edge is 0 - and in such a case get the normal of that edge). $\endgroup$ Commented Oct 7, 2023 at 14:21
  • $\begingroup$ @ÉricoPatto I explained the raycasting and why the $0$ threshold didn't work initially. See the edit. $\endgroup$ Commented Oct 7, 2023 at 14:41
  • $\begingroup$ I understood the Raycast and the problem with the 0 threshold. I suggested the "about 5 errors" you mentioned might be because the Raycast axis points toward (0.1, 0, -1), while the "Greater Than" is performing a dot product with the slightly different vector (0, 0, -1). I wonder why the Raycast axis isn't vertical. $\endgroup$ Commented Oct 8, 2023 at 13:19
  • $\begingroup$ @ÉricoPatto ohhhhh GOOD CATCH $\endgroup$ Commented Oct 8, 2023 at 13:28

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .