1#ifndef BVH_V2_BINNED_SAH_BUILDER_H
2#define BVH_V2_BINNED_SAH_BUILDER_H
18template <
typename Node,
size_t BinCount = 8>
33 std::span<const BBox> bboxes,
34 std::span<const Vec> centers,
65 using Bins = std::array<Bin, BinCount>;
71 std::span<const BBox> bboxes,
72 std::span<const Vec> centers,
88 auto bin_scale =
Vec(BinCount) / bbox.get_diagonal();
89 auto bin_offset = -bbox.min * bin_scale;
91 for (
size_t i = begin; i < end; ++i) {
94 size_t index = std::min(BinCount - 1,
103 std::array<Scalar, BinCount> right_costs;
104 for (
size_t i = BinCount - 1; i > 0; --i) {
105 right_accum.
add(bins[i]);
110 for (
size_t i = 0; i < BinCount - 1; ++i) {
111 left_accum.
add(bins[i]);
113 if (cost < best_split.
cost)
114 best_split =
Split { i + 1, cost, axis };
119 size_t mid = (begin + end + 1) / 2;
124 [&] (
size_t i,
size_t j) { return centers_[i][axis] < centers_[j][axis]; });
128 std::optional<size_t>
try_split(
const BBox& bbox,
size_t begin,
size_t end)
override {
130 fill_bins(per_axis_bins, bbox, begin, end);
132 auto largest_axis = bbox.get_diagonal().get_largest_axis();
133 auto best_split =
Split { BinCount / 2, std::numeric_limits<Scalar>::max(), largest_axis };
138 auto leaf_cost =
config_.sah.get_non_split_cost(begin, end, bbox);
139 if (best_split.cost >= leaf_cost) {
140 if (end - begin <=
config_.max_leaf_size)
146 bbox.get_diagonal()[best_split.axis] /
static_cast<Scalar>(BinCount),
147 static_cast<Scalar>(best_split.bin_id),
148 bbox.min[best_split.axis]);
151 [&] (
size_t i) { return centers_[i][best_split.axis] < split_pos; }) -
prim_ids_.begin();
152 if (index == begin || index == end)
155 return std::make_optional(index);
size_t size(const MatrixT &matrix)
retrieve the size of a square matrix
size_t fallback_split(size_t axis, size_t begin, size_t end)
std::array< Bin, BinCount > Bins
BVH_ALWAYS_INLINE void fill_bins(PerAxisBins &per_axis_bins, const BBox &bbox, size_t begin, size_t end)
std::array< Bins, Node::dimension > PerAxisBins
std::optional< size_t > try_split(const BBox &bbox, size_t begin, size_t end) override
void find_best_split(size_t axis, const Bins &bins, Split &best_split)
static BVH_ALWAYS_INLINE Bvh< Node > build(std::span< const BBox > bboxes, std::span< const Vec > centers, const Config &config={})
std::vector< size_t > & get_prim_ids() override
std::vector< size_t > prim_ids_
BVH_ALWAYS_INLINE BinnedSahBuilder(std::span< const BBox > bboxes, std::span< const Vec > centers, const Config &config)
BVH_ALWAYS_INLINE T get_leaf_cost(size_t begin, size_t end, const BBox< T, N > &bbox) const
bvh::v2::BBox< Scalar, Node::dimension > BBox
bvh::v2::Vec< Scalar, Node::dimension > Vec
std::span< const Vec > centers_
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)
BVH_ALWAYS_INLINE T robust_max(T a, T b)
BVH_ALWAYS_INLINE T fast_mul_add(T a, T b, T c)
Fast multiply-add operation.
BVH_ALWAYS_INLINE void static_for(F &&f)
Executes the given function once for every integer in the range [Begin, End).
static constexpr BBox make_empty()
BBox & extend(const Vec< T, N > &point)
BVH_ALWAYS_INLINE void add(const BBox &bbox, size_t prim_count=1)
BVH_ALWAYS_INLINE Scalar get_cost(const SplitHeuristic< Scalar > &sah) const
BVH_ALWAYS_INLINE void add(const Bin &bin)
Binary BVH node, containing its bounds and an index into its children or the primitives it contains.
static constexpr size_t dimension