Advertisement
Geometrian

Traversal

Oct 12th, 2017
324
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 3.90 KB | None | 0 0
  1. template <class TypeNode> bool BVH_Basic<TypeNode>::_traverse_helper(Ray const& ray_rt, HitRecord* hit_wld, TypeNode const* node_start, Objects::ObjectBase const* target_object) const {
  2.     TypeNode const* stack_nodes[MCRT_MAX_BVH_TRAVERSAL_FRAMES];
  3.     Float           stack_dists[MCRT_MAX_BVH_TRAVERSAL_FRAMES];
  4.     size_t stack_ptr = 0;
  5.  
  6.     bool result = false;
  7.     bool recursed = false;
  8.  
  9.     TypeNode const* node = node_start;
  10.     LOOP:
  11.         Float min_possible_t0, min_possible_t1;
  12.         bool hit0, hit1;
  13.         if (!node->info.is_leaf) {
  14.             //Internal node
  15.  
  16.             TypeNode const* child0 = node->internal.get_child0();
  17.             TypeNode const* child1 = node->internal.get_child1();
  18.  
  19.             auto bound_child0 = node->internal.get_bound_child0();
  20.             auto bound_child1 = node->internal.get_bound_child1();
  21.             hit0 = ray_rt.intersects(bound_child0, &min_possible_t0);
  22.             hit1 = ray_rt.intersects(bound_child1, &min_possible_t1);
  23.  
  24.             hit_wld->statistics.tests_bounds = static_cast<uint16_t>(hit_wld->statistics.tests_bounds+2);
  25.  
  26.             if (!hit0) {
  27.                 if (!hit1) { //This ray did not hit either child of `node`.
  28.                     //Fall out to pop stack.
  29.                 } else { //This ray hit child 1 but not child 0.  No need to push stack.
  30.                     if (min_possible_t1<hit_wld->closest.distance) { //Haven't already found closer hit
  31.                         node = child1;
  32.                         goto LOOP;
  33.                     } else {
  34.                         //Fall out to pop stack.
  35.                     }
  36.                 }
  37.             } else {
  38.                 if (!hit1) { //This ray hit child 0 but not child 1.  No need to push stack.
  39.                     if (min_possible_t0<hit_wld->closest.distance) { //Haven't already found closer hit
  40.                         node = child0;
  41.                         goto LOOP;
  42.                     } else {
  43.                         //Fall out to pop stack.
  44.                     }
  45.                 } else {
  46.                     //This ray hit both children.  Push stack with the farther of the two.
  47.                     assert_term(stack_ptr<MCRT_MAX_BVH_TRAVERSAL_FRAMES,"Stack overflow!");
  48.                     if (min_possible_t0<=min_possible_t1) { //Traverse left first
  49.                         if (min_possible_t0<hit_wld->closest.distance) { //Haven't already found closer hit
  50.                             stack_nodes[stack_ptr] = child1;
  51.                             stack_dists[stack_ptr] = min_possible_t1;
  52.                             ++stack_ptr;
  53.                             node = child0;
  54.                             goto LOOP;
  55.                         } else { //Neither child is closer than a previous hit.
  56.                             //Fall out to pop stack.
  57.                         }
  58.                     } else { //Traverse right first
  59.                         if (min_possible_t1<hit_wld->closest.distance) { //Haven't already found closer hit
  60.                             stack_nodes[stack_ptr] = child0;
  61.                             stack_dists[stack_ptr] = min_possible_t0;
  62.                             ++stack_ptr;
  63.                             node = child1;
  64.                             goto LOOP;
  65.                         } else { //Neither child is closer than a previous hit.
  66.                             //Fall out to pop stack.
  67.                         }
  68.                     }
  69.                 }
  70.             }
  71.         } else {
  72.             //Leaf node
  73.             Objects::ObjectBase const* obj;
  74.             #define TEST_LEAF_OBJ(IND)\
  75.                 obj = node->leaf.get_child##IND(scene->objects);\
  76.                 if (obj->type!=Objects::ObjectBase::TYPE::PRIM_POINT) {\
  77.                     hit##IND = ray_rt.intersects(node->leaf.get_bound_child##IND(), &min_possible_t##IND);\
  78.                     ++hit_wld->statistics.tests_bounds;\
  79.                     if (hit##IND && min_possible_t##IND<hit_wld->closest.distance) {\
  80.                         TEST_OBJ_##IND:\
  81.                         if (target_object==nullptr || obj==target_object) {\
  82.                             bool result_sub = obj->intersect_from_rt(ray_rt, hit_wld);\
  83.                             if (result_sub) {\
  84.                                 result = true;\
  85.                                 recursed = false;\
  86.                             }\
  87.                             ++hit_wld->statistics.tests_objects;\
  88.                         }\
  89.                     }\
  90.                 } else goto TEST_OBJ_##IND;
  91.                                           TEST_LEAF_OBJ(0)
  92.             if (node->info.num_objs>=2) { TEST_LEAF_OBJ(1) }
  93.             //Fall out to pop stack
  94.         }
  95.  
  96.         //Pop stack
  97.         POP_STACK:
  98.             if (stack_ptr>0) {
  99.                 --stack_ptr;
  100.                 if (hit_wld->closest.distance < stack_dists[stack_ptr]) {
  101.                     //Found closer hit during previous traversal
  102.                     goto POP_STACK;
  103.                 } else {
  104.                     node = stack_nodes[stack_ptr];
  105.                     goto LOOP;
  106.                 }
  107.             }
  108.  
  109.     if (result) {
  110.         if (!recursed) hit_wld->closest.object->parent_node->get_lcl_to_rt_hit(hit_wld,ray_rt.ts);
  111.         return  true;
  112.     } else {
  113.         return false;
  114.     }
  115. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement