6#include <cgv/math/intersection.h>
11void bvh::build(
const std::vector<const ray_intersectable*>& primitives,
size_t max_depth) {
12 _max_depth = max_depth;
15 this->_primitives = primitives;
21 _root->bounds = bounds;
22 _root->primitive_indices.resize(_primitives.size());
23 std::iota(_root->primitive_indices.begin(), _root->primitive_indices.end(), 0);
24 _root->child_a.reset();
25 _root->child_b.reset();
31void bvh::split(
bvh_node* node,
int depth) {
33 if(depth == _max_depth)
37 const unsigned split_axis = cgv::math::max_index(node->bounds.get_extent());
38 const float split_position = node->bounds.get_center()[split_axis];
40 node->child_a = std::make_unique<bvh_node>();
41 node->child_b = std::make_unique<bvh_node>();
42 bvh_node* child_a = node->child_a.get();
43 bvh_node* child_b = node->child_b.get();
46 for(
const size_t i : node->primitive_indices) {
49 bool in_a = primitive_bounds.
get_center()[split_axis] < split_position;
50 bvh_node* child = in_a ? child_a : child_b;
56 node->primitive_indices.clear();
58 split(child_a, depth + 1);
59 split(child_b, depth + 1);
64 std::stack<bvh_node*> node_stack;
65 node_stack.push(_root.get());
68 float min_t = std::numeric_limits<float>::max();
73 while(!node_stack.empty()) {
74 const bvh_node* node = node_stack.top();
78 if(cgv::math::ray_box_intersection(ray, node->bounds.get_min_pnt(), node->bounds.get_max_pnt(), bounds_ts) > 0) {
80 if(!node->child_a && !node->child_b) {
82 for(
const size_t i : node->primitive_indices) {
84 if(primitive->
intersect(ray, intersection)) {
85 if(intersection.
t > std::numeric_limits<float>::epsilon() && intersection.
t < min_t) {
86 min_t = intersection.
t;
95 node_stack.push(node->child_a.get());
96 node_stack.push(node->child_b.get());
102 if(result.
intersection.
t < std::numeric_limits<float>::max())
void build(const std::vector< const ray_intersectable * > &primitives, size_t max_depth=8)
Build the hierarchy over the given primitives.
bvh_result closest_intersection(const cgv::ray3 &ray) const
Calculate the closest intersection with positive distance, if any, of the given ray with the stored p...
An interface to define objects that are intersectable with a ray.
virtual bool intersect(const cgv::ray3 &ray, ray_intersection_info &info) const =0
Test if the object is intersected by the given ray.
virtual cgv::box3 get_bounds() const =0
Return the axis-aligned bounding box of the primitive.
this header is dependency free
A single node of a bounding volume hierarchy.
std::vector< size_t > primitive_indices
The list of primitive indices contained in this node. After building the tree, only leaf nodes will h...
cgv::box3 bounds
The node's axis aligned bounding box.
The result of a BVH intersection test.
size_t primitive_index
The index of the hit primitive as given during BVH construction.
ray_intersection_info intersection
Intersection information of the hit.
bool is_hit
True if a primitive was hit.
const ray_intersectable * primitive
A pointer to the hit primitive.
Holds information about a single intersection of a ray and primitive.
float t
The ray parameter.
Struct template for fixed n-dimensional rays with arbitrary data type defined by origin and direction...