Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/thirdparty/embree/common/math/quaternion.h
9912 views
1
// Copyright 2009-2021 Intel Corporation
2
// SPDX-License-Identifier: Apache-2.0
3
4
#pragma once
5
6
#include "vec3.h"
7
#include "vec4.h"
8
9
#include "transcendental.h"
10
11
namespace embree
12
{
13
////////////////////////////////////////////////////////////////
14
// Quaternion Struct
15
////////////////////////////////////////////////////////////////
16
17
template<typename T>
18
struct QuaternionT
19
{
20
typedef Vec3<T> Vector;
21
22
////////////////////////////////////////////////////////////////////////////////
23
/// Construction
24
////////////////////////////////////////////////////////////////////////////////
25
26
__forceinline QuaternionT () { }
27
__forceinline QuaternionT ( const QuaternionT& other ) { r = other.r; i = other.i; j = other.j; k = other.k; }
28
__forceinline QuaternionT& operator=( const QuaternionT& other ) { r = other.r; i = other.i; j = other.j; k = other.k; return *this; }
29
30
__forceinline QuaternionT( const T& r ) : r(r), i(zero), j(zero), k(zero) {}
31
__forceinline explicit QuaternionT( const Vec3<T>& v ) : r(zero), i(v.x), j(v.y), k(v.z) {}
32
__forceinline explicit QuaternionT( const Vec4<T>& v ) : r(v.x), i(v.y), j(v.z), k(v.w) {}
33
__forceinline QuaternionT( const T& r, const T& i, const T& j, const T& k ) : r(r), i(i), j(j), k(k) {}
34
__forceinline QuaternionT( const T& r, const Vec3<T>& v ) : r(r), i(v.x), j(v.y), k(v.z) {}
35
36
__inline QuaternionT( const Vec3<T>& vx, const Vec3<T>& vy, const Vec3<T>& vz );
37
__inline QuaternionT( const T& yaw, const T& pitch, const T& roll );
38
39
////////////////////////////////////////////////////////////////////////////////
40
/// Constants
41
////////////////////////////////////////////////////////////////////////////////
42
43
__forceinline QuaternionT( ZeroTy ) : r(zero), i(zero), j(zero), k(zero) {}
44
__forceinline QuaternionT( OneTy ) : r( one), i(zero), j(zero), k(zero) {}
45
46
/*! return quaternion for rotation around arbitrary axis */
47
static __forceinline QuaternionT rotate(const Vec3<T>& u, const T& r) {
48
return QuaternionT<T>(cos(T(0.5)*r),sin(T(0.5)*r)*normalize(u));
49
}
50
51
/*! returns the rotation axis of the quaternion as a vector */
52
__forceinline Vec3<T> v( ) const { return Vec3<T>(i, j, k); }
53
54
public:
55
T r, i, j, k;
56
};
57
58
template<typename T> __forceinline QuaternionT<T> operator *( const T & a, const QuaternionT<T>& b ) { return QuaternionT<T>(a * b.r, a * b.i, a * b.j, a * b.k); }
59
template<typename T> __forceinline QuaternionT<T> operator *( const QuaternionT<T>& a, const T & b ) { return QuaternionT<T>(a.r * b, a.i * b, a.j * b, a.k * b); }
60
61
////////////////////////////////////////////////////////////////
62
// Unary Operators
63
////////////////////////////////////////////////////////////////
64
65
template<typename T> __forceinline QuaternionT<T> operator +( const QuaternionT<T>& a ) { return QuaternionT<T>(+a.r, +a.i, +a.j, +a.k); }
66
template<typename T> __forceinline QuaternionT<T> operator -( const QuaternionT<T>& a ) { return QuaternionT<T>(-a.r, -a.i, -a.j, -a.k); }
67
template<typename T> __forceinline QuaternionT<T> conj ( const QuaternionT<T>& a ) { return QuaternionT<T>(a.r, -a.i, -a.j, -a.k); }
68
template<typename T> __forceinline T abs ( const QuaternionT<T>& a ) { return sqrt(a.r*a.r + a.i*a.i + a.j*a.j + a.k*a.k); }
69
template<typename T> __forceinline QuaternionT<T> rcp ( const QuaternionT<T>& a ) { return conj(a)*rcp(a.r*a.r + a.i*a.i + a.j*a.j + a.k*a.k); }
70
template<typename T> __forceinline QuaternionT<T> normalize ( const QuaternionT<T>& a ) { return a*rsqrt(a.r*a.r + a.i*a.i + a.j*a.j + a.k*a.k); }
71
72
// evaluates a*q-r
73
template<typename T> __forceinline QuaternionT<T>
74
msub(const T& a, const QuaternionT<T>& q, const QuaternionT<T>& p)
75
{
76
return QuaternionT<T>(msub(a, q.r, p.r),
77
msub(a, q.i, p.i),
78
msub(a, q.j, p.j),
79
msub(a, q.k, p.k));
80
}
81
// evaluates a*q-r
82
template<typename T> __forceinline QuaternionT<T>
83
madd (const T& a, const QuaternionT<T>& q, const QuaternionT<T>& p)
84
{
85
return QuaternionT<T>(madd(a, q.r, p.r),
86
madd(a, q.i, p.i),
87
madd(a, q.j, p.j),
88
madd(a, q.k, p.k));
89
}
90
91
////////////////////////////////////////////////////////////////
92
// Binary Operators
93
////////////////////////////////////////////////////////////////
94
95
template<typename T> __forceinline QuaternionT<T> operator +( const T & a, const QuaternionT<T>& b ) { return QuaternionT<T>(a + b.r, b.i, b.j, b.k); }
96
template<typename T> __forceinline QuaternionT<T> operator +( const QuaternionT<T>& a, const T & b ) { return QuaternionT<T>(a.r + b, a.i, a.j, a.k); }
97
template<typename T> __forceinline QuaternionT<T> operator +( const QuaternionT<T>& a, const QuaternionT<T>& b ) { return QuaternionT<T>(a.r + b.r, a.i + b.i, a.j + b.j, a.k + b.k); }
98
template<typename T> __forceinline QuaternionT<T> operator -( const T & a, const QuaternionT<T>& b ) { return QuaternionT<T>(a - b.r, -b.i, -b.j, -b.k); }
99
template<typename T> __forceinline QuaternionT<T> operator -( const QuaternionT<T>& a, const T & b ) { return QuaternionT<T>(a.r - b, a.i, a.j, a.k); }
100
template<typename T> __forceinline QuaternionT<T> operator -( const QuaternionT<T>& a, const QuaternionT<T>& b ) { return QuaternionT<T>(a.r - b.r, a.i - b.i, a.j - b.j, a.k - b.k); }
101
102
template<typename T> __forceinline Vec3<T> operator *( const QuaternionT<T>& a, const Vec3<T> & b ) { return (a*QuaternionT<T>(b)*conj(a)).v(); }
103
template<typename T> __forceinline QuaternionT<T> operator *( const QuaternionT<T>& a, const QuaternionT<T>& b ) {
104
return QuaternionT<T>(a.r*b.r - a.i*b.i - a.j*b.j - a.k*b.k,
105
a.r*b.i + a.i*b.r + a.j*b.k - a.k*b.j,
106
a.r*b.j - a.i*b.k + a.j*b.r + a.k*b.i,
107
a.r*b.k + a.i*b.j - a.j*b.i + a.k*b.r);
108
}
109
template<typename T> __forceinline QuaternionT<T> operator /( const T & a, const QuaternionT<T>& b ) { return a*rcp(b); }
110
template<typename T> __forceinline QuaternionT<T> operator /( const QuaternionT<T>& a, const T & b ) { return a*rcp(b); }
111
template<typename T> __forceinline QuaternionT<T> operator /( const QuaternionT<T>& a, const QuaternionT<T>& b ) { return a*rcp(b); }
112
113
template<typename T> __forceinline QuaternionT<T>& operator +=( QuaternionT<T>& a, const T & b ) { return a = a+b; }
114
template<typename T> __forceinline QuaternionT<T>& operator +=( QuaternionT<T>& a, const QuaternionT<T>& b ) { return a = a+b; }
115
template<typename T> __forceinline QuaternionT<T>& operator -=( QuaternionT<T>& a, const T & b ) { return a = a-b; }
116
template<typename T> __forceinline QuaternionT<T>& operator -=( QuaternionT<T>& a, const QuaternionT<T>& b ) { return a = a-b; }
117
template<typename T> __forceinline QuaternionT<T>& operator *=( QuaternionT<T>& a, const T & b ) { return a = a*b; }
118
template<typename T> __forceinline QuaternionT<T>& operator *=( QuaternionT<T>& a, const QuaternionT<T>& b ) { return a = a*b; }
119
template<typename T> __forceinline QuaternionT<T>& operator /=( QuaternionT<T>& a, const T & b ) { return a = a*rcp(b); }
120
template<typename T> __forceinline QuaternionT<T>& operator /=( QuaternionT<T>& a, const QuaternionT<T>& b ) { return a = a*rcp(b); }
121
122
template<typename T, typename M> __forceinline QuaternionT<T>
123
select(const M& m, const QuaternionT<T>& q, const QuaternionT<T>& p)
124
{
125
return QuaternionT<T>(select(m, q.r, p.r),
126
select(m, q.i, p.i),
127
select(m, q.j, p.j),
128
select(m, q.k, p.k));
129
}
130
131
132
template<typename T> __forceinline Vec3<T> xfmPoint ( const QuaternionT<T>& a, const Vec3<T>& b ) { return (a*QuaternionT<T>(b)*conj(a)).v(); }
133
template<typename T> __forceinline Vec3<T> xfmVector( const QuaternionT<T>& a, const Vec3<T>& b ) { return (a*QuaternionT<T>(b)*conj(a)).v(); }
134
template<typename T> __forceinline Vec3<T> xfmNormal( const QuaternionT<T>& a, const Vec3<T>& b ) { return (a*QuaternionT<T>(b)*conj(a)).v(); }
135
136
template<typename T> __forceinline T dot(const QuaternionT<T>& a, const QuaternionT<T>& b) { return a.r*b.r + a.i*b.i + a.j*b.j + a.k*b.k; }
137
138
////////////////////////////////////////////////////////////////////////////////
139
/// Comparison Operators
140
////////////////////////////////////////////////////////////////////////////////
141
142
template<typename T> __forceinline bool operator ==( const QuaternionT<T>& a, const QuaternionT<T>& b ) { return a.r == b.r && a.i == b.i && a.j == b.j && a.k == b.k; }
143
template<typename T> __forceinline bool operator !=( const QuaternionT<T>& a, const QuaternionT<T>& b ) { return a.r != b.r || a.i != b.i || a.j != b.j || a.k != b.k; }
144
145
146
////////////////////////////////////////////////////////////////////////////////
147
/// Orientation Functions
148
////////////////////////////////////////////////////////////////////////////////
149
150
template<typename T> QuaternionT<T>::QuaternionT( const Vec3<T>& vx, const Vec3<T>& vy, const Vec3<T>& vz )
151
{
152
if ( vx.x + vy.y + vz.z >= T(zero) )
153
{
154
const T t = T(one) + (vx.x + vy.y + vz.z);
155
const T s = rsqrt(t)*T(0.5f);
156
r = t*s;
157
i = (vy.z - vz.y)*s;
158
j = (vz.x - vx.z)*s;
159
k = (vx.y - vy.x)*s;
160
}
161
else if ( vx.x >= max(vy.y, vz.z) )
162
{
163
const T t = (T(one) + vx.x) - (vy.y + vz.z);
164
const T s = rsqrt(t)*T(0.5f);
165
r = (vy.z - vz.y)*s;
166
i = t*s;
167
j = (vx.y + vy.x)*s;
168
k = (vz.x + vx.z)*s;
169
}
170
else if ( vy.y >= vz.z ) // if ( vy.y >= max(vz.z, vx.x) )
171
{
172
const T t = (T(one) + vy.y) - (vz.z + vx.x);
173
const T s = rsqrt(t)*T(0.5f);
174
r = (vz.x - vx.z)*s;
175
i = (vx.y + vy.x)*s;
176
j = t*s;
177
k = (vy.z + vz.y)*s;
178
}
179
else //if ( vz.z >= max(vy.y, vx.x) )
180
{
181
const T t = (T(one) + vz.z) - (vx.x + vy.y);
182
const T s = rsqrt(t)*T(0.5f);
183
r = (vx.y - vy.x)*s;
184
i = (vz.x + vx.z)*s;
185
j = (vy.z + vz.y)*s;
186
k = t*s;
187
}
188
}
189
190
template<typename T> QuaternionT<T>::QuaternionT( const T& yaw, const T& pitch, const T& roll )
191
{
192
const T cya = cos(yaw *T(0.5f));
193
const T cpi = cos(pitch*T(0.5f));
194
const T cro = cos(roll *T(0.5f));
195
const T sya = sin(yaw *T(0.5f));
196
const T spi = sin(pitch*T(0.5f));
197
const T sro = sin(roll *T(0.5f));
198
r = cro*cya*cpi + sro*sya*spi;
199
i = cro*cya*spi + sro*sya*cpi;
200
j = cro*sya*cpi - sro*cya*spi;
201
k = sro*cya*cpi - cro*sya*spi;
202
}
203
204
//////////////////////////////////////////////////////////////////////////////
205
/// Output Operators
206
//////////////////////////////////////////////////////////////////////////////
207
208
template<typename T> static embree_ostream operator<<(embree_ostream cout, const QuaternionT<T>& q) {
209
return cout << "{ r = " << q.r << ", i = " << q.i << ", j = " << q.j << ", k = " << q.k << " }";
210
}
211
212
/*! default template instantiations */
213
typedef QuaternionT<float> Quaternion3f;
214
typedef QuaternionT<double> Quaternion3d;
215
216
template<int N> using Quaternion3vf = QuaternionT<vfloat<N>>;
217
typedef QuaternionT<vfloat<4>> Quaternion3vf4;
218
typedef QuaternionT<vfloat<8>> Quaternion3vf8;
219
typedef QuaternionT<vfloat<16>> Quaternion3vf16;
220
221
//////////////////////////////////////////////////////////////////////////////
222
/// Interpolation
223
//////////////////////////////////////////////////////////////////////////////
224
template<typename T>
225
__forceinline QuaternionT<T>lerp(const QuaternionT<T>& q0,
226
const QuaternionT<T>& q1,
227
const T& factor)
228
{
229
QuaternionT<T> q;
230
q.r = lerp(q0.r, q1.r, factor);
231
q.i = lerp(q0.i, q1.i, factor);
232
q.j = lerp(q0.j, q1.j, factor);
233
q.k = lerp(q0.k, q1.k, factor);
234
return q;
235
}
236
237
template<typename T>
238
__forceinline QuaternionT<T> slerp(const QuaternionT<T>& q0,
239
const QuaternionT<T>& q1_,
240
const T& t)
241
{
242
T cosTheta = dot(q0, q1_);
243
QuaternionT<T> q1 = select(cosTheta < 0.f, -q1_, q1_);
244
cosTheta = select(cosTheta < 0.f, -cosTheta, cosTheta);
245
246
// spherical linear interpolation
247
const T phi = t * fastapprox::acos(cosTheta);
248
T sinPhi, cosPhi;
249
fastapprox::sincos(phi, sinPhi, cosPhi);
250
QuaternionT<T> qperp = sinPhi * normalize(msub(cosTheta, q0, q1));
251
QuaternionT<T> qslerp = msub(cosPhi, q0, qperp);
252
253
// regular linear interpolation as fallback
254
QuaternionT<T> qlerp = normalize(lerp(q0, q1, t));
255
256
return select(cosTheta > 0.9995f, qlerp, qslerp);
257
}
258
}
259
260