1 // g++ -O0 -std=c++11 -Wall main_bug_1.cpp  -o main_bug_1
2 #include "nanort.h"
3 #include <iostream>
4 
5 typedef double real;
6 
main(int argc,char * argv[])7 int main(int argc, char * argv[])
8 {
9     std::cout << "This program exposes a possible accuracy bug with nanort." << std::endl<<std::flush;
10     std::cout << "A slight variation on direction[0] makes nanort misses a real intersection." << std::endl<<std::flush;
11     std::cout << "Called without argument, we run a normal case where a ray creates an intersection on a single triangle" << std::endl<<std::flush;
12     std::cout << "Called with one argument, we slightty changes the direction and have a no intersection result, that is not normal" << std::endl<<std::flush;
13     bool activate_precision_bug = false;
14     if (argc>1)
15     {
16         activate_precision_bug = true;
17     }
18     real vertices[9];
19     unsigned int triangles[3] ={0,1,2};
20 
21     const real xMin=-1.0, xMax=+1.0;
22     const real zMin=-3.0, zMax=+3.0;
23     vertices[3 * 0] = xMax; vertices[3 * 0 + 1] = 2.0; vertices[3 * 0 + 2] = zMin;
24     vertices[3 * 1] = xMin; vertices[3 * 1 + 1] = 2.0; vertices[3 * 1 + 2] = zMin;
25     vertices[3 * 2] = xMax; vertices[3 * 2 + 1] = 2.0; vertices[3 * 2 + 2] = zMax;
26 
27     real origins[3];
28     real directions[3];
29 
30     origins[0] = -0.36; origins[1] = +7.93890843; origins[2] = 1.2160368;
31     directions[1] = -8.66025404e-01; directions[2] = -0.5;
32     directions[0] = 0.0;
33     if (activate_precision_bug)
34     {
35         directions[0] = -5.30287619e-17;
36     }
37     std::cout << "directions[0] = " << directions[0] << std::endl;
38 
39     nanort::BVHBuildOptions<real> build_options; // Use default option
40     nanort::TriangleMesh<real> triangle_mesh(vertices, triangles, sizeof(real) * 3);
41     nanort::TriangleSAHPred<real> triangle_pred(vertices, triangles, sizeof(real) * 3);
42     nanort::BVHAccel<real> accel;
43     build_options.cache_bbox = true;
44     int ret = accel.Build((size_t) 1, triangle_mesh, triangle_pred, build_options);
45     assert(ret);
46     nanort::Ray<real> ray;
47     nanort::TriangleIntersector<real, nanort::TriangleIntersection<real> > triangle_intersector(vertices, triangles, sizeof(real) * 3);
48     nanort::TriangleIntersection<real> isect;
49 
50     ray.org[0] = origins[0];
51     ray.org[1] = origins[1];
52     ray.org[2] = origins[2];
53 
54 
55     const real length = sqrt(directions[0] * directions[0] +
56                              directions[1] * directions[1] +
57                              directions[2] * directions[2]);
58     ray.dir[0] = directions[0]/length;
59     ray.dir[1] = directions[1]/length;
60     ray.dir[2] = directions[2]/length;
61 
62     ray.min_t = 0.0;
63     ray.max_t =  1.0e+30;
64 
65     const bool hit = accel.Traverse(ray, triangle_intersector, &isect);
66     if (hit)
67     {
68         std::cout << "We have the expected result" << std::endl<<std::flush;
69         std::cout << "Intersection isect.u =" << isect.u << " v = " << isect.v << std::endl<<std::flush;
70     }
71     else
72     {
73         std::cout << "No intersection detected" << std::endl<<std::flush;
74         std::cout << "We get the wrong result" << std::endl<<std::flush;
75 
76     }
77     return 0;
78 }
79