Intersection Precision Limits at Extreme Ranges?

Intersection Precision Limits at Extreme Ranges?

Our application uses Embree to test whether primitives in a mesh are visible at a given camera position in theta/phi space (we convert to Cartesian).  We use triangle meshes and the RTC_INTERSECT1/4/8 flags, depending on the CPU architecture when the program is run.  The meshes we're interested in have extremely small primitive areas relative to the ray origin.  Specifically, for testing we use a square mesh made up of 200 triangle primitives along the x-y plane - the primitive normals are all facing the +z axis and each triangle has an area of 5E-7, so the length of the square is 0.01 units.

Our test is to generate a ray for each triangle whose origin is X units away and the direction is targeting the triangle centroid - all rays have the same origin.  I've observed that when the ray origin and triangle normals are perfect aligned (i.e. ray dir dot normal = -1), there's no error.  However, as soon as the origin moves off-axis, the rays for some facets are either 1) Reporting no intersection (geomID/primID is -1) or 2) Reporting a primitive other than the target.  These errors become worse as the ray dir and normals become orthogonal (i.e. dir dot normal = 0) and as the origin is moved further away from the mesh.  As a rough data point, when the ray origin is moved to 10000 units and org.z approaches 0.0, about half of the rays are reporting no intersection or the wrong primitive.  When using the RTC_SCENE_ROBUST flag, the error is even worse.  Note that for real applications, we can't set our origins any closer than 1000 units from the mesh.

I'm not a domain expert in raytracing, so I guess my question is what's causing this behavior?  Is it error in the BVH traversal or the intersection algorithm?  Some folks here believe that the limitations are due to the single-precision implementation, is this accurate?  I recently read a paper by Thiago Ize named "Robust BVH Ray Traversal" that seems to exhibit the same behavior, i.e. mis-hits or no-hits, so I'm wondering if it's the BVH that Embree chooses based on whatever flags are pushed into the scene that causes errors.  If this is true, is there any sort performance data available or a way to calculate a limit to the range/primitive area/relative camera angle we should be using?

Thanks!

5 posts / 0 new
Last post
For more complete information about compiler optimizations, see our Optimization Notice.

Hi Jake. The geometry you are trying to intersect cannot be handled properly with single precision floating point numbers. If the edge of a triangle is only 0.01 units long, and the ray 10000 units away, then you need at least log2(10000/0.01) = 20 bits to represent the ray direction sufficiently accurate to be able to distinguish between the triangles. In single precision floating point you just have 24 bits of precision, thus you really stress the limits with this geometry.

As you realized the robust mode of Embree will not help you either, however, the robust mode will at least guarantee you to hit some triangle of the mesh (even though for precision reasons it may still be the wrong one).

Thanks Sven, your example gives some insight into how we should be move forward.  Would setting tnear to a value other than 0 help with our range issue?  My understanding from the API is that a value other than 0 would effectively move the beginning of the ray segment closer to the mesh.  Our main concern is that the rays all need to be coherent from a certain range (10k-1k units).  I suppose if changing tnear doesn't work we could do something like creating a plane at a closer range outside of Embree and generating the ray origins and dirs as points on the plane to simulate coherence at a further distance.

Changing tnear does not help with precision, as the issue is already that the single precision ray origin and direction have not sufficient precision. If moving the start of the ray closer is an option, then you could move the origin closer to the geometry. Thus use double precision to intersect the rays in user code with a plane in front of your geometry, and then use Embree to start tracing from the hitpoints of this plane.

Hi Jake. The geometry you are trying to intersect cannot be handled properly with single precision floating point numbers. If the edge of a triangle is only 0.01 units long, and the ray 10000 units away, then you need at least log2(10000/0.01) = 20 bits to represent the ray direction sufficiently accurate to be able to distinguish between the triangles. In single precision floating point you just have 24 bits of precision, thus you really stress the limits with this geometry.

As you realized the robust mode of Embree will not help you either, however, the robust mode will at least guarantee you to hit some triangle of the mesh (even though for precision reasons it may still be the wrong one).

Leave a Comment

Please sign in to add a comment. Not a member? Join today