17 #include <vsg/maths/mat4.h>
20 # pragma GCC diagnostic push
21 # pragma GCC diagnostic ignored "-Wpedantic"
23 #if defined(__clang__)
24 # pragma clang diagnostic push
25 # pragma clang diagnostic ignored "-Wgnu-anonymous-struct"
26 # pragma clang diagnostic ignored "-Wnested-anon-types"
43 value_type x, y, z, w;
48 value{0.0, 0.0, 0.0, 1.0} {}
50 value{v.x, v.y, v.z, v.w} {}
51 constexpr
t_quat(value_type in_x, value_type in_y, value_type in_z, value_type in_w) :
52 value{in_x, in_y, in_z, in_w} {}
55 set(angle_radians, axis);
64 value{
static_cast<T
>(v.x),
static_cast<T
>(v.y),
static_cast<T
>(v.z),
static_cast<T
>(v.w)} {}
68 constexpr std::size_t size()
const {
return 4; }
70 value_type& operator[](std::size_t i) {
return value[i]; }
71 value_type operator[](std::size_t i)
const {
return value[i]; }
76 value[0] =
static_cast<value_type
>(rhs[0]);
77 value[1] =
static_cast<value_type
>(rhs[1]);
78 value[2] =
static_cast<value_type
>(rhs[2]);
79 value[3] =
static_cast<value_type
>(rhs[3]);
83 T* data() {
return value; }
84 const T* data()
const {
return value; }
86 void set(value_type in_x, value_type in_y, value_type in_z, value_type in_w)
96 const value_type epsilon = 1e-7;
97 value_type len = length(axis);
105 value_type inversenorm = 1.0 / len;
106 value_type coshalfangle = cos(0.5 * angle_radians);
107 value_type sinhalfangle = sin(0.5 * angle_radians);
109 x = axis.x * sinhalfangle * inversenorm;
110 y = axis.y * sinhalfangle * inversenorm;
111 z = axis.z * sinhalfangle * inversenorm;
117 const value_type epsilon = 1e-7;
119 value_type dot_pd = vsg::dot(from, to);
120 value_type div = std::sqrt(length2(from) * length2(to));
122 if (div - dot_pd < epsilon)
124 axis = orthogonal(from);
128 axis = cross(from, to);
131 value_type len = length(axis);
133 double angle_radians = acos(dot_pd / div);
135 value_type inversenorm = 1.0 / len;
136 value_type coshalfangle = cos(0.5 * angle_radians);
137 value_type sinhalfangle = sin(0.5 * angle_radians);
139 x = axis.x * sinhalfangle * inversenorm;
140 y = axis.y * sinhalfangle * inversenorm;
141 z = axis.z * sinhalfangle * inversenorm;
145 explicit operator bool()
const noexcept {
return value[0] != 0.0 || value[1] != 0.0 || value[2] != 0.0 || value[3] != 0.0; }
157 return lhs[0] == rhs[0] && lhs[1] == rhs[1] && lhs[2] == rhs[2] && lhs[3] == rhs[3];
161 constexpr
bool operator!=(
const t_quat<T>& lhs,
const t_quat<T>& rhs)
163 return lhs[0] != rhs[0] || lhs[1] != rhs[1] || lhs[2] != rhs[2] || lhs[3] != rhs[3];
167 constexpr
bool operator<(
const t_quat<T>& lhs,
const t_quat<T>& rhs)
169 if (lhs[0] < rhs[0])
return true;
170 if (lhs[0] > rhs[0])
return false;
171 if (lhs[1] < rhs[1])
return true;
172 if (lhs[1] > rhs[1])
return false;
173 if (lhs[2] < rhs[2])
return true;
174 if (lhs[2] > rhs[2])
return false;
175 return lhs[3] < rhs[3];
179 constexpr t_quat<T> operator-(
const t_quat<T>& lhs,
const t_quat<T>& rhs)
181 return t_quat<T>(lhs[0] - rhs[0], lhs[1] - rhs[1], lhs[2] - rhs[2], lhs[3] - rhs[3]);
185 constexpr t_quat<T> conjugate(
const t_quat<T>& v)
187 return t_quat<T>(-v[0], -v[1], -v[2], v[3]);
191 constexpr t_quat<T> operator-(
const t_quat<T>& v)
197 constexpr t_quat<T> operator+(
const t_quat<T>& lhs,
const t_quat<T>& rhs)
199 return t_quat<T>(lhs[0] + rhs[0], lhs[1] + rhs[1], lhs[2] + rhs[2], lhs[3] + rhs[3]);
204 constexpr t_quat<T> operator*(
const t_quat<T>& lhs,
const t_quat<T>& rhs)
206 t_quat<T> q(rhs[3] * lhs[0] + rhs[0] * lhs[3] + rhs[1] * lhs[2] - rhs[2] * lhs[1],
207 rhs[3] * lhs[1] - rhs[0] * lhs[2] + rhs[1] * lhs[3] + rhs[2] * lhs[0],
208 rhs[3] * lhs[2] + rhs[0] * lhs[1] - rhs[1] * lhs[0] + rhs[2] * lhs[3],
209 rhs[3] * lhs[3] - rhs[0] * lhs[0] - rhs[1] * lhs[1] - rhs[2] * lhs[2]);
216 constexpr t_vec3<T> operator*(
const t_quat<T>& q,
const t_vec3<T>& v)
220 t_vec3<T> qvec(q[0], q[1], q[2]);
222 uuv = cross(qvec, uv);
230 constexpr t_quat<T> operator*(
const t_quat<T>& lhs, T rhs)
232 return t_quat<T>(lhs[0] * rhs, lhs[1] * rhs, lhs[2] * rhs, lhs[3] * rhs);
236 constexpr t_quat<T> operator/(
const t_quat<T>& lhs, T rhs)
238 T inv =
static_cast<T
>(1.0) / rhs;
239 return t_quat<T>(lhs[0] * inv, lhs[1] * inv, lhs[2] * inv, lhs[3] * inv);
243 constexpr T length(
const t_quat<T>& v)
245 return std::sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2] + v[3] * v[3]);
249 constexpr t_quat<T> normalize(
const t_quat<T>& v)
251 T inverse_len =
static_cast<T
>(1.0) / length(v);
252 return t_quat<T>(v[0] * inverse_len, v[1] * inverse_len, v[2] * inverse_len, v[3] * inverse_len);
256 constexpr T dot(
const t_quat<T>& lhs,
const t_quat<T>& rhs)
258 return lhs[0] * rhs[0] + lhs[1] * rhs[1] + lhs[2] * rhs[2] + lhs[3] * rhs[3];
262 constexpr t_quat<T> inverse(
const t_quat<T>& v)
264 t_quat<T> c = conjugate(v);
265 T inverse_len =
static_cast<T
>(1.0) / length(v);
266 return t_quat<T>(c[0] * inverse_len, c[1] * inverse_len, c[2] * inverse_len, c[3] * inverse_len);
270 constexpr t_quat<T> mix(
const t_quat<T>& from, t_quat<T> to, T r)
272 T epsilon = std::numeric_limits<T>::epsilon();
275 T cosomega = dot(from, to);
278 cosomega = -cosomega;
285 if ((one - cosomega) > epsilon)
287 T omega = acos(cosomega);
288 T sinomega = sin(omega);
289 T scale_from = sin((one - r) * omega) / sinomega;
290 T scale_to = sin(r * omega) / sinomega;
291 return (from * scale_from) + (to * scale_to);
296 return (from * (one - r)) + (to * r);
302 #if defined(__clang__)
303 # pragma clang diagnostic pop
305 #if defined(__GNUC__)
306 # pragma GCC diagnostic pop
t_quat template class that represents a quaternion
Definition: quat.h:35