Jolt Physics
A multi core friendly Game Physics Engine
Loading...
Searching...
No Matches
Quat.inl
Go to the documentation of this file.
1// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
2// SPDX-FileCopyrightText: 2021 Jorrit Rouwe
3// SPDX-License-Identifier: MIT
4
6
8{
9#ifdef JPH_USE_SSE
10 __m128 abcd = mValue.mValue;
11 __m128 xyzw = inRHS.mValue.mValue;
12
13 // Names based on logical order, opposite of shuffle order.
14 __m128 abca = _mm_shuffle_ps(abcd, abcd, _MM_SHUFFLE(0, 2, 1, 0));
15 __m128 bcab = _mm_shuffle_ps(abcd, abcd, _MM_SHUFFLE(1, 0, 2, 1));
16 __m128 cabc = _mm_shuffle_ps(abcd, abcd, _MM_SHUFFLE(2, 1, 0, 2));
17 __m128 dddd = _mm_shuffle_ps(abcd, abcd, _MM_SHUFFLE(3, 3, 3, 3));
18
19 __m128 wwwx = _mm_shuffle_ps(xyzw, xyzw, _MM_SHUFFLE(0, 3, 3, 3));
20 __m128 zxyy = _mm_shuffle_ps(xyzw, xyzw, _MM_SHUFFLE(1, 1, 0, 2));
21 __m128 yzxz = _mm_shuffle_ps(xyzw, xyzw, _MM_SHUFFLE(2, 0, 2, 1));
22
23 __m128 m2 = _mm_mul_ps(bcab, zxyy);
24#ifdef JPH_USE_FMADD
25 __m128 m3 = _mm_fmadd_ps(abca, wwwx, m2);
26#else
27 __m128 m1 = _mm_mul_ps(abca, wwwx);
28 __m128 m3 = _mm_add_ps(m1, m2);
29#endif
30
31 // Negate last (logical) component.
32 m3 = _mm_xor_ps(_mm_set_ps(-0.0f, 0.0f, 0.0f, 0.0f), m3);
33
34#ifdef JPH_USE_FMADD
35 __m128 m5 = _mm_fnmadd_ps(cabc, yzxz, m3);
36 __m128 m7 = _mm_fmadd_ps(dddd, xyzw, m5);
37#else
38 __m128 m4 = _mm_mul_ps(dddd, xyzw);
39 __m128 m5 = _mm_mul_ps(cabc, yzxz);
40 __m128 m6 = _mm_sub_ps(m4, m5);
41 __m128 m7 = _mm_add_ps(m3, m6);
42#endif
43
44 // [(aw+bz)+(dx-cy),(bw+cx)+(dy-az),(cw+ay)+(dz-bx),-(ax+by)+(dw-cz)]
45 return Quat(Vec4(m7));
46#elif defined(JPH_USE_NEON)
47 float32x4_t abcd = mValue.mValue;
48 float32x4_t xyzw = inRHS.mValue.mValue;
49
50 float32x4_t abca = vcopyq_laneq_f32(abcd, 3, abcd, 0);
51 float32x4_t bcab = JPH_NEON_SHUFFLE_F32x4(abcd, abcd, 1, 2, 0, 1);
52 float32x4_t cabc = JPH_NEON_SHUFFLE_F32x4(abcd, abcd, 2, 0, 1, 2);
53 float32x4_t dddd = vdupq_laneq_f32(abcd, 3);
54
55 float32x4_t wwwx = vcopyq_laneq_f32(vdupq_laneq_f32(xyzw, 3), 3, xyzw, 0);
56 float32x4_t zxyy = JPH_NEON_SHUFFLE_F32x4(xyzw, xyzw, 2, 0, 1, 1);
57 float32x4_t yzxz = JPH_NEON_SHUFFLE_F32x4(xyzw, xyzw, 1, 2, 0, 2);
58
59 float32x4_t m1 = vmulq_f32(abca, wwwx);
60 float32x4_t m2 = vmulq_f32(bcab, zxyy);
61 float32x4_t m3 = vaddq_f32(m1, m2);
62
63 uint32x4_t w_neg_mask = JPH_NEON_UINT32x4(0, 0, 0, 0x80000000u);
64 m3 = vreinterpretq_f32_u32(veorq_u32(vreinterpretq_u32_f32(m3), w_neg_mask));
65
66 float32x4_t m4 = vmulq_f32(dddd, xyzw);
67 float32x4_t m5 = vmulq_f32(cabc, yzxz);
68 float32x4_t m6 = vsubq_f32(m4, m5);
69 float32x4_t m7 = vaddq_f32(m3, m6);
70
71 return Quat(Vec4(m7));
72#else
73 float a = mValue.GetX();
74 float b = mValue.GetY();
75 float c = mValue.GetZ();
76 float d = mValue.GetW();
77
78 float x = inRHS.mValue.GetX();
79 float y = inRHS.mValue.GetY();
80 float z = inRHS.mValue.GetZ();
81 float w = inRHS.mValue.GetW();
82
83 return Quat((a * w + b * z) + (d * x - c * y),
84 (b * w + c * x) + (d * y - a * z),
85 (c * w + a * y) + (d * z - b * x),
86 -(a * x + b * y) + (d * w - c * z));
87#endif
88}
89
91{
92#ifdef JPH_USE_SSE
93 __m128 abc0 = inLHS.mValue;
94 __m128 xyzw = inRHS.mValue.mValue;
95
96 // Names based on logical order, opposite of shuffle order.
97 __m128 abca = _mm_shuffle_ps(abc0, abc0, _MM_SHUFFLE(0, 2, 1, 0));
98 __m128 bcab = _mm_shuffle_ps(abc0, abc0, _MM_SHUFFLE(1, 0, 2, 1));
99 __m128 cabc = _mm_shuffle_ps(abc0, abc0, _MM_SHUFFLE(2, 1, 0, 2));
100
101 __m128 wwwx = _mm_shuffle_ps(xyzw, xyzw, _MM_SHUFFLE(0, 3, 3, 3));
102 __m128 zxyy = _mm_shuffle_ps(xyzw, xyzw, _MM_SHUFFLE(1, 1, 0, 2));
103 __m128 yzxz = _mm_shuffle_ps(xyzw, xyzw, _MM_SHUFFLE(2, 0, 2, 1));
104
105 __m128 m2 = _mm_mul_ps(bcab, zxyy);
106#ifdef JPH_USE_FMADD
107 __m128 m3 = _mm_fmadd_ps(abca, wwwx, m2);
108#else
109 __m128 m1 = _mm_mul_ps(abca, wwwx);
110 __m128 m3 = _mm_add_ps(m1, m2);
111#endif
112
113 // Negate last (logical) component.
114 m3 = _mm_xor_ps(_mm_set_ps(-0.0f, 0.0f, 0.0f, 0.0f), m3);
115
116 __m128 m4 = _mm_mul_ps(cabc, yzxz);
117
118 // [(aw+bz)-cy,(bw+cx)-az,(cw+ay)-bx,-(ax+by)-cz]
119 return Quat(Vec4(_mm_sub_ps(m3, m4)));
120#elif defined(JPH_USE_NEON)
121 float32x4_t abc0 = inLHS.mValue;
122 float32x4_t xyzw = inRHS.mValue.mValue;
123
124 float32x4_t abca = vcopyq_laneq_f32(abc0, 3, abc0, 0);
125 float32x4_t bcab = JPH_NEON_SHUFFLE_F32x4(abc0, abc0, 1, 2, 0, 1);
126 float32x4_t cabc = JPH_NEON_SHUFFLE_F32x4(abc0, abc0, 2, 0, 1, 2);
127
128 float32x4_t wwwx = vcopyq_laneq_f32(vdupq_laneq_f32(xyzw, 3), 3, xyzw, 0);
129 float32x4_t zxyy = JPH_NEON_SHUFFLE_F32x4(xyzw, xyzw, 2, 0, 1, 1);
130 float32x4_t yzxz = JPH_NEON_SHUFFLE_F32x4(xyzw, xyzw, 1, 2, 0, 2);
131
132 float32x4_t m1 = vmulq_f32(abca, wwwx);
133 float32x4_t m2 = vmulq_f32(bcab, zxyy);
134 float32x4_t m3 = vaddq_f32(m1, m2);
135
136 uint32x4_t w_neg_mask = JPH_NEON_UINT32x4(0, 0, 0, 0x80000000u);
137 m3 = vreinterpretq_f32_u32(veorq_u32(vreinterpretq_u32_f32(m3), w_neg_mask));
138
139 float32x4_t m4 = vmulq_f32(cabc, yzxz);
140 float32x4_t m7 = vsubq_f32(m3, m4);
141
142 return Quat(Vec4(m7));
143#else
144 float a = inLHS.GetX();
145 float b = inLHS.GetY();
146 float c = inLHS.GetZ();
147
148 float x = inRHS.mValue.GetX();
149 float y = inRHS.mValue.GetY();
150 float z = inRHS.mValue.GetZ();
151 float w = inRHS.mValue.GetW();
152
153 return Quat((a * w + b * z) - c * y,
154 (b * w + c * x) - a * z,
155 (c * w + a * y) - b * x,
156 -(a * x + b * y) - c * z);
157#endif
158}
159
160Quat Quat::sRotation(Vec3Arg inAxis, float inAngle)
161{
162 // returns [inAxis * sin(0.5f * inAngle), cos(0.5f * inAngle)]
163 JPH_ASSERT(inAxis.IsNormalized());
164 Vec4 s, c;
165 Vec4::sReplicate(0.5f * inAngle).SinCos(s, c);
166 return Quat(Vec4::sSelect(Vec4(inAxis) * s, c, UVec4(0, 0, 0, 0xffffffffU)));
167}
168
169void Quat::GetAxisAngle(Vec3 &outAxis, float &outAngle) const
170{
172 Quat w_pos = EnsureWPositive();
173 float abs_w = w_pos.GetW();
174 if (abs_w >= 1.0f)
175 {
176 outAxis = Vec3::sZero();
177 outAngle = 0.0f;
178 }
179 else
180 {
181 outAngle = 2.0f * ACos(abs_w);
182 outAxis = w_pos.GetXYZ().NormalizedOr(Vec3::sZero());
183 }
184}
185
186Vec3 Quat::GetAngularVelocity(float inDeltaTime) const
187{
189
190 // w = cos(angle / 2), ensure it is positive so that we get an angle in the range [0, PI]
191 Quat w_pos = EnsureWPositive();
192
193 // The imaginary part of the quaternion is axis * sin(angle / 2),
194 // if the length is small use the approximation sin(x) = x to calculate angular velocity
195 Vec3 xyz = w_pos.GetXYZ();
196 float xyz_len_sq = xyz.LengthSq();
197 if (xyz_len_sq < 4.0e-4f) // Max error introduced is sin(0.02) - 0.02 = 7e-5 (when w is near 1 the angle becomes more inaccurate in the code below, so don't make this number too small)
198 return (2.0f / inDeltaTime) * xyz;
199
200 // Otherwise calculate the angle from w = cos(angle / 2) and determine the axis by normalizing the imaginary part
201 // Note that it is also possible to calculate the angle through angle = 2 * atan2(|xyz|, w). This is more accurate but also 2x as expensive.
202 float angle = 2.0f * ACos(w_pos.GetW());
203 return (xyz / (Sqrt(xyz_len_sq) * inDeltaTime)) * angle;
204}
205
207{
208 /*
209 Uses (inFrom = v1, inTo = v2):
210
211 angle = arcos(v1 . v2 / |v1||v2|)
212 axis = normalize(v1 x v2)
213
214 Quaternion is then:
215
216 s = sin(angle / 2)
217 x = axis.x * s
218 y = axis.y * s
219 z = axis.z * s
220 w = cos(angle / 2)
221
222 Using identities:
223
224 sin(2 * a) = 2 * sin(a) * cos(a)
225 cos(2 * a) = cos(a)^2 - sin(a)^2
226 sin(a)^2 + cos(a)^2 = 1
227
228 This reduces to:
229
230 x = (v1 x v2).x
231 y = (v1 x v2).y
232 z = (v1 x v2).z
233 w = |v1||v2| + v1 . v2
234
235 which then needs to be normalized because the whole equation was multiplied by 2 cos(angle / 2)
236 */
237
238 float len_v1_v2 = Sqrt(inFrom.LengthSq() * inTo.LengthSq());
239 float w = len_v1_v2 + inFrom.Dot(inTo);
240
241 if (w == 0.0f)
242 {
243 if (len_v1_v2 == 0.0f)
244 {
245 // If either of the vectors has zero length, there is no rotation and we return identity
246 return Quat::sIdentity();
247 }
248 else
249 {
250 // If vectors are perpendicular, take one of the many 180 degree rotations that exist
251 return Quat(Vec4(inFrom.GetNormalizedPerpendicular(), 0));
252 }
253 }
254
255 Vec3 v = inFrom.Cross(inTo);
256 return Quat(Vec4(v, w)).Normalized();
257}
258
259template <class Random>
260Quat Quat::sRandom(Random &inRandom)
261{
262 std::uniform_real_distribution<float> zero_to_one(0.0f, 1.0f);
263 float x0 = zero_to_one(inRandom);
264 float r1 = Sqrt(1.0f - x0), r2 = Sqrt(x0);
265 std::uniform_real_distribution<float> zero_to_two_pi(0.0f, 2.0f * JPH_PI);
266 Vec4 s, c;
267 Vec4(zero_to_two_pi(inRandom), zero_to_two_pi(inRandom), 0, 0).SinCos(s, c);
268 return Quat(s.GetX() * r1, c.GetX() * r1, s.GetY() * r2, c.GetY() * r2);
269}
270
272{
273 Vec4 half(0.5f * inAngles);
274 Vec4 s, c;
275 half.SinCos(s, c);
276
277 float cx = c.GetX();
278 float sx = s.GetX();
279 float cy = c.GetY();
280 float sy = s.GetY();
281 float cz = c.GetZ();
282 float sz = s.GetZ();
283
284 return Quat(
285 cz * sx * cy - sz * cx * sy,
286 cz * cx * sy + sz * sx * cy,
287 sz * cx * cy - cz * sx * sy,
288 cz * cx * cy + sz * sx * sy);
289}
290
292{
293 float y_sq = GetY() * GetY();
294
295 // X
296 float t0 = 2.0f * (GetW() * GetX() + GetY() * GetZ());
297 float t1 = 1.0f - 2.0f * (GetX() * GetX() + y_sq);
298
299 // Y
300 float t2 = 2.0f * (GetW() * GetY() - GetZ() * GetX());
301 t2 = t2 > 1.0f? 1.0f : t2;
302 t2 = t2 < -1.0f? -1.0f : t2;
303
304 // Z
305 float t3 = 2.0f * (GetW() * GetZ() + GetX() * GetY());
306 float t4 = 1.0f - 2.0f * (y_sq + GetZ() * GetZ());
307
308 return Vec3(ATan2(t0, t1), ASin(t2), ATan2(t3, t4));
309}
310
312{
313 Quat twist(Vec4(GetXYZ().Dot(inAxis) * inAxis, GetW()));
314 float twist_len = twist.LengthSq();
315 if (twist_len != 0.0f)
316 return twist / Sqrt(twist_len);
317 else
318 return Quat::sIdentity();
319}
320
321void Quat::GetSwingTwist(Quat &outSwing, Quat &outTwist) const
322{
323 float x = GetX(), y = GetY(), z = GetZ(), w = GetW();
324 float s = Sqrt(Square(w) + Square(x));
325 if (s != 0.0f)
326 {
327 outTwist = Quat(x / s, 0, 0, w / s);
328 outSwing = Quat(0, (w * y - x * z) / s, (w * z + x * y) / s, s);
329 }
330 else
331 {
332 // If both x and w are zero, this must be a 180 degree rotation around either y or z
333 outTwist = Quat::sIdentity();
334 outSwing = *this;
335 }
336}
337
338Quat Quat::LERP(QuatArg inDestination, float inFraction) const
339{
340 float scale0 = 1.0f - inFraction;
341 return Quat(Vec4::sReplicate(scale0) * mValue + Vec4::sReplicate(inFraction) * inDestination.mValue);
342}
343
344Quat Quat::SLERP(QuatArg inDestination, float inFraction) const
345{
346 // Difference at which to LERP instead of SLERP
347 const float delta = 0.0001f;
348
349 // Calc cosine
350 float sign_scale1 = 1.0f;
351 float cos_omega = Dot(inDestination);
352
353 // Adjust signs (if necessary)
354 if (cos_omega < 0.0f)
355 {
356 cos_omega = -cos_omega;
357 sign_scale1 = -1.0f;
358 }
359
360 // Calculate coefficients
361 float scale0, scale1;
362 if (1.0f - cos_omega > delta)
363 {
364 // Standard case (slerp)
365 float omega = ACos(cos_omega);
366 float sin_omega = Sin(omega);
367 scale0 = Sin((1.0f - inFraction) * omega) / sin_omega;
368 scale1 = sign_scale1 * Sin(inFraction * omega) / sin_omega;
369 }
370 else
371 {
372 // Quaternions are very close so we can do a linear interpolation
373 scale0 = 1.0f - inFraction;
374 scale1 = sign_scale1 * inFraction;
375 }
376
377 // Interpolate between the two quaternions
378 return Quat(Vec4::sReplicate(scale0) * mValue + Vec4::sReplicate(scale1) * inDestination.mValue).Normalized();
379}
380
382{
383 // Rotating a vector by a quaternion is done by: p' = q * (p, 0) * q^-1 (q^-1 = conjugated(q) for a unit quaternion)
384 // Using Rodrigues formula: https://en.m.wikipedia.org/wiki/Euler%E2%80%93Rodrigues_formula
385 // This is equivalent to: p' = p + 2 * (q.w * q.xyz x p + q.xyz x (q.xyz x p))
386 //
387 // This is:
388 //
389 // Vec3 xyz = GetXYZ();
390 // Vec3 q_cross_p = xyz.Cross(inValue);
391 // Vec3 q_cross_q_cross_p = xyz.Cross(q_cross_p);
392 // Vec3 v = mValue.SplatW3() * q_cross_p + q_cross_q_cross_p;
393 // return inValue + (v + v);
394 //
395 // But we can write out the cross products in a more efficient way:
397 Vec3 xyz = GetXYZ();
399 Vec3 q_cross_p = (inValue.Swizzle<SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_X>() * xyz - yzx * inValue).Swizzle<SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_X>();
400 Vec3 q_cross_q_cross_p = (q_cross_p.Swizzle<SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_X>() * xyz - yzx * q_cross_p).Swizzle<SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_X>();
401 Vec3 v = mValue.SplatW3() * q_cross_p + q_cross_q_cross_p;
402 return inValue + (v + v);
403}
404
406{
408 Vec3 xyz = GetXYZ(); // Needs to be negated, but we do this in the equations below
410 Vec3 q_cross_p = (yzx * inValue - inValue.Swizzle<SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_X>() * xyz).Swizzle<SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_X>();
411 Vec3 q_cross_q_cross_p = (yzx * q_cross_p - q_cross_p.Swizzle<SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_X>() * xyz).Swizzle<SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_X>();
412 Vec3 v = mValue.SplatW3() * q_cross_p + q_cross_q_cross_p;
413 return inValue + (v + v);
414}
415
417{
418 // This is *this * Vec3::sAxisX() written out:
420 Vec4 t = mValue + mValue;
421 return Vec3(t.SplatX() * mValue + (t.SplatW() * mValue.Swizzle<SWIZZLE_W, SWIZZLE_Z, SWIZZLE_Y, SWIZZLE_X>()).FlipSign<1, 1, -1, 1>() - Vec4(1, 0, 0, 0));
422}
423
425{
426 // This is *this * Vec3::sAxisY() written out:
428 Vec4 t = mValue + mValue;
429 return Vec3(t.SplatY() * mValue + (t.SplatW() * mValue.Swizzle<SWIZZLE_Z, SWIZZLE_W, SWIZZLE_X, SWIZZLE_Y>()).FlipSign<-1, 1, 1, 1>() - Vec4(0, 1, 0, 0));
430}
431
433{
434 // This is *this * Vec3::sAxisZ() written out:
436 Vec4 t = mValue + mValue;
437 return Vec3(t.SplatZ() * mValue + (t.SplatW() * mValue.Swizzle<SWIZZLE_Y, SWIZZLE_X, SWIZZLE_W, SWIZZLE_Z>()).FlipSign<1, -1, 1, 1>() - Vec4(0, 0, 1, 0));
438}
439
440void Quat::StoreFloat3(Float3 *outV) const
441{
444}
445
446void Quat::StoreFloat4(Float4 *outV) const
447{
448 mValue.StoreFloat4(outV);
449}
450
452{
454 float w = Sqrt(max(1.0f - v.LengthSq(), 0.0f)); // It is possible that the length of v is a fraction above 1, and we don't want to introduce NaN's in that case so we clamp to 0
455 return Quat(Vec4(v, w));
456}
457
#define JPH_NAMESPACE_END
Definition Core.h:428
#define JPH_NAMESPACE_BEGIN
Definition Core.h:422
#define xyz
Definition HLSLToCPP.h:513
#define yzx
Definition HLSLToCPP.h:516
#define JPH_ASSERT(...)
Definition IssueReporting.h:33
JPH_INLINE constexpr T Square(T inV)
Square a value.
Definition Math.h:55
JPH_INLINE float Sqrt(float inV)
Take the square root of a float value.
Definition Math.h:61
@ SWIZZLE_Z
Use the Z component.
Definition Swizzle.h:14
@ SWIZZLE_W
Use the W component.
Definition Swizzle.h:15
@ SWIZZLE_X
Use the X component.
Definition Swizzle.h:12
@ SWIZZLE_Y
Use the Y component.
Definition Swizzle.h:13
JPH_INLINE float ACos(float inX)
Definition Trigonometry.h:42
JPH_INLINE float ATan2(float inY, float inX)
Arc tangent of y / x using the signs of the arguments to determine the correct quadrant (returns valu...
Definition Trigonometry.h:74
JPH_NAMESPACE_BEGIN JPH_INLINE float Sin(float inX)
Sine of x (input in radians)
Definition Trigonometry.h:12
JPH_INLINE float ASin(float inX)
Definition Trigonometry.h:35
Class that holds 3 floats. Used as a storage class. Convert to Vec3 for calculations.
Definition Float3.h:13
Class that holds 4 float values. Convert to Vec4 to perform calculations.
Definition Float4.h:11
Definition Quat.h:33
static Quat sRandom(Random &inRandom)
Random unit quaternion.
Definition Quat.inl:260
JPH_INLINE Vec3 InverseRotate(Vec3Arg inValue) const
Rotate a vector by the inverse of this quaternion.
Definition Quat.inl:405
JPH_INLINE float GetW() const
Get W component (real part)
Definition Quat.h:79
static JPH_INLINE Quat sMultiplyImaginary(Vec3Arg inLHS, QuatArg inRHS)
Multiply a quaternion with imaginary components and no real component (x, y, z, 0) with a quaternion.
Definition Quat.inl:90
static Quat sEulerAngles(Vec3Arg inAngles)
Conversion from Euler angles. Rotation order is X then Y then Z (RotZ * RotY * RotX)....
Definition Quat.inl:271
JPH_INLINE float GetY() const
Get Y component (imaginary part j)
Definition Quat.h:73
JPH_INLINE float GetZ() const
Get Z component (imaginary part k)
Definition Quat.h:76
static JPH_INLINE Quat sRotation(Vec3Arg inAxis, float inAngle)
Rotation from axis and angle.
Definition Quat.inl:160
JPH_INLINE float GetX() const
Get X component (imaginary part i)
Definition Quat.h:70
JPH_INLINE Vec3 GetAngularVelocity(float inDeltaTime) const
Calculate angular velocity given that this quaternion represents the rotation that is reached after i...
Definition Quat.inl:186
JPH_INLINE Quat LERP(QuatArg inDestination, float inFraction) const
Definition Quat.inl:338
static JPH_INLINE Quat sLoadFloat3Unsafe(const Float3 &inV)
Load 3 floats from memory (X, Y and Z component and then calculates W) reads 32 bits extra which it d...
Definition Quat.inl:451
JPH_INLINE float LengthSq() const
Definition Quat.h:136
JPH_INLINE void GetAxisAngle(Vec3 &outAxis, float &outAngle) const
Get axis and angle that represents this quaternion, outAngle will always be in the range .
Definition Quat.inl:169
static JPH_INLINE Quat sIdentity()
Definition Quat.h:104
JPH_INLINE void GetSwingTwist(Quat &outSwing, Quat &outTwist) const
Definition Quat.inl:321
JPH_INLINE void StoreFloat4(Float4 *outV) const
Store as 4 floats.
Definition Quat.inl:446
static JPH_INLINE Quat sFromTo(Vec3Arg inFrom, Vec3Arg inTo)
Definition Quat.inl:206
friend Quat operator*(float inValue, QuatArg inRHS)
Definition Quat.h:158
JPH_INLINE Quat EnsureWPositive() const
Ensures that the W component is positive by negating the entire quaternion if it is not....
Definition Quat.h:191
JPH_INLINE Quat GetTwist(Vec3Arg inAxis) const
Definition Quat.inl:311
JPH_INLINE float Dot(QuatArg inRHS) const
Dot product.
Definition Quat.h:182
Quat()=default
Intentionally not initialized for performance reasons.
JPH_INLINE Vec3 RotateAxisZ() const
Rotate a the vector (0, 0, 1) with this quaternion.
Definition Quat.inl:432
JPH_INLINE Vec3 RotateAxisX() const
Rotate a the vector (1, 0, 0) with this quaternion.
Definition Quat.inl:416
JPH_INLINE Vec3 RotateAxisY() const
Rotate a the vector (0, 1, 0) with this quaternion.
Definition Quat.inl:424
Vec3 GetEulerAngles() const
Conversion to Euler angles. Rotation order is X then Y then Z (RotZ * RotY * RotX)....
Definition Quat.inl:291
bool IsNormalized(float inTolerance=1.0e-5f) const
If the length of this quaternion is 1 +/- inTolerance.
Definition Quat.h:60
JPH_INLINE void StoreFloat3(Float3 *outV) const
Store as 3 floats to memory (X, Y and Z component). Ensures that W is positive before storing.
Definition Quat.inl:440
JPH_INLINE Vec3 GetXYZ() const
Get the imaginary part of the quaternion.
Definition Quat.h:82
Vec4 mValue
4 vector that stores [x, y, z, w] parts of the quaternion
Definition Quat.h:264
JPH_INLINE Quat SLERP(QuatArg inDestination, float inFraction) const
Definition Quat.inl:344
Definition UVec4.h:12
Definition Vec3.h:17
JPH_INLINE float Dot(Vec3Arg inV2) const
Dot product.
Definition Vec3.inl:943
JPH_INLINE Vec3 Normalized() const
Normalize vector.
Definition Vec3.inl:1044
JPH_INLINE Vec3 Cross(Vec3Arg inV2) const
Cross product.
Definition Vec3.inl:841
JPH_INLINE Vec3 GetNormalizedPerpendicular() const
Get normalized vector that is perpendicular to this vector.
Definition Vec3.inl:1218
JPH_INLINE float GetX() const
Get individual components.
Definition Vec3.h:127
JPH_INLINE bool IsNormalized(float inTolerance=1.0e-6f) const
Test if vector is normalized.
Definition Vec3.inl:1129
JPH_INLINE Vec3 NormalizedOr(Vec3Arg inZeroValue) const
Normalize vector or return inZeroValue if the length of the vector is zero.
Definition Vec3.inl:1076
Type mValue
Definition Vec3.h:299
JPH_INLINE float GetY() const
Definition Vec3.h:128
JPH_INLINE void StoreFloat3(Float3 *outV) const
Store 3 floats to memory.
Definition Vec3.inl:1154
JPH_INLINE float LengthSq() const
Squared length of vector.
Definition Vec3.inl:972
static JPH_INLINE Vec3 sZero()
Vector with all zeros.
Definition Vec3.inl:125
static JPH_INLINE Vec3 sLoadFloat3Unsafe(const Float3 &inV)
Load 3 floats from memory (reads 32 bits extra which it doesn't use)
Definition Vec3.inl:167
JPH_INLINE float GetZ() const
Definition Vec3.h:129
JPH_INLINE Vec3 Swizzle() const
Swizzle the elements in inV.
Definition Vec4.h:14
JPH_INLINE Vec4 SplatX() const
Replicate the X component to all components.
Definition Vec4.inl:808
JPH_INLINE Vec3 SplatW3() const
Replicate the W component to all components.
Definition Vec4.inl:920
JPH_INLINE Vec4 FlipSign() const
Flips the signs of the components, e.g. FlipSign<-1, 1, -1, 1>() will flip the signs of the X and Z c...
Definition Vec4.inl:1104
JPH_INLINE float GetW() const
Definition Vec4.h:122
JPH_INLINE Vec4 SplatY() const
Replicate the Y component to all components.
Definition Vec4.inl:824
JPH_INLINE Vec4 SplatZ() const
Replicate the Z component to all components.
Definition Vec4.inl:840
JPH_INLINE Vec4 SplatW() const
Replicate the W component to all components.
Definition Vec4.inl:856
JPH_INLINE float GetX() const
Get individual components.
Definition Vec4.h:119
JPH_INLINE Vec4 Swizzle() const
Swizzle the elements in inV.
Type mValue
Definition Vec4.h:314
JPH_INLINE float GetZ() const
Definition Vec4.h:121
static JPH_INLINE Vec4 sSelect(Vec4Arg inNotSet, Vec4Arg inSet, UVec4Arg inControl)
Component wise select, returns inNotSet when highest bit of inControl = 0 and inSet when highest bit ...
Definition Vec4.inl:377
JPH_INLINE float GetY() const
Definition Vec4.h:120
static JPH_INLINE Vec4 sReplicate(float inV)
Replicate inV across all components.
Definition Vec4.inl:97
void SinCos(Vec4 &outSin, Vec4 &outCos) const
Calculate the sine and cosine for each element of this vector (input in radians)
Definition Vec4.inl:1221
JPH_INLINE void StoreFloat4(Float4 *outV) const
Store 4 floats to memory.
Definition Vec4.inl:1138