1#ifndef BVH_V2_TOP_DOWN_SAH_BUILDER_H
2#define BVH_V2_TOP_DOWN_SAH_BUILDER_H
9#if __has_include(<span>)
23template <
typename Node>
60 std::span<const BBox> bboxes,
61 std::span<const Vec> centers,
67 assert(bboxes.size() == centers.size());
72 virtual std::optional<size_t>
try_split(
const BBox& bbox,
size_t begin,
size_t end) = 0;
79 const auto prim_count =
bboxes_.size();
83 bvh.nodes.emplace_back();
86 std::stack<WorkItem> stack;
87 stack.push(
WorkItem { 0, 0, prim_count });
88 while (!stack.empty()) {
89 auto item = stack.top();
92 auto& node =
bvh.nodes[item.node_id];
94 if (
auto split_pos =
try_split(node.get_bbox(), item.begin, item.end)) {
95 auto first_child =
bvh.nodes.size();
98 bvh.nodes.resize(first_child + 2);
102 auto first_range = std::make_pair(item.begin, *split_pos);
103 auto second_range = std::make_pair(*split_pos, item.end);
109 if (first_bbox.get_half_area() < second_bbox.get_half_area()) {
110 std::swap(first_bbox, second_bbox);
111 std::swap(first_range, second_range);
114 auto first_item =
WorkItem { first_child + 0, first_range.first, first_range.second };
115 auto second_item =
WorkItem { first_child + 1, second_range.first, second_range.second };
116 bvh.nodes[first_child + 0].set_bbox(first_bbox);
117 bvh.nodes[first_child + 1].set_bbox(second_bbox);
120 if (first_item.size() < second_item.size())
121 std::swap(first_item, second_item);
123 stack.push(first_item);
124 stack.push(second_item);
133 bvh.nodes.shrink_to_fit();
140 for (
size_t i = begin; i < end; ++i)
141 bbox.extend(
bboxes_[prim_ids[i]]);
Base class for all SAH-based, top-down builders.
BVH_ALWAYS_INLINE const std::vector< size_t > & get_prim_ids() const
virtual std::optional< size_t > try_split(const BBox &bbox, size_t begin, size_t end)=0
std::span< const Vec > centers_
BVH_ALWAYS_INLINE BBox compute_bbox(size_t begin, size_t end) const
typename Node::Scalar Scalar
std::span< const BBox > bboxes_
BVH_ALWAYS_INLINE TopDownSahBuilder(std::span< const BBox > bboxes, std::span< const Vec > centers, const Config &config)
virtual std::vector< size_t > & get_prim_ids()=0
static BVH_ALWAYS_INLINE constexpr BBox make_empty()
static BVH_ALWAYS_INLINE Index make_inner(size_t first_child)
static BVH_ALWAYS_INLINE Index make_leaf(size_t first_prim, size_t prim_count)
SplitHeuristic< Scalar > sah
SAH heuristic parameters that control how primitives are partitioned.
size_t min_leaf_size
Nodes containing less than this amount of primitives will not be split.
size_t max_leaf_size
Nodes that cannot be split based on the SAH and have a number of primitives larger than this will be ...
BVH_ALWAYS_INLINE size_t size() const