39#ifndef EASY3D_CORE_QUATERNION_H
40#define EASY3D_CORE_QUATERNION_H
42#include <easy3d/core/constant.h>
43#include <easy3d/core/vec.h>
44#include <easy3d/core/mat.h>
105 template <
typename FT>
116 _q[0] = _q[1] = _q[2] = FT(0); _q[3] = FT(1);
144 Quat(FT q0, FT q1, FT q2, FT q3)
145 { _q[0]=q0; _q[1]=q1; _q[2]=q2; _q[3]=q3; }
149 {
for (
int i=0; i<4; ++i) _q[i] = Q._q[i]; }
153 for (
int i=0; i<4; ++i)
166 { _q[0]=q0; _q[1]=q1; _q[2]=q2; _q[3]=q3; }
223 a._q[3]*b._q[0] + b._q[3]*a._q[0] + a._q[1]*b._q[2] - a._q[2]*b._q[1],
224 a._q[3]*b._q[1] + b._q[3]*a._q[1] + a._q[2]*b._q[0] - a._q[0]*b._q[2],
225 a._q[3]*b._q[2] + b._q[3]*a._q[2] + a._q[0]*b._q[1] - a._q[1]*b._q[0],
226 a._q[3]*b._q[3] - b._q[0]*a._q[0] - a._q[1]*b._q[1] - a._q[2]*b._q[2]
272 void invert() { _q[0] = -_q[0]; _q[1] = -_q[1]; _q[2] = -_q[2]; }
286 return std::sqrt(_q[0] * _q[0] + _q[1] * _q[1] + _q[2] * _q[2] + _q[3] * _q[3]);
296 const FT
norm = std::sqrt(_q[0] * _q[0] + _q[1] * _q[1] + _q[2] * _q[2] + _q[3] * _q[3]);
297 for (
int i=0; i<4; ++i)
308 const FT
norm = std::sqrt(_q[0] * _q[0] + _q[1] * _q[1] + _q[2] * _q[2] + _q[3] * _q[3]);
309 for (
int i=0; i<4; ++i)
311 return Quat(Q[0], Q[1], Q[2], Q[3]);
342 static FT
dot(
const Quat<FT>& a,
const Quat<FT>& b) {
return a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + a[3] * b[3]; }
372 struct { FT x; FT y; FT z; FT w; };
384 template <
typename FT>
387 const FT fromSqNorm = from.
length2();
388 const FT toSqNorm = to.
length2();
392 _q[0] = _q[1] = _q[2] = 0.0;
398 const FT axisSqNorm =
axis.length2();
404 FT
angle = std::asin(std::sqrt(axisSqNorm / (fromSqNorm * toSqNorm)));
413 template <
typename FT>
420 _q[0] = FT(0); _q[1] = FT(0); _q[2] = FT(0); _q[3] = FT(1);
424 const FT sin_half_angle = std::sin(
angle / 2.0f);
425 _q[0] = sin_half_angle*
axis[0] /
norm;
426 _q[1] = sin_half_angle*
axis[1] /
norm;
427 _q[2] = sin_half_angle*
axis[2] /
norm;
428 _q[3] = (FT)std::cos(
angle / 2.0f);
433 template <
typename FT>
436 const FT q00 = FT(2.0l * _q[0] * _q[0]);
437 const FT q11 = FT(2.0l * _q[1] * _q[1]);
438 const FT q22 = FT(2.0l * _q[2] * _q[2]);
440 const FT q01 = FT(2.0l * _q[0] * _q[1]);
441 const FT q02 = FT(2.0l * _q[0] * _q[2]);
442 const FT q03 = FT(2.0l * _q[0] * _q[3]);
444 const FT q12 = FT(2.0l * _q[1] * _q[2]);
445 const FT q13 = FT(2.0l * _q[1] * _q[3]);
447 const FT q23 = FT(2.0l * _q[2] * _q[3]);
450 FT((1.0 - q11 - q22)*v[0] + (q01 - q23)*v[1] + (q02 + q13)*v[2]),
451 FT((q01 + q23)*v[0] + (1.0 - q22 - q00)*v[1] + (q12 - q03)*v[2]),
452 FT((q02 - q13)*v[0] + (q12 + q03)*v[1] + (1.0 - q11 - q00)*v[2]));
455 template <
typename FT>
460 const FT onePlusTrace = FT(1.0) + m(0, 0) + m(1, 1) + m(2, 2);
462 if (onePlusTrace > 1E-5) {
464 const FT s = std::sqrt(onePlusTrace) * FT(2.0);
465 _q[0] = (m(2, 1) - m(1, 2)) / s;
466 _q[1] = (m(0, 2) - m(2, 0)) / s;
467 _q[2] = (m(1, 0) - m(0, 1)) / s;
468 _q[3] = FT(0.25) * s;
473 if ((m(0, 0) > m(1, 1)) && (m(0, 0) > m(2, 2))) {
474 const FT s = std::sqrt(FT(1.0) + m(0, 0) - m(1, 1) - m(2, 2)) * FT(2.0);
475 _q[0] = FT(0.25) * s;
476 _q[1] = (m(0, 1) + m(1, 0)) / s;
477 _q[2] = (m(0, 2) + m(2, 0)) / s;
478 _q[3] = (m(1, 2) - m(2, 1)) / s;
480 else if (m(1, 1) > m(2, 2)) {
481 const FT s = std::sqrt(FT(1.0) + m(1, 1) - m(0, 0) - m(2, 2)) * FT(2.0);
482 _q[0] = (m(0, 1) + m(1, 0)) / s;
483 _q[1] = FT(0.25) * s;
484 _q[2] = (m(1, 2) + m(2, 1)) / s;
485 _q[3] = (m(0, 2) - m(2, 0)) / s;
488 const FT s = std::sqrt(FT(1.0) + m(2, 2) - m(0, 0) - m(1, 1)) * FT(2.0);
489 _q[0] = (m(0, 2) + m(2, 0)) / s;
490 _q[1] = (m(1, 2) + m(2, 1)) / s;
491 _q[2] = FT(0.25) * s;
492 _q[3] = (m(0, 1) - m(1, 0)) / s;
498 template <
typename FT>
506 for (
int i = 0; i < 3; ++i) {
507 m(i, 0) = X[i] / normX;
508 m(i, 1) = Y[i] / normY;
509 m(i, 2) = Z[i] / normZ;
515 template <
typename FT>
523 angle = FT(2.0) * std::acos(_q[3]);
525 const FT sinus =
axis.length();
535 template <
typename FT>
538 Vec3 res(_q[0], _q[1], _q[2]);
539 const FT sinus = res.
length();
548 return (std::acos(_q[3]) <= M_PI / 2.0) ? res : -res;
551 template <
typename FT>
559 const FT
angle = FT(2.0) * std::acos(_q[3]);
600 template <
typename FT>
603 const FT q00 = FT(2.0l * _q[0] * _q[0]);
604 const FT q11 = FT(2.0l * _q[1] * _q[1]);
605 const FT q22 = FT(2.0l * _q[2] * _q[2]);
607 const FT q01 = FT(2.0l * _q[0] * _q[1]);
608 const FT q02 = FT(2.0l * _q[0] * _q[2]);
609 const FT q03 = FT(2.0l * _q[0] * _q[3]);
611 const FT q12 = FT(2.0l * _q[1] * _q[2]);
612 const FT q13 = FT(2.0l * _q[1] * _q[3]);
614 const FT q23 = FT(2.0l * _q[2] * _q[3]);
617 m(0, 0) = FT(1.0) - q11 - q22;
622 m(1, 1) = FT(1.0) - q22 - q00;
627 m(2, 2) = FT(1.0) - q11 - q00;
641 template <
typename FT>
647 template <
typename FT>
654 if ((1.0 - std::fabs(cosAngle)) < 0.01)
662 FT
angle = std::acos(std::fabs(cosAngle));
663 FT sinAngle = std::sin(
angle);
664 c1 = std::sin(
angle * (1.0 - t)) / sinAngle;
665 c2 = std::sin(
angle * t) / sinAngle;
669 if (allowFlip && (cosAngle < 0.0))
672 return Quat(c1*a[0] + c2*b[0], c1*a[1] + c2*b[1], c1*a[2] + c2*b[2], c1*a[3] + c2*b[3]);
675 template <
typename FT>
683 template <
typename FT>
686 FT len = std::sqrt(_q[0] * _q[0] + _q[1] * _q[1] + _q[2] * _q[2]);
689 return Quat(_q[0], _q[1], _q[2], 0.0);
696 } FT coef = std::acos(_q[3]) / len;
697 return Quat(_q[0] * coef, _q[1] * coef, _q[2] * coef, 0.0);
701 template <
typename FT>
704 FT theta = std::sqrt(_q[0] * _q[0] + _q[1] * _q[1] + _q[2] * _q[2]);
707 return Quat(_q[0], _q[1], _q[2], std::cos(theta));
710 FT coef = std::sin(theta) / theta;
711 return Quat(_q[0] * coef, _q[1] * coef, _q[2] * coef, std::cos(theta));
715 template <
typename FT>
723 template <
typename FT>
729 for (
int i = 0; i < 4; ++i)
730 e._q[i] = -0.25 * (l1._q[i] + l2._q[i]);
731 e = center*(e.
exp());
739 template <
typename FT>
744 FT seed = rand() / (FT)RAND_MAX;
745 FT r1 = std::sqrt(1.0f - seed);
746 FT r2 = std::sqrt(seed);
747 FT t1 = 2.0f * M_PI * (rand() / (FT)RAND_MAX);
748 FT t2 = 2.0f * M_PI * (rand() / (FT)RAND_MAX);
749 return Quat(std::sin(t1)*r1, std::cos(t1)*r1, std::sin(t2)*r2, std::cos(t2)*r2);
753 template <
typename FT>
inline
756 return os << Q[0] <<
' ' << Q[1] <<
' ' << Q[2] <<
' ' << Q[3];
760 template <
typename FT>
inline
762 return is >> Q[0] >> Q[1] >> Q[2] >> Q[3];
766 template <
class FT>
inline
768 for (
int i=0; i<4; ++i) {
769 if (std::isnan(Q[i]) || std::isinf(Q[i]))
3 by 3 matrix. Extends Mat with 3D-specific functionality and constructors.
Definition mat.h:1844
4 by 4 matrix. Extends Mat with 4D-specific functionality and constructors.
Definition mat.h:2180
The Quaternion class represents 3D rotations and orientations.
Definition quat.h:107
friend Quat operator*(const Quat &a, const Quat &b)
Returns the composition of the a and b rotations. The order is important. When applied to a Vec v (se...
Definition quat.h:220
Quat(const thisclass &Q)
Definition quat.h:148
static Quat ln_dif(const Quat< FT > &a, const Quat< FT > &b)
Returns log(a. inverse() * b). Useful for squad_tangent().
Definition quat.h:716
Quat(const Mat3< FT > &m)
Constructor from rotation matrix. See also set_from_rotation_matrix().
Definition quat.h:120
void set_axis_angle(const Vec3 &axis, FT angle)
Definition quat.h:414
FT length() const
Return the length of the quaternion.
Definition quat.h:285
static Quat squad_tangent(const Quat< FT > &before, const Quat< FT > ¢er, const Quat< FT > &after)
Returns a tangent Quaternion for center, defined by before and after Quaternions. Useful for smooth s...
Definition quat.h:724
void set_value(FT q0, FT q1, FT q2, FT q3)
Definition quat.h:165
Vec3 inverse_rotate(const Vec3 &v) const
Returns the image of v by the Quaternion inverse() rotation. rotate() performs an inverse transformat...
Definition quat.h:257
Quat inverse() const
Inversion. Returns the inverse Quaternion (inverse rotation). Result has a negated axis() direction a...
Definition quat.h:266
Vec3 rotate(const Vec3 &v) const
Returns the image of v by the Quaternion rotation.
Definition quat.h:434
void set_from_rotated_basis(const Vec3 &X, const Vec3 &Y, const Vec3 &Z)
Set a Quaternion from the three axis of a rotated frame. It actually fills the three columns of a mat...
Definition quat.h:499
FT normalize()
Normalizes the Quaternion coefficients. This method should not need to be called since we only deal w...
Definition quat.h:295
Quat log()
Returns the logarithm of the Quaternion. See also exp().
Definition quat.h:684
FT & operator[](int i)
Bracket operator returning an l-value. i must range in [0..3].
Definition quat.h:206
Quat(const Vec3 &axis, FT angle)
Constructor from rotation axis (non null) and angle (in radians). See also set_axis_angle().
Definition quat.h:126
friend Vec3 operator*(const Quat &q, const Vec3 &v)
Returns the image of v by the rotation q. Same as q.rotate(v).
Definition quat.h:245
void set_from_rotation_matrix(const Mat3< FT > &m)
Set the Quaternion from a (supposedly correct) 3x3 rotation matrix. The matrix is expressed in Europe...
Definition quat.h:456
Mat4< FT > matrix() const
Returns the Quaternion associated 4x4 rotation matrix. Use glMultMatrixf(q.matrix()) to apply the rot...
Definition quat.h:601
Quat normalized() const
Returns a normalized version of the Quaternion.
Definition quat.h:306
void invert()
Inverses the Quaternion (same rotation angle(), but negated axis()).
Definition quat.h:272
Quat & operator=(const thisclass &Q)
Definition quat.h:152
Quat & operator*=(const Quat &q)
Quaternion rotation is composed with q. See operator*(), since this is equivalent to this = this * q.
Definition quat.h:236
Quat(FT q0, FT q1, FT q2, FT q3)
Constructor from the four values of a Quaternion. First three values are axis*std::sin(angle/2) and t...
Definition quat.h:144
void negate()
Negates all the coefficients of the Quaternion. This results in an other representation of the same r...
Definition quat.h:282
Vec< 3, FT > Vec3
3D vector type
Definition quat.h:109
static Quat slerp(const Quat< FT > &a, const Quat< FT > &b, FT t, bool allowFlip=true)
Slerp(Spherical Linear intERPolation) interpolation. Returns the slerp interpolation of Quaternions a...
Definition quat.h:648
Quat(const Vec3 &from, const Vec3 &to)
Constructs a quaternion that will rotate from the from direction to the to direction.
Definition quat.h:385
FT operator[](int i) const
Bracket operator, with a constant return value. i must range in [0..3].
Definition quat.h:203
static thisclass random_quat()
Returns a random unit Quaternion. You can create a randomly directed unit vector using:
Definition quat.h:740
Mat4< FT > inverse_matrix() const
Returns the associated 4x4 inverse rotation matrix. This is simply the matrix() of the inverse().
Definition quat.h:642
static FT dot(const Quat< FT > &a, const Quat< FT > &b)
Returns the "dot" product of a and b: a[0]*b[0] + a[1]*b[1] + a[2]*b[2] + a[3]*b[3].
Definition quat.h:342
Quat< FT > thisclass
Quaternion type.
Definition quat.h:110
Quat exp()
Returns the exponential of the Quaternion. See also log().
Definition quat.h:702
static Quat squad(const Quat< FT > &a, const Quat< FT > &tgA, const Quat< FT > &tgB, const Quat< FT > &b, FT t)
Returns the slerp interpolation of the two Quaternions a and b, at time t, using tangents tgA and tgB...
Definition quat.h:676
Quat()
Default constructor, builds an identity rotation.
Definition quat.h:114
void get_axis_angle(Vec3 &axis, FT &angle) const
Returns the axis vector and the angle (in radians) of the rotation represented by the Quaternion.
Definition quat.h:516
Base class for vector types. It provides generic functionality for N dimensional vectors.
Definition vec.h:30
T length() const
Returns the length of this vector.
Definition vec.h:115
T length2() const
Returns the squared length of this vector.
Definition vec.h:106
Definition collider.cpp:182
Vec< N, T > normalize(const Vec< N, T > &v)
Computes and returns the normalized vector (Note: the input vector is not modified).
Definition vec.h:299
Vec< 3, T > cross(const Vec< 3, T > &v1, const Vec< 3, T > &v2)
Compute the cross product of two 3D vectors.
Definition vec.h:685
Vec< 3, T > orthogonal(const Vec< 3, T > &v)
Compute a vector that is orthogonal to the given vector.
Definition vec.h:712
FT epsilon()
Function returning the epsilon value for a given type.
std::ostream & operator<<(std::ostream &os, Graph::Vertex v)
Output stream support for Graph::Vertex.
Definition graph.h:1300
Mat< N, N, T > inverse(const Mat< N, N, T > &m)
Returns the inverse of an N x N (square) matrix.
Definition mat.h:1190
std::istream & operator>>(std::istream &is, GenericLine< DIM, FT > &line)
Input stream support for GenericLine.
Definition line.h:183
bool has_nan(const GenericBox< DIM, FT > &box)
Check if the representation of a box has NaN.
Definition box.h:373
FT dot(const std::vector< FT > &, const std::vector< FT > &)
Inner product for vectors.
Definition matrix.h:1834
FT norm(const Matrix< FT > &)
utilities
Definition matrix.h:1455