libs/yocto/yocto_scene.cpp
// Splits a BVH node using the SAH heuristic. Returns split position and axis.
Splits a BVH node using the SAH heuristic. Returns split position and axis.
Splits a BVH node using the SAH heuristic . Returns split position and axis .
static pair<int, int> split_sah(
    vector<scene_bvh_primitive>& primitives, int start, int end) {
  auto split_axis = 0;
  auto mid        = (start + end) / 2;
  auto cbbox = invalidb3f;
  for (auto i = start; i < end; i++) cbbox = merge(cbbox, primitives[i].center);
  auto csize = cbbox.max - cbbox.min;
  if (csize == zero3f) return {mid, split_axis};
  const int nbins    = 16;
  auto      middle   = 0.0f;
  auto      min_cost = flt_max;
  auto      area     = [](auto& b) {
    auto size = b.max - b.min;
    return 1e-12f + 2 * size.x * size.y + 2 * size.x * size.z +
           2 * size.y * size.z;
  };
  for (auto saxis = 0; saxis < 3; saxis++) {
    for (auto b = 1; b < nbins; b++) {
      auto split     = cbbox.min[saxis] + b * csize[saxis] / nbins;
      auto left_bbox = invalidb3f, right_bbox = invalidb3f;
      auto left_nprims = 0, right_nprims = 0;
      for (auto i = start; i < end; i++) {
        if (primitives[i].center[saxis] < split) {
          left_bbox = merge(left_bbox, primitives[i].bbox);
          left_nprims += 1;
        } else {
          right_bbox = merge(right_bbox, primitives[i].bbox);
          right_nprims += 1;
        }
      }
      auto cost = 1 + left_nprims * area(left_bbox) / area(cbbox) +
                  right_nprims * area(right_bbox) / area(cbbox);
      if (cost < min_cost) {
        min_cost   = cost;
        middle     = split;
        split_axis = saxis;
      }
    }
  }
  mid = (int)(std::partition(primitives.data() + start, primitives.data() + end,
                  [split_axis, middle](auto& primitive) {
                    return primitive.center[split_axis] < middle;
                  }) -
              primitives.data());
  if (mid == start || mid == end) {
    split_axis = 0;
    mid        = (start + end) / 2;
    throw std::runtime_error("bad bvh split");
  }
  return {mid, split_axis};
}
static pair < int , int > split_sah ( vector < scene_bvh_primitive > & primitives , int start , int end ) { auto split_axis = 0 ; auto mid = ( start + end ) / 2 ; auto cbbox = invalidb3f ; for ( auto i = start ; i < end ; i ++ ) cbbox = merge ( cbbox , primitives [ i ] . center ) ; auto csize = cbbox . max - cbbox . min ; if ( csize == zero3f ) return { mid , split_axis } ; const int nbins = 16 ; auto middle = 0.0f ; auto min_cost = flt_max ; auto area = [ ] ( auto & b ) { auto size = b . max - b . min ; return 1e-12f + 2 * size . x * size . y + 2 * size . x * size . z + 2 * size . y * size . z ; } ; for ( auto saxis = 0 ; saxis < 3 ; saxis ++ ) { for ( auto b = 1 ; b < nbins ; b ++ ) { auto split = cbbox . min [ saxis ] + b * csize [ saxis ] / nbins ; auto left_bbox = invalidb3f , right_bbox = invalidb3f ; auto left_nprims = 0 , right_nprims = 0 ; for ( auto i = start ; i < end ; i ++ ) { if ( primitives [ i ] . center [ saxis ] < split ) { left_bbox = merge ( left_bbox , primitives [ i ] . bbox ) ; left_nprims += 1 ; } else { right_bbox = merge ( right_bbox , primitives [ i ] . bbox ) ; right_nprims += 1 ; } } auto cost = 1 + left_nprims * area ( left_bbox ) / area ( cbbox ) + right_nprims * area ( right_bbox ) / area ( cbbox ) ; if ( cost < min_cost ) { min_cost = cost ; middle = split ; split_axis = saxis ; } } } mid = ( int ) ( std :: partition ( primitives . data ( ) + start , primitives . data ( ) + end , [ split_axis , middle ] ( auto & primitive ) { return primitive . center [ split_axis ] < middle ; } ) - primitives . data ( ) ) ; if ( mid == start || mid == end ) { split_axis = 0 ; mid = ( start + end ) / 2 ; throw std :: runtime_error ( " " ) ; } return { mid , split_axis } ; }
Splits a BVH node using the SAH heuristic.
Splits a BVH node using the SAH heuristic .
// initialize split axis and position // compute primintive bounds and size // consider N bins, compute their cost and keep the minimum // split // if we were not able to split, just break the primitives in half