RavEngine
Loading...
Searching...
No Matches
soa_quaternion.h
1//----------------------------------------------------------------------------//
2// //
3// ozz-animation is hosted at http://github.com/guillaumeblanc/ozz-animation //
4// and distributed under the MIT License (MIT). //
5// //
6// Copyright (c) Guillaume Blanc //
7// //
8// Permission is hereby granted, free of charge, to any person obtaining a //
9// copy of this software and associated documentation files (the "Software"), //
10// to deal in the Software without restriction, including without limitation //
11// the rights to use, copy, modify, merge, publish, distribute, sublicense, //
12// and/or sell copies of the Software, and to permit persons to whom the //
13// Software is furnished to do so, subject to the following conditions: //
14// //
15// The above copyright notice and this permission notice shall be included in //
16// all copies or substantial portions of the Software. //
17// //
18// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR //
19// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, //
20// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL //
21// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER //
22// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING //
23// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER //
24// DEALINGS IN THE SOFTWARE. //
25// //
26//----------------------------------------------------------------------------//
27
28#ifndef OZZ_OZZ_BASE_MATHS_SOA_QUATERNION_H_
29#define OZZ_OZZ_BASE_MATHS_SOA_QUATERNION_H_
30
31#include <cassert>
32
33#include "ozz/base/maths/soa_float.h"
34#include "ozz/base/platform.h"
35
36namespace ozz {
37namespace math {
38
40 SimdFloat4 x, y, z, w;
41
42 // Loads a quaternion from 4 SimdFloat4 values.
43 static OZZ_INLINE SoaQuaternion Load(_SimdFloat4 _x, _SimdFloat4 _y,
44 _SimdFloat4 _z, const SimdFloat4& _w) {
45 const SoaQuaternion r = {_x, _y, _z, _w};
46 return r;
47 }
48
49 // Returns the identity SoaQuaternion.
50 static OZZ_INLINE SoaQuaternion identity() {
51 const SimdFloat4 zero = simd_float4::zero();
52 const SoaQuaternion r = {zero, zero, zero, simd_float4::one()};
53 return r;
54 }
55};
56
57// Returns the conjugate of _q. This is the same as the inverse if _q is
58// normalized. Otherwise the magnitude of the inverse is 1.f/|_q|.
59OZZ_INLINE SoaQuaternion Conjugate(const SoaQuaternion& _q) {
60 const SoaQuaternion r = {-_q.x, -_q.y, -_q.z, _q.w};
61 return r;
62}
63
64// Returns the negate of _q. This represent the same rotation as q.
65OZZ_INLINE SoaQuaternion operator-(const SoaQuaternion& _q) {
66 const SoaQuaternion r = {-_q.x, -_q.y, -_q.z, -_q.w};
67 return r;
68}
69
70// Returns the 4D dot product of quaternion _a and _b.
71OZZ_INLINE SimdFloat4 Dot(const SoaQuaternion& _a, const SoaQuaternion& _b) {
72 return _a.x * _b.x + _a.y * _b.y + _a.z * _b.z + _a.w * _b.w;
73}
74
75// Returns the normalized SoaQuaternion _q.
76OZZ_INLINE SoaQuaternion Normalize(const SoaQuaternion& _q) {
77 const SimdFloat4 len2 = _q.x * _q.x + _q.y * _q.y + _q.z * _q.z + _q.w * _q.w;
78 const SimdFloat4 inv_len = math::simd_float4::one() / Sqrt(len2);
79 const SoaQuaternion r = {_q.x * inv_len, _q.y * inv_len, _q.z * inv_len,
80 _q.w * inv_len};
81 return r;
82}
83
84// Returns the estimated normalized SoaQuaternion _q.
85OZZ_INLINE SoaQuaternion NormalizeEst(const SoaQuaternion& _q) {
86 const SimdFloat4 len2 = _q.x * _q.x + _q.y * _q.y + _q.z * _q.z + _q.w * _q.w;
87 // Uses RSqrtEstNR (with one more Newton-Raphson step) as quaternions loose
88 // much precision due to normalization.
89 const SimdFloat4 inv_len = RSqrtEstNR(len2);
90 const SoaQuaternion r = {_q.x * inv_len, _q.y * inv_len, _q.z * inv_len,
91 _q.w * inv_len};
92 return r;
93}
94
95// Test if each quaternion of _q is normalized.
96OZZ_INLINE SimdInt4 IsNormalized(const SoaQuaternion& _q) {
97 const SimdFloat4 len2 = _q.x * _q.x + _q.y * _q.y + _q.z * _q.z + _q.w * _q.w;
98 return CmpLt(Abs(len2 - math::simd_float4::one()),
99 simd_float4::Load1(kNormalizationToleranceSq));
100}
101
102// Test if each quaternion of _q is normalized. using estimated tolerance.
103OZZ_INLINE SimdInt4 IsNormalizedEst(const SoaQuaternion& _q) {
104 const SimdFloat4 len2 = _q.x * _q.x + _q.y * _q.y + _q.z * _q.z + _q.w * _q.w;
105 return CmpLt(Abs(len2 - math::simd_float4::one()),
106 simd_float4::Load1(kNormalizationToleranceEstSq));
107}
108
109// Returns the linear interpolation of SoaQuaternion _a and _b with coefficient
110// _f.
111OZZ_INLINE SoaQuaternion Lerp(const SoaQuaternion& _a, const SoaQuaternion& _b,
112 _SimdFloat4 _f) {
113 const SoaQuaternion r = {(_b.x - _a.x) * _f + _a.x, (_b.y - _a.y) * _f + _a.y,
114 (_b.z - _a.z) * _f + _a.z,
115 (_b.w - _a.w) * _f + _a.w};
116 return r;
117}
118
119// Returns the linear interpolation of SoaQuaternion _a and _b with coefficient
120// _f.
121OZZ_INLINE SoaQuaternion NLerp(const SoaQuaternion& _a, const SoaQuaternion& _b,
122 _SimdFloat4 _f) {
123 const SoaFloat4 lerp = {(_b.x - _a.x) * _f + _a.x, (_b.y - _a.y) * _f + _a.y,
124 (_b.z - _a.z) * _f + _a.z, (_b.w - _a.w) * _f + _a.w};
125 const SimdFloat4 len2 =
126 lerp.x * lerp.x + lerp.y * lerp.y + lerp.z * lerp.z + lerp.w * lerp.w;
127 const SimdFloat4 inv_len = math::simd_float4::one() / Sqrt(len2);
128 const SoaQuaternion r = {lerp.x * inv_len, lerp.y * inv_len, lerp.z * inv_len,
129 lerp.w * inv_len};
130 return r;
131}
132
133// Returns the estimated linear interpolation of SoaQuaternion _a and _b with
134// coefficient _f.
135OZZ_INLINE SoaQuaternion NLerpEst(const SoaQuaternion& _a,
136 const SoaQuaternion& _b, _SimdFloat4 _f) {
137 const SoaFloat4 lerp = {(_b.x - _a.x) * _f + _a.x, (_b.y - _a.y) * _f + _a.y,
138 (_b.z - _a.z) * _f + _a.z, (_b.w - _a.w) * _f + _a.w};
139 const SimdFloat4 len2 =
140 lerp.x * lerp.x + lerp.y * lerp.y + lerp.z * lerp.z + lerp.w * lerp.w;
141 // Uses RSqrtEstNR (with one more Newton-Raphson step) as quaternions loose
142 // much precision due to normalization.
143 const SimdFloat4 inv_len = RSqrtEstNR(len2);
144 const SoaQuaternion r = {lerp.x * inv_len, lerp.y * inv_len, lerp.z * inv_len,
145 lerp.w * inv_len};
146 return r;
147}
148} // namespace math
149} // namespace ozz
150
151// Returns the addition of _a and _b.
152OZZ_INLINE ozz::math::SoaQuaternion operator+(
154 const ozz::math::SoaQuaternion r = {_a.x + _b.x, _a.y + _b.y, _a.z + _b.z,
155 _a.w + _b.w};
156 return r;
157}
158
159// Returns the multiplication of _q and scalar value _f.
160OZZ_INLINE ozz::math::SoaQuaternion operator*(
161 const ozz::math::SoaQuaternion& _q, const ozz::math::SimdFloat4& _f) {
162 const ozz::math::SoaQuaternion r = {_q.x * _f, _q.y * _f, _q.z * _f,
163 _q.w * _f};
164 return r;
165}
166
167// Returns the multiplication of _a and _b. If both _a and _b are normalized,
168// then the result is normalized.
169OZZ_INLINE ozz::math::SoaQuaternion operator*(
171 const ozz::math::SoaQuaternion r = {
172 _a.w * _b.x + _a.x * _b.w + _a.y * _b.z - _a.z * _b.y,
173 _a.w * _b.y + _a.y * _b.w + _a.z * _b.x - _a.x * _b.z,
174 _a.w * _b.z + _a.z * _b.w + _a.x * _b.y - _a.y * _b.x,
175 _a.w * _b.w - _a.x * _b.x - _a.y * _b.y - _a.z * _b.z};
176 return r;
177}
178
179// Returns true if each element of _a is equal to each element of _b.
180// Uses a bitwise comparison of _a and _b, no tolerance is applied.
181OZZ_INLINE ozz::math::SimdInt4 operator==(const ozz::math::SoaQuaternion& _a,
182 const ozz::math::SoaQuaternion& _b) {
183 const ozz::math::SimdInt4 x = ozz::math::CmpEq(_a.x, _b.x);
184 const ozz::math::SimdInt4 y = ozz::math::CmpEq(_a.y, _b.y);
185 const ozz::math::SimdInt4 z = ozz::math::CmpEq(_a.z, _b.z);
186 const ozz::math::SimdInt4 w = ozz::math::CmpEq(_a.w, _b.w);
187 return ozz::math::And(ozz::math::And(ozz::math::And(x, y), z), w);
188}
189#endif // OZZ_OZZ_BASE_MATHS_SOA_QUATERNION_H_
GLM_FUNC_DECL qua< T, Q > lerp(qua< T, Q > const &x, qua< T, Q > const &y, T a)
Definition quaternion_common.inl:29
Definition simd_math_config.h:121
Definition simd_math_config.h:129
Definition soa_quaternion.h:39