Plasma Engine  2.0
Loading...
Searching...
No Matches
SimdQuat_inl.h
1#pragma once
2
3PL_ALWAYS_INLINE plSimdQuat::plSimdQuat() = default;
4
5PL_ALWAYS_INLINE plSimdQuat::plSimdQuat(const plSimdVec4f& v)
6 : m_v(v)
7{
8}
9
10PL_ALWAYS_INLINE const plSimdQuat plSimdQuat::MakeIdentity()
11{
12 return plSimdQuat(plSimdVec4f(0.0f, 0.0f, 0.0f, 1.0f));
13}
14
19
20inline plSimdQuat plSimdQuat::MakeFromAxisAndAngle(const plSimdVec4f& vRotationAxis, const plSimdFloat& fAngle)
21{
23 const plAngle halfAngle = plAngle::MakeFromRadian(fAngle) * 0.5f;
24 float s = plMath::Sin(halfAngle);
25 float c = plMath::Cos(halfAngle);
26
27 plSimdQuat res;
28 res.m_v = vRotationAxis * s;
29 res.m_v.SetW(c);
30 return res;
31}
32
33PL_ALWAYS_INLINE void plSimdQuat::Normalize()
34{
35 m_v.Normalize<4>();
36}
37
38inline plResult plSimdQuat::GetRotationAxisAndAngle(plSimdVec4f& ref_vAxis, plSimdFloat& ref_fAngle, const plSimdFloat& fEpsilon) const
39{
41 const plAngle acos = plMath::ACos(m_v.w().Max(-1).Min(1));
42 const float d = plMath::Sin(acos);
43
44 if (d < fEpsilon)
45 {
46 ref_vAxis.Set(1.0f, 0.0f, 0.0f, 0.0f);
47 }
48 else
49 {
50 ref_vAxis = m_v / d;
51 }
52
53 ref_fAngle = acos * 2;
54
55 return PL_SUCCESS;
56}
57
58PL_ALWAYS_INLINE plSimdMat4f plSimdQuat::GetAsMat4() const
59{
60 const plSimdVec4f xyz = m_v;
61 const plSimdVec4f x2y2z2 = xyz + xyz;
62 const plSimdVec4f xx2yy2zz2 = x2y2z2.CompMul(xyz);
63
64 // diagonal terms
65 // 1 - (yy2 + zz2)
66 // 1 - (xx2 + zz2)
67 // 1 - (xx2 + yy2)
68 const plSimdVec4f yy2_xx2_xx2 = xx2yy2zz2.Get<plSwizzle::YXXX>();
69 const plSimdVec4f zz2_zz2_yy2 = xx2yy2zz2.Get<plSwizzle::ZZYX>();
70 plSimdVec4f diagonal = plSimdVec4f(1.0f) - (yy2_xx2_xx2 + zz2_zz2_yy2);
71 diagonal.SetW(plSimdFloat::MakeZero());
72
73 // non diagonal terms
74 // xy2 +- wz2
75 // yz2 +- wx2
76 // xz2 +- wy2
77 const plSimdVec4f x_y_x = xyz.Get<plSwizzle::XYXX>();
78 const plSimdVec4f y2_z2_z2 = x2y2z2.Get<plSwizzle::YZZX>();
79 const plSimdVec4f base = x_y_x.CompMul(y2_z2_z2);
80
81 const plSimdVec4f z2_x2_y2 = x2y2z2.Get<plSwizzle::ZXYX>();
82 const plSimdVec4f offset = z2_x2_y2 * m_v.w();
83
84 const plSimdVec4f adds = base + offset;
85 const plSimdVec4f subs = base - offset;
86
87 // final matrix layout
88 // col0 = (diaX, addX, subZ, diaW)
89 const plSimdVec4f addX_u_diaX_u = adds.GetCombined<plSwizzle::XXXX>(diagonal);
90 const plSimdVec4f subZ_u_diaW_u = subs.GetCombined<plSwizzle::ZXWX>(diagonal);
91 const plSimdVec4f col0 = addX_u_diaX_u.GetCombined<plSwizzle::ZXXZ>(subZ_u_diaW_u);
92
93 // col1 = (subX, diaY, addY, diaW)
94 const plSimdVec4f subX_u_diaY_u = subs.GetCombined<plSwizzle::XXYX>(diagonal);
95 const plSimdVec4f addY_u_diaW_u = adds.GetCombined<plSwizzle::YXWX>(diagonal);
96 const plSimdVec4f col1 = subX_u_diaY_u.GetCombined<plSwizzle::XZXZ>(addY_u_diaW_u);
97
98 // col2 = (addZ, subY, diaZ, diaW)
99 const plSimdVec4f addZ_u_subY_u = adds.GetCombined<plSwizzle::ZXYX>(subs);
100 const plSimdVec4f col2 = addZ_u_subY_u.GetCombined<plSwizzle::XZZW>(diagonal);
101
102 return plSimdMat4f::MakeFromColumns(col0, col1, col2, plSimdVec4f(0, 0, 0, 1));
103}
104
105PL_ALWAYS_INLINE bool plSimdQuat::IsValid(const plSimdFloat& fEpsilon) const
106{
107 return m_v.IsNormalized<4>(fEpsilon);
108}
109
110PL_ALWAYS_INLINE bool plSimdQuat::IsNaN() const
111{
112 return m_v.IsNaN<4>();
113}
114
115PL_ALWAYS_INLINE plSimdQuat plSimdQuat::operator-() const
116{
117 return plSimdQuat(m_v.FlipSign(plSimdVec4b(true, true, true, false)));
118}
119
120PL_ALWAYS_INLINE plSimdVec4f plSimdQuat::operator*(const plSimdVec4f& v) const
121{
122 plSimdVec4f t = m_v.CrossRH(v);
123 t += t;
124 return v + t * m_v.w() + m_v.CrossRH(t);
125}
126
127PL_ALWAYS_INLINE plSimdQuat plSimdQuat::operator*(const plSimdQuat& q2) const
128{
129 plSimdQuat q;
130
131 q.m_v = q2.m_v * m_v.w() + m_v * q2.m_v.w() + m_v.CrossRH(q2.m_v);
132 q.m_v.SetW(m_v.w() * q2.m_v.w() - m_v.Dot<3>(q2.m_v));
133
134 return q;
135}
136
137PL_ALWAYS_INLINE bool plSimdQuat::operator==(const plSimdQuat& q2) const
138{
139 return (m_v == q2.m_v).AllSet<4>();
140}
141
142PL_ALWAYS_INLINE bool plSimdQuat::operator!=(const plSimdQuat& q2) const
143{
144 return (m_v != q2.m_v).AnySet<4>();
145}
Float wrapper struct for a safe usage and conversions of angles.
Definition Angle.h:10
static constexpr plAngle MakeFromRadian(float fRadian)
Creates an instance of plAngle that was initialized from radian. (No need for any conversion)
Definition Angle_inl.h:38
Definition SimdFloat.h:7
static plSimdFloat MakeZero()
Creates an plSimdFloat that is initialized to zero.
Definition FPUFloat_inl.h:36
A 4x4 matrix class.
Definition SimdMat4f.h:7
static plSimdMat4f MakeFromColumns(const plSimdVec4f &vCol0, const plSimdVec4f &vCol1, const plSimdVec4f &vCol2, const plSimdVec4f &vCol3)
Creates a matrix from 4 column vectors.
Definition SimdMat4f_inl.h:16
Definition SimdQuat.h:6
static plSimdQuat MakeFromElements(plSimdFloat x, plSimdFloat y, plSimdFloat z, plSimdFloat w)
Sets the individual elements of the quaternion directly. Note that x,y,z do NOT represent a rotation ...
Definition SimdQuat_inl.h:15
static plSimdQuat MakeFromAxisAndAngle(const plSimdVec4f &vRotationAxis, const plSimdFloat &fAngle)
Creates a quaternion from a rotation-axis and an angle (angle is given in Radians or as an plAngle)
Definition SimdQuat_inl.h:20
plSimdMat4f GetAsMat4() const
Returns the Quaternion as a matrix.
Definition SimdQuat_inl.h:58
plSimdVec4f operator*(const plSimdVec4f &v) const
Rotates v by q.
Definition SimdQuat_inl.h:120
plSimdQuat operator-() const
Returns a Quaternion that represents the negative / inverted rotation.
Definition SimdQuat_inl.h:115
bool IsNaN() const
Checks whether any component is NaN.
Definition SimdQuat_inl.h:110
bool IsValid(const plSimdFloat &fEpsilon=plMath::DefaultEpsilon< float >()) const
Checks whether all components are neither NaN nor infinite and that the quaternion is normalized.
Definition SimdQuat_inl.h:105
static const plSimdQuat MakeIdentity()
Static function that returns a quaternion that represents the identity rotation (none).
Definition SimdQuat_inl.h:10
plResult GetRotationAxisAndAngle(plSimdVec4f &ref_vAxis, plSimdFloat &ref_fAngle, const plSimdFloat &fEpsilon=plMath::DefaultEpsilon< float >()) const
Returns the rotation-axis and angle (in Radians), that this quaternion rotates around.
Definition SimdQuat_inl.h:38
void Normalize()
Normalizes the quaternion to unit length. ALL rotation-quaternions should be normalized at all times ...
Definition SimdQuat_inl.h:33
Definition SimdVec4b.h:7
A 4-component SIMD vector class.
Definition SimdVec4f.h:8
plSimdVec4f CrossRH(const plSimdVec4f &v) const
3D cross product, w is ignored.
Definition FPUVec4f_inl.h:473
plSimdVec4f GetCombined(const plSimdVec4f &other) const
x = this[s0], y = this[s1], z = other[s2], w = other[s3]
PL_ALWAYS_INLINE plAngle ACos(float f)
Returns the arcus cosinus of f.
Definition MathFloat_inl.h:82
PL_ALWAYS_INLINE float Sin(plAngle a)
***** Trigonometric Functions *****
Definition MathFloat_inl.h:62
PL_ALWAYS_INLINE float Cos(plAngle a)
Takes an angle, returns its cosine.
Definition MathFloat_inl.h:67
Default enum for returning failure or success, instead of using a bool.
Definition Types.h:54