1// Copyright 2009-2021 Intel Corporation
2// SPDX-License-Identifier: Apache-2.0
3
4#pragma once
5
6#include "default.h"
7
8#define MBLUR_BIN_LBBOX 1
9
10namespace embree
11{
12#if MBLUR_BIN_LBBOX
13
14 /*! A primitive reference stores the bounds of the primitive and its ID. */
15 struct PrimRefMB
16 {
17 typedef LBBox3fa BBox;
18
19 __forceinline PrimRefMB () {}
20
21 __forceinline PrimRefMB (const LBBox3fa& lbounds_i, unsigned int activeTimeSegments, BBox1f time_range, unsigned int totalTimeSegments, unsigned int geomID, unsigned int primID)
22 : lbounds((LBBox3fx)lbounds_i), time_range(time_range)
23 {
24 assert(activeTimeSegments > 0);
25 lbounds.bounds0.lower.a = geomID;
26 lbounds.bounds0.upper.a = primID;
27 lbounds.bounds1.lower.a = activeTimeSegments;
28 lbounds.bounds1.upper.a = totalTimeSegments;
29 }
30
31 __forceinline PrimRefMB (EmptyTy empty, const LBBox3fa& lbounds_i, unsigned int activeTimeSegments, BBox1f time_range, unsigned int totalTimeSegments, size_t id)
32 : lbounds((LBBox3fx)lbounds_i), time_range(time_range)
33 {
34 assert(activeTimeSegments > 0);
35#if defined(__64BIT__)
36 lbounds.bounds0.lower.a = id & 0xFFFFFFFF;
37 lbounds.bounds0.upper.a = (id >> 32) & 0xFFFFFFFF;
38#else
39 lbounds.bounds0.lower.a = id;
40 lbounds.bounds0.upper.a = 0;
41#endif
42 lbounds.bounds1.lower.a = activeTimeSegments;
43 lbounds.bounds1.upper.a = totalTimeSegments;
44 }
45
46 __forceinline PrimRefMB (const LBBox3fa& lbounds_i, unsigned int activeTimeSegments, BBox1f time_range, unsigned int totalTimeSegments, size_t id)
47 : lbounds((LBBox3fx)lbounds_i), time_range(time_range)
48 {
49 assert(activeTimeSegments > 0);
50#if defined(__64BIT__)
51 lbounds.bounds0.lower.u = id & 0xFFFFFFFF;
52 lbounds.bounds0.upper.u = (id >> 32) & 0xFFFFFFFF;
53#else
54 lbounds.bounds0.lower.u = id;
55 lbounds.bounds0.upper.u = 0;
56#endif
57 lbounds.bounds1.lower.a = activeTimeSegments;
58 lbounds.bounds1.upper.a = totalTimeSegments;
59 }
60
61 /*! returns bounds for binning */
62 __forceinline LBBox3fa bounds() const {
63 return lbounds;
64 }
65
66 /*! returns the number of time segments of this primref */
67 __forceinline unsigned size() const {
68 return lbounds.bounds1.lower.a;
69 }
70
71 __forceinline unsigned totalTimeSegments() const {
72 return lbounds.bounds1.upper.a;
73 }
74
75 /* calculate overlapping time segment range */
76 __forceinline range<int> timeSegmentRange(const BBox1f& range) const {
77 return getTimeSegmentRange(range,time_range,float(totalTimeSegments()));
78 }
79
80 /* returns time that corresponds to time step */
81 __forceinline float timeStep(const int i) const {
82 assert(i>=0 && i<=(int)totalTimeSegments());
83 return time_range.lower + time_range.size()*float(i)/float(totalTimeSegments());
84 }
85
86 /*! checks if time range overlaps */
87 __forceinline bool time_range_overlap(const BBox1f& range) const
88 {
89 if (0.9999f*time_range.upper <= range.lower) return false;
90 if (1.0001f*time_range.lower >= range.upper) return false;
91 return true;
92 }
93
94 /*! returns center for binning */
95 __forceinline Vec3fa binCenter() const {
96 return center2(lbounds.interpolate(0.5f));
97 }
98
99 /*! returns bounds and centroid used for binning */
100 __forceinline void binBoundsAndCenter(LBBox3fa& bounds_o, Vec3fa& center_o) const
101 {
102 bounds_o = bounds();
103 center_o = binCenter();
104 }
105
106 /*! returns the geometry ID */
107 __forceinline unsigned geomID() const {
108 return lbounds.bounds0.lower.a;
109 }
110
111 /*! returns the primitive ID */
112 __forceinline unsigned primID() const {
113 return lbounds.bounds0.upper.a;
114 }
115
116 /*! returns an size_t sized ID */
117 __forceinline size_t ID() const {
118#if defined(__64BIT__)
119 return size_t(lbounds.bounds0.lower.u) + (size_t(lbounds.bounds0.upper.u) << 32);
120#else
121 return size_t(lbounds.bounds0.lower.u);
122#endif
123 }
124
125 /*! special function for operator< */
126 __forceinline uint64_t ID64() const {
127 return (((uint64_t)primID()) << 32) + (uint64_t)geomID();
128 }
129
130 /*! allows sorting the primrefs by ID */
131 friend __forceinline bool operator<(const PrimRefMB& p0, const PrimRefMB& p1) {
132 return p0.ID64() < p1.ID64();
133 }
134
135 /*! Outputs primitive reference to a stream. */
136 friend __forceinline embree_ostream operator<<(embree_ostream cout, const PrimRefMB& ref) {
137 return cout << "{ time_range = " << ref.time_range << ", bounds = " << ref.bounds() << ", geomID = " << ref.geomID() << ", primID = " << ref.primID() << ", active_segments = " << ref.size() << ", total_segments = " << ref.totalTimeSegments() << " }";
138 }
139
140 public:
141 LBBox3fx lbounds;
142 BBox1f time_range; // entire geometry time range
143 };
144
145#else
146
147 /*! A primitive reference stores the bounds of the primitive and its ID. */
148 struct __aligned(16) PrimRefMB
149 {
150 typedef BBox3fa BBox;
151
152 __forceinline PrimRefMB () {}
153
154 __forceinline PrimRefMB (const LBBox3fa& bounds, unsigned int activeTimeSegments, BBox1f time_range, unsigned int totalTimeSegments, unsigned int geomID, unsigned int primID)
155 : bbox(bounds.interpolate(0.5f)), _activeTimeSegments(activeTimeSegments), _totalTimeSegments(totalTimeSegments), time_range(time_range)
156 {
157 assert(activeTimeSegments > 0);
158 bbox.lower.a = geomID;
159 bbox.upper.a = primID;
160 }
161
162 __forceinline PrimRefMB (EmptyTy empty, const LBBox3fa& bounds, unsigned int activeTimeSegments, BBox1f time_range, unsigned int totalTimeSegments, size_t id)
163 : bbox(bounds.interpolate(0.5f)), _activeTimeSegments(activeTimeSegments), _totalTimeSegments(totalTimeSegments), time_range(time_range)
164 {
165 assert(activeTimeSegments > 0);
166#if defined(__64BIT__)
167 bbox.lower.u = id & 0xFFFFFFFF;
168 bbox.upper.u = (id >> 32) & 0xFFFFFFFF;
169#else
170 bbox.lower.u = id;
171 bbox.upper.u = 0;
172#endif
173 }
174
175 /*! returns bounds for binning */
176 __forceinline BBox3fa bounds() const {
177 return bbox;
178 }
179
180 /*! returns the number of time segments of this primref */
181 __forceinline unsigned int size() const {
182 return _activeTimeSegments;
183 }
184
185 __forceinline unsigned int totalTimeSegments() const {
186 return _totalTimeSegments;
187 }
188
189 /* calculate overlapping time segment range */
190 __forceinline range<int> timeSegmentRange(const BBox1f& range) const {
191 return getTimeSegmentRange(range,time_range,float(_totalTimeSegments));
192 }
193
194 /* returns time that corresponds to time step */
195 __forceinline float timeStep(const int i) const {
196 assert(i>=0 && i<=(int)_totalTimeSegments);
197 return time_range.lower + time_range.size()*float(i)/float(_totalTimeSegments);
198 }
199
200 /*! checks if time range overlaps */
201 __forceinline bool time_range_overlap(const BBox1f& range) const
202 {
203 if (0.9999f*time_range.upper <= range.lower) return false;
204 if (1.0001f*time_range.lower >= range.upper) return false;
205 return true;
206 }
207
208 /*! returns center for binning */
209 __forceinline Vec3fa binCenter() const {
210 return center2(bounds());
211 }
212
213 /*! returns bounds and centroid used for binning */
214 __forceinline void binBoundsAndCenter(BBox3fa& bounds_o, Vec3fa& center_o) const
215 {
216 bounds_o = bounds();
217 center_o = center2(bounds());
218 }
219
220 /*! returns the geometry ID */
221 __forceinline unsigned int geomID() const {
222 return bbox.lower.a;
223 }
224
225 /*! returns the primitive ID */
226 __forceinline unsigned int primID() const {
227 return bbox.upper.a;
228 }
229
230 /*! returns an size_t sized ID */
231 __forceinline size_t ID() const {
232#if defined(__64BIT__)
233 return size_t(bbox.lower.u) + (size_t(bbox.upper.u) << 32);
234#else
235 return size_t(bbox.lower.u);
236#endif
237 }
238
239 /*! special function for operator< */
240 __forceinline uint64_t ID64() const {
241 return (((uint64_t)primID()) << 32) + (uint64_t)geomID();
242 }
243
244 /*! allows sorting the primrefs by ID */
245 friend __forceinline bool operator<(const PrimRefMB& p0, const PrimRefMB& p1) {
246 return p0.ID64() < p1.ID64();
247 }
248
249 /*! Outputs primitive reference to a stream. */
250 friend __forceinline embree_ostream operator<<(embree_ostream cout, const PrimRefMB& ref) {
251 return cout << "{ bounds = " << ref.bounds() << ", geomID = " << ref.geomID() << ", primID = " << ref.primID() << ", active_segments = " << ref.size() << ", total_segments = " << ref.totalTimeSegments() << " }";
252 }
253
254 public:
255 BBox3fa bbox; // bounds, geomID, primID
256 unsigned int _activeTimeSegments;
257 unsigned int _totalTimeSegments;
258 BBox1f time_range; // entire geometry time range
259 };
260
261#endif
262}
263