libs/yocto/yocto_scene.cpp
// Intersect ray with a bvh->
Intersect ray with a bvh->
Intersect ray with a bvh - >
static bool intersect_scene_bvh(const scene_model* scene, const ray3f& ray_,
    int& instance, int& element, vec2f& uv, float& distance, bool find_any,
    bool non_rigid_frames) {
#ifdef YOCTO_EMBREE
  if (scene->embree_bvh) {
    return intersect_scene_embree_bvh(
        scene, ray_, instance, element, uv, distance, find_any);
  }
#endif
  auto bvh = scene->bvh;
  if (bvh->nodes.empty()) return false;
  int  node_stack[128];
  auto node_cur          = 0;
  node_stack[node_cur++] = 0;
  auto hit = false;
  auto ray = ray_;
  auto ray_dinv  = vec3f{1 / ray.d.x, 1 / ray.d.y, 1 / ray.d.z};
  auto ray_dsign = vec3i{(ray_dinv.x < 0) ? 1 : 0, (ray_dinv.y < 0) ? 1 : 0,
      (ray_dinv.z < 0) ? 1 : 0};
  while (node_cur) {
    auto& node = bvh->nodes[node_stack[--node_cur]];
    if (!intersect_bbox(ray, ray_dinv, node.bbox)) continue;
    if (node.internal) {
      if (ray_dsign[node.axis]) {
        node_stack[node_cur++] = node.start + 0;
        node_stack[node_cur++] = node.start + 1;
      } else {
        node_stack[node_cur++] = node.start + 1;
        node_stack[node_cur++] = node.start + 0;
      }
    } else {
      for (auto idx = node.start; idx < node.start + node.num; idx++) {
        auto object_ = scene->instances[scene->bvh->primitives[idx]];
        auto inv_ray = transform_ray(
            inverse(object_->frame, non_rigid_frames), ray);
        if (intersect_shape_bvh(
                object_->shape, inv_ray, element, uv, distance, find_any)) {
          hit      = true;
          instance = scene->bvh->primitives[idx];
          ray.tmax = distance;
        }
      }
    }
    if (find_any && hit) return hit;
  }
  return hit;
}
static bool intersect_scene_bvh ( const scene_model * scene , const ray3f & ray_ , int & instance , int & element , vec2f & uv , float & distance , bool find_any , bool non_rigid_frames ) { #ifdef YOCTO_EMBREE if ( scene -> embree_bvh ) { return intersect_scene_embree_bvh ( scene , ray_ , instance , element , uv , distance , find_any ) ; } #endif auto bvh = scene -> bvh ; if ( bvh -> nodes . empty ( ) ) return false ; int node_stack [ 128 ] ; auto node_cur = 0 ; node_stack [ node_cur ++ ] = 0 ; auto hit = false ; auto ray = ray_ ; auto ray_dinv = vec3f { 1 / ray . d . x , 1 / ray . d . y , 1 / ray . d . z } ; auto ray_dsign = vec3i { ( ray_dinv . x < 0 ) ? 1 : 0 , ( ray_dinv . y < 0 ) ? 1 : 0 , ( ray_dinv . z < 0 ) ? 1 : 0 } ; while ( node_cur ) { auto & node = bvh -> nodes [ node_stack [ -- node_cur ] ] ; if ( ! intersect_bbox ( ray , ray_dinv , node . bbox ) ) continue ; if ( node . internal ) { if ( ray_dsign [ node . axis ] ) { node_stack [ node_cur ++ ] = node . start + 0 ; node_stack [ node_cur ++ ] = node . start + 1 ; } else { node_stack [ node_cur ++ ] = node . start + 1 ; node_stack [ node_cur ++ ] = node . start + 0 ; } } else { for ( auto idx = node . start ; idx < node . start + node . num ; idx ++ ) { auto object_ = scene -> instances [ scene -> bvh -> primitives [ idx ] ] ; auto inv_ray = transform_ray ( inverse ( object_ -> frame , non_rigid_frames ) , ray ) ; if ( intersect_shape_bvh ( object_ -> shape , inv_ray , element , uv , distance , find_any ) ) { hit = true ; instance = scene -> bvh -> primitives [ idx ] ; ray . tmax = distance ; } } } if ( find_any && hit ) return hit ; } return hit ; }
Intersect ray with a bvh->
Intersect ray with a bvh - >
// call Embree if needed // get bvh and scene pointers for fast access // check empty // node stack // shared variables // copy ray to modify it // prepare ray for fast queries // walking stack // grab node // intersect bbox // if (!intersect_bbox(ray, ray_dinv, ray_dsign, node.bbox)) continue; // intersect node, switching based on node type // for each type, iterate over the the primitive list // for internal nodes, attempts to proceed along the // split axis from smallest to largest nodes // check for early exit