1// Copyright 2009-2021 Intel Corporation
2// SPDX-License-Identifier: Apache-2.0
3
4#pragma once
5
6#include "bvh_node_base.h"
7
8namespace embree
9{
10 /*! Motion Blur AABBNode */
11 template<typename NodeRef, int N>
12 struct AABBNodeMB_t : public BaseNode_t<NodeRef, N>
13 {
14 using BaseNode_t<NodeRef,N>::children;
15 typedef BVHNodeRecord<NodeRef> NodeRecord;
16 typedef BVHNodeRecordMB<NodeRef> NodeRecordMB;
17 typedef BVHNodeRecordMB4D<NodeRef> NodeRecordMB4D;
18
19 struct Create
20 {
21 template<typename BuildRecord>
22 __forceinline NodeRef operator() (BuildRecord* children, const size_t num, const FastAllocator::CachedAllocator& alloc) const
23 {
24 AABBNodeMB_t* node = (AABBNodeMB_t*) alloc.malloc0(sizeof(AABBNodeMB_t),NodeRef::byteNodeAlignment); node->clear();
25 return NodeRef::encodeNode(node);
26 }
27 };
28
29 struct Set
30 {
31 template<typename BuildRecord>
32 __forceinline NodeRecordMB operator() (const BuildRecord& precord, const BuildRecord* crecords, NodeRef ref, NodeRecordMB* children, const size_t num) const
33 {
34#if defined(DEBUG)
35 // check that empty children are only at the end of the child list
36 bool emptyChild = false;
37 for (size_t i=0; i<num; i++) {
38 emptyChild |= (children[i].ref == NodeRef::emptyNode);
39 assert(emptyChild == (children[i].ref == NodeRef::emptyNode));
40 }
41#endif
42 AABBNodeMB_t* node = ref.getAABBNodeMB();
43
44 LBBox3fa bounds = empty;
45 for (size_t i=0; i<num; i++) {
46 node->setRef(i,children[i].ref);
47 node->setBounds(i,children[i].lbounds);
48 bounds.extend(children[i].lbounds);
49 }
50 return NodeRecordMB(ref,bounds);
51 }
52 };
53
54 struct SetTimeRange
55 {
56 __forceinline SetTimeRange(BBox1f tbounds) : tbounds(tbounds) {}
57
58 template<typename BuildRecord>
59 __forceinline NodeRecordMB operator() (const BuildRecord& precord, const BuildRecord* crecords, NodeRef ref, NodeRecordMB* children, const size_t num) const
60 {
61 AABBNodeMB_t* node = ref.getAABBNodeMB();
62
63 LBBox3fa bounds = empty;
64 for (size_t i=0; i<num; i++) {
65 node->setRef(i, children[i].ref);
66 node->setBounds(i, children[i].lbounds, tbounds);
67 bounds.extend(children[i].lbounds);
68 }
69 return NodeRecordMB(ref,bounds);
70 }
71
72 BBox1f tbounds;
73 };
74
75 /*! Clears the node. */
76 __forceinline void clear() {
77 lower_x = lower_y = lower_z = vfloat<N>(pos_inf);
78 upper_x = upper_y = upper_z = vfloat<N>(neg_inf);
79 lower_dx = lower_dy = lower_dz = vfloat<N>(0.0f);
80 upper_dx = upper_dy = upper_dz = vfloat<N>(0.0f);
81 BaseNode_t<NodeRef,N>::clear();
82 }
83
84 /*! Sets ID of child. */
85 __forceinline void setRef(size_t i, NodeRef ref) {
86 children[i] = ref;
87 }
88
89 /*! Sets bounding box of child. */
90 __forceinline void setBounds(size_t i, const BBox3fa& bounds0_i, const BBox3fa& bounds1_i)
91 {
92 /*! for empty bounds we have to avoid inf-inf=nan */
93 BBox3fa bounds0(min(bounds0_i.lower,Vec3fa(+FLT_MAX)),max(bounds0_i.upper,Vec3fa(-FLT_MAX)));
94 BBox3fa bounds1(min(bounds1_i.lower,Vec3fa(+FLT_MAX)),max(bounds1_i.upper,Vec3fa(-FLT_MAX)));
95 bounds0 = bounds0.enlarge_by(4.0f*float(ulp));
96 bounds1 = bounds1.enlarge_by(4.0f*float(ulp));
97 Vec3fa dlower = bounds1.lower-bounds0.lower;
98 Vec3fa dupper = bounds1.upper-bounds0.upper;
99
100 lower_x[i] = bounds0.lower.x; lower_y[i] = bounds0.lower.y; lower_z[i] = bounds0.lower.z;
101 upper_x[i] = bounds0.upper.x; upper_y[i] = bounds0.upper.y; upper_z[i] = bounds0.upper.z;
102
103 lower_dx[i] = dlower.x; lower_dy[i] = dlower.y; lower_dz[i] = dlower.z;
104 upper_dx[i] = dupper.x; upper_dy[i] = dupper.y; upper_dz[i] = dupper.z;
105 }
106
107 /*! Sets bounding box of child. */
108 __forceinline void setBounds(size_t i, const LBBox3fa& bounds) {
109 setBounds(i, bounds.bounds0, bounds.bounds1);
110 }
111
112 /*! Sets bounding box of child. */
113 __forceinline void setBounds(size_t i, const LBBox3fa& bounds, const BBox1f& tbounds) {
114 setBounds(i, bounds.global(tbounds));
115 }
116
117 /*! Sets bounding box and ID of child. */
118 __forceinline void set(size_t i, NodeRef ref, const BBox3fa& bounds) {
119 lower_x[i] = bounds.lower.x; lower_y[i] = bounds.lower.y; lower_z[i] = bounds.lower.z;
120 upper_x[i] = bounds.upper.x; upper_y[i] = bounds.upper.y; upper_z[i] = bounds.upper.z;
121 children[i] = ref;
122 }
123
124 /*! Sets bounding box and ID of child. */
125 __forceinline void set(size_t i, const NodeRecordMB4D& child)
126 {
127 setRef(i, child.ref);
128 setBounds(i, child.lbounds, child.dt);
129 }
130
131 /*! Return bounding box for time 0 */
132 __forceinline BBox3fa bounds0(size_t i) const {
133 return BBox3fa(Vec3fa(lower_x[i],lower_y[i],lower_z[i]),
134 Vec3fa(upper_x[i],upper_y[i],upper_z[i]));
135 }
136
137 /*! Return bounding box for time 1 */
138 __forceinline BBox3fa bounds1(size_t i) const {
139 return BBox3fa(Vec3fa(lower_x[i]+lower_dx[i],lower_y[i]+lower_dy[i],lower_z[i]+lower_dz[i]),
140 Vec3fa(upper_x[i]+upper_dx[i],upper_y[i]+upper_dy[i],upper_z[i]+upper_dz[i]));
141 }
142
143 /*! Returns bounds of node. */
144 __forceinline BBox3fa bounds() const {
145 return BBox3fa(Vec3fa(reduce_min(min(lower_x,lower_x+lower_dx)),
146 reduce_min(min(lower_y,lower_y+lower_dy)),
147 reduce_min(min(lower_z,lower_z+lower_dz))),
148 Vec3fa(reduce_max(max(upper_x,upper_x+upper_dx)),
149 reduce_max(max(upper_y,upper_y+upper_dy)),
150 reduce_max(max(upper_z,upper_z+upper_dz))));
151 }
152
153 /*! Return bounding box of child i */
154 __forceinline BBox3fa bounds(size_t i) const {
155 return merge(bounds0(i),bounds1(i));
156 }
157
158 /*! Return linear bounding box of child i */
159 __forceinline LBBox3fa lbounds(size_t i) const {
160 return LBBox3fa(bounds0(i),bounds1(i));
161 }
162
163 /*! Return bounding box of child i at specified time */
164 __forceinline BBox3fa bounds(size_t i, float time) const {
165 return lerp(bounds0(i),bounds1(i),time);
166 }
167
168 /*! Returns the expected surface area when randomly sampling the time. */
169 __forceinline float expectedHalfArea(size_t i) const {
170 return lbounds(i).expectedHalfArea();
171 }
172
173 /*! Returns the expected surface area when randomly sampling the time. */
174 __forceinline float expectedHalfArea(size_t i, const BBox1f& t0t1) const {
175 return lbounds(i).expectedHalfArea(t0t1);
176 }
177
178 /*! swap two children of the node */
179 __forceinline void swap(size_t i, size_t j)
180 {
181 assert(i<N && j<N);
182 std::swap(children[i],children[j]);
183
184 std::swap(lower_x[i],lower_x[j]);
185 std::swap(upper_x[i],upper_x[j]);
186 std::swap(lower_y[i],lower_y[j]);
187 std::swap(upper_y[i],upper_y[j]);
188 std::swap(lower_z[i],lower_z[j]);
189 std::swap(upper_z[i],upper_z[j]);
190
191 std::swap(lower_dx[i],lower_dx[j]);
192 std::swap(upper_dx[i],upper_dx[j]);
193 std::swap(lower_dy[i],lower_dy[j]);
194 std::swap(upper_dy[i],upper_dy[j]);
195 std::swap(lower_dz[i],lower_dz[j]);
196 std::swap(upper_dz[i],upper_dz[j]);
197 }
198
199 /*! compacts a node (moves empty children to the end) */
200 __forceinline static void compact(AABBNodeMB_t* a)
201 {
202 /* find right most filled node */
203 ssize_t j=N;
204 for (j=j-1; j>=0; j--)
205 if (a->child(j) != NodeRef::emptyNode)
206 break;
207
208 /* replace empty nodes with filled nodes */
209 for (ssize_t i=0; i<j; i++) {
210 if (a->child(i) == NodeRef::emptyNode) {
211 a->swap(i,j);
212 for (j=j-1; j>i; j--)
213 if (a->child(j) != NodeRef::emptyNode)
214 break;
215 }
216 }
217 }
218
219 /*! Returns reference to specified child */
220 __forceinline NodeRef& child(size_t i) { assert(i<N); return children[i]; }
221 __forceinline const NodeRef& child(size_t i) const { assert(i<N); return children[i]; }
222
223 /*! stream output operator */
224 friend embree_ostream operator<<(embree_ostream cout, const AABBNodeMB_t& n)
225 {
226 cout << "AABBNodeMB {" << embree_endl;
227 for (size_t i=0; i<N; i++)
228 {
229 const BBox3fa b0 = n.bounds0(i);
230 const BBox3fa b1 = n.bounds1(i);
231 cout << " child" << i << " { " << embree_endl;
232 cout << " bounds0 = " << b0 << ", " << embree_endl;
233 cout << " bounds1 = " << b1 << ", " << embree_endl;
234 cout << " }";
235 }
236 cout << "}";
237 return cout;
238 }
239
240 public:
241 vfloat<N> lower_x; //!< X dimension of lower bounds of all N children.
242 vfloat<N> upper_x; //!< X dimension of upper bounds of all N children.
243 vfloat<N> lower_y; //!< Y dimension of lower bounds of all N children.
244 vfloat<N> upper_y; //!< Y dimension of upper bounds of all N children.
245 vfloat<N> lower_z; //!< Z dimension of lower bounds of all N children.
246 vfloat<N> upper_z; //!< Z dimension of upper bounds of all N children.
247
248 vfloat<N> lower_dx; //!< X dimension of lower bounds of all N children.
249 vfloat<N> upper_dx; //!< X dimension of upper bounds of all N children.
250 vfloat<N> lower_dy; //!< Y dimension of lower bounds of all N children.
251 vfloat<N> upper_dy; //!< Y dimension of upper bounds of all N children.
252 vfloat<N> lower_dz; //!< Z dimension of lower bounds of all N children.
253 vfloat<N> upper_dz; //!< Z dimension of upper bounds of all N children.
254 };
255}
256