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; };
377 template <
typename FT> std::ostream&
operator<<(std::ostream& os,
const Quat<FT>& q);
378 template <
typename FT> std::istream&
operator>>(std::istream& is, Quat<FT>& q);
384 template <
typename FT>
389 const FT fromSqNorm = from.
length2();
390 const FT toSqNorm = to.
length2();
394 _q[0] = _q[1] = _q[2] = 0.0;
400 const FT axisSqNorm = axis.
length2();
406 FT angle = std::asin(std::sqrt(axisSqNorm / (fromSqNorm * toSqNorm)));
409 angle = FT(M_PI - angle);
411 set_axis_angle(axis, angle);
415 template <
typename FT>
422 _q[0] = FT(0); _q[1] = FT(0); _q[2] = FT(0); _q[3] = FT(1);
426 const FT sin_half_angle = std::sin(angle / 2.0f);
427 _q[0] = sin_half_angle*axis[0] /
norm;
428 _q[1] = sin_half_angle*axis[1] /
norm;
429 _q[2] = sin_half_angle*axis[2] /
norm;
430 _q[3] = (FT)std::cos(angle / 2.0f);
435 template <
typename FT>
438 const FT q00 = FT(2.0l * _q[0] * _q[0]);
439 const FT q11 = FT(2.0l * _q[1] * _q[1]);
440 const FT q22 = FT(2.0l * _q[2] * _q[2]);
442 const FT q01 = FT(2.0l * _q[0] * _q[1]);
443 const FT q02 = FT(2.0l * _q[0] * _q[2]);
444 const FT q03 = FT(2.0l * _q[0] * _q[3]);
446 const FT q12 = FT(2.0l * _q[1] * _q[2]);
447 const FT q13 = FT(2.0l * _q[1] * _q[3]);
449 const FT q23 = FT(2.0l * _q[2] * _q[3]);
452 FT((1.0 - q11 - q22)*v[0] + (q01 - q23)*v[1] + (q02 + q13)*v[2]),
453 FT((q01 + q23)*v[0] + (1.0 - q22 - q00)*v[1] + (q12 - q03)*v[2]),
454 FT((q02 - q13)*v[0] + (q12 + q03)*v[1] + (1.0 - q11 - q00)*v[2]));
457 template <
typename FT>
462 const FT onePlusTrace = FT(1.0) + m(0, 0) + m(1, 1) + m(2, 2);
464 if (onePlusTrace > 1E-5) {
466 const FT s = std::sqrt(onePlusTrace) * FT(2.0);
467 _q[0] = (m(2, 1) - m(1, 2)) / s;
468 _q[1] = (m(0, 2) - m(2, 0)) / s;
469 _q[2] = (m(1, 0) - m(0, 1)) / s;
470 _q[3] = FT(0.25) * s;
475 if ((m(0, 0) > m(1, 1)) && (m(0, 0) > m(2, 2))) {
476 const FT s = std::sqrt(FT(1.0) + m(0, 0) - m(1, 1) - m(2, 2)) * FT(2.0);
477 _q[0] = FT(0.25) * s;
478 _q[1] = (m(0, 1) + m(1, 0)) / s;
479 _q[2] = (m(0, 2) + m(2, 0)) / s;
480 _q[3] = (m(1, 2) - m(2, 1)) / s;
482 else if (m(1, 1) > m(2, 2)) {
483 const FT s = std::sqrt(FT(1.0) + m(1, 1) - m(0, 0) - m(2, 2)) * FT(2.0);
484 _q[0] = (m(0, 1) + m(1, 0)) / s;
485 _q[1] = FT(0.25) * s;
486 _q[2] = (m(1, 2) + m(2, 1)) / s;
487 _q[3] = (m(0, 2) - m(2, 0)) / s;
490 const FT s = std::sqrt(FT(1.0) + m(2, 2) - m(0, 0) - m(1, 1)) * FT(2.0);
491 _q[0] = (m(0, 2) + m(2, 0)) / s;
492 _q[1] = (m(1, 2) + m(2, 1)) / s;
493 _q[2] = FT(0.25) * s;
494 _q[3] = (m(0, 1) - m(1, 0)) / s;
500 template <
typename FT>
508 for (
int i = 0; i < 3; ++i) {
509 m(i, 0) = X[i] / normX;
510 m(i, 1) = Y[i] / normY;
511 m(i, 2) = Z[i] / normZ;
514 set_from_rotation_matrix(m);
517 template <
typename FT>
525 angle = FT(2.0) * std::acos(_q[3]);
526 axis =
Vec3(_q[0], _q[1], _q[2]);
527 const FT sinus = axis.
length();
532 angle = 2.0*M_PI - angle;
537 template <
typename FT>
540 Vec3 res(_q[0], _q[1], _q[2]);
541 const FT sinus = res.
length();
550 return (std::acos(_q[3]) <= M_PI / 2.0) ? res : -res;
553 template <
typename FT>
561 const FT angle = FT(2.0) * std::acos(_q[3]);
562 return (angle <= M_PI) ? angle : FT(2.0*M_PI - angle);
602 template <
typename FT>
605 const FT q00 = FT(2.0l * _q[0] * _q[0]);
606 const FT q11 = FT(2.0l * _q[1] * _q[1]);
607 const FT q22 = FT(2.0l * _q[2] * _q[2]);
609 const FT q01 = FT(2.0l * _q[0] * _q[1]);
610 const FT q02 = FT(2.0l * _q[0] * _q[2]);
611 const FT q03 = FT(2.0l * _q[0] * _q[3]);
613 const FT q12 = FT(2.0l * _q[1] * _q[2]);
614 const FT q13 = FT(2.0l * _q[1] * _q[3]);
616 const FT q23 = FT(2.0l * _q[2] * _q[3]);
619 m(0, 0) = FT(1.0) - q11 - q22;
624 m(1, 1) = FT(1.0) - q22 - q00;
629 m(2, 2) = FT(1.0) - q11 - q00;
643 template <
typename FT>
649 template <
typename FT>
656 if ((1.0 - std::fabs(cosAngle)) < 0.01)
664 FT angle = std::acos(std::fabs(cosAngle));
665 FT sinAngle = std::sin(angle);
666 c1 = std::sin(angle * (1.0 - t)) / sinAngle;
667 c2 = std::sin(angle * t) / sinAngle;
671 if (allowFlip && (cosAngle < 0.0))
674 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]);
677 template <
typename FT>
685 template <
typename FT>
688 FT len = std::sqrt(_q[0] * _q[0] + _q[1] * _q[1] + _q[2] * _q[2]);
691 return Quat(_q[0], _q[1], _q[2], 0.0);
698 } FT coef = std::acos(_q[3]) / len;
699 return Quat(_q[0] * coef, _q[1] * coef, _q[2] * coef, 0.0);
703 template <
typename FT>
706 FT theta = std::sqrt(_q[0] * _q[0] + _q[1] * _q[1] + _q[2] * _q[2]);
709 return Quat(_q[0], _q[1], _q[2], std::cos(theta));
712 FT coef = std::sin(theta) / theta;
713 return Quat(_q[0] * coef, _q[1] * coef, _q[2] * coef, std::cos(theta));
717 template <
typename FT>
725 template <
typename FT>
731 for (
int i = 0; i < 4; ++i)
732 e._q[i] = -0.25 * (l1._q[i] + l2._q[i]);
733 e = center*(e.
exp());
741 template <
typename FT>
746 FT seed = rand() / (FT)RAND_MAX;
747 FT r1 = std::sqrt(1.0f - seed);
748 FT r2 = std::sqrt(seed);
749 FT t1 = 2.0f * M_PI * (rand() / (FT)RAND_MAX);
750 FT t2 = 2.0f * M_PI * (rand() / (FT)RAND_MAX);
751 return Quat(std::sin(t1)*r1, std::cos(t1)*r1, std::sin(t2)*r2, std::cos(t2)*r2);
755 template <
typename FT>
inline
758 return os << Q[0] <<
' ' << Q[1] <<
' ' << Q[2] <<
' ' << Q[3];
762 template <
typename FT>
inline
764 return is >> Q[0] >> Q[1] >> Q[2] >> Q[3];
768 template <
class FT>
inline
770 for (
int i=0; i<4; ++i) {
771 if (std::isnan(Q[i]) || std::isinf(Q[i]))
3x3 matrix. Extends Mat with 3D-specific functionality and constructors.
Definition: mat.h:1620
4x4 matrix. Extends Mat with 4D-specific functionality and constructors.
Definition: mat.h:1940
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:718
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:416
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:726
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:436
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:501
FT angle() const
Returns the angle (in radians) of the rotation represented by the Quaternion. This value is always in...
Definition: quat.h:554
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:686
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
Vec3 axis() const
Returns the normalized axis direction of the rotation represented by the Quaternion....
Definition: quat.h:538
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:458
Mat4< FT > matrix() const
Returns the Quaternion associated 4x4 rotation matrix. Use glMultMatrixf(q.matrix()) to apply the rot...
Definition: quat.h:603
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
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:650
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:742
Mat4< FT > inverse_matrix() const
Returns the associated 4x4 inverse rotation matrix. This is simply the matrix() of the inverse().
Definition: quat.h:644
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 exp()
Returns the exponential of the Quaternion. See also log().
Definition: quat.h:704
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:678
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:518
Base class for vector types. It provides generic functionality for N dimensional vectors.
Definition: vec.h:34
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
bool has_nan(const GenericBox< DIM, FT > &box)
Definition: box.h:284
FT epsilon()
Function returning the epsilon value for a given type.
std::istream & operator>>(std::istream &is, GenericLine< DIM, FT > &line)
Definition: line.h:133
std::ostream & operator<<(std::ostream &os, Graph::Vertex v)
Definition: graph.h:920
Vec< 3, T > orthogonal(const Vec< 3, T > &v)
Compute a vector that is orthogonal to the given vector.
Definition: vec.h:561
Mat< N, N, T > inverse(const Mat< N, N, T > &m)
Return the inverse of N x N (square) matrix m.
Definition: mat.h:977
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:534
FT dot(const std::vector< FT > &, const std::vector< FT > &)
Inner product for vectors.
Definition: matrix.h:1803
FT norm(const Matrix< FT > &)
utilities
Definition: matrix.h:1424
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