Quaternion.cpp 2.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  1. #include <cmath>
  2. #include "client/math/Quaternion.h"
  3. Quaternion::Quaternion() : xyz(0.0f, 0.0f, 0.0f), w(0.0f) {
  4. }
  5. Quaternion::Quaternion(float x, float y, float z, float w) : xyz(x, y, z), w(w) {
  6. normalize();
  7. }
  8. Quaternion::Quaternion(const Vector& axis, float angle) {
  9. Vector unit(axis);
  10. xyz.set(unit.normalize());
  11. float sin;
  12. sincosf(angle * (M_PI / 360.0f), &sin, &w);
  13. xyz.mul(sin);
  14. }
  15. Quaternion Quaternion::lerp(float f, const Quaternion& other) const {
  16. return interpolate(1 - f, f, other);
  17. }
  18. Quaternion Quaternion::slerp(float f, const Quaternion& other) const {
  19. float angle = xyz.dot(other.xyz) + w * other.w;
  20. if(angle >= 1.0f) {
  21. return *this;
  22. } else if(angle < -1.0f) {
  23. angle = -1.0f;
  24. }
  25. float arccos = acosf(angle);
  26. float sin = 1.0f / sinf(arccos);
  27. return interpolate(sinf((1 - f) * arccos) * sin, sinf(f * arccos) * sin, other);
  28. }
  29. Quaternion Quaternion::interpolate(float a, float b, const Quaternion& other) const {
  30. Vector interpolated(xyz);
  31. interpolated.mul(a).addMul(other.xyz, b);
  32. return Quaternion(interpolated.getX(), interpolated.getY(), interpolated.getZ(), w * a + other.w * b);
  33. }
  34. void Quaternion::normalize() {
  35. float f = 1.0f / sqrtf(xyz.dot(xyz) + w * w);
  36. xyz.mul(f);
  37. w *= f;
  38. }
  39. Matrix Quaternion::toMatrix() const {
  40. float x = xyz.getX();
  41. float y = xyz.getY();
  42. float z = xyz.getZ();
  43. float x2 = 2 * x * x;
  44. float y2 = 2 * y * y;
  45. float z2 = 2 * z * z;
  46. float xy = 2 * x * y;
  47. float xz = 2 * x * z;
  48. float xw = 2 * x * w;
  49. float zw = 2 * z * w;
  50. float yz = 2 * y * z;
  51. float yw = 2 * y * w;
  52. Matrix m;
  53. m.set(0, 1 - y2 - z2).set(1, xy - zw).set(2, xz + yw);
  54. m.set(4, xy + zw).set(5, 1 - x2 - z2).set(6, yz - xw);
  55. m.set(8, xz - yw).set(9, yz + xw).set(10, 1 - x2 - y2);
  56. return m;
  57. }
  58. void Quaternion::mul(const Quaternion& other) {
  59. Vector v;
  60. v.addMul(other.xyz, w).addMul(xyz, other.w).add(Vector(xyz).cross(other.xyz));
  61. w = w * other.w - xyz.dot(other.xyz);
  62. xyz.set(v);
  63. }