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 
8 namespace 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>
operatorAABBNodeMB_t::Create22       __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>
operatorAABBNodeMB_t::Set32       __forceinline NodeRecordMB operator() (const BuildRecord& precord, const BuildRecord* crecords, NodeRef ref, NodeRecordMB* children, const size_t num) const
33       {
34         AABBNodeMB_t* node = ref.getAABBNodeMB();
35 
36         LBBox3fa bounds = empty;
37         for (size_t i=0; i<num; i++) {
38           node->setRef(i,children[i].ref);
39           node->setBounds(i,children[i].lbounds);
40           bounds.extend(children[i].lbounds);
41         }
42         return NodeRecordMB(ref,bounds);
43       }
44     };
45 
46     struct SetTimeRange
47     {
SetTimeRangeAABBNodeMB_t::SetTimeRange48       __forceinline SetTimeRange(BBox1f tbounds) : tbounds(tbounds) {}
49 
50       template<typename BuildRecord>
operatorAABBNodeMB_t::SetTimeRange51       __forceinline NodeRecordMB operator() (const BuildRecord& precord, const BuildRecord* crecords, NodeRef ref, NodeRecordMB* children, const size_t num) const
52       {
53         AABBNodeMB_t* node = ref.getAABBNodeMB();
54 
55         LBBox3fa bounds = empty;
56         for (size_t i=0; i<num; i++) {
57           node->setRef(i, children[i].ref);
58           node->setBounds(i, children[i].lbounds, tbounds);
59           bounds.extend(children[i].lbounds);
60         }
61         return NodeRecordMB(ref,bounds);
62       }
63 
64       BBox1f tbounds;
65     };
66 
67     /*! Clears the node. */
clearAABBNodeMB_t68     __forceinline void clear()  {
69       lower_x = lower_y = lower_z = vfloat<N>(pos_inf);
70       upper_x = upper_y = upper_z = vfloat<N>(neg_inf);
71       lower_dx = lower_dy = lower_dz = vfloat<N>(0.0f);
72       upper_dx = upper_dy = upper_dz = vfloat<N>(0.0f);
73       BaseNode_t<NodeRef,N>::clear();
74     }
75 
76     /*! Sets ID of child. */
setRefAABBNodeMB_t77     __forceinline void setRef(size_t i, NodeRef ref) {
78       children[i] = ref;
79     }
80 
81     /*! Sets bounding box of child. */
setBoundsAABBNodeMB_t82     __forceinline void setBounds(size_t i, const BBox3fa& bounds0_i, const BBox3fa& bounds1_i)
83     {
84       /*! for empty bounds we have to avoid inf-inf=nan */
85       BBox3fa bounds0(min(bounds0_i.lower,Vec3fa(+FLT_MAX)),max(bounds0_i.upper,Vec3fa(-FLT_MAX)));
86       BBox3fa bounds1(min(bounds1_i.lower,Vec3fa(+FLT_MAX)),max(bounds1_i.upper,Vec3fa(-FLT_MAX)));
87       bounds0 = bounds0.enlarge_by(4.0f*float(ulp));
88       bounds1 = bounds1.enlarge_by(4.0f*float(ulp));
89       Vec3fa dlower = bounds1.lower-bounds0.lower;
90       Vec3fa dupper = bounds1.upper-bounds0.upper;
91 
92       lower_x[i] = bounds0.lower.x; lower_y[i] = bounds0.lower.y; lower_z[i] = bounds0.lower.z;
93       upper_x[i] = bounds0.upper.x; upper_y[i] = bounds0.upper.y; upper_z[i] = bounds0.upper.z;
94 
95       lower_dx[i] = dlower.x; lower_dy[i] = dlower.y; lower_dz[i] = dlower.z;
96       upper_dx[i] = dupper.x; upper_dy[i] = dupper.y; upper_dz[i] = dupper.z;
97     }
98 
99     /*! Sets bounding box of child. */
setBoundsAABBNodeMB_t100     __forceinline void setBounds(size_t i, const LBBox3fa& bounds) {
101       setBounds(i, bounds.bounds0, bounds.bounds1);
102     }
103 
104     /*! Sets bounding box of child. */
setBoundsAABBNodeMB_t105     __forceinline void setBounds(size_t i, const LBBox3fa& bounds, const BBox1f& tbounds) {
106       setBounds(i, bounds.global(tbounds));
107     }
108 
109     /*! Sets bounding box and ID of child. */
setAABBNodeMB_t110     __forceinline void set(size_t i, NodeRef ref, const BBox3fa& bounds) {
111       lower_x[i] = bounds.lower.x; lower_y[i] = bounds.lower.y; lower_z[i] = bounds.lower.z;
112       upper_x[i] = bounds.upper.x; upper_y[i] = bounds.upper.y; upper_z[i] = bounds.upper.z;
113       children[i] = ref;
114     }
115 
116     /*! Sets bounding box and ID of child. */
setAABBNodeMB_t117     __forceinline void set(size_t i, const NodeRecordMB4D& child)
118     {
119       setRef(i, child.ref);
120       setBounds(i, child.lbounds, child.dt);
121     }
122 
123     /*! Return bounding box for time 0 */
bounds0AABBNodeMB_t124     __forceinline BBox3fa bounds0(size_t i) const {
125       return BBox3fa(Vec3fa(lower_x[i],lower_y[i],lower_z[i]),
126                      Vec3fa(upper_x[i],upper_y[i],upper_z[i]));
127     }
128 
129     /*! Return bounding box for time 1 */
bounds1AABBNodeMB_t130     __forceinline BBox3fa bounds1(size_t i) const {
131       return BBox3fa(Vec3fa(lower_x[i]+lower_dx[i],lower_y[i]+lower_dy[i],lower_z[i]+lower_dz[i]),
132                      Vec3fa(upper_x[i]+upper_dx[i],upper_y[i]+upper_dy[i],upper_z[i]+upper_dz[i]));
133     }
134 
135     /*! Returns bounds of node. */
boundsAABBNodeMB_t136     __forceinline BBox3fa bounds() const {
137       return BBox3fa(Vec3fa(reduce_min(min(lower_x,lower_x+lower_dx)),
138                             reduce_min(min(lower_y,lower_y+lower_dy)),
139                             reduce_min(min(lower_z,lower_z+lower_dz))),
140                      Vec3fa(reduce_max(max(upper_x,upper_x+upper_dx)),
141                             reduce_max(max(upper_y,upper_y+upper_dy)),
142                             reduce_max(max(upper_z,upper_z+upper_dz))));
143     }
144 
145     /*! Return bounding box of child i */
boundsAABBNodeMB_t146     __forceinline BBox3fa bounds(size_t i) const {
147       return merge(bounds0(i),bounds1(i));
148     }
149 
150     /*! Return linear bounding box of child i */
lboundsAABBNodeMB_t151     __forceinline LBBox3fa lbounds(size_t i) const {
152       return LBBox3fa(bounds0(i),bounds1(i));
153     }
154 
155     /*! Return bounding box of child i at specified time */
boundsAABBNodeMB_t156     __forceinline BBox3fa bounds(size_t i, float time) const {
157       return lerp(bounds0(i),bounds1(i),time);
158     }
159 
160     /*! Returns the expected surface area when randomly sampling the time. */
expectedHalfAreaAABBNodeMB_t161     __forceinline float expectedHalfArea(size_t i) const {
162       return lbounds(i).expectedHalfArea();
163     }
164 
165     /*! Returns the expected surface area when randomly sampling the time. */
expectedHalfAreaAABBNodeMB_t166     __forceinline float expectedHalfArea(size_t i, const BBox1f& t0t1) const {
167       return lbounds(i).expectedHalfArea(t0t1);
168     }
169 
170     /*! swap two children of the node */
swapAABBNodeMB_t171     __forceinline void swap(size_t i, size_t j)
172     {
173       assert(i<N && j<N);
174       std::swap(children[i],children[j]);
175 
176       std::swap(lower_x[i],lower_x[j]);
177       std::swap(upper_x[i],upper_x[j]);
178       std::swap(lower_y[i],lower_y[j]);
179       std::swap(upper_y[i],upper_y[j]);
180       std::swap(lower_z[i],lower_z[j]);
181       std::swap(upper_z[i],upper_z[j]);
182 
183       std::swap(lower_dx[i],lower_dx[j]);
184       std::swap(upper_dx[i],upper_dx[j]);
185       std::swap(lower_dy[i],lower_dy[j]);
186       std::swap(upper_dy[i],upper_dy[j]);
187       std::swap(lower_dz[i],lower_dz[j]);
188       std::swap(upper_dz[i],upper_dz[j]);
189     }
190 
191     /*! compacts a node (moves empty children to the end) */
compactAABBNodeMB_t192     __forceinline static void compact(AABBNodeMB_t* a)
193     {
194       /* find right most filled node */
195       ssize_t j=N;
196       for (j=j-1; j>=0; j--)
197         if (a->child(j) != NodeRef::emptyNode)
198           break;
199 
200       /* replace empty nodes with filled nodes */
201       for (ssize_t i=0; i<j; i++) {
202         if (a->child(i) == NodeRef::emptyNode) {
203           a->swap(i,j);
204           for (j=j-1; j>i; j--)
205             if (a->child(j) != NodeRef::emptyNode)
206               break;
207         }
208       }
209     }
210 
211     /*! Returns reference to specified child */
childAABBNodeMB_t212     __forceinline       NodeRef& child(size_t i)       { assert(i<N); return children[i]; }
childAABBNodeMB_t213     __forceinline const NodeRef& child(size_t i) const { assert(i<N); return children[i]; }
214 
215     /*! stream output operator */
216     friend embree_ostream operator<<(embree_ostream cout, const AABBNodeMB_t& n)
217     {
218       cout << "AABBNodeMB {" << embree_endl;
219       for (size_t i=0; i<N; i++)
220       {
221         const BBox3fa b0 = n.bounds0(i);
222         const BBox3fa b1 = n.bounds1(i);
223         cout << "  child" << i << " { " << embree_endl;
224         cout << "    bounds0 = " << b0 << ", " << embree_endl;
225         cout << "    bounds1 = " << b1 << ", " << embree_endl;
226         cout << "  }";
227       }
228       cout << "}";
229       return cout;
230     }
231 
232   public:
233     vfloat<N> lower_x;        //!< X dimension of lower bounds of all N children.
234     vfloat<N> upper_x;        //!< X dimension of upper bounds of all N children.
235     vfloat<N> lower_y;        //!< Y dimension of lower bounds of all N children.
236     vfloat<N> upper_y;        //!< Y dimension of upper bounds of all N children.
237     vfloat<N> lower_z;        //!< Z dimension of lower bounds of all N children.
238     vfloat<N> upper_z;        //!< Z dimension of upper bounds of all N children.
239 
240     vfloat<N> lower_dx;        //!< X dimension of lower bounds of all N children.
241     vfloat<N> upper_dx;        //!< X dimension of upper bounds of all N children.
242     vfloat<N> lower_dy;        //!< Y dimension of lower bounds of all N children.
243     vfloat<N> upper_dy;        //!< Y dimension of upper bounds of all N children.
244     vfloat<N> lower_dz;        //!< Z dimension of lower bounds of all N children.
245     vfloat<N> upper_dz;        //!< Z dimension of upper bounds of all N children.
246   };
247 }
248