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,
89 auto bin_offset = -bbox.
min * bin_scale;
91 for (
size_t i = begin; i < end; ++i) {
93 static_for<0, Node::dimension>([&] (
size_t axis) {
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 };
139 if (best_split.cost >= leaf_cost) {
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();
155 return std::make_optional(
index);
size_t size(const MatrixT &matrix)
retrieve the size of a square matrix
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t index
Single-threaded top-down builder that partitions primitives based on a binned approximation of the Su...
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_ALWAYS_INLINE T get_non_split_cost(size_t begin, size_t end, const BBox< T, N > &bbox) const
Base class for all SAH-based, top-down builders.
bvh::v2::Vec< Scalar, Node::dimension > Vec
std::span< const Vec > centers_
typename Node::Scalar Scalar
std::span< const BBox > bboxes_
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 Vec< T, N > get_diagonal() const
BVH_ALWAYS_INLINE BBox & extend(const Vec< T, N > &point)
static BVH_ALWAYS_INLINE constexpr BBox make_empty()
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
SplitHeuristic< Scalar > sah
SAH heuristic parameters that control how primitives are partitioned.
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 ...