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