Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- 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 {
- TypeNode const* stack_nodes[MCRT_MAX_BVH_TRAVERSAL_FRAMES];
- Float stack_dists[MCRT_MAX_BVH_TRAVERSAL_FRAMES];
- size_t stack_ptr = 0;
- bool result = false;
- bool recursed = false;
- TypeNode const* node = node_start;
- LOOP:
- Float min_possible_t0, min_possible_t1;
- bool hit0, hit1;
- if (!node->info.is_leaf) {
- //Internal node
- TypeNode const* child0 = node->internal.get_child0();
- TypeNode const* child1 = node->internal.get_child1();
- auto bound_child0 = node->internal.get_bound_child0();
- auto bound_child1 = node->internal.get_bound_child1();
- hit0 = ray_rt.intersects(bound_child0, &min_possible_t0);
- hit1 = ray_rt.intersects(bound_child1, &min_possible_t1);
- hit_wld->statistics.tests_bounds = static_cast<uint16_t>(hit_wld->statistics.tests_bounds+2);
- if (!hit0) {
- if (!hit1) { //This ray did not hit either child of `node`.
- //Fall out to pop stack.
- } else { //This ray hit child 1 but not child 0. No need to push stack.
- if (min_possible_t1<hit_wld->closest.distance) { //Haven't already found closer hit
- node = child1;
- goto LOOP;
- } else {
- //Fall out to pop stack.
- }
- }
- } else {
- if (!hit1) { //This ray hit child 0 but not child 1. No need to push stack.
- if (min_possible_t0<hit_wld->closest.distance) { //Haven't already found closer hit
- node = child0;
- goto LOOP;
- } else {
- //Fall out to pop stack.
- }
- } else {
- //This ray hit both children. Push stack with the farther of the two.
- assert_term(stack_ptr<MCRT_MAX_BVH_TRAVERSAL_FRAMES,"Stack overflow!");
- if (min_possible_t0<=min_possible_t1) { //Traverse left first
- if (min_possible_t0<hit_wld->closest.distance) { //Haven't already found closer hit
- stack_nodes[stack_ptr] = child1;
- stack_dists[stack_ptr] = min_possible_t1;
- ++stack_ptr;
- node = child0;
- goto LOOP;
- } else { //Neither child is closer than a previous hit.
- //Fall out to pop stack.
- }
- } else { //Traverse right first
- if (min_possible_t1<hit_wld->closest.distance) { //Haven't already found closer hit
- stack_nodes[stack_ptr] = child0;
- stack_dists[stack_ptr] = min_possible_t0;
- ++stack_ptr;
- node = child1;
- goto LOOP;
- } else { //Neither child is closer than a previous hit.
- //Fall out to pop stack.
- }
- }
- }
- }
- } else {
- //Leaf node
- Objects::ObjectBase const* obj;
- #define TEST_LEAF_OBJ(IND)\
- obj = node->leaf.get_child##IND(scene->objects);\
- if (obj->type!=Objects::ObjectBase::TYPE::PRIM_POINT) {\
- hit##IND = ray_rt.intersects(node->leaf.get_bound_child##IND(), &min_possible_t##IND);\
- ++hit_wld->statistics.tests_bounds;\
- if (hit##IND && min_possible_t##IND<hit_wld->closest.distance) {\
- TEST_OBJ_##IND:\
- if (target_object==nullptr || obj==target_object) {\
- bool result_sub = obj->intersect_from_rt(ray_rt, hit_wld);\
- if (result_sub) {\
- result = true;\
- recursed = false;\
- }\
- ++hit_wld->statistics.tests_objects;\
- }\
- }\
- } else goto TEST_OBJ_##IND;
- TEST_LEAF_OBJ(0)
- if (node->info.num_objs>=2) { TEST_LEAF_OBJ(1) }
- //Fall out to pop stack
- }
- //Pop stack
- POP_STACK:
- if (stack_ptr>0) {
- --stack_ptr;
- if (hit_wld->closest.distance < stack_dists[stack_ptr]) {
- //Found closer hit during previous traversal
- goto POP_STACK;
- } else {
- node = stack_nodes[stack_ptr];
- goto LOOP;
- }
- }
- if (result) {
- if (!recursed) hit_wld->closest.object->parent_node->get_lcl_to_rt_hit(hit_wld,ray_rt.ts);
- return true;
- } else {
- return false;
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement