Blender V5.0
bvh/split.h
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2009-2010 NVIDIA Corporation
2 * SPDX-FileCopyrightText: 2011-2022 Blender Foundation
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Adapted code from NVIDIA Corporation. */
7
8#pragma once
9
10#include "bvh/build.h"
11#include "bvh/params.h"
12
14
15class BVHBuild;
16class Hair;
17class Mesh;
18class PointCloud;
19struct Transform;
20
21/* Object Split */
22
24 public:
25 float sah;
26 int dim;
30
31 BVHObjectSplit() = default;
32 BVHObjectSplit(BVHBuild *builder,
33 BVHSpatialStorage *storage,
34 const BVHRange &range,
35 vector<BVHReference> &references,
36 const float nodeSAH,
37 const BVHUnaligned *unaligned_heuristic = nullptr,
38 const Transform *aligned_space = nullptr);
39
40 void split(BVHRange &left, BVHRange &right, const BVHRange &range);
41
42 protected:
47
49 {
50 if (aligned_space_ == nullptr) {
51 return prim.bounds();
52 }
53 return unaligned_heuristic_->compute_aligned_prim_boundbox(prim, *aligned_space_);
54 }
55};
56
57/* Spatial Split */
58
60 public:
61 float sah;
62 int dim;
63 float pos;
64
66 BVHSpatialSplit(const BVHBuild &builder,
67 BVHSpatialStorage *storage,
68 const BVHRange &range,
69 vector<BVHReference> &references,
70 const float nodeSAH,
71 const BVHUnaligned *unaligned_heuristic = nullptr,
72 const Transform *aligned_space = nullptr);
73
74 void split(BVHBuild *builder, BVHRange &left, BVHRange &right, const BVHRange &range);
75
76 void split_reference(const BVHBuild &builder,
78 BVHReference &right,
79 const BVHReference &ref,
80 const int dim,
81 float pos);
82
83 protected:
88
89 /* Lower-level functions which calculates boundaries of left and right nodes
90 * needed for spatial split.
91 *
92 * Operates directly with primitive specified by its index, reused by higher
93 * level splitting functions.
94 */
95 void split_triangle_primitive(const Mesh *mesh,
96 const Transform *tfm,
97 const int prim_index,
98 const int dim,
99 const float pos,
100 BoundBox &left_bounds,
101 BoundBox &right_bounds);
102 void split_curve_primitive(const Hair *hair,
103 const Transform *tfm,
104 const int prim_index,
105 const int segment_index,
106 const int dim,
107 const float pos,
108 BoundBox &left_bounds,
109 BoundBox &right_bounds);
110 void split_point_primitive(const PointCloud *pointcloud,
111 const Transform *tfm,
112 const int prim_index,
113 const int dim,
114 const float pos,
115 BoundBox &left_bounds,
116 BoundBox &right_bounds);
117
118 /* Lower-level functions which calculates boundaries of left and right nodes
119 * needed for spatial split.
120 *
121 * Operates with BVHReference, internally uses lower level API functions.
122 */
124 const Mesh *mesh,
125 const int dim,
126 const float pos,
127 BoundBox &left_bounds,
128 BoundBox &right_bounds);
129 void split_curve_reference(const BVHReference &ref,
130 const Hair *hair,
131 const int dim,
132 const float pos,
133 BoundBox &left_bounds,
134 BoundBox &right_bounds);
135 void split_point_reference(const BVHReference &ref,
136 const PointCloud *pointcloud,
137 const int dim,
138 const float pos,
139 BoundBox &left_bounds,
140 BoundBox &right_bounds);
141 void split_object_reference(const Object *object,
142 const int dim,
143 const float pos,
144 BoundBox &left_bounds,
145 BoundBox &right_bounds);
146
148 {
149 if (aligned_space_ == nullptr) {
150 return prim.bounds();
151 }
152 return unaligned_heuristic_->compute_aligned_prim_boundbox(prim, *aligned_space_);
153 }
154
156 {
157 if (aligned_space_ == nullptr) {
158 return point;
159 }
160 return transform_point(aligned_space_, point);
161 }
162};
163
164/* Mixed Object-Spatial Split */
165
167 public:
170
171 float leafSAH;
172 float nodeSAH;
173 float minSAH;
174
176
178
179 BVHMixedSplit() = default;
180
182 BVHSpatialStorage *storage,
183 const BVHRange &range,
184 vector<BVHReference> &references,
185 const int level,
186 const BVHUnaligned *unaligned_heuristic = nullptr,
187 const Transform *aligned_space = nullptr)
188 {
189 if (aligned_space == nullptr) {
190 bounds = range.bounds();
191 }
192 else {
193 bounds = unaligned_heuristic->compute_aligned_boundbox(
194 range, &references.at(0), *aligned_space);
195 }
196 /* find split candidates. */
197 const float area = bounds.safe_area();
198
199 leafSAH = area * builder->params.primitive_cost(range.size());
200 nodeSAH = area * builder->params.node_cost(2);
201
202 object = BVHObjectSplit(
203 builder, storage, range, references, nodeSAH, unaligned_heuristic, aligned_space);
204
205 if (builder->params.use_spatial_split && level < BVHParams::MAX_SPATIAL_DEPTH) {
206 BoundBox overlap = object.left_bounds;
207 overlap.intersect(object.right_bounds);
208
209 if (overlap.safe_area() >= builder->spatial_min_overlap) {
211 *builder, storage, range, references, nodeSAH, unaligned_heuristic, aligned_space);
212 }
213 }
214
215 /* leaf SAH is the lowest => create leaf. */
216 minSAH = min(min(leafSAH, object.sah), spatial.sah);
217 no_split = (minSAH == leafSAH && builder->range_within_max_leaf_size(range, references));
218 }
219
221 BVHRange &left,
222 BVHRange &right,
223 const BVHRange &range)
224 {
225 if (builder->params.use_spatial_split && minSAH == spatial.sah) {
226 spatial.split(builder, left, right, range);
227 }
228 if (!left.size() || !right.size()) {
229 object.split(left, right, range);
230 }
231 }
232};
233
bool range_within_max_leaf_size(const BVHRange &range, const vector< BVHReference > &references) const
Definition build.cpp:656
BVHParams params
Definition build.h:122
float spatial_min_overlap
Definition build.h:132
BVHMixedSplit()=default
BVHSpatialSplit spatial
Definition bvh/split.h:169
__forceinline void split(BVHBuild *builder, BVHRange &left, BVHRange &right, const BVHRange &range)
Definition bvh/split.h:220
BVHObjectSplit object
Definition bvh/split.h:168
__forceinline BVHMixedSplit(BVHBuild *builder, BVHSpatialStorage *storage, const BVHRange &range, vector< BVHReference > &references, const int level, const BVHUnaligned *unaligned_heuristic=nullptr, const Transform *aligned_space=nullptr)
Definition bvh/split.h:181
BoundBox bounds
Definition bvh/split.h:177
BVHSpatialStorage * storage_
Definition bvh/split.h:43
vector< BVHReference > * references_
Definition bvh/split.h:44
BVHObjectSplit()=default
BoundBox left_bounds
Definition bvh/split.h:28
BoundBox right_bounds
Definition bvh/split.h:29
__forceinline BoundBox get_prim_bounds(const BVHReference &prim) const
Definition bvh/split.h:48
void split(BVHRange &left, BVHRange &right, const BVHRange &range)
Definition bvh/split.cpp:91
const Transform * aligned_space_
Definition bvh/split.h:46
const BVHUnaligned * unaligned_heuristic_
Definition bvh/split.h:45
@ MAX_SPATIAL_DEPTH
Definition params.h:111
bool use_spatial_split
Definition params.h:60
__forceinline float primitive_cost(const int n) const
Definition params.h:153
__forceinline float node_cost(const int n) const
Definition params.h:158
__forceinline int size() const
Definition params.h:281
__forceinline const BoundBox & bounds() const
Definition params.h:269
__forceinline const BoundBox & bounds() const
Definition params.h:204
const BVHUnaligned * unaligned_heuristic_
Definition bvh/split.h:86
void split_curve_reference(const BVHReference &ref, const Hair *hair, const int dim, const float pos, BoundBox &left_bounds, BoundBox &right_bounds)
__forceinline float3 get_unaligned_point(const float3 &point) const
Definition bvh/split.h:155
__forceinline BoundBox get_prim_bounds(const BVHReference &prim) const
Definition bvh/split.h:147
void split_reference(const BVHBuild &builder, BVHReference &left, BVHReference &right, const BVHReference &ref, const int dim, float pos)
void split_triangle_reference(const BVHReference &ref, const Mesh *mesh, const int dim, const float pos, BoundBox &left_bounds, BoundBox &right_bounds)
BVHSpatialStorage * storage_
Definition bvh/split.h:84
const Transform * aligned_space_
Definition bvh/split.h:87
vector< BVHReference > * references_
Definition bvh/split.h:85
void split_curve_primitive(const Hair *hair, const Transform *tfm, const int prim_index, const int segment_index, const int dim, const float pos, BoundBox &left_bounds, BoundBox &right_bounds)
void split_point_primitive(const PointCloud *pointcloud, const Transform *tfm, const int prim_index, const int dim, const float pos, BoundBox &left_bounds, BoundBox &right_bounds)
void split_triangle_primitive(const Mesh *mesh, const Transform *tfm, const int prim_index, const int dim, const float pos, BoundBox &left_bounds, BoundBox &right_bounds)
void split_object_reference(const Object *object, const int dim, const float pos, BoundBox &left_bounds, BoundBox &right_bounds)
void split(BVHBuild *builder, BVHRange &left, BVHRange &right, const BVHRange &range)
void split_point_reference(const BVHReference &ref, const PointCloud *pointcloud, const int dim, const float pos, BoundBox &left_bounds, BoundBox &right_bounds)
Definition hair.h:13
#define __forceinline
#define CCL_NAMESPACE_END
uint pos
static int left
#define min(a, b)
Definition sort.cc:36
#define FLT_MAX
Definition stdcycles.h:14
__forceinline void intersect(const BoundBox &bbox)
Definition boundbox.h:85
__forceinline float safe_area() const
Definition boundbox.h:92
ccl_device_inline float3 transform_point(const ccl_private Transform *t, const float3 a)
Definition transform.h:56