ClangFormat: apply to source, most of intern
[blender.git] / intern / cycles / bvh / bvh_split.h
1 /*
2  * Adapted from code copyright 2009-2010 NVIDIA Corporation
3  * Modifications Copyright 2011, Blender Foundation.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17
18 #ifndef __BVH_SPLIT_H__
19 #define __BVH_SPLIT_H__
20
21 #include "bvh/bvh_build.h"
22 #include "bvh/bvh_params.h"
23
24 CCL_NAMESPACE_BEGIN
25
26 class BVHBuild;
27 struct Transform;
28
29 /* Object Split */
30
31 class BVHObjectSplit {
32  public:
33   float sah;
34   int dim;
35   int num_left;
36   BoundBox left_bounds;
37   BoundBox right_bounds;
38
39   BVHObjectSplit()
40   {
41   }
42   BVHObjectSplit(BVHBuild *builder,
43                  BVHSpatialStorage *storage,
44                  const BVHRange &range,
45                  vector<BVHReference> *references,
46                  float nodeSAH,
47                  const BVHUnaligned *unaligned_heuristic = NULL,
48                  const Transform *aligned_space = NULL);
49
50   void split(BVHRange &left, BVHRange &right, const BVHRange &range);
51
52  protected:
53   BVHSpatialStorage *storage_;
54   vector<BVHReference> *references_;
55   const BVHUnaligned *unaligned_heuristic_;
56   const Transform *aligned_space_;
57
58   __forceinline BoundBox get_prim_bounds(const BVHReference &prim) const
59   {
60     if (aligned_space_ == NULL) {
61       return prim.bounds();
62     }
63     else {
64       return unaligned_heuristic_->compute_aligned_prim_boundbox(prim, *aligned_space_);
65     }
66   }
67 };
68
69 /* Spatial Split */
70
71 class BVHSpatialSplit {
72  public:
73   float sah;
74   int dim;
75   float pos;
76
77   BVHSpatialSplit() : sah(FLT_MAX), dim(0), pos(0.0f), storage_(NULL), references_(NULL)
78   {
79   }
80   BVHSpatialSplit(const BVHBuild &builder,
81                   BVHSpatialStorage *storage,
82                   const BVHRange &range,
83                   vector<BVHReference> *references,
84                   float nodeSAH,
85                   const BVHUnaligned *unaligned_heuristic = NULL,
86                   const Transform *aligned_space = NULL);
87
88   void split(BVHBuild *builder, BVHRange &left, BVHRange &right, const BVHRange &range);
89
90   void split_reference(const BVHBuild &builder,
91                        BVHReference &left,
92                        BVHReference &right,
93                        const BVHReference &ref,
94                        int dim,
95                        float pos);
96
97  protected:
98   BVHSpatialStorage *storage_;
99   vector<BVHReference> *references_;
100   const BVHUnaligned *unaligned_heuristic_;
101   const Transform *aligned_space_;
102
103   /* Lower-level functions which calculates boundaries of left and right nodes
104    * needed for spatial split.
105    *
106    * Operates directly with primitive specified by it's index, reused by higher
107    * level splitting functions.
108    */
109   void split_triangle_primitive(const Mesh *mesh,
110                                 const Transform *tfm,
111                                 int prim_index,
112                                 int dim,
113                                 float pos,
114                                 BoundBox &left_bounds,
115                                 BoundBox &right_bounds);
116   void split_curve_primitive(const Mesh *mesh,
117                              const Transform *tfm,
118                              int prim_index,
119                              int segment_index,
120                              int dim,
121                              float pos,
122                              BoundBox &left_bounds,
123                              BoundBox &right_bounds);
124
125   /* Lower-level functions which calculates boundaries of left and right nodes
126    * needed for spatial split.
127    *
128    * Operates with BVHReference, internally uses lower level API functions.
129    */
130   void split_triangle_reference(const BVHReference &ref,
131                                 const Mesh *mesh,
132                                 int dim,
133                                 float pos,
134                                 BoundBox &left_bounds,
135                                 BoundBox &right_bounds);
136   void split_curve_reference(const BVHReference &ref,
137                              const Mesh *mesh,
138                              int dim,
139                              float pos,
140                              BoundBox &left_bounds,
141                              BoundBox &right_bounds);
142   void split_object_reference(
143       const Object *object, int dim, float pos, BoundBox &left_bounds, BoundBox &right_bounds);
144
145   __forceinline BoundBox get_prim_bounds(const BVHReference &prim) const
146   {
147     if (aligned_space_ == NULL) {
148       return prim.bounds();
149     }
150     else {
151       return unaligned_heuristic_->compute_aligned_prim_boundbox(prim, *aligned_space_);
152     }
153   }
154
155   __forceinline float3 get_unaligned_point(const float3 &point) const
156   {
157     if (aligned_space_ == NULL) {
158       return point;
159     }
160     else {
161       return transform_point(aligned_space_, point);
162     }
163   }
164 };
165
166 /* Mixed Object-Spatial Split */
167
168 class BVHMixedSplit {
169  public:
170   BVHObjectSplit object;
171   BVHSpatialSplit spatial;
172
173   float leafSAH;
174   float nodeSAH;
175   float minSAH;
176
177   bool no_split;
178
179   BoundBox bounds;
180
181   BVHMixedSplit()
182   {
183   }
184
185   __forceinline BVHMixedSplit(BVHBuild *builder,
186                               BVHSpatialStorage *storage,
187                               const BVHRange &range,
188                               vector<BVHReference> *references,
189                               int level,
190                               const BVHUnaligned *unaligned_heuristic = NULL,
191                               const Transform *aligned_space = NULL)
192   {
193     if (aligned_space == NULL) {
194       bounds = range.bounds();
195     }
196     else {
197       bounds = unaligned_heuristic->compute_aligned_boundbox(
198           range, &references->at(0), *aligned_space);
199     }
200     /* find split candidates. */
201     float area = bounds.safe_area();
202
203     leafSAH = area * builder->params.primitive_cost(range.size());
204     nodeSAH = area * builder->params.node_cost(2);
205
206     object = BVHObjectSplit(
207         builder, storage, range, references, nodeSAH, unaligned_heuristic, aligned_space);
208
209     if (builder->params.use_spatial_split && level < BVHParams::MAX_SPATIAL_DEPTH) {
210       BoundBox overlap = object.left_bounds;
211       overlap.intersect(object.right_bounds);
212
213       if (overlap.safe_area() >= builder->spatial_min_overlap) {
214         spatial = BVHSpatialSplit(
215             *builder, storage, range, references, nodeSAH, unaligned_heuristic, aligned_space);
216       }
217     }
218
219     /* leaf SAH is the lowest => create leaf. */
220     minSAH = min(min(leafSAH, object.sah), spatial.sah);
221     no_split = (minSAH == leafSAH && builder->range_within_max_leaf_size(range, *references));
222   }
223
224   __forceinline void split(BVHBuild *builder,
225                            BVHRange &left,
226                            BVHRange &right,
227                            const BVHRange &range)
228   {
229     if (builder->params.use_spatial_split && minSAH == spatial.sah)
230       spatial.split(builder, left, right, range);
231     if (!left.size() || !right.size())
232       object.split(left, right, range);
233   }
234 };
235
236 CCL_NAMESPACE_END
237
238 #endif /* __BVH_SPLIT_H__ */