43 prim_type(prim_type_),
44 prim_index(prim_index_),
45 prim_object(prim_object_),
46 prim_time(prim_time_),
49 progress_start_time(0.0),
50 unaligned_heuristic(objects_)
66 if (mesh->has_motion_blur()) {
69 const size_t num_triangles = mesh->num_triangles();
70 for (
uint j = 0; j < num_triangles; j++) {
73 if (attr_mP ==
NULL) {
88 const size_t num_verts = mesh->verts.size();
89 const size_t num_steps = mesh->motion_steps;
93 for (
size_t step = 0; step < num_steps - 1; step++) {
108 const float num_bvh_steps_inv_1 = 1.0f / (num_bvh_steps - 1);
109 const size_t num_verts = mesh->verts.size();
110 const size_t num_steps = mesh->motion_steps;
119 prev_bounds.
grow(prev_verts[0]);
120 prev_bounds.
grow(prev_verts[1]);
121 prev_bounds.
grow(prev_verts[2]);
123 for (
int bvh_step = 1; bvh_step < num_bvh_steps; ++bvh_step) {
124 const float curr_time = (
float)(bvh_step)*num_bvh_steps_inv_1;
128 curr_bounds.
grow(curr_verts[0]);
129 curr_bounds.
grow(curr_verts[1]);
130 curr_bounds.
grow(curr_verts[2]);
134 const float prev_time = (
float)(bvh_step - 1) * num_bvh_steps_inv_1;
143 prev_bounds = curr_bounds;
152 if (hair->has_motion_blur()) {
158 const size_t num_curves = hair->num_curves();
159 for (
uint j = 0; j < num_curves; j++) {
161 const float *curve_radius = &hair->get_curve_radius()[0];
162 for (
int k = 0; k < curve.num_keys - 1; k++) {
163 if (curve_attr_mP ==
NULL) {
166 curve.bounds_grow(k, &hair->get_curve_keys()[0], curve_radius,
bounds);
181 curve.bounds_grow(k, &hair->get_curve_keys()[0], curve_radius,
bounds);
182 const size_t num_keys = hair->get_curve_keys().size();
183 const size_t num_steps = hair->get_motion_steps();
184 const float4 *key_steps = curve_attr_mP->
data_float4();
185 for (
size_t step = 0; step < num_steps - 1; step++) {
186 curve.bounds_grow(k, key_steps + step * num_keys,
bounds);
201 const float num_bvh_steps_inv_1 = 1.0f / (num_bvh_steps - 1);
202 const size_t num_steps = hair->get_motion_steps();
203 const float3 *curve_keys = &hair->get_curve_keys()[0];
204 const float4 *key_steps = curve_attr_mP->
data_float4();
205 const size_t num_keys = hair->get_curve_keys().size();
211 curve.cardinal_motion_keys(curve_keys,
223 curve.bounds_grow(prev_keys, prev_bounds);
225 for (
int bvh_step = 1; bvh_step < num_bvh_steps; ++bvh_step) {
226 const float curr_time = (
float)(bvh_step)*num_bvh_steps_inv_1;
228 curve.cardinal_motion_keys(curve_keys,
240 curve.bounds_grow(curr_keys, curr_bounds);
244 const float prev_time = (
float)(bvh_step - 1) * num_bvh_steps_inv_1;
254 prev_bounds = curr_bounds;
271 const float3 *points_data = &pointcloud->points[0];
272 const float *radius_data = &pointcloud->radius[0];
273 const size_t num_points = pointcloud->
num_points();
274 const float4 *motion_data = (point_attr_mP) ? point_attr_mP->
data_float4() :
NULL;
275 const size_t num_steps = pointcloud->get_motion_steps();
277 if (point_attr_mP ==
NULL) {
279 for (
uint j = 0; j < num_points; j++) {
282 point.bounds_grow(points_data, radius_data,
bounds);
296 for (
uint j = 0; j < num_points; j++) {
299 point.bounds_grow(points_data, radius_data,
bounds);
300 for (
size_t step = 0; step < num_steps - 1; step++) {
301 point.bounds_grow(motion_data[step * num_points + j],
bounds);
316 const float num_bvh_steps_inv_1 = 1.0f / (num_bvh_steps - 1);
318 for (
uint j = 0; j < num_points; j++) {
320 const size_t num_steps = pointcloud->get_motion_steps();
321 const float4 *point_steps = point_attr_mP->
data_float4();
327 float4 prev_key = point.motion_key(
328 points_data, radius_data, point_steps, num_points, num_steps, 0.0f, j);
330 point.bounds_grow(prev_key, prev_bounds);
332 for (
int bvh_step = 1; bvh_step < num_bvh_steps; ++bvh_step) {
333 const float curr_time = (
float)(bvh_step)*num_bvh_steps_inv_1;
334 float4 curr_key = point.motion_key(
335 points_data, radius_data, point_steps, num_points, num_steps, curr_time, j);
337 point.bounds_grow(curr_key, curr_bounds);
341 const float prev_time = (
float)(bvh_step - 1) * num_bvh_steps_inv_1;
350 prev_bounds = curr_bounds;
362 Mesh *mesh =
static_cast<Mesh *
>(geom);
366 Hair *hair =
static_cast<Hair *
>(geom);
384 size_t num = 0, num_curves = hair->num_curves();
386 for (
size_t i = 0; i < num_curves; i++) {
387 num += hair->get_curve(i).num_keys - 1;
396 Mesh *mesh =
static_cast<Mesh *
>(geom);
400 Hair *hair =
static_cast<Hair *
>(geom);
414 size_t num_alloc_references = 0;
416 foreach (
Object *ob, objects) {
421 if (!ob->get_geometry()->is_instanced()) {
425 num_alloc_references++;
439 foreach (
Object *ob, objects) {
445 if (!ob->get_geometry()->is_instanced()) {
500 double build_start_time;
547 if (rootnode !=
NULL) {
549 <<
" Build time: " <<
time_dt() - build_start_time <<
"\n"
550 <<
" Total number of nodes: "
553 <<
" Number of inner nodes: "
556 <<
" Number of leaf nodes: "
559 <<
" Number of unaligned nodes: "
562 <<
" Allocation slop factor: "
566 <<
" Maximum depth: "
584 "Building BVH %.0f%%, duplicates %.0f%%", progress_start * 100.0, duplicates * 100.0);
639 size_t size = range.size();
643 if (size > max_leaf_size) {
647 size_t num_triangles = 0;
648 size_t num_motion_triangles = 0;
649 size_t num_curves = 0;
650 size_t num_motion_curves = 0;
651 size_t num_points = 0;
652 size_t num_motion_points = 0;
654 for (
int i = 0; i <
size; i++) {
667 num_motion_triangles++;
694 size_t size = range.size();
712 float unalignedSplitSAH =
FLT_MAX;
713 float unalignedLeafSAH =
FLT_MAX;
715 bool do_unalinged_split =
false;
724 if (unalignedLeafSAH < unalignedSplitSAH && unalignedSplitSAH < splitSAH &&
731 if (unalignedSplitSAH < splitSAH) {
732 do_unalinged_split =
true;
738 if (do_unalinged_split) {
746 if (do_unalinged_split) {
770 if (do_unalinged_split) {
806 if (split.no_split) {
816 float unalignedSplitSAH =
FLT_MAX;
819 bool do_unalinged_split =
false;
829 if (unalignedSplitSAH < splitSAH) {
830 do_unalinged_split =
true;
836 if (do_unalinged_split) {
837 unaligned_split.
split(
this, left, right, range);
840 split.split(
this, left, right, range);
846 if (do_unalinged_split) {
882 task_pool.
push([=, refs = std::move(left_references)]()
mutable {
885 task_pool.
push([=, refs = std::move(right_references)]()
mutable {
890 if (do_unalinged_split) {
914 const uint visibility = objects[ref->
prim_object()]->visibility_for_tracing();
953 typedef StackAllocator<256, int> LeafStackAllocator;
954 typedef StackAllocator<256, float2> LeafTimeStackAllocator;
955 typedef StackAllocator<256, BVHReference> LeafReferenceStackAllocator;
971 int num_new_prims = 0;
973 for (
int i = 0; i < range.size(); i++) {
977 p_ref[type_index].push_back(ref);
978 p_type[type_index].push_back(ref.
prim_type());
979 p_index[type_index].push_back(ref.
prim_index());
984 visibility[type_index] |= objects[ref.
prim_object()]->visibility_for_tracing();
988 object_references.push_back(ref);
1004 size_t start_index = 0;
1007 local_prim_type.resize(num_new_prims);
1008 local_prim_index.resize(num_new_prims);
1009 local_prim_object.resize(num_new_prims);
1011 local_prim_time.resize(num_new_prims);
1014 int num = (
int)p_type[i].
size();
1016 assert(p_type[i].
size() == p_index[i].
size());
1017 assert(p_type[i].
size() == p_object[i].
size());
1019 bool alignment_found =
false;
1020 for (
int j = 0; j < num; ++j) {
1021 const int index = start_index + j;
1022 local_prim_type[index] = p_type[i][j];
1023 local_prim_index[index] = p_index[i][j];
1024 local_prim_object[index] = p_object[i][j];
1026 local_prim_time[index] = p_time[i][j];
1034 float time_from = 1.0f, time_to = 0.0f;
1035 for (
int j = 0; j < num; ++j) {
1043 if (alignment_found) {
1046 for (
int j = 0; j < num; ++j) {
1055 leaves[num_leaves++] = leaf_node;
1060 const int num_new_leaf_data = start_index;
1061 const size_t new_leaf_data_size =
sizeof(
int) * num_new_leaf_data;
1074 const size_t range_end = start_index + range.size();
1082 const size_t reserve = (size_t)(range_end + (
float)range_end * factor);
1099 if (new_leaf_data_size > 0) {
1100 memcpy(&
prim_type[start_index], &local_prim_type[0], new_leaf_data_size);
1101 memcpy(&
prim_index[start_index], &local_prim_index[0], new_leaf_data_size);
1102 memcpy(&
prim_object[start_index], &local_prim_object[0], new_leaf_data_size);
1104 memcpy(&
prim_time[start_index], &local_prim_time[0],
sizeof(
float2) * num_new_leaf_data);
1114 start_index = range.start();
1115 if (new_leaf_data_size > 0) {
1116 memcpy(&
prim_type[start_index], &local_prim_type[0], new_leaf_data_size);
1117 memcpy(&
prim_index[start_index], &local_prim_index[0], new_leaf_data_size);
1118 memcpy(&
prim_object[start_index], &local_prim_object[0], new_leaf_data_size);
1120 memcpy(&
prim_time[start_index], &local_prim_time[0],
sizeof(
float2) * num_new_leaf_data);
1129 for (
int i = 0; i < num_leaves; ++i) {
1131 leaf->
lo += start_index;
1132 leaf->
hi += start_index;
1136 if (num_leaves == 0 || ob_num) {
1148 if (num_leaves == 1) {
1155 else if (num_leaves == 2) {
1156 return new InnerNode(range.bounds(), leaves[0], leaves[1]);
1158 else if (num_leaves == 3) {
1161 return new InnerNode(range.bounds(), leaves[0], inner);
1165 assert(num_leaves <= 5);
1172 if (num_leaves == 5) {
1173 return new InnerNode(range.bounds(), inner_c, leaves[4]);
1178#undef MAX_ITEMS_PER_LEAF
1188 for (
int i = 0; i < iterations; i++) {
1197 if (node->is_leaf() || max_depth < 0) {
1204 for (
size_t c = 0; c < 2; c++) {
1214 float4 child_area =
make_float4(area0, area1, 0.0f, 0.0f);
1219 int best_child = -1, best_target = -1, best_other = -1;
1221 for (
size_t c = 0; c < 2; c++) {
1228 BoundBox &other = (c == 0) ? bounds1 : bounds0;
1235 float cost0 =
merge(other, target1).half_area() - child_area[c];
1236 float cost1 =
merge(target0, other).half_area() - child_area[c];
1238 if (
min(cost0, cost1) < best_cost) {
1239 best_child = (
int)c;
1240 best_other = (
int)(1 - c);
1242 if (cost0 < cost1) {
1254 if (best_cost >= 0) {
1258 assert(best_child == 0 || best_child == 1);
1259 assert(best_target != -1);
typedef double(DMatrix)[4][4]
static void split(const char *text, const char *seps, char ***str, int *count)
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
static btDbvtVolume bounds(btDbvtNode **leaves, int count)
static size_t count_primitives(Geometry *geom)
static size_t count_curve_segments(Hair *hair)
@ BVH_STAT_UNALIGNED_COUNT
Attribute * find(ustring name) const
BVHNode * create_object_leaf_nodes(const BVHReference *ref, int start, int num)
BVHNode * create_leaf_node(const BVHRange &range, const vector< BVHReference > &references)
void thread_build_spatial_split_node(InnerNode *node, int child, const BVHRange &range, vector< BVHReference > &references, int level)
BVHBuild(const vector< Object * > &objects, array< int > &prim_type, array< int > &prim_index, array< int > &prim_object, array< float2 > &prim_time, const BVHParams ¶ms, Progress &progress)
bool range_within_max_leaf_size(const BVHRange &range, const vector< BVHReference > &references) const
thread_spin_lock spatial_spin_lock
void add_references(BVHRange &root)
void add_reference_object(BoundBox &root, BoundBox ¢er, Object *ob, int i)
BVHNode * build_node(const BVHRange &range, vector< BVHReference > &references, int level, BVHSpatialStorage *storage)
void add_reference_curves(BoundBox &root, BoundBox ¢er, Hair *hair, int i)
size_t spatial_free_index
BVHUnaligned unaligned_heuristic
void add_reference_geometry(BoundBox &root, BoundBox ¢er, Geometry *geom, int i)
friend class BVHObjectBinning
array< float2 > & prim_time
array< int > & prim_index
void rotate(BVHNode *node, int max_depth)
enumerable_thread_specific< BVHSpatialStorage > spatial_storage
size_t progress_original_total
void thread_build_node(InnerNode *node, int child, const BVHObjectBinning &range, int level)
float spatial_min_overlap
double progress_start_time
array< int > & prim_object
void add_reference_points(BoundBox &root, BoundBox ¢er, PointCloud *pointcloud, int i)
friend class BVHMixedSplit
vector< BVHReference > references
void add_reference_triangles(BoundBox &root, BoundBox ¢er, Mesh *mesh, int i)
__forceinline void split(BVHBuild *builder, BVHRange &left, BVHRange &right, const BVHRange &range)
void split(BVHReference *prims, BVHObjectBinning &left_o, BVHObjectBinning &right_o) const
__forceinline const BoundBox & unaligned_bounds()
int max_triangle_leaf_size
int num_motion_triangle_steps
float spatial_split_alpha
__forceinline bool small_enough_for_leaf(int size, int level)
int max_motion_curve_leaf_size
int max_motion_point_leaf_size
int max_motion_triangle_leaf_size
int num_motion_point_steps
float unaligned_split_threshold
int num_motion_curve_steps
__forceinline const BoundBox & bounds() const
__forceinline int prim_type() const
__forceinline int prim_object() const
__forceinline float time_from() const
__forceinline const BoundBox & bounds() const
__forceinline float time_to() const
__forceinline int prim_index() const
Transform compute_aligned_space(const BVHObjectBinning &range, const BVHReference *references) const
BoundBox compute_aligned_boundbox(const BVHObjectBinning &range, const BVHReference *references, const Transform &aligned_space, BoundBox *cent_bounds=NULL) const
BoundBox compute_aligned_prim_boundbox(const BVHReference &prim, const Transform &aligned_space) const
bool has_motion_blur() const
BVHNode * children[kNumMaxChildren]
void set_substatus(const string &substatus_)
T * resize(size_t newsize)
void reserve(size_t newcapacity)
#define CCL_NAMESPACE_END
draw_view in_light_buf[] float
draw_view push_constant(Type::INT, "radiance_src") .push_constant(Type capture_info_buf storage_buf(1, Qualifier::READ, "ObjectBounds", "bounds_buf[]") .push_constant(Type draw_view int
#define PRIMITIVE_PACK_SEGMENT(type, segment)
@ ATTR_STD_MOTION_VERTEX_POSITION
#define PRIMITIVE_INDEX(type)
OrientationBounds merge(const OrientationBounds &cone_a, const OrientationBounds &cone_b)
CCL_NAMESPACE_BEGIN ccl_device_inline float3 zero_float3()
string string_human_readable_number(size_t num)
CCL_NAMESPACE_BEGIN string string_printf(const char *format,...)
int getSubtreeSize(BVH_STAT stat=BVH_STAT_NODE_COUNT) const
virtual bool is_leaf() const =0
void set_aligned_space(const Transform &aligned_space)
__forceinline float half_area() const
__forceinline float safe_area() const
__forceinline void grow(const float3 &pt)
__forceinline float3 center2() const
bool valid(const float3 *verts) const
void motion_verts(const float3 *verts, const float3 *vert_steps, size_t num_verts, size_t num_steps, float time, float3 r_verts[3]) const
void bounds_grow(const float3 *verts, BoundBox &bounds) const
size_t num_triangles() const
NODE_DECLARE BoundBox bounds
bool is_traceable() const
Point get_point(int i) const
size_t num_points() const
void push(TaskRunFunction &&task)
void wait_work(Summary *stats=NULL)
std::unique_lock< std::mutex > thread_scoped_lock
CCL_NAMESPACE_BEGIN double time_dt()