70 for (
uint j = 0; j < num_triangles; j++) {
73 if (attr_mP ==
NULL) {
82 else if (
params.num_motion_triangle_steps == 0 ||
params.use_spatial_split) {
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++) {
107 const int num_bvh_steps =
params.num_motion_triangle_steps * 2 + 1;
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;
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) {
174 else if (
params.num_motion_curve_steps == 0 ||
params.use_spatial_split) {
182 const size_t num_keys = hair->get_curve_keys().size();
183 const size_t num_steps = hair->get_motion_steps();
185 for (
size_t step = 0; step < num_steps - 1; step++) {
200 const int num_bvh_steps =
params.num_motion_curve_steps * 2 + 1;
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];
205 const size_t num_keys = hair->get_curve_keys().size();
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;
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();
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);
290 else if (
params.num_motion_point_steps == 0 ||
params.use_spatial_split) {
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);
315 const int num_bvh_steps =
params.num_motion_point_steps * 2 + 1;
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();
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;
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++) {
396 Mesh *mesh =
static_cast<Mesh *
>(geom);
400 Hair *hair =
static_cast<Hair *
>(geom);
414 size_t num_alloc_references = 0;
421 if (!ob->get_geometry()->is_instanced()) {
425 num_alloc_references++;
445 if (!ob->get_geometry()->is_instanced()) {
491 params.use_spatial_split =
false;
500 double build_start_time;
519 if (
params.use_spatial_split) {
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);
640 size_t max_leaf_size =
max(
max(
params.max_triangle_leaf_size,
params.max_curve_leaf_size),
641 params.max_point_leaf_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++;
683 return (num_triangles <=
params.max_triangle_leaf_size) &&
684 (num_motion_triangles <=
params.max_motion_triangle_leaf_size) &&
685 (num_curves <=
params.max_curve_leaf_size) &&
686 (num_motion_curves <=
params.max_motion_curve_leaf_size) &&
687 (num_points <=
params.max_point_leaf_size) &&
688 (num_motion_points <=
params.max_motion_point_leaf_size);
702 if (!(range.
size() > 0 &&
params.top_level && level == 0)) {
704 if ((
params.small_enough_for_leaf(
size, level)) ||
712 float unalignedSplitSAH =
FLT_MAX;
713 float unalignedLeafSAH =
FLT_MAX;
715 bool do_unalinged_split =
false;
716 if (
params.use_unaligned_nodes && splitSAH >
params.unaligned_split_threshold * leafSAH) {
722 unalignedLeafSAH =
params.sah_primitive_cost * unaligned_range.
leafSAH;
723 if (!(range.
size() > 0 &&
params.top_level && level == 0)) {
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) {
795 if (!(range.
size() > 0 &&
params.top_level && level == 0)) {
796 if (
params.small_enough_for_leaf(range.
size(), level)) {
805 if (!(range.
size() > 0 &&
params.top_level && level == 0)) {
806 if (
split.no_split) {
811 float leafSAH =
params.sah_primitive_cost *
split.leafSAH;
816 float unalignedSplitSAH =
FLT_MAX;
819 bool do_unalinged_split =
false;
820 if (
params.use_unaligned_nodes && splitSAH >
params.unaligned_split_threshold * leafSAH) {
829 if (unalignedSplitSAH < splitSAH) {
830 do_unalinged_split =
true;
836 if (do_unalinged_split) {
837 unaligned_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) {
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());
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];
1028 if (
params.use_unaligned_nodes && !alignment_found) {
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;
1063 if (
params.use_spatial_split) {
1074 const size_t range_end = start_index + range.
size();
1079 if (range_end >=
prim_type.capacity()) {
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) {
1158 else if (num_leaves == 3) {
1165 assert(num_leaves <= 5);
1172 if (num_leaves == 5) {
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++) {
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)
in reality light always falls off quadratically Particle Retrieve the data of the particle that spawned the object for example to give variation to multiple instances of an object Point Retrieve information about points in a point cloud Retrieve the edges of an object as it appears to Cycles topology will always appear triangulated Convert a blackbody temperature to an RGB value Normal Generate a perturbed normal from an RGB normal map image Typically used for faking highly detailed surfaces Generate an OSL shader from a file or text data block Image Sample an image file as a texture Gabor Generate Gabor noise Gradient Generate interpolated color and intensity values based on the input vector Magic Generate a psychedelic color texture Voronoi Generate Worley noise based on the distance to random points Typically used to generate textures such as or biological cells Brick Generate a procedural texture producing bricks Texture Retrieve multiple types of texture coordinates nTypically used as inputs for texture nodes Vector Convert a point
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
vector< Object * > objects
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()
__forceinline int size() const
__forceinline int start() const
__forceinline const BoundBox & bounds() const
__forceinline void set_start(int start_)
__forceinline int end() 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
bool has_motion_blur() const
Curve get_curve(size_t i) const
size_t num_curves() const
PrimitiveType primitive_type() const override
BVHNode * children[kNumMaxChildren]
#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
void cardinal_motion_keys(const float3 *curve_keys, const float *curve_radius, const float4 *key_steps, size_t num_curve_keys, size_t num_steps, float time, size_t k0, size_t k1, size_t k2, size_t k3, float4 r_keys[4]) const
void bounds_grow(const int k, const float3 *curve_keys, const float *curve_radius, BoundBox &bounds) 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
Triangle get_triangle(size_t i) const
size_t num_triangles() const
PrimitiveType primitive_type() const override
NODE_DECLARE BoundBox bounds
bool is_traceable() const
Point get_point(int i) const
size_t num_points() const
VecBase< float, 4 > float4
std::unique_lock< std::mutex > thread_scoped_lock
CCL_NAMESPACE_BEGIN double time_dt()