Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/thirdparty/embree/common/math/vec3.h
9912 views
1
// Copyright 2009-2021 Intel Corporation
2
// SPDX-License-Identifier: Apache-2.0
3
4
#pragma once
5
6
#include "emath.h"
7
8
namespace embree
9
{
10
struct Vec3fa;
11
12
////////////////////////////////////////////////////////////////////////////////
13
/// Generic 3D vector Class
14
////////////////////////////////////////////////////////////////////////////////
15
16
template<typename T> struct Vec3
17
{
18
enum { N = 3 };
19
20
union {
21
struct {
22
T x, y, z;
23
};
24
#if !(defined(__WIN32__) && _MSC_VER == 1800) // workaround for older VS 2013 compiler
25
T components[N];
26
#endif
27
};
28
29
typedef T Scalar;
30
31
////////////////////////////////////////////////////////////////////////////////
32
/// Construction
33
////////////////////////////////////////////////////////////////////////////////
34
35
__forceinline Vec3( ) {}
36
__forceinline explicit Vec3( const T& a ) : x(a), y(a), z(a) {}
37
__forceinline Vec3( const T& x, const T& y, const T& z ) : x(x), y(y), z(z) {}
38
39
__forceinline Vec3( const Vec3& other ) { x = other.x; y = other.y; z = other.z; }
40
__forceinline Vec3( const Vec3fa& other );
41
42
template<typename T1> __forceinline Vec3( const Vec3<T1>& a ) : x(T(a.x)), y(T(a.y)), z(T(a.z)) {}
43
template<typename T1> __forceinline Vec3& operator =(const Vec3<T1>& other) { x = other.x; y = other.y; z = other.z; return *this; }
44
45
__forceinline Vec3& operator =(const Vec3& other) { x = other.x; y = other.y; z = other.z; return *this; }
46
47
////////////////////////////////////////////////////////////////////////////////
48
/// Constants
49
////////////////////////////////////////////////////////////////////////////////
50
51
__forceinline Vec3( ZeroTy ) : x(zero), y(zero), z(zero) {}
52
__forceinline Vec3( OneTy ) : x(one), y(one), z(one) {}
53
__forceinline Vec3( PosInfTy ) : x(pos_inf), y(pos_inf), z(pos_inf) {}
54
__forceinline Vec3( NegInfTy ) : x(neg_inf), y(neg_inf), z(neg_inf) {}
55
56
#if defined(__WIN32__) && (_MSC_VER == 1800) // workaround for older VS 2013 compiler
57
__forceinline const T& operator []( const size_t axis ) const { assert(axis < 3); return (&x)[axis]; }
58
__forceinline T& operator []( const size_t axis ) { assert(axis < 3); return (&x)[axis]; }
59
#else
60
__forceinline const T& operator [](const size_t axis) const { assert(axis < 3); return components[axis]; }
61
__forceinline T& operator [](const size_t axis) { assert(axis < 3); return components[axis]; }
62
#endif
63
};
64
65
////////////////////////////////////////////////////////////////////////////////
66
/// Unary Operators
67
////////////////////////////////////////////////////////////////////////////////
68
69
template<typename T> __forceinline Vec3<T> operator +( const Vec3<T>& a ) { return Vec3<T>(+a.x, +a.y, +a.z); }
70
template<typename T> __forceinline Vec3<T> operator -( const Vec3<T>& a ) { return Vec3<T>(-a.x, -a.y, -a.z); }
71
template<typename T> __forceinline Vec3<T> abs ( const Vec3<T>& a ) { return Vec3<T>(abs (a.x), abs (a.y), abs (a.z)); }
72
template<typename T> __forceinline Vec3<T> rcp ( const Vec3<T>& a ) { return Vec3<T>(rcp (a.x), rcp (a.y), rcp (a.z)); }
73
template<typename T> __forceinline Vec3<T> rsqrt ( const Vec3<T>& a ) { return Vec3<T>(rsqrt(a.x), rsqrt(a.y), rsqrt(a.z)); }
74
template<typename T> __forceinline Vec3<T> sqrt ( const Vec3<T>& a ) { return Vec3<T>(sqrt (a.x), sqrt (a.y), sqrt (a.z)); }
75
76
template<typename T> __forceinline Vec3<T> zero_fix( const Vec3<T>& a )
77
{
78
return Vec3<T>(select(abs(a.x)<min_rcp_input,T(min_rcp_input),a.x),
79
select(abs(a.y)<min_rcp_input,T(min_rcp_input),a.y),
80
select(abs(a.z)<min_rcp_input,T(min_rcp_input),a.z));
81
}
82
template<typename T> __forceinline Vec3<T> rcp_safe(const Vec3<T>& a) { return rcp(zero_fix(a)); }
83
84
////////////////////////////////////////////////////////////////////////////////
85
/// Binary Operators
86
////////////////////////////////////////////////////////////////////////////////
87
88
template<typename T> __forceinline Vec3<T> operator +( const Vec3<T>& a, const Vec3<T>& b ) { return Vec3<T>(a.x + b.x, a.y + b.y, a.z + b.z); }
89
template<typename T> __forceinline Vec3<T> operator -( const Vec3<T>& a, const Vec3<T>& b ) { return Vec3<T>(a.x - b.x, a.y - b.y, a.z - b.z); }
90
template<typename T> __forceinline Vec3<T> operator *( const Vec3<T>& a, const Vec3<T>& b ) { return Vec3<T>(a.x * b.x, a.y * b.y, a.z * b.z); }
91
template<typename T> __forceinline Vec3<T> operator *( const T& a, const Vec3<T>& b ) { return Vec3<T>(a * b.x, a * b.y, a * b.z); }
92
template<typename T> __forceinline Vec3<T> operator *( const Vec3<T>& a, const T& b ) { return Vec3<T>(a.x * b , a.y * b , a.z * b ); }
93
template<typename T> __forceinline Vec3<T> operator /( const Vec3<T>& a, const T& b ) { return Vec3<T>(a.x / b , a.y / b , a.z / b ); }
94
template<typename T> __forceinline Vec3<T> operator /( const T& a, const Vec3<T>& b ) { return Vec3<T>(a / b.x, a / b.y, a / b.z); }
95
template<typename T> __forceinline Vec3<T> operator /( const Vec3<T>& a, const Vec3<T>& b ) { return Vec3<T>(a.x / b.x, a.y / b.y, a.z / b.z); }
96
97
template<typename T> __forceinline Vec3<T> min(const Vec3<T>& a, const Vec3<T>& b) { return Vec3<T>(min(a.x, b.x), min(a.y, b.y), min(a.z, b.z)); }
98
template<typename T> __forceinline Vec3<T> max(const Vec3<T>& a, const Vec3<T>& b) { return Vec3<T>(max(a.x, b.x), max(a.y, b.y), max(a.z, b.z)); }
99
100
template<typename T> __forceinline Vec3<T> operator >>( const Vec3<T>& a, const int b ) { return Vec3<T>(a.x >> b, a.y >> b, a.z >> b); }
101
template<typename T> __forceinline Vec3<T> operator <<( const Vec3<T>& a, const int b ) { return Vec3<T>(a.x << b, a.y << b, a.z << b); }
102
103
////////////////////////////////////////////////////////////////////////////////
104
/// Ternary Operators
105
////////////////////////////////////////////////////////////////////////////////
106
107
template<typename T> __forceinline Vec3<T> madd ( const Vec3<T>& a, const Vec3<T>& b, const Vec3<T>& c) { return Vec3<T>( madd(a.x,b.x,c.x), madd(a.y,b.y,c.y), madd(a.z,b.z,c.z)); }
108
template<typename T> __forceinline Vec3<T> msub ( const Vec3<T>& a, const Vec3<T>& b, const Vec3<T>& c) { return Vec3<T>( msub(a.x,b.x,c.x), msub(a.y,b.y,c.y), msub(a.z,b.z,c.z)); }
109
template<typename T> __forceinline Vec3<T> nmadd ( const Vec3<T>& a, const Vec3<T>& b, const Vec3<T>& c) { return Vec3<T>(nmadd(a.x,b.x,c.x),nmadd(a.y,b.y,c.y),nmadd(a.z,b.z,c.z));}
110
template<typename T> __forceinline Vec3<T> nmsub ( const Vec3<T>& a, const Vec3<T>& b, const Vec3<T>& c) { return Vec3<T>(nmsub(a.x,b.x,c.x),nmsub(a.y,b.y,c.y),nmsub(a.z,b.z,c.z)); }
111
112
template<typename T> __forceinline Vec3<T> madd ( const T& a, const Vec3<T>& b, const Vec3<T>& c) { return Vec3<T>( madd(a,b.x,c.x), madd(a,b.y,c.y), madd(a,b.z,c.z)); }
113
template<typename T> __forceinline Vec3<T> msub ( const T& a, const Vec3<T>& b, const Vec3<T>& c) { return Vec3<T>( msub(a,b.x,c.x), msub(a,b.y,c.y), msub(a,b.z,c.z)); }
114
template<typename T> __forceinline Vec3<T> nmadd ( const T& a, const Vec3<T>& b, const Vec3<T>& c) { return Vec3<T>(nmadd(a,b.x,c.x),nmadd(a,b.y,c.y),nmadd(a,b.z,c.z));}
115
template<typename T> __forceinline Vec3<T> nmsub ( const T& a, const Vec3<T>& b, const Vec3<T>& c) { return Vec3<T>(nmsub(a,b.x,c.x),nmsub(a,b.y,c.y),nmsub(a,b.z,c.z)); }
116
117
////////////////////////////////////////////////////////////////////////////////
118
/// Assignment Operators
119
////////////////////////////////////////////////////////////////////////////////
120
121
template<typename T> __forceinline Vec3<T>& operator +=( Vec3<T>& a, const T b ) { a.x += b; a.y += b; a.z += b; return a; }
122
template<typename T> __forceinline Vec3<T>& operator +=( Vec3<T>& a, const Vec3<T>& b ) { a.x += b.x; a.y += b.y; a.z += b.z; return a; }
123
template<typename T> __forceinline Vec3<T>& operator -=( Vec3<T>& a, const Vec3<T>& b ) { a.x -= b.x; a.y -= b.y; a.z -= b.z; return a; }
124
template<typename T> __forceinline Vec3<T>& operator *=( Vec3<T>& a, const T& b ) { a.x *= b ; a.y *= b ; a.z *= b ; return a; }
125
template<typename T> __forceinline Vec3<T>& operator /=( Vec3<T>& a, const T& b ) { a.x /= b ; a.y /= b ; a.z /= b ; return a; }
126
127
////////////////////////////////////////////////////////////////////////////////
128
/// Reduction Operators
129
////////////////////////////////////////////////////////////////////////////////
130
131
template<typename T> __forceinline T reduce_add( const Vec3<T>& a ) { return a.x + a.y + a.z; }
132
template<typename T> __forceinline T reduce_mul( const Vec3<T>& a ) { return a.x * a.y * a.z; }
133
template<typename T> __forceinline T reduce_min( const Vec3<T>& a ) { return min(a.x, a.y, a.z); }
134
template<typename T> __forceinline T reduce_max( const Vec3<T>& a ) { return max(a.x, a.y, a.z); }
135
136
////////////////////////////////////////////////////////////////////////////////
137
/// Comparison Operators
138
////////////////////////////////////////////////////////////////////////////////
139
140
template<typename T> __forceinline bool operator ==( const Vec3<T>& a, const Vec3<T>& b ) { return a.x == b.x && a.y == b.y && a.z == b.z; }
141
template<typename T> __forceinline bool operator !=( const Vec3<T>& a, const Vec3<T>& b ) { return a.x != b.x || a.y != b.y || a.z != b.z; }
142
template<typename T> __forceinline bool operator < ( const Vec3<T>& a, const Vec3<T>& b ) {
143
if (a.x != b.x) return a.x < b.x;
144
if (a.y != b.y) return a.y < b.y;
145
if (a.z != b.z) return a.z < b.z;
146
return false;
147
}
148
149
////////////////////////////////////////////////////////////////////////////////
150
/// Shift Operators
151
////////////////////////////////////////////////////////////////////////////////
152
153
template<typename T> __forceinline Vec3<T> shift_right_1( const Vec3<T>& a ) {
154
return Vec3<T>(shift_right_1(a.x),shift_right_1(a.y),shift_right_1(a.z));
155
}
156
157
////////////////////////////////////////////////////////////////////////////////
158
/// Select
159
////////////////////////////////////////////////////////////////////////////////
160
161
template<typename T> __forceinline Vec3<T> select ( bool s, const Vec3<T>& t, const Vec3<T>& f ) {
162
return Vec3<T>(select(s,t.x,f.x),select(s,t.y,f.y),select(s,t.z,f.z));
163
}
164
165
template<typename T> __forceinline Vec3<T> select ( const Vec3<bool>& s, const Vec3<T>& t, const Vec3<T>& f ) {
166
return Vec3<T>(select(s.x,t.x,f.x),select(s.y,t.y,f.y),select(s.z,t.z,f.z));
167
}
168
169
template<typename T> __forceinline Vec3<T> select ( const typename T::Bool& s, const Vec3<T>& t, const Vec3<T>& f ) {
170
return Vec3<T>(select(s,t.x,f.x),select(s,t.y,f.y),select(s,t.z,f.z));
171
}
172
173
template<typename T>
174
__forceinline Vec3<T> lerp(const Vec3<T>& v0, const Vec3<T>& v1, const T& t) {
175
return madd(Vec3<T>(T(1.0f)-t),v0,t*v1);
176
}
177
178
template<typename T> __forceinline int maxDim ( const Vec3<T>& a )
179
{
180
const Vec3<T> b = abs(a);
181
if (b.x > b.y) {
182
if (b.x > b.z) return 0; else return 2;
183
} else {
184
if (b.y > b.z) return 1; else return 2;
185
}
186
}
187
188
////////////////////////////////////////////////////////////////////////////////
189
/// Comparison Operators
190
////////////////////////////////////////////////////////////////////////////////
191
192
template<typename T> __forceinline Vec3<bool> eq_mask( const Vec3<T>& a, const Vec3<T>& b ) { return Vec3<bool>(a.x==b.x,a.y==b.y,a.z==b.z); }
193
template<typename T> __forceinline Vec3<bool> neq_mask(const Vec3<T>& a, const Vec3<T>& b ) { return Vec3<bool>(a.x!=b.x,a.y!=b.y,a.z!=b.z); }
194
template<typename T> __forceinline Vec3<bool> lt_mask( const Vec3<T>& a, const Vec3<T>& b ) { return Vec3<bool>(a.x< b.x,a.y< b.y,a.z< b.z); }
195
template<typename T> __forceinline Vec3<bool> le_mask( const Vec3<T>& a, const Vec3<T>& b ) { return Vec3<bool>(a.x<=b.x,a.y<=b.y,a.z<=b.z); }
196
template<typename T> __forceinline Vec3<bool> gt_mask( const Vec3<T>& a, const Vec3<T>& b ) { return Vec3<bool>(a.x> b.x,a.y> b.y,a.z> b.z); }
197
template<typename T> __forceinline Vec3<bool> ge_mask( const Vec3<T>& a, const Vec3<T>& b ) { return Vec3<bool>(a.x>=b.x,a.y>=b.y,a.z>=b.z); }
198
199
////////////////////////////////////////////////////////////////////////////////
200
/// Euclidean Space Operators
201
////////////////////////////////////////////////////////////////////////////////
202
203
template<typename T> __forceinline T sqr ( const Vec3<T>& a ) { return dot(a,a); }
204
template<typename T> __forceinline T dot ( const Vec3<T>& a, const Vec3<T>& b ) { return madd(a.x,b.x,madd(a.y,b.y,a.z*b.z)); }
205
template<typename T> __forceinline T length ( const Vec3<T>& a ) { return sqrt(sqr(a)); }
206
template<typename T> __forceinline T rcp_length( const Vec3<T>& a ) { return rsqrt(sqr(a)); }
207
template<typename T> __forceinline Vec3<T> normalize( const Vec3<T>& a ) { return a*rsqrt(sqr(a)); }
208
template<typename T> __forceinline T distance ( const Vec3<T>& a, const Vec3<T>& b ) { return length(a-b); }
209
template<typename T> __forceinline Vec3<T> cross ( const Vec3<T>& a, const Vec3<T>& b ) { return Vec3<T>(msub(a.y,b.z,a.z*b.y), msub(a.z,b.x,a.x*b.z), msub(a.x,b.y,a.y*b.x)); }
210
template<typename T> __forceinline Vec3<T> stable_triangle_normal( const Vec3<T>& a, const Vec3<T>& b, const Vec3<T>& c )
211
{
212
const T ab_x = a.z*b.y, ab_y = a.x*b.z, ab_z = a.y*b.x;
213
const T bc_x = b.z*c.y, bc_y = b.x*c.z, bc_z = b.y*c.x;
214
const Vec3<T> cross_ab(msub(a.y,b.z,ab_x), msub(a.z,b.x,ab_y), msub(a.x,b.y,ab_z));
215
const Vec3<T> cross_bc(msub(b.y,c.z,bc_x), msub(b.z,c.x,bc_y), msub(b.x,c.y,bc_z));
216
const auto sx = abs(ab_x) < abs(bc_x);
217
const auto sy = abs(ab_y) < abs(bc_y);
218
const auto sz = abs(ab_z) < abs(bc_z);
219
return Vec3<T>(select(sx,cross_ab.x,cross_bc.x),
220
select(sy,cross_ab.y,cross_bc.y),
221
select(sz,cross_ab.z,cross_bc.z));
222
}
223
224
template<typename T> __forceinline T sum ( const Vec3<T>& a ) { return a.x+a.y+a.z; }
225
226
template<typename T> __forceinline T halfArea ( const Vec3<T>& d ) { return madd(d.x,(d.y+d.z),d.y*d.z); }
227
template<typename T> __forceinline T area ( const Vec3<T>& d ) { return 2.0f*halfArea(d); }
228
229
template<typename T> __forceinline Vec3<T> normalize_safe( const Vec3<T>& a ) {
230
const T d = dot(a,a); return select(d == T( zero ), a , a*rsqrt(d) );
231
}
232
233
template<typename T> __forceinline T sqr_point_to_line_distance(const Vec3<T>& P, const Vec3<T>& Q0, const Vec3<T>& Q1)
234
{
235
const Vec3<T> N = cross(P-Q0,Q1-Q0);
236
const Vec3<T> D = Q1-Q0;
237
return dot(N,N)*rcp(dot(D,D));
238
}
239
240
template<typename T> __forceinline T sqr_point_to_line_distance(const Vec3<T>& PmQ0, const Vec3<T>& Q1mQ0)
241
{
242
const Vec3<T> N = cross(PmQ0,Q1mQ0);
243
const Vec3<T> D = Q1mQ0;
244
return dot(N,N)*rcp(dot(D,D));
245
}
246
247
////////////////////////////////////////////////////////////////////////////////
248
/// Output Operators
249
////////////////////////////////////////////////////////////////////////////////
250
251
template<typename T> __forceinline embree_ostream operator<<(embree_ostream cout, const Vec3<T>& a) {
252
return cout << "(" << a.x << ", " << a.y << ", " << a.z << ")";
253
}
254
255
typedef Vec3<bool > Vec3b;
256
typedef Vec3<int > Vec3i;
257
typedef Vec3<float> Vec3f;
258
}
259
260
#include "vec3ba.h"
261
#include "vec3ia.h"
262
#include "vec3fa.h"
263
264
////////////////////////////////////////////////////////////////////////////////
265
/// SSE / AVX / MIC specializations
266
////////////////////////////////////////////////////////////////////////////////
267
268
#if defined(__SSE__) || defined(__ARM_NEON)
269
#include "../simd/sse.h"
270
#endif
271
272
#if defined(__AVX__)
273
#include "../simd/avx.h"
274
#endif
275
276
#if defined(__AVX512F__)
277
#include "../simd/avx512.h"
278
#endif
279
280
namespace embree
281
{
282
template<typename Out, typename In>
283
__forceinline Vec3<Out> broadcast(const Vec3<In>& a, const size_t k) {
284
return Vec3<Out>(Out(a.x[k]), Out(a.y[k]), Out(a.z[k]));
285
}
286
287
template<> __forceinline Vec3<float>::Vec3(const Vec3fa& a) { x = a.x; y = a.y; z = a.z; }
288
289
#if !defined(__SYCL_DEVICE_ONLY__)
290
291
#if defined(__AVX__)
292
template<> __forceinline Vec3<vfloat4>::Vec3(const Vec3fa& a) {
293
x = a.x; y = a.y; z = a.z;
294
}
295
#elif defined(__SSE__) || defined(__ARM_NEON)
296
template<>
297
__forceinline Vec3<vfloat4>::Vec3(const Vec3fa& a) {
298
const vfloat4 v = vfloat4(a.m128); x = shuffle<0,0,0,0>(v); y = shuffle<1,1,1,1>(v); z = shuffle<2,2,2,2>(v);
299
}
300
#endif
301
302
#if defined(__SSE__) || defined(__ARM_NEON)
303
template<>
304
__forceinline Vec3<vfloat4> broadcast<vfloat4,vfloat4>(const Vec3<vfloat4>& a, const size_t k) {
305
return Vec3<vfloat4>(vfloat4::broadcast(&a.x[k]), vfloat4::broadcast(&a.y[k]), vfloat4::broadcast(&a.z[k]));
306
}
307
308
template<int i0, int i1, int i2, int i3>
309
__forceinline Vec3<vfloat4> shuffle(const Vec3<vfloat4>& b) {
310
return Vec3<vfloat4>(shuffle<i0,i1,i2,i3>(b.x), shuffle<i0,i1,i2,i3>(b.y), shuffle<i0,i1,i2,i3>(b.z));
311
}
312
#endif
313
314
#if defined(__AVX__)
315
template<>
316
__forceinline Vec3<vfloat8>::Vec3(const Vec3fa& a) {
317
x = a.x; y = a.y; z = a.z;
318
}
319
320
template<>
321
__forceinline Vec3<vfloat8> broadcast<vfloat8,vfloat4>(const Vec3<vfloat4>& a, const size_t k) {
322
return Vec3<vfloat8>(vfloat8::broadcast(&a.x[k]), vfloat8::broadcast(&a.y[k]), vfloat8::broadcast(&a.z[k]));
323
}
324
template<>
325
__forceinline Vec3<vfloat8> broadcast<vfloat8,vfloat8>(const Vec3<vfloat8>& a, const size_t k) {
326
return Vec3<vfloat8>(vfloat8::broadcast(&a.x[k]), vfloat8::broadcast(&a.y[k]), vfloat8::broadcast(&a.z[k]));
327
}
328
329
template<int i0, int i1, int i2, int i3>
330
__forceinline Vec3<vfloat8> shuffle(const Vec3<vfloat8>& b) {
331
return Vec3<vfloat8>(shuffle<i0,i1,i2,i3>(b.x), shuffle<i0,i1,i2,i3>(b.y), shuffle<i0,i1,i2,i3>(b.z));
332
}
333
#endif
334
335
#if defined(__AVX512F__)
336
template<> __forceinline Vec3<vfloat16>::Vec3(const Vec3fa& a) : x(a.x), y(a.y), z(a.z) {}
337
#endif
338
339
#else
340
341
#if defined(__SSE__)
342
template<> __forceinline Vec3<vfloat4>::Vec3(const Vec3fa& a) {
343
x = a.x; y = a.y; z = a.z;
344
}
345
#endif
346
#if defined(__AVX__)
347
template<> __forceinline Vec3<vfloat8>::Vec3(const Vec3fa& a) {
348
x = a.x; y = a.y; z = a.z;
349
}
350
#endif
351
#if defined(__AVX512F__)
352
template<> __forceinline Vec3<vfloat16>::Vec3(const Vec3fa& a) {
353
x = a.x; y = a.y; z = a.z;
354
}
355
#endif
356
#endif
357
}
358
359