Ray in the triangle plane

I have two triangles(T0,T1) in my scene and I shoot a ray from {-1,1,0} in the direction {1,0,0}, tmin=0, tmax=2. I was hoping that this ray would intersect with both T0, T1 or at least T1 but neither is the case. I’m having hard time understanding how rt cores are handling ray-triangle intersections when they are in same plane. could someone explain?

Triangle T0 = {
{-1,-1,0},
{-1,1,0},
{1,1,0}}

Triangle T1 = {
{-0.5,0,0},
{-0.5,2,0},
{1.5,2,0}}

environment - optix 7.5, CUDA - 11.1, ubuntu 18.04, rtx 2060

Hi @dmandara, welcome!

Do you have motion blur enabled in your OptiX pipeline? Do you have the ALLOW_UPDATE flag on your BVH? Either of those might have an effect here.

This is a good question, but there are some reasons you shouldn’t necessarily expect to get away with this, since OptiX & RTX are intended for 3D ray tracing, and not 2D ray tracing:

  • The bounding box might have a volume of zero. Should a 3d ray traverse a bbox with zero volume?
  • The ray is in the same plane as the triangles - there is no unique solution to the intersection. Should a ray in the triangle’s plane hit the triangle, and if so what should be the hit point? It makes sense to want to hit the closest edge, but we’re talking about solving for the point-intersection of a single primitive in the case where there is no point intersection, the shape of the intersection is a line segment.
  • The ray’s origin is one of the vertices of T0, should a ray be allowed to strike a surface at the ray’s origin?

A hit-t value of zero is guaranteed not to happen with RTX hardware, and the reason is because the ray needs to be guaranteed to move forward when it hits something, otherwise for example you or the driver or the hardware could accidentally end up in an infinite loop when casting secondary rays or using any-hit shaders. This means you should not expect to hit T0.

A flat AABB with non-zero area and zero volume I believe should be acceptable. You can test this by sending a ray that has a non-zero ray.direction.Z at one of these two triangles. You can also test the t=0 behavior by enabling an any-hit shader and launching a ray from Z=0 with a non-zero ray.direction.Z.

That leaves the question of a ray in the plane of the triangle. I first assumed it should be a miss, but I don’t know the definitive answer, so I’ve started asking a few people. I will respond again once I have a definitive answer - it could be supported or rejected by Optix or by the driver or by the hardware. Because the mathematical hit point is not a point, then whether hitting a triangle edge-on is supported must be a conscious choice, regardless of whether it’s guaranteed or is currently an implementation detail.

In the mean time, one question you might want to consider, if you depend on 2d behavior and want to hit the edges of your 2d triangles, is whether you can or should try to ‘extrude’ the edges of your 2d world into +/- Z in 3d. If the ray is in the Z=0 plane, and you use 3d triangles to represent 2d edges, with verts both above and below zero, then you can certainly get the hit behavior you want. Is that reasonable or unreasonable for your use-case?


David.

2 Likes

Thanks for the reply!

I had ALLOW_UPDATE flag on but removing it did not change the result.

The approach you suggested looks very interesting but it doesn’t seem cost-effective - 6 representative triangles for one triangle. And I’m also not sure if this approach aligns with our needs yet.

Looking forward to hearing what your investigation on a ray in the plane of the triangle leads to!

Let me put it clearly, your idea of ray tracing triangles in 2D using any 3D ray casting SDK is not going to work.

That is like hitting a 3D triangle edge-on which is ill defined due to finite floating point accuracy reasons and everything David explained.
Whatever the outcome is, that is implementation dependent and not a suitable solution.

The approach you suggested looks very interesting but it doesn’t seem cost-effective - 6 representative triangles for one triangle.

If you want to use the ray tracing hardware for finding intersection points between the 2D triangle outlines and a 2D ray, extruding the 2D edges into 3D instead is a feasible solution when using 3D ray casting SDKs.

Representing each edge with two triangles will result in the fastest ray-primitive intersection performance on RTX boards because the ray-triangle intersection will be handled by the hardware RT cores.

If you’re concerned about memory consumption, how many 2D edges do you need to support and how many rays do you need to shoot into the scene to find intersections?

It would also be possible to implement a custom intersection program which would take your 2D line data and extrudes it into a quad, though that would only result in two instead of four vertices but the axis aligned bounding box around that would still need the same information and ray-custom-primitive intersections will run on the streaming multiprocessors instead, which will be slower than the hardware ray-triangle intersections running on the RT cores. Though since you know that the intersection is 2D only, you could optimize that custom intersection program a little.

And I’m also not sure if this approach aligns with our needs yet.

What exactly are your requirements then?

If you’re insisting to handle this in 2D, you could also simply not use any ray casting SDK and calculate the 2D ray-line intersections yourself and completely parallelize that with native CUDA kernels.
Determining a 2D ray-line intersection is simple linear algebra and with some additional spatial structure on top, like a quad tree or a BVH in 2D, you could reduce the number of required ray-line intersection tests.

Done right, that should be the most memory efficient solution and would still be accelerated by the GPU streaming multiprocessors (and should be faster than the above mentioned custom primitives method).

This is not the first time this exact same topic has been discussed on this forum and extruding edges into two triangles perpendicular to the 2D plane is simply the first option when using 3D ray casting SDKs for that.
https://forums.developer.nvidia.com/t/how-does-optix-code-compilation-work/218678/17
https://forums.developer.nvidia.com/t/using-optix7-in-2d-space/182505

Sorry for the slow reply, I just wanted to write to confirm that our hardware and driver experts have told me that tracing a ray into a triangle that is in the same plane as the triangle is not expected to produce an edge hit. You might have hits anywhere in the triangle if your ray is not exactly in the plane of the triangle, but has some slight directional offset due to tiny numerical precision error. If the ray is exactly in the plane of the triangle (with all Z values being zero, for example), I’m told you should expect the ray to miss the triangle.

So for 2d scenes in a plane, your options are to extrude your 2d edges into 3d quads, or you could use our linear curve primitive to represent edges. Both of these options are detailed in the threads that Detlef linked to. The linear curve primitive requires less memory than using a pair of triangles, but it also has a non-zero radius and therefore isn’t the best choice if you need a very precise distance to the edge.


David.

1 Like

Thank you @dhart and @droettger for the suggestions and discussion!

I implemented extruding the triangle into 3d space along with preserving the original triangle. I was concerned about the number of triangles but its fast enough.

I did not use linear curve primitive so far, I will check it out.

1 Like

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