1// Copyright 2009-2021 Intel Corporation
2// SPDX-License-Identifier: Apache-2.0
3
4#pragma once
5
6#include "bvh_node_aabb_mb.h"
7
8namespace embree
9{
10 /*! Aligned 4D Motion Blur Node */
11 template<typename NodeRef, int N>
12 struct AABBNodeMB4D_t : public AABBNodeMB_t<NodeRef, N>
13 {
14 using BaseNode_t<NodeRef,N>::children;
15 using AABBNodeMB_t<NodeRef,N>::set;
16
17 typedef BVHNodeRecord<NodeRef> NodeRecord;
18 typedef BVHNodeRecordMB<NodeRef> NodeRecordMB;
19 typedef BVHNodeRecordMB4D<NodeRef> NodeRecordMB4D;
20
21 struct Create
22 {
23 template<typename BuildRecord>
24 __forceinline NodeRef operator() (BuildRecord*, const size_t, const FastAllocator::CachedAllocator& alloc, bool hasTimeSplits = true) const
25 {
26 if (hasTimeSplits)
27 {
28 AABBNodeMB4D_t* node = (AABBNodeMB4D_t*) alloc.malloc0(sizeof(AABBNodeMB4D_t),NodeRef::byteNodeAlignment); node->clear();
29 return NodeRef::encodeNode(node);
30 }
31 else
32 {
33 AABBNodeMB_t<NodeRef,N>* node = (AABBNodeMB_t<NodeRef,N>*) alloc.malloc0(sizeof(AABBNodeMB_t<NodeRef,N>),NodeRef::byteNodeAlignment); node->clear();
34 return NodeRef::encodeNode(node);
35 }
36 }
37 };
38
39 struct Set
40 {
41 template<typename BuildRecord>
42 __forceinline void operator() (const BuildRecord&, const BuildRecord*, NodeRef ref, NodeRecordMB4D* children, const size_t num) const
43 {
44#if defined(DEBUG)
45 // check that empty children are only at the end of the child list
46 bool emptyChild = false;
47 for (size_t i=0; i<num; i++) {
48 emptyChild |= (children[i].ref == NodeRef::emptyNode);
49 assert(emptyChild == (children[i].ref == NodeRef::emptyNode));
50 }
51#endif
52 if (likely(ref.isAABBNodeMB())) {
53 for (size_t i=0; i<num; i++)
54 ref.getAABBNodeMB()->set(i, children[i]);
55 } else {
56 for (size_t i=0; i<num; i++)
57 ref.getAABBNodeMB4D()->set(i, children[i]);
58 }
59 }
60 };
61
62 /*! Clears the node. */
63 __forceinline void clear() {
64 lower_t = vfloat<N>(pos_inf);
65 upper_t = vfloat<N>(neg_inf);
66 AABBNodeMB_t<NodeRef,N>::clear();
67 }
68
69 /*! Sets bounding box of child. */
70 __forceinline void setBounds(size_t i, const LBBox3fa& bounds, const BBox1f& tbounds)
71 {
72 AABBNodeMB_t<NodeRef,N>::setBounds(i, bounds.global(tbounds));
73 lower_t[i] = tbounds.lower;
74 upper_t[i] = tbounds.upper == 1.0f ? 1.0f+float(ulp) : tbounds.upper;
75 }
76
77 /*! Sets bounding box and ID of child. */
78 __forceinline void set(size_t i, const NodeRecordMB4D& child) {
79 AABBNodeMB_t<NodeRef,N>::setRef(i,child.ref);
80 setBounds(i, child.lbounds, child.dt);
81 }
82
83 /*! Returns the expected surface area when randomly sampling the time. */
84 __forceinline float expectedHalfArea(size_t i) const {
85 return AABBNodeMB_t<NodeRef,N>::lbounds(i).expectedHalfArea(timeRange(i));
86 }
87
88 /*! returns time range for specified child */
89 __forceinline BBox1f timeRange(size_t i) const {
90 return BBox1f(lower_t[i],upper_t[i]);
91 }
92
93 /*! stream output operator */
94 friend embree_ostream operator<<(embree_ostream cout, const AABBNodeMB4D_t& n)
95 {
96 cout << "AABBNodeMB4D {" << embree_endl;
97 for (size_t i=0; i<N; i++)
98 {
99 const BBox3fa b0 = n.bounds0(i);
100 const BBox3fa b1 = n.bounds1(i);
101 cout << " child" << i << " { " << embree_endl;
102 cout << " bounds0 = " << lerp(b0,b1,n.lower_t[i]) << ", " << embree_endl;
103 cout << " bounds1 = " << lerp(b0,b1,n.upper_t[i]) << ", " << embree_endl;
104 cout << " time_bounds = " << n.lower_t[i] << ", " << n.upper_t[i] << embree_endl;
105 cout << " }";
106 }
107 cout << "}";
108 return cout;
109 }
110
111 public:
112 vfloat<N> lower_t; //!< time dimension of lower bounds of all N children
113 vfloat<N> upper_t; //!< time dimension of upper bounds of all N children
114 };
115}
116