matrix_interpolation.inl 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. /// @ref gtx_matrix_interpolation
  2. #include "../ext/scalar_constants.hpp"
  3. #include <limits>
  4. namespace glm
  5. {
  6. template<typename T, qualifier Q>
  7. GLM_FUNC_QUALIFIER void axisAngle(mat<4, 4, T, Q> const& m, vec<3, T, Q>& axis, T& angle)
  8. {
  9. T const epsilon =
  10. std::numeric_limits<T>::epsilon() * static_cast<T>(1e2);
  11. bool const nearSymmetrical =
  12. abs(m[1][0] - m[0][1]) < epsilon &&
  13. abs(m[2][0] - m[0][2]) < epsilon &&
  14. abs(m[2][1] - m[1][2]) < epsilon;
  15. if(nearSymmetrical)
  16. {
  17. bool const nearIdentity =
  18. abs(m[1][0] + m[0][1]) < epsilon &&
  19. abs(m[2][0] + m[0][2]) < epsilon &&
  20. abs(m[2][1] + m[1][2]) < epsilon &&
  21. abs(m[0][0] + m[1][1] + m[2][2] - T(3.0)) < epsilon;
  22. if (nearIdentity)
  23. {
  24. angle = static_cast<T>(0.0);
  25. axis = vec<3, T, Q>(
  26. static_cast<T>(1.0), static_cast<T>(0.0), static_cast<T>(0.0));
  27. return;
  28. }
  29. angle = pi<T>();
  30. T xx = (m[0][0] + static_cast<T>(1.0)) * static_cast<T>(0.5);
  31. T yy = (m[1][1] + static_cast<T>(1.0)) * static_cast<T>(0.5);
  32. T zz = (m[2][2] + static_cast<T>(1.0)) * static_cast<T>(0.5);
  33. T xy = (m[1][0] + m[0][1]) * static_cast<T>(0.25);
  34. T xz = (m[2][0] + m[0][2]) * static_cast<T>(0.25);
  35. T yz = (m[2][1] + m[1][2]) * static_cast<T>(0.25);
  36. if((xx > yy) && (xx > zz))
  37. {
  38. if(xx < epsilon)
  39. {
  40. axis.x = static_cast<T>(0.0);
  41. axis.y = static_cast<T>(0.7071);
  42. axis.z = static_cast<T>(0.7071);
  43. }
  44. else
  45. {
  46. axis.x = sqrt(xx);
  47. axis.y = xy / axis.x;
  48. axis.z = xz / axis.x;
  49. }
  50. }
  51. else if (yy > zz)
  52. {
  53. if(yy < epsilon)
  54. {
  55. axis.x = static_cast<T>(0.7071);
  56. axis.y = static_cast<T>(0.0);
  57. axis.z = static_cast<T>(0.7071);
  58. }
  59. else
  60. {
  61. axis.y = sqrt(yy);
  62. axis.x = xy / axis.y;
  63. axis.z = yz / axis.y;
  64. }
  65. }
  66. else
  67. {
  68. if (zz < epsilon)
  69. {
  70. axis.x = static_cast<T>(0.7071);
  71. axis.y = static_cast<T>(0.7071);
  72. axis.z = static_cast<T>(0.0);
  73. }
  74. else
  75. {
  76. axis.z = sqrt(zz);
  77. axis.x = xz / axis.z;
  78. axis.y = yz / axis.z;
  79. }
  80. }
  81. return;
  82. }
  83. T const angleCos = (m[0][0] + m[1][1] + m[2][2] - static_cast<T>(1)) * static_cast<T>(0.5);
  84. if(angleCos >= static_cast<T>(1.0))
  85. {
  86. angle = static_cast<T>(0.0);
  87. }
  88. else if (angleCos <= static_cast<T>(-1.0))
  89. {
  90. angle = pi<T>();
  91. }
  92. else
  93. {
  94. angle = acos(angleCos);
  95. }
  96. axis = glm::normalize(glm::vec<3, T, Q>(
  97. m[1][2] - m[2][1], m[2][0] - m[0][2], m[0][1] - m[1][0]));
  98. }
  99. template<typename T, qualifier Q>
  100. GLM_FUNC_QUALIFIER mat<4, 4, T, Q> axisAngleMatrix(vec<3, T, Q> const& axis, T const angle)
  101. {
  102. T c = cos(angle);
  103. T s = sin(angle);
  104. T t = static_cast<T>(1) - c;
  105. vec<3, T, Q> n = normalize(axis);
  106. return mat<4, 4, T, Q>(
  107. t * n.x * n.x + c, t * n.x * n.y + n.z * s, t * n.x * n.z - n.y * s, static_cast<T>(0.0),
  108. t * n.x * n.y - n.z * s, t * n.y * n.y + c, t * n.y * n.z + n.x * s, static_cast<T>(0.0),
  109. t * n.x * n.z + n.y * s, t * n.y * n.z - n.x * s, t * n.z * n.z + c, static_cast<T>(0.0),
  110. static_cast<T>(0.0), static_cast<T>(0.0), static_cast<T>(0.0), static_cast<T>(1.0));
  111. }
  112. template<typename T, qualifier Q>
  113. GLM_FUNC_QUALIFIER mat<4, 4, T, Q> extractMatrixRotation(mat<4, 4, T, Q> const& m)
  114. {
  115. return mat<4, 4, T, Q>(
  116. m[0][0], m[0][1], m[0][2], static_cast<T>(0.0),
  117. m[1][0], m[1][1], m[1][2], static_cast<T>(0.0),
  118. m[2][0], m[2][1], m[2][2], static_cast<T>(0.0),
  119. static_cast<T>(0.0), static_cast<T>(0.0), static_cast<T>(0.0), static_cast<T>(1.0));
  120. }
  121. template<typename T, qualifier Q>
  122. GLM_FUNC_QUALIFIER mat<4, 4, T, Q> interpolate(mat<4, 4, T, Q> const& m1, mat<4, 4, T, Q> const& m2, T const delta)
  123. {
  124. mat<4, 4, T, Q> m1rot = extractMatrixRotation(m1);
  125. mat<4, 4, T, Q> dltRotation = m2 * transpose(m1rot);
  126. vec<3, T, Q> dltAxis;
  127. T dltAngle;
  128. axisAngle(dltRotation, dltAxis, dltAngle);
  129. mat<4, 4, T, Q> out = axisAngleMatrix(dltAxis, dltAngle * delta) * m1rot;
  130. out[3][0] = m1[3][0] + delta * (m2[3][0] - m1[3][0]);
  131. out[3][1] = m1[3][1] + delta * (m2[3][1] - m1[3][1]);
  132. out[3][2] = m1[3][2] + delta * (m2[3][2] - m1[3][2]);
  133. return out;
  134. }
  135. }//namespace glm