Cycles: Implementation of object reference nodes spatial split
[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_build.h"
22 #include "bvh_params.h"
23
24 CCL_NAMESPACE_BEGIN
25
26 class BVHBuild;
27
28 /* Object Split */
29
30 class BVHObjectSplit
31 {
32 public:
33         float sah;
34         int dim;
35         int num_left;
36         BoundBox left_bounds;
37         BoundBox right_bounds;
38
39         BVHObjectSplit() {}
40         BVHObjectSplit(BVHBuild *builder, const BVHRange& range, float nodeSAH);
41
42         void split(BVHBuild *builder, BVHRange& left, BVHRange& right, const BVHRange& range);
43 };
44
45 /* Spatial Split */
46
47 class BVHSpatialSplit
48 {
49 public:
50         float sah;
51         int dim;
52         float pos;
53
54         BVHSpatialSplit() : sah(FLT_MAX), dim(0), pos(0.0f) {}
55         BVHSpatialSplit(BVHBuild *builder, const BVHRange& range, float nodeSAH);
56
57         void split(BVHBuild *builder, BVHRange& left, BVHRange& right, const BVHRange& range);
58         void split_reference(BVHBuild *builder,
59                              BVHReference& left,
60                              BVHReference& right,
61                              const BVHReference& ref,
62                              int dim,
63                              float pos);
64
65 protected:
66         /* Lower-level functions which calculates boundaries of left and right nodes
67          * needed for spatial split.
68          *
69          * Operates directly with primitive specified by it's index, reused by higher
70          * level splitting functions.
71          */
72         void split_triangle_primitive(const Mesh *mesh,
73                                       const Transform *tfm,
74                                       int prim_index,
75                                       int dim,
76                                       float pos,
77                                       BoundBox& left_bounds,
78                                       BoundBox& right_bounds);
79         void split_curve_primitive(const Mesh *mesh,
80                                    const Transform *tfm,
81                                    int prim_index,
82                                    int segment_index,
83                                    int dim,
84                                    float pos,
85                                    BoundBox& left_bounds,
86                                    BoundBox& right_bounds);
87
88         /* Lower-level functions which calculates boundaries of left and right nodes
89          * needed for spatial split.
90          *
91          * Operates with BVHReference, internally uses lower level API functions.
92          */
93         void split_triangle_reference(const BVHReference& ref,
94                                       const Mesh *mesh,
95                                       int dim,
96                                       float pos,
97                                       BoundBox& left_bounds,
98                                       BoundBox& right_bounds);
99         void split_curve_reference(const BVHReference& ref,
100                                    const Mesh *mesh,
101                                    int dim,
102                                    float pos,
103                                    BoundBox& left_bounds,
104                                    BoundBox& right_bounds);
105         void split_object_reference(const Object *object,
106                                     int dim,
107                                     float pos,
108                                     BoundBox& left_bounds,
109                                     BoundBox& right_bounds);
110 };
111
112 /* Mixed Object-Spatial Split */
113
114 class BVHMixedSplit
115 {
116 public:
117         BVHObjectSplit object;
118         BVHSpatialSplit spatial;
119
120         float leafSAH;
121         float nodeSAH;
122         float minSAH;
123
124         bool no_split;
125
126         __forceinline BVHMixedSplit(BVHBuild *builder, const BVHRange& range, int level)
127         {
128                 /* find split candidates. */
129                 float area = range.bounds().safe_area();
130
131                 leafSAH = area * builder->params.primitive_cost(range.size());
132                 nodeSAH = area * builder->params.node_cost(2);
133
134                 object = BVHObjectSplit(builder, range, nodeSAH);
135
136                 if(builder->params.use_spatial_split && level < BVHParams::MAX_SPATIAL_DEPTH) {
137                         BoundBox overlap = object.left_bounds;
138                         overlap.intersect(object.right_bounds);
139
140                         if(overlap.safe_area() >= builder->spatial_min_overlap)
141                                 spatial = BVHSpatialSplit(builder, range, nodeSAH);
142                 }
143
144                 /* leaf SAH is the lowest => create leaf. */
145                 minSAH = min(min(leafSAH, object.sah), spatial.sah);
146                 no_split = (minSAH == leafSAH && builder->range_within_max_leaf_size(range));
147         }
148
149         __forceinline void split(BVHBuild *builder, BVHRange& left, BVHRange& right, const BVHRange& range)
150         {
151                 if(builder->params.use_spatial_split && minSAH == spatial.sah)
152                         spatial.split(builder, left, right, range);
153                 if(!left.size() || !right.size())
154                         object.split(builder, left, right, range);
155         }
156 };
157
158 CCL_NAMESPACE_END
159
160 #endif /* __BVH_SPLIT_H__ */
161