pickWithRay misses front surface (triangle-corner?)

Sometimes the function pickWithRay() misses the front surface of a connected object and rather picks the back:

Note that rotating the sphere by 180 degrees around Y seemingly fixes it.

This error leads to serous (somewhat irreproducible) problems. Giving the object double-sided meshes also does not really help.
My suspicion is that it has to do with a “<” sign instead of a “<=” sign somewhere in the default triangle predicate. Or (worse to fix) it is a roundoff-errror, in which case the predicate probably needs some epsilon tolerance?

… its actually hitting the edge between two triangles rather than the corner.

… but I suspect the corner might have the same problem.
Here is a link to an algorithm which seems to include such EPSILON values:

as far as I can see its not possible to write your own intersection, since both mesh picking predicates do not really calculate the intersection.

We already use this algorithm for the ray / triangle intersection code:

In fact, adding epsilon in the code will make things worse, as it will return a non intersection more often.

You could try a workaround by shooting an additional ray with a slightly perturbed direction. If the distance of the intersection for this ray is too different from the distance found with the first ray, shoot a third ray to decide which distance to pick.

Do you mind changing lines 216 and 224 to
bv < -EPS || bv > 1+EPS
And likewise
For a try?

My workaround is to perturb all my rays by just a little EPS to massively decrease the chance of this happening.
But I really think this should be fixed in the source somehow. Having a tiny bit of overlap of neighboring triangles is not such an issue.

Yes, that’s something that could be done. I think we can add a “epsilon” property to the ray class for this. I will make a PR tomorrow.

Here’s the PR:

It adds an epsilon property to the Ray class.

Thanks! (would it not make sense to have the default epsilon being some small value?)

I set the default value to 0 to keep backward compatibility.

I can see this. Bu this that means that the bug (a ray not hitting the front surface) is still present and it may take other a lot of effort to find out whats wrong and to discover this somewhat hidden feature. Can you come up with a use-case where a tiny default epsilon would actually hurt?
I doubt that anyone relies on the beam missing the front surface.

Is there a reason that the Ray is not working properly without RayHelper? I actually find my old comment in my code from many years ago lol:

// Add the ray helper, for some reason the ray doesnt work
// properly without adding the helper and attaching it to a mesh
// @TODO: Ask on forums?
let rayHelper = new RayHelper(ray);

The helper states that it’s useful for debugging, but I never pick anything without it. Should the documentation be changed if it’s always needed?

I never used the ray helper for ray intersections, except for the playground example. The ray works fine without it, except for the bug reported here.

Ha - ok weird :frowning:

cc @sebavan regarding setting a non-zero default value for epsilon (even if it’s a breaking change, I’ve no strong opinion about it).

As mentioned, I would much prefer Epsilon to be by default bigger than zero.
Should we ask someone else? @RaananW ?
Is there a way to test it within a playground? Did you try it with the above example and does it work well?

I am fine with setting the epsilon to our default epsilon value.

Here you are!

2 Likes

Brilliant! The examples above are now fixed in the new Bablyon Version. Thanks!