Easy3D 2.5.3
quat.h
1/********************************************************************
2 * Copyright (C) 2015 Liangliang Nan <liangliang.nan@gmail.com>
3 * https://3d.bk.tudelft.nl/liangliang/
4 *
5 * This file is part of Easy3D. If it is useful in your research/work,
6 * I would be grateful if you show your appreciation by citing it:
7 * ------------------------------------------------------------------
8 * Liangliang Nan.
9 * Easy3D: a lightweight, easy-to-use, and efficient C++ library
10 * for processing and rendering 3D data.
11 * Journal of Open Source Software, 6(64), 3255, 2021.
12 * ------------------------------------------------------------------
13 *
14 * Easy3D is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License Version 3
16 * as published by the Free Software Foundation.
17 *
18 * Easy3D is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with this program. If not, see <http://www.gnu.org/licenses/>.
25 ********************************************************************/
26
39#ifndef EASY3D_CORE_QUATERNION_H
40#define EASY3D_CORE_QUATERNION_H
41
42#include <easy3d/core/constant.h>
43#include <easy3d/core/vec.h>
44#include <easy3d/core/mat.h>
45
46
47namespace easy3d {
48
105 template <typename FT>
106 class Quat
107 {
108 public:
109 typedef Vec<3, FT> Vec3;
110 typedef Quat<FT> thisclass;
111
112 public:
115 {
116 _q[0] = _q[1] = _q[2] = FT(0); _q[3] = FT(1);
117 }
118
120 explicit Quat(const Mat3<FT>& m)
121 {
123 }
124
126 Quat(const Vec3& axis, FT angle)
127 {
129 }
130
136 Quat(const Vec3& from, const Vec3& to);
137
144 Quat(FT q0, FT q1, FT q2, FT q3)
145 { _q[0]=q0; _q[1]=q1; _q[2]=q2; _q[3]=q3; }
146
148 Quat(const thisclass& Q)
149 { for (int i=0; i<4; ++i) _q[i] = Q._q[i]; }
150
153 for (int i=0; i<4; ++i)
154 _q[i] = Q._q[i];
155 return (*this);
156 }
157
162 void set_axis_angle(const Vec3& axis, FT angle);
163
165 void set_value(FT q0, FT q1, FT q2, FT q3)
166 { _q[0]=q0; _q[1]=q1; _q[2]=q2; _q[3]=q3; }
167
175
180 void set_from_rotated_basis(const Vec3& X, const Vec3& Y, const Vec3& Z);
181
186 Vec3 axis() const;
187
193 FT angle() const;
194
198 void get_axis_angle(Vec3& axis, FT& angle) const;
199
203 FT operator[](int i) const { return _q[i]; }
204
206 FT& operator[](int i) { return _q[i]; }
207
208 /* Rotation computations */
209
220 friend Quat operator*(const Quat& a, const Quat& b)
221 {
222 return Quat(
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]
227 );
228 }
229
236 Quat& operator*=(const Quat &q) {
237 *this = (*this)*q;
238 return *this;
239 }
240
245 friend Vec3 operator*(const Quat& q, const Vec3& v) { return q.rotate(v); }
246
251 Vec3 rotate(const Vec3& v) const;
252
257 Vec3 inverse_rotate(const Vec3& v) const {
258 return inverse().rotate(v);
259 }
260
266 Quat inverse() const { return Quat(-_q[0], -_q[1], -_q[2], _q[3]); }
267
272 void invert() { _q[0] = -_q[0]; _q[1] = -_q[1]; _q[2] = -_q[2]; }
273
282 void negate() { invert(); _q[3] = -_q[3]; }
283
285 FT length() const {
286 return std::sqrt(_q[0] * _q[0] + _q[1] * _q[1] + _q[2] * _q[2] + _q[3] * _q[3]);
287 }
288
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)
298 _q[i] /= norm;
299 return norm;
300 }
301
306 Quat normalized() const {
307 FT Q[4];
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)
310 Q[i] = _q[i] / norm;
311 return Quat(Q[0], Q[1], Q[2], Q[3]);
312 }
313
319
322
332 static Quat slerp(const Quat<FT>& a, const Quat<FT>& b, FT t, bool allowFlip = true);
333
339 static Quat squad(const Quat<FT>& a, const Quat<FT>& tgA, const Quat<FT>& tgB, const Quat<FT>& b, FT t);
340
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]; }
343
348
350 static Quat ln_dif(const Quat<FT>& a, const Quat<FT>& b);
355 static Quat squad_tangent(const Quat<FT>& before, const Quat<FT>& center, const Quat<FT>& after);
356
367
368 //data intentionally left public to allow q.x ...
369 public:
370 /* The internal data representation is private, use operator[] to access values. */
371 union {
372 struct { FT x; FT y; FT z; FT w; };
373 FT _q[4];
374 };
375 };
376
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);
379
380
381 //-------------- implementation -----------------
382
383
384 template <typename FT>
385 Quat<FT>::Quat(const Vec3& from, const Vec3& to)
386 {
387 const FT epsilon = FT(1E-10);
388
389 const FT fromSqNorm = from.length2();
390 const FT toSqNorm = to.length2();
391 // Identity Quaternion when one vector is null
392 if ((fromSqNorm < epsilon) || (toSqNorm < epsilon))
393 {
394 _q[0] = _q[1] = _q[2] = 0.0;
395 _q[3] = 1.0;
396 }
397 else
398 {
399 Vec3 axis = cross(from, to);
400 const FT axisSqNorm = axis.length2();
401
402 // Aligned vectors, pick any axis, not aligned with from or to
403 if (axisSqNorm < epsilon)
404 axis = orthogonal(from);
405
406 FT angle = std::asin(std::sqrt(axisSqNorm / (fromSqNorm * toSqNorm)));
407
408 if (easy3d::dot(from, to) < 0.0)
409 angle = FT(M_PI - angle);
410
411 set_axis_angle(axis, angle);
412 }
413 }
414
415 template <typename FT>
416 void Quat<FT>::set_axis_angle(const Vec3& axis, FT angle)
417 {
418 const FT norm = axis.length();
419 if (norm < 1E-8)
420 {
421 // Null rotation
422 _q[0] = FT(0); _q[1] = FT(0); _q[2] = FT(0); _q[3] = FT(1);
423 }
424 else
425 {
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);
431 }
432 }
433
434
435 template <typename FT>
436 typename Quat<FT>::Vec3 Quat<FT>::rotate(const Vec3& v) const
437 {
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]);
441
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]);
445
446 const FT q12 = FT(2.0l * _q[1] * _q[2]);
447 const FT q13 = FT(2.0l * _q[1] * _q[3]);
448
449 const FT q23 = FT(2.0l * _q[2] * _q[3]);
450
451 return Vec3(
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]));
455 }
456
457 template <typename FT>
459 {
460 // see http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/index.htm
461 // Compute one plus the trace of the matrix
462 const FT onePlusTrace = FT(1.0) + m(0, 0) + m(1, 1) + m(2, 2);
463
464 if (onePlusTrace > 1E-5) {
465 // Direct computation
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;
471 }
472 else
473 {
474 // Computation depends on major diagonal term
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;
481 }
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;
488 }
489 else {
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;
495 }
496 }
497 normalize();
498 }
499
500 template <typename FT>
501 void Quat<FT>::set_from_rotated_basis(const Vec3& X, const Vec3& Y, const Vec3& Z)
502 {
503 Mat3<FT> m;
504 FT normX = X.length();
505 FT normY = Y.length();
506 FT normZ = Z.length();
507
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;
512 }
513
514 set_from_rotation_matrix(m);
515 }
516
517 template <typename FT>
518 void Quat<FT>::get_axis_angle(Vec3& axis, FT& angle) const
519 {
520 // The normalize() is here to prevent failure introduced by numerical error.
521 // We call std::acos(_q[3]), but _q[3] equaling to 1 can actually be e.g., 1.00000012.
522 if (_q[3] > FT(1)) {
523 const_cast<Quat*>(this)->normalize();
524 }
525 angle = FT(2.0) * std::acos(_q[3]);
526 axis = Vec3(_q[0], _q[1], _q[2]);
527 const FT sinus = axis.length();
528 if (sinus > 1E-8)
529 axis = axis / sinus;
530
531 if (angle > M_PI) {
532 angle = 2.0*M_PI - angle;
533 axis = -axis;
534 }
535 }
536
537 template <typename FT>
539 {
540 Vec3 res(_q[0], _q[1], _q[2]);
541 const FT sinus = res.length();
542 if (sinus > 1E-8)
543 res = res / sinus;
544
545 // The normalize() is here to prevent failure introduced by numerical error.
546 // We call std::acos(_q[3]), but _q[3] equaling to 1 can actually be e.g., 1.00000012.
547 if (_q[3] > FT(1)) {
548 const_cast<Quat*>(this)->normalize();
549 }
550 return (std::acos(_q[3]) <= M_PI / 2.0) ? res : -res;
551 }
552
553 template <typename FT>
555 {
556 // The normalize() is here to prevent failure introduced by numerical error.
557 // We call std::acos(_q[3]), but _q[3] equaling to 1 can actually be e.g., 1.00000012.
558 if (_q[3] > FT(1)) {
559 const_cast<Quat*>(this)->normalize();
560 }
561 const FT angle = FT(2.0) * std::acos(_q[3]);
562 return (angle <= M_PI) ? angle : FT(2.0*M_PI - angle);
563 }
564
565
566 //Mat4 quat_to_matrix(const Quat& q)
567 //{
568 // Mat4 M;
569 //
570 // const double x = q.vector()[0];
571 // const double y = q.vector()[1];
572 // const double z = q.vector()[2];
573 // const double w = q.scalar();
574 // const double s = 2 / norm(q);
575 //
576 // M(0, 0) = 1 - s*(y*y + z*z); M(0, 1) = s*(x*y - w*z); M(0, 2) = s*(x*z + w*y); M(0, 3) = 0;
577 // M(1, 0) = s*(x*y + w*z); M(1, 1) = 1 - s*(x*x + z*z); M(1, 2) = s*(y*z - w*x); M(1, 3) = 0;
578 // M(2, 0) = s*(x*z - w*y); M(2, 1) = s*(y*z + w*x); M(2, 2) = 1 - s*(x*x + y*y); M(2, 3) = 0;
579 // M(3, 0) = 0; M(3, 1) = 0; M(3, 2) = 0; M(3, 3) = 1;
580 //
581 // return M;
582 //}
583 //
584 //Mat4 unit_quat_to_matrix(const Quat& q)
585 //{
586 // Mat4 M;
587 //
588 // const double x = q.vector()[0];
589 // const double y = q.vector()[1];
590 // const double z = q.vector()[2];
591 // const double w = q.scalar();
592 //
593 // M(0, 0) = 1 - 2 * (y*y + z*z); M(0, 1) = 2 * (x*y - w*z); M(0, 2) = 2 * (x*z + w*y); M(0, 3) = 0;
594 // M(1, 0) = 2 * (x*y + w*z); M(1, 1) = 1 - 2 * (x*x + z*z); M(1, 2) = 2 * (y*z - w*x); M(1, 3) = 0;
595 // M(2, 0) = 2 * (x*z - w*y); M(2, 1) = 2 * (y*z + w*x); M(2, 2) = 1 - 2 * (x*x + y*y); M(2, 3) = 0;
596 // M(3, 0) = 0; M(3, 1) = 0; M(3, 2) = 0; M(3, 3) = 1;
597 //
598 // return M;
599 //}
600
601
602 template <typename FT>
604 {
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]);
608
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]);
612
613 const FT q12 = FT(2.0l * _q[1] * _q[2]);
614 const FT q13 = FT(2.0l * _q[1] * _q[3]);
615
616 const FT q23 = FT(2.0l * _q[2] * _q[3]);
617
618 Mat4<FT> m;
619 m(0, 0) = FT(1.0) - q11 - q22;
620 m(0, 1) = q01 - q23;
621 m(0, 2) = q02 + q13;
622
623 m(1, 0) = q01 + q23;
624 m(1, 1) = FT(1.0) - q22 - q00;
625 m(1, 2) = q12 - q03;
626
627 m(2, 0) = q02 - q13;
628 m(2, 1) = q12 + q03;
629 m(2, 2) = FT(1.0) - q11 - q00;
630
631 m(3, 0) = FT(0.0);
632 m(3, 1) = FT(0.0);
633 m(3, 2) = FT(0.0);
634
635 m(0, 3) = FT(0.0);
636 m(1, 3) = FT(0.0);
637 m(2, 3) = FT(0.0);
638 m(3, 3) = FT(1.0);
639
640 return m;
641 }
642
643 template <typename FT>
645 {
646 return inverse().matrix();
647 }
648
649 template <typename FT>
650 Quat<FT> Quat<FT>::slerp(const Quat<FT>& a, const Quat<FT>& b, FT t, bool allowFlip)
651 {
652 FT cosAngle = Quat<FT>::dot(a, b);
653
654 FT c1, c2;
655 // Linear interpolation for close orientations
656 if ((1.0 - std::fabs(cosAngle)) < 0.01)
657 {
658 c1 = FT(1.0) - t;
659 c2 = t;
660 }
661 else
662 {
663 // Spherical interpolation
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;
668 }
669
670 // Use the shortest path
671 if (allowFlip && (cosAngle < 0.0))
672 c1 = -c1;
673
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]);
675 }
676
677 template <typename FT>
678 Quat<FT> Quat<FT>::squad(const Quat<FT>& a, const Quat<FT>& tgA, const Quat<FT>& tgB, const Quat<FT>& b, FT t)
679 {
680 Quat<FT> ab = Quat<FT>::slerp(a, b, t);
681 Quat<FT> tg = Quat<FT>::slerp(tgA, tgB, t, false);
682 return Quat<FT>::slerp(ab, tg, 2.0*t*(1.0 - t), false);
683 }
684
685 template <typename FT>
687 {
688 FT len = std::sqrt(_q[0] * _q[0] + _q[1] * _q[1] + _q[2] * _q[2]);
689
690 if (len < 1E-6)
691 return Quat(_q[0], _q[1], _q[2], 0.0);
692 else
693 {
694 // The normalize() is here to prevent failure introduced by numerical error.
695 // We call std::acos(_q[3]), but _q[3] equaling to 1 can actually be e.g., 1.00000012.
696 if (_q[3] > FT(1)) {
697 const_cast<Quat*>(this)->normalize();
698 } FT coef = std::acos(_q[3]) / len;
699 return Quat(_q[0] * coef, _q[1] * coef, _q[2] * coef, 0.0);
700 }
701 }
702
703 template <typename FT>
705 {
706 FT theta = std::sqrt(_q[0] * _q[0] + _q[1] * _q[1] + _q[2] * _q[2]);
707
708 if (theta < 1E-6)
709 return Quat(_q[0], _q[1], _q[2], std::cos(theta));
710 else
711 {
712 FT coef = std::sin(theta) / theta;
713 return Quat(_q[0] * coef, _q[1] * coef, _q[2] * coef, std::cos(theta));
714 }
715 }
716
717 template <typename FT>
718 Quat<FT> Quat<FT>::ln_dif(const Quat& a, const Quat& b)
719 {
720 Quat<FT> dif = a.inverse()*b;
721 dif.normalize();
722 return dif.log();
723 }
724
725 template <typename FT>
726 Quat<FT> Quat<FT>::squad_tangent(const Quat<FT>& before, const Quat<FT>& center, const Quat<FT>& after)
727 {
728 Quat<FT> l1 = Quat<FT>::ln_dif(center, before);
729 Quat<FT> l2 = Quat<FT>::ln_dif(center, after);
730 Quat<FT> e;
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());
734
735 // if (Quat<FT>::dot(e,b) < 0.0)
736 // e.negate();
737
738 return e;
739 }
740
741 template <typename FT>
743 {
744 // The rand() function is not very portable and may not be available on your system.
745 // Add the appropriate include or replace it by another random function in case of problem.
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);
752 }
753
755 template <typename FT> inline
756 std::ostream& operator<<(std::ostream& os, const Quat<FT>& Q)
757 {
758 return os << Q[0] << ' ' << Q[1] << ' ' << Q[2] << ' ' << Q[3];
759 }
760
762 template <typename FT> inline
763 std::istream& operator>>(std::istream& is, Quat<FT>& Q) {
764 return is >> Q[0] >> Q[1] >> Q[2] >> Q[3];
765 }
766
768 template <class FT> inline
769 bool has_nan(const Quat<FT>& Q) {
770 for (int i=0; i<4; ++i) {
771 if (std::isnan(Q[i]) || std::isinf(Q[i]))
772 return true;
773 }
774 return false;
775 }
776
777}
778
779
780#endif // EASY3D_CORE_QUATERNION_H
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 > &center, 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