Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Incorrect intersection results when using RTC_SCENE_FLAG_ROBUST #387

Open
SallyLam opened this issue Aug 6, 2022 · 9 comments
Open

Incorrect intersection results when using RTC_SCENE_FLAG_ROBUST #387

SallyLam opened this issue Aug 6, 2022 · 9 comments

Comments

@SallyLam
Copy link

SallyLam commented Aug 6, 2022

The intersection results are occasionally incorrect, even when using the flag RTC_SCENE_FLAG_ROBUST. It reports a hit when there are actually no intersection between the ray and the reported triangle, and the tfar returned is some large number that doesn't make sense.

An example failure case is shown in the code below. The scene contains one triangle.
Embree returns an Intersection at t = 12291.2.
In reality, there are no intersection between the ray and the triangle. Also, the distance between the ray origin and any vertices is less than 600, which is significantly different from the returned tfar.
It is very confusing why it returns a hit, and how it computes such a tfar.

I see this kind of errors quite often. From my observation, it tends to happen when the triangle is somewhat skinny. (In the example below, the triangle has edge lengths of around 11.159, 9.721, and 1.438, which is... quite skinny. However, it is still weird that we're getting a false positive hit.)

Could you please help investigate why this is happening and how to fix it? Thanks!

// The following code is adapted from Embree's example code on https://www.embree.org/api.html.
// The only differences are the scene build quality, scene flags, triangle position, and ray origin and direction.

#include <embree3/rtcore.h>
#include <limits>
#include <iostream>

int main()
{
  RTCDevice device = rtcNewDevice(NULL);

  RTCScene scene = rtcNewScene(device);
  rtcSetSceneBuildQuality(scene, RTC_BUILD_QUALITY_HIGH);
  rtcSetSceneFlags(scene, RTC_SCENE_FLAG_CONTEXT_FILTER_FUNCTION | RTC_SCENE_FLAG_ROBUST);

  RTCGeometry geom = rtcNewGeometry(device, RTC_GEOMETRY_TYPE_TRIANGLE);

  float *vb = (float *)rtcSetNewGeometryBuffer(geom,
                                               RTC_BUFFER_TYPE_VERTEX, 0, RTC_FORMAT_FLOAT3, 3 * sizeof(float), 3);
  vb[0] = -1.454641f; vb[1] = 5.068154f; vb[2] = -4.543064f; // 1st vertex
  vb[3] = 0.877591f; vb[4] = -3.057641f; vb[5] = 2.740851f; // 2nd vertex
  vb[6] = 0.577049f; vb[7] = -2.010513f; vb[8] = 1.802213f; // 3rd vertex

  unsigned *ib = (unsigned *)rtcSetNewGeometryBuffer(geom,
                                                     RTC_BUFFER_TYPE_INDEX, 0, RTC_FORMAT_UINT3, 3 * sizeof(unsigned), 1);
  ib[0] = 0; ib[1] = 1; ib[2] = 2;

  rtcCommitGeometry(geom);
  rtcAttachGeometry(scene, geom);
  rtcReleaseGeometry(geom);
  rtcCommitScene(scene);

  RTCRayHit rayhit; 
  rayhit.ray.org_x  = 119.973877f; rayhit.ray.org_y = -438.062073f; rayhit.ray.org_z = 377.931061f;
  rayhit.ray.dir_x  = -0.208998f; rayhit.ray.dir_y = 0.728189f; rayhit.ray.dir_z =  -0.652733f;
  rayhit.ray.tnear  = 0.f;
  rayhit.ray.tfar   = std::numeric_limits<float>::infinity();
  rayhit.hit.geomID = RTC_INVALID_GEOMETRY_ID;

  RTCIntersectContext context;
  rtcInitIntersectContext(&context);

  rtcIntersect1(scene, &context, &rayhit);

  if (rayhit.hit.geomID != RTC_INVALID_GEOMETRY_ID) {
    std::cout << "Intersection at t = " << rayhit.ray.tfar << std::endl;
  } else {
    std::cout << "No Intersection" << std::endl;
  }

  rtcReleaseScene(scene);
  rtcReleaseDevice(device);
}
@SallyLam
Copy link
Author

SallyLam commented Aug 6, 2022

FYI, I'm using the latest Embree 3.13.4 on macOS.

@SallyLam
Copy link
Author

SallyLam commented Aug 10, 2022

After a closer inspection of the data, I realized that the failing "triangle" actually has vertices that are basically collinear. The weird intersection result is less surprising now that the input geometry is not very reasonable.

That said, I found that if I tweak the ray, it doesn't give such false positive results, so it's not consistently failing when given collinear "triangles".

It will be nice if Embree can handle such cases more elegantly. :)
E.g., do not report an unreasonable intersection/tfar, or specify in the documentation that invalid triangles can lead to undefined behaviors.

@loopless
Copy link

loopless commented Jun 16, 2023

This robustness problem has been with embree for some time. Even with 100% water tight geometry and the ROBUST flag on the ray will sometimes report "a miss" in some cases when it intersects an edge. I suppose no-one will notice this when used for visualization but for other applications it is frustrating. Sadly, if you posted such a question on the Optix forum you would get an answer instantly and a follow up from an nVidia dev. Yet here we are nearly a year later with no comment.

@xue-fc
Copy link

xue-fc commented Jun 18, 2023

This robustness problem has been with embree for some time. Even with 100% water tight geometry and the ROBUST flag on the ray will sometimes report "a miss" in some cases when it intersects an edge. I suppose no-one will notice this when used for visualization but for other applications it is frustrating. Sadly, if you posted such a question on the Optix forum you would get an answer instantly and a follow up from an nVidia dev. Yet here we are nearly a year later with no comment.

The ray-triangle intersection algorithm used by embree is not perfectly watertight. I don't know why the developers do not choose Woop algorithm as suggested by DXR, even it has been implemented in embree. https://github.com/embree/embree/blob/0fcb306c9176221219dd15e27fe0527ed334948f/kernels/bvh/bvh8_factory.cpp#L497-L507
Could you please explain about this? Thanks very much! @svenwoop

@svenwoop
Copy link
Contributor

Could you please try out if that experimental BVH8Triangle4vIntersector1Woop works better for you? The ray/triangle intersection of it should be watertight. Just enable the ENABLE_WOOP_TEST in code block above and enable RTC_SCENE_FLAG_ROBUST for your scenes? You need to compile and run on AVX enabled machine for this codepath to be selected, but if that help we could fix that and give you a compile time option to enable this.

@pwais
Copy link

pwais commented Jul 28, 2023

Dear Dr Woop @svenwoop ,

I read your paper on watertight intersections, very cool work! And then I found of course there are open source implementations of it ...

I have been testing some scenes that have lots of ray-to-vertex and ray-to-edge direct hits and I am seeing lots of holes in the results returned back from embree. I have tried two wrappers thus far:

Interestingly, both wrappers give me similar holes (i.e. lack of ray returns) but NOT identical outputs for the exact same bit-for-bit rays.

Based upon your comment above, it seems you suggest trying embree version 4 (i.e. HEAD in this repo) and to toggle the BVH config ... do you think this could help resolve the issue I'm seeing? In particular:

  • Do you know, briefly, what may have changed between embree v3 and v4 with respect to ray-to-edge and ray-to-vertex intersections? (Could it be nothing changed and the projects I cite above are not using embree 3 correctly?)
  • Your most recent comment here is with regards to the BVH but I thought the point of the BVH was to cull and not explicitly test intersections... is the bvh in embree v4 dramatically different than v3 ?

Thanks for any advice you can provide!

@svenwoop
Copy link
Contributor

Embree 3 and Embree 4 will behave identical regarding consistency along edges. Please try out enabling the RTC_SCENE_FLAG_ROBUST scene mode if that gives you sufficient quality. If that is not enough please try to enable that ENABLE_WOOP_TEST define described above. Thus should increase quality further.

@pwais
Copy link

pwais commented Jul 31, 2023

Thank you @svenwoop ! It seems both of the implementations I cited use RTC_SCENE_FLAG_ROBUST . I tried installing libembree-dev and somehow that seems to change the issue, though I would be surprised if that package were built using ENABLE_WOOP_TEST. Is ENABLE_WOOP_TEST disabled by default because it makes intersection tests slower? How come it's not a standard build arg e.g. the AVX flags or a RTC scene arg?

@svenwoop
Copy link
Contributor

svenwoop commented Aug 1, 2023

The ENABLE_WOOP_TEST is just an experimental feature, this is why it cannot get directly enabled in cmake. You have to patch the code to try this out. Embree is designed for rendering where 100% watertightness is not required.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants