Control MIDI in Ableton Live with a MYO armband
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

Quaternion.hpp 4.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. // Copyright (C) 2013-2014 Thalmic Labs Inc.
  2. // Distributed under the Myo SDK license agreement. See LICENSE.txt for details.
  3. #pragma once
  4. #include <cmath>
  5. #include "Vector3.hpp"
  6. namespace myo {
  7. /// A quaternion that can be used to represent a rotation.
  8. /// This type provides only very basic functionality to store quaternions that's sufficient to retrieve the data to
  9. /// be placed in a full featured quaternion type.
  10. template<typename T>
  11. class Quaternion {
  12. public:
  13. /// Construct a quaternion that represents zero rotation (i.e. the multiplicative identity).
  14. Quaternion()
  15. : _x(0)
  16. , _y(0)
  17. , _z(0)
  18. , _w(1)
  19. {
  20. }
  21. /// Construct a quaternion with the provided components.
  22. Quaternion(T x, T y, T z, T w)
  23. : _x(x)
  24. , _y(y)
  25. , _z(z)
  26. , _w(w)
  27. {
  28. }
  29. /// Set the components of this quaternion to be those of the other.
  30. Quaternion& operator=(const Quaternion other)
  31. {
  32. _x = other._x;
  33. _y = other._y;
  34. _z = other._z;
  35. _w = other._w;
  36. return *this;
  37. }
  38. /// Return the x-component of this quaternion's vector.
  39. T x() const { return _x; }
  40. /// Return the y-component of this quaternion's vector.
  41. T y() const { return _y; }
  42. /// Return the z-component of this quaternion's vector.
  43. T z() const { return _z; }
  44. /// Return the w-component (scalar) of this quaternion.
  45. T w() const { return _w; }
  46. /// Return the quaternion multiplied by \a rhs.
  47. /// Note that quaternion multiplication is not commutative.
  48. Quaternion operator*(const Quaternion& rhs) const
  49. {
  50. return Quaternion(
  51. _w * rhs._x + _x * rhs._w + _y * rhs._z - _z * rhs._y,
  52. _w * rhs._y - _x * rhs._z + _y * rhs._w + _z * rhs._x,
  53. _w * rhs._z + _x * rhs._y - _y * rhs._x + _z * rhs._w,
  54. _w * rhs._w - _x * rhs._x - _y * rhs._y - _z * rhs._z
  55. );
  56. }
  57. /// Multiply this quaternion by \a rhs.
  58. /// Return this quaternion updated with the result.
  59. Quaternion& operator*=(const Quaternion& rhs)
  60. {
  61. *this = *this * rhs;
  62. return *this;
  63. }
  64. /// Return the unit quaternion corresponding to the same rotation as this one.
  65. Quaternion normalized() const
  66. {
  67. T magnitude = std::sqrt(_x * _x + _y * _y + _z * _z + _w * _w);
  68. return Quaternion(_x / magnitude, _y / magnitude, _z / magnitude, _w / magnitude);
  69. }
  70. /// Return this quaternion's conjugate.
  71. Quaternion conjugate() const
  72. {
  73. return Quaternion(-_x, -_y, -_z, _w);
  74. }
  75. /// Return a quaternion that represents a right-handed rotation of \a angle radians about the given \a axis.
  76. /// \a axis The unit vector representing the axis of rotation.
  77. /// \a angle The angle of rotation, in radians.
  78. static Quaternion fromAxisAngle(const myo::Vector3<T>& axis, T angle)
  79. {
  80. return Quaternion(axis.x() * std::sin(angle / 2),
  81. axis.y() * std::sin(angle / 2),
  82. axis.z() * std::sin(angle / 2),
  83. std::cos(angle / 2));
  84. }
  85. private:
  86. T _x, _y, _z, _w;
  87. };
  88. /// Return a copy of this \a vec rotated by \a quat.
  89. /// \relates myo::Quaternion
  90. template<typename T>
  91. Vector3<T> rotate(const Quaternion<T>& quat, const Vector3<T>& vec)
  92. {
  93. myo::Quaternion<T> qvec(vec.x(), vec.y(), vec.z(), 0);
  94. myo::Quaternion<T> result = quat * qvec * quat.conjugate();
  95. return Vector3<T>(result.x(), result.y(), result.z());
  96. }
  97. /// Return a quaternion that represents a rotation from vector \a from to \a to.
  98. /// \relates myo::Quaternion
  99. /// See http://stackoverflow.com/questions/1171849/finding-quaternion-representing-the-rotation-from-one-vector-to-another
  100. /// for some explanation.
  101. template<typename T>
  102. Quaternion<T> rotate(const Vector3<T>& from, const Vector3<T>& to)
  103. {
  104. Vector3<T> cross = from.cross(to);
  105. // The product of the square of magnitudes and the cosine of the angle between from and to.
  106. T cosTheta = from.dot(to);
  107. // Return identity if the vectors are the same direction.
  108. if (cosTheta >= 1) {
  109. return Quaternion<T>();
  110. }
  111. // The product of the square of the magnitudes
  112. T k = std::sqrt(from.dot(from) * to.dot(to));
  113. // Return identity in the degenerate case.
  114. if (k <= 0) {
  115. return Quaternion<T>();
  116. }
  117. // Special handling for vectors facing opposite directions.
  118. if (cosTheta / k <= -1) {
  119. Vector3<T> xAxis(1, 0, 0);
  120. Vector3<T> yAxis(0, 1, 0);
  121. cross = from.cross(std::abs(from.dot(xAxis)) < 1 ? xAxis : yAxis);
  122. k = cosTheta = 0;
  123. }
  124. return Quaternion<T>(
  125. cross.x(),
  126. cross.y(),
  127. cross.z(),
  128. k + cosTheta);
  129. }
  130. } // namespace myo