Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/thirdparty/embree/common/math/bbox.h
9912 views
1
// Copyright 2009-2021 Intel Corporation
2
// SPDX-License-Identifier: Apache-2.0
3
4
#pragma once
5
6
#include "vec2.h"
7
#include "vec3.h"
8
9
namespace embree
10
{
11
namespace internal {
12
13
template <typename T> __forceinline T divideByTwo(const T& v) { return v / T(2); }
14
template <> __forceinline float divideByTwo<float>(const float& v) { return v * 0.5f; }
15
template <> __forceinline double divideByTwo<double>(const double& v) { return v * 0.5; }
16
17
} // namespace internal
18
template<typename T>
19
struct BBox
20
{
21
T lower, upper;
22
23
////////////////////////////////////////////////////////////////////////////////
24
/// Construction
25
////////////////////////////////////////////////////////////////////////////////
26
27
__forceinline BBox ( ) { }
28
template<typename T1>
29
__forceinline BBox ( const BBox<T1>& other ) : lower(other.lower), upper(other.upper) {}
30
__forceinline BBox& operator=( const BBox& other ) { lower = other.lower; upper = other.upper; return *this; }
31
32
__forceinline BBox ( const T& v ) : lower(v), upper(v) {}
33
__forceinline BBox ( const T& lower, const T& upper ) : lower(lower), upper(upper) {}
34
35
////////////////////////////////////////////////////////////////////////////////
36
/// Extending Bounds
37
////////////////////////////////////////////////////////////////////////////////
38
39
__forceinline const BBox& extend(const BBox& other) { lower = min(lower,other.lower); upper = max(upper,other.upper); return *this; }
40
__forceinline const BBox& extend(const T & other) { lower = min(lower,other ); upper = max(upper,other ); return *this; }
41
42
/*! tests if box is empty */
43
__forceinline bool empty() const { for (int i=0; i<T::N; i++) if (lower[i] > upper[i]) return true; return false; }
44
45
/*! computes the size of the box */
46
__forceinline T size() const { return upper - lower; }
47
48
/*! computes the center of the box */
49
__forceinline T center() const { return internal::divideByTwo<T>(lower+upper); }
50
51
/*! computes twice the center of the box */
52
__forceinline T center2() const { return lower+upper; }
53
54
/*! merges two boxes */
55
__forceinline static const BBox merge (const BBox& a, const BBox& b) {
56
return BBox(min(a.lower, b.lower), max(a.upper, b.upper));
57
}
58
59
/*! intersects two boxes */
60
__forceinline static const BBox intersect (const BBox& a, const BBox& b) {
61
return BBox(max(a.lower, b.lower), min(a.upper, b.upper));
62
}
63
64
/*! enlarge box by some scaling factor */
65
__forceinline BBox enlarge_by(const float a) const {
66
return BBox(lower - T(a)*abs(lower), upper + T(a)*abs(upper));
67
}
68
69
////////////////////////////////////////////////////////////////////////////////
70
/// Constants
71
////////////////////////////////////////////////////////////////////////////////
72
73
__forceinline BBox( EmptyTy ) : lower(pos_inf), upper(neg_inf) {}
74
__forceinline BBox( FullTy ) : lower(neg_inf), upper(pos_inf) {}
75
__forceinline BBox( FalseTy ) : lower(pos_inf), upper(neg_inf) {}
76
__forceinline BBox( TrueTy ) : lower(neg_inf), upper(pos_inf) {}
77
__forceinline BBox( NegInfTy ): lower(pos_inf), upper(neg_inf) {}
78
__forceinline BBox( PosInfTy ): lower(neg_inf), upper(pos_inf) {}
79
};
80
81
template<> __forceinline bool BBox<float>::empty() const {
82
return lower > upper;
83
}
84
85
#if defined(__SSE__) || defined(__ARM_NEON)
86
template<> __forceinline bool BBox<Vec3fa>::empty() const {
87
return !all(le_mask(lower,upper));
88
}
89
template<> __forceinline bool BBox<Vec3fx>::empty() const {
90
return !all(le_mask(lower,upper));
91
}
92
#endif
93
94
/*! tests if box is finite */
95
__forceinline bool isvalid( const BBox<Vec3fa>& v ) {
96
return all(gt_mask(v.lower,Vec3fa_t(-FLT_LARGE)) & lt_mask(v.upper,Vec3fa_t(+FLT_LARGE)));
97
}
98
99
/*! tests if box is finite and non-empty*/
100
__forceinline bool isvalid_non_empty( const BBox<Vec3fa>& v ) {
101
return all(gt_mask(v.lower,Vec3fa_t(-FLT_LARGE)) & lt_mask(v.upper,Vec3fa_t(+FLT_LARGE)) & le_mask(v.lower,v.upper));
102
}
103
104
/*! tests if box has finite entries */
105
__forceinline bool is_finite( const BBox<Vec3fa>& b) {
106
return is_finite(b.lower) && is_finite(b.upper);
107
}
108
109
/*! test if point contained in box */
110
__forceinline bool inside ( const BBox<Vec3fa>& b, const Vec3fa& p ) { return all(ge_mask(p,b.lower) & le_mask(p,b.upper)); }
111
112
/*! computes the center of the box */
113
template<typename T> __forceinline const T center2(const BBox<T>& box) { return box.lower + box.upper; }
114
template<typename T> __forceinline const T center (const BBox<T>& box) { return internal::divideByTwo<T>(center2(box)); }
115
116
/*! computes the volume of a bounding box */
117
__forceinline float volume ( const BBox<Vec3fa>& b ) { return reduce_mul(b.size()); }
118
__forceinline float safeVolume( const BBox<Vec3fa>& b ) { if (b.empty()) return 0.0f; else return volume(b); }
119
120
/*! computes the volume of a bounding box */
121
__forceinline float volume( const BBox<Vec3f>& b ) { return reduce_mul(b.size()); }
122
123
/*! computes the surface area of a bounding box */
124
template<typename T> __forceinline const T area( const BBox<Vec2<T> >& b ) { const Vec2<T> d = b.size(); return d.x*d.y; }
125
126
template<typename T> __forceinline const T halfArea( const BBox<Vec3<T> >& b ) { return halfArea(b.size()); }
127
template<typename T> __forceinline const T area( const BBox<Vec3<T> >& b ) { return T(2)*halfArea(b); }
128
129
__forceinline float halfArea( const BBox<Vec3fa>& b ) { return halfArea(b.size()); }
130
__forceinline float area( const BBox<Vec3fa>& b ) { return 2.0f*halfArea(b); }
131
132
__forceinline float halfArea( const BBox<Vec3fx>& b ) { return halfArea(b.size()); }
133
__forceinline float area( const BBox<Vec3fx>& b ) { return 2.0f*halfArea(b); }
134
135
template<typename Vec> __forceinline float safeArea( const BBox<Vec>& b ) { if (b.empty()) return 0.0f; else return area(b); }
136
137
template<typename T> __forceinline float expectedApproxHalfArea(const BBox<T>& box) {
138
return halfArea(box);
139
}
140
141
/*! merges bounding boxes and points */
142
template<typename T> __forceinline const BBox<T> merge( const BBox<T>& a, const T& b ) { return BBox<T>(min(a.lower, b ), max(a.upper, b )); }
143
template<typename T> __forceinline const BBox<T> merge( const T& a, const BBox<T>& b ) { return BBox<T>(min(a , b.lower), max(a , b.upper)); }
144
template<typename T> __forceinline const BBox<T> merge( const BBox<T>& a, const BBox<T>& b ) { return BBox<T>(min(a.lower, b.lower), max(a.upper, b.upper)); }
145
146
/*! Merges three boxes. */
147
template<typename T> __forceinline const BBox<T> merge( const BBox<T>& a, const BBox<T>& b, const BBox<T>& c ) { return merge(a,merge(b,c)); }
148
149
/*! Merges four boxes. */
150
template<typename T> __forceinline BBox<T> merge(const BBox<T>& a, const BBox<T>& b, const BBox<T>& c, const BBox<T>& d) {
151
return merge(merge(a,b),merge(c,d));
152
}
153
154
/*! Comparison Operators */
155
template<typename T> __forceinline bool operator==( const BBox<T>& a, const BBox<T>& b ) { return a.lower == b.lower && a.upper == b.upper; }
156
template<typename T> __forceinline bool operator!=( const BBox<T>& a, const BBox<T>& b ) { return a.lower != b.lower || a.upper != b.upper; }
157
158
/*! scaling */
159
template<typename T> __forceinline BBox<T> operator *( const float& a, const BBox<T>& b ) { return BBox<T>(a*b.lower,a*b.upper); }
160
template<typename T> __forceinline BBox<T> operator *( const T& a, const BBox<T>& b ) { return BBox<T>(a*b.lower,a*b.upper); }
161
162
/*! translations */
163
template<typename T> __forceinline BBox<T> operator +( const BBox<T>& a, const BBox<T>& b ) { return BBox<T>(a.lower+b.lower,a.upper+b.upper); }
164
template<typename T> __forceinline BBox<T> operator -( const BBox<T>& a, const BBox<T>& b ) { return BBox<T>(a.lower-b.lower,a.upper-b.upper); }
165
template<typename T> __forceinline BBox<T> operator +( const BBox<T>& a, const T & b ) { return BBox<T>(a.lower+b ,a.upper+b ); }
166
template<typename T> __forceinline BBox<T> operator -( const BBox<T>& a, const T & b ) { return BBox<T>(a.lower-b ,a.upper-b ); }
167
168
/*! extension */
169
template<typename T> __forceinline BBox<T> enlarge(const BBox<T>& a, const T& b) { return BBox<T>(a.lower-b, a.upper+b); }
170
171
/*! intersect bounding boxes */
172
template<typename T> __forceinline const BBox<T> intersect( const BBox<T>& a, const BBox<T>& b ) { return BBox<T>(max(a.lower, b.lower), min(a.upper, b.upper)); }
173
template<typename T> __forceinline const BBox<T> intersect( const BBox<T>& a, const BBox<T>& b, const BBox<T>& c ) { return intersect(a,intersect(b,c)); }
174
template<typename T> __forceinline const BBox<T> intersect( const BBox<T>& a, const BBox<T>& b, const BBox<T>& c, const BBox<T>& d ) { return intersect(intersect(a,b),intersect(c,d)); }
175
176
/*! subtract bounds from each other */
177
template<typename T> __forceinline void subtract(const BBox<T>& a, const BBox<T>& b, BBox<T>& c, BBox<T>& d)
178
{
179
c.lower = a.lower;
180
c.upper = min(a.upper,b.lower);
181
d.lower = max(a.lower,b.upper);
182
d.upper = a.upper;
183
}
184
185
/*! tests if bounding boxes (and points) are disjoint (empty intersection) */
186
template<typename T> __inline bool disjoint( const BBox<T>& a, const BBox<T>& b ) { return intersect(a,b).empty(); }
187
template<typename T> __inline bool disjoint( const BBox<T>& a, const T& b ) { return disjoint(a,BBox<T>(b)); }
188
template<typename T> __inline bool disjoint( const T& a, const BBox<T>& b ) { return disjoint(BBox<T>(a),b); }
189
190
/*! tests if bounding boxes (and points) are conjoint (non-empty intersection) */
191
template<typename T> __inline bool conjoint( const BBox<T>& a, const BBox<T>& b ) { return !intersect(a,b).empty(); }
192
template<typename T> __inline bool conjoint( const BBox<T>& a, const T& b ) { return conjoint(a,BBox<T>(b)); }
193
template<typename T> __inline bool conjoint( const T& a, const BBox<T>& b ) { return conjoint(BBox<T>(a),b); }
194
195
/*! subset relation */
196
template<typename T> __inline bool subset( const BBox<T>& a, const BBox<T>& b )
197
{
198
for ( size_t i = 0; i < T::N; i++ ) if ( a.lower[i] < b.lower[i] ) return false;
199
for ( size_t i = 0; i < T::N; i++ ) if ( a.upper[i] > b.upper[i] ) return false;
200
return true;
201
}
202
203
template<> __inline bool subset( const BBox<Vec3fa>& a, const BBox<Vec3fa>& b ) {
204
return all(ge_mask(a.lower,b.lower)) && all(le_mask(a.upper,b.upper));
205
}
206
207
template<> __inline bool subset( const BBox<Vec3fx>& a, const BBox<Vec3fx>& b ) {
208
return all(ge_mask(a.lower,b.lower)) && all(le_mask(a.upper,b.upper));
209
}
210
211
/*! blending */
212
template<typename T>
213
__forceinline BBox<T> lerp(const BBox<T>& b0, const BBox<T>& b1, const float t) {
214
return BBox<T>(lerp(b0.lower,b1.lower,t),lerp(b0.upper,b1.upper,t));
215
}
216
217
/*! output operator */
218
template<typename T> __forceinline embree_ostream operator<<(embree_ostream cout, const BBox<T>& box) {
219
return cout << "[" << box.lower << "; " << box.upper << "]";
220
}
221
222
/*! default template instantiations */
223
typedef BBox<float> BBox1f;
224
typedef BBox<Vec2f> BBox2f;
225
typedef BBox<Vec2fa> BBox2fa;
226
typedef BBox<Vec3f> BBox3f;
227
typedef BBox<Vec3fa> BBox3fa;
228
typedef BBox<Vec3fx> BBox3fx;
229
typedef BBox<Vec3ff> BBox3ff;
230
}
231
232
////////////////////////////////////////////////////////////////////////////////
233
/// SSE / AVX / MIC specializations
234
////////////////////////////////////////////////////////////////////////////////
235
236
#if defined (__SSE__) || defined(__ARM_NEON)
237
#include "../simd/sse.h"
238
#endif
239
240
#if defined (__AVX__)
241
#include "../simd/avx.h"
242
#endif
243
244
#if defined(__AVX512F__)
245
#include "../simd/avx512.h"
246
#endif
247
248
namespace embree
249
{
250
template<int N>
251
__forceinline BBox<Vec3<vfloat<N>>> transpose(const BBox3fa* bounds);
252
253
template<>
254
__forceinline BBox<Vec3<vfloat4>> transpose<4>(const BBox3fa* bounds)
255
{
256
BBox<Vec3<vfloat4>> dest;
257
258
transpose((vfloat4&)bounds[0].lower,
259
(vfloat4&)bounds[1].lower,
260
(vfloat4&)bounds[2].lower,
261
(vfloat4&)bounds[3].lower,
262
dest.lower.x,
263
dest.lower.y,
264
dest.lower.z);
265
266
transpose((vfloat4&)bounds[0].upper,
267
(vfloat4&)bounds[1].upper,
268
(vfloat4&)bounds[2].upper,
269
(vfloat4&)bounds[3].upper,
270
dest.upper.x,
271
dest.upper.y,
272
dest.upper.z);
273
274
return dest;
275
}
276
277
#if defined(__AVX__)
278
template<>
279
__forceinline BBox<Vec3<vfloat8>> transpose<8>(const BBox3fa* bounds)
280
{
281
BBox<Vec3<vfloat8>> dest;
282
283
transpose((vfloat4&)bounds[0].lower,
284
(vfloat4&)bounds[1].lower,
285
(vfloat4&)bounds[2].lower,
286
(vfloat4&)bounds[3].lower,
287
(vfloat4&)bounds[4].lower,
288
(vfloat4&)bounds[5].lower,
289
(vfloat4&)bounds[6].lower,
290
(vfloat4&)bounds[7].lower,
291
dest.lower.x,
292
dest.lower.y,
293
dest.lower.z);
294
295
transpose((vfloat4&)bounds[0].upper,
296
(vfloat4&)bounds[1].upper,
297
(vfloat4&)bounds[2].upper,
298
(vfloat4&)bounds[3].upper,
299
(vfloat4&)bounds[4].upper,
300
(vfloat4&)bounds[5].upper,
301
(vfloat4&)bounds[6].upper,
302
(vfloat4&)bounds[7].upper,
303
dest.upper.x,
304
dest.upper.y,
305
dest.upper.z);
306
307
return dest;
308
}
309
#endif
310
311
template<int N>
312
__forceinline BBox3fa merge(const BBox3fa* bounds);
313
314
template<>
315
__forceinline BBox3fa merge<4>(const BBox3fa* bounds)
316
{
317
const Vec3fa lower = min(min(bounds[0].lower,bounds[1].lower),
318
min(bounds[2].lower,bounds[3].lower));
319
const Vec3fa upper = max(max(bounds[0].upper,bounds[1].upper),
320
max(bounds[2].upper,bounds[3].upper));
321
return BBox3fa(lower,upper);
322
}
323
324
#if defined(__AVX__)
325
template<>
326
__forceinline BBox3fa merge<8>(const BBox3fa* bounds)
327
{
328
const Vec3fa lower = min(min(min(bounds[0].lower,bounds[1].lower),min(bounds[2].lower,bounds[3].lower)),
329
min(min(bounds[4].lower,bounds[5].lower),min(bounds[6].lower,bounds[7].lower)));
330
const Vec3fa upper = max(max(max(bounds[0].upper,bounds[1].upper),max(bounds[2].upper,bounds[3].upper)),
331
max(max(bounds[4].upper,bounds[5].upper),max(bounds[6].upper,bounds[7].upper)));
332
return BBox3fa(lower,upper);
333
}
334
#endif
335
}
336
337
338