ImathFrame.h 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  1. //
  2. // SPDX-License-Identifier: BSD-3-Clause
  3. // Copyright Contributors to the OpenEXR Project.
  4. //
  5. //
  6. // Functions for computing reference frames.
  7. //
  8. #ifndef INCLUDED_IMATHFRAME_H
  9. #define INCLUDED_IMATHFRAME_H
  10. #include "ImathNamespace.h"
  11. IMATH_INTERNAL_NAMESPACE_HEADER_ENTER
  12. /// @cond Doxygen_Suppress
  13. template <class T> class Vec3;
  14. template <class T> class Matrix44;
  15. /// @endcond
  16. ///
  17. /// @{
  18. /// @name Functions for computing reference frames
  19. ///
  20. /// These methods compute a set of reference frames, defined by their
  21. /// transformation matrix, along a curve. It is designed so that the
  22. /// array of points and the array of matrices used to fetch these
  23. /// routines don't need to be ordered as the curve.
  24. ///
  25. /// A typical usage would be :
  26. ///
  27. /// m[0] = IMATH_INTERNAL_NAMESPACE::firstFrame( p[0], p[1], p[2] );
  28. /// for( int i = 1; i < n - 1; i++ )
  29. /// {
  30. /// m[i] = IMATH_INTERNAL_NAMESPACE::nextFrame( m[i-1], p[i-1], p[i], t[i-1], t[i] );
  31. /// }
  32. /// m[n-1] = IMATH_INTERNAL_NAMESPACE::lastFrame( m[n-2], p[n-2], p[n-1] );
  33. ///
  34. /// See Graphics Gems I for the underlying algorithm.
  35. template <class T>
  36. Matrix44<T> constexpr firstFrame (const Vec3<T>&, // First point
  37. const Vec3<T>&, // Second point
  38. const Vec3<T>&) IMATH_NOEXCEPT; // Third point
  39. template <class T>
  40. Matrix44<T> constexpr nextFrame (const Matrix44<T>&, // Previous matrix
  41. const Vec3<T>&, // Previous point
  42. const Vec3<T>&, // Current point
  43. Vec3<T>&, // Previous tangent
  44. Vec3<T>&) IMATH_NOEXCEPT; // Current tangent
  45. template <class T>
  46. Matrix44<T> constexpr lastFrame (const Matrix44<T>&, // Previous matrix
  47. const Vec3<T>&, // Previous point
  48. const Vec3<T>&) IMATH_NOEXCEPT; // Last point
  49. ///
  50. /// Compute the first reference frame along a curve.
  51. ///
  52. /// This function returns the transformation matrix to the reference
  53. /// frame defined by the three points `pi`, `pj` and `pk`. Note that
  54. /// if the two vectors <`pi`,`pj`> and <`pi`,`pk`> are colinears, an
  55. /// arbitrary twist value will be choosen.
  56. ///
  57. /// Throw `std::domain_error` if `pi` and `pj` are equal.
  58. ///
  59. /// @param pi
  60. /// First point
  61. /// @param pj
  62. /// Second point
  63. /// @param pk
  64. /// Third point
  65. ///
  66. template <class T>
  67. Matrix44<T> constexpr firstFrame (const Vec3<T>& pi, // first point
  68. const Vec3<T>& pj, // secont point
  69. const Vec3<T>& pk) IMATH_NOEXCEPT // third point
  70. {
  71. Vec3<T> t = pj - pi;
  72. t.normalizeExc();
  73. Vec3<T> n = t.cross (pk - pi);
  74. n.normalize();
  75. if (n.length() == 0.0f)
  76. {
  77. int i = fabs (t[0]) < fabs (t[1]) ? 0 : 1;
  78. if (fabs (t[2]) < fabs (t[i]))
  79. i = 2;
  80. Vec3<T> v (0.0, 0.0, 0.0);
  81. v[i] = 1.0;
  82. n = t.cross (v);
  83. n.normalize();
  84. }
  85. Vec3<T> b = t.cross (n);
  86. Matrix44<T> M;
  87. M[0][0] = t[0];
  88. M[0][1] = t[1];
  89. M[0][2] = t[2];
  90. M[0][3] = 0.0, M[1][0] = n[0];
  91. M[1][1] = n[1];
  92. M[1][2] = n[2];
  93. M[1][3] = 0.0, M[2][0] = b[0];
  94. M[2][1] = b[1];
  95. M[2][2] = b[2];
  96. M[2][3] = 0.0, M[3][0] = pi[0];
  97. M[3][1] = pi[1];
  98. M[3][2] = pi[2];
  99. M[3][3] = 1.0;
  100. return M;
  101. }
  102. ///
  103. /// Compute the next reference frame along a curve.
  104. ///
  105. /// This function returns the transformation matrix to the next reference
  106. /// frame defined by the previously computed transformation matrix and the
  107. /// new point and tangent vector along the curve.
  108. ///
  109. /// @param Mi
  110. /// The previous matrix
  111. /// @param pi
  112. /// The previous point
  113. /// @param pj
  114. /// The current point
  115. /// @param ti
  116. /// The previous tangent vector
  117. /// @param tj
  118. /// The current tangent vector
  119. template <class T>
  120. Matrix44<T> constexpr nextFrame (const Matrix44<T>& Mi, // Previous matrix
  121. const Vec3<T>& pi, // Previous point
  122. const Vec3<T>& pj, // Current point
  123. Vec3<T>& ti, // Previous tangent vector
  124. Vec3<T>& tj) IMATH_NOEXCEPT // Current tangent vector
  125. {
  126. Vec3<T> a (0.0, 0.0, 0.0); /// Rotation axis.
  127. T r = 0.0; // Rotation angle.
  128. if (ti.length() != 0.0 && tj.length() != 0.0)
  129. {
  130. ti.normalize();
  131. tj.normalize();
  132. T dot = ti.dot (tj);
  133. //
  134. // This is *really* necessary :
  135. //
  136. if (dot > 1.0)
  137. dot = 1.0;
  138. else if (dot < -1.0)
  139. dot = -1.0;
  140. r = acosf (dot);
  141. a = ti.cross (tj);
  142. }
  143. if (a.length() != 0.0 && r != 0.0)
  144. {
  145. Matrix44<T> R;
  146. R.setAxisAngle (a, r);
  147. Matrix44<T> Tj;
  148. Tj.translate (pj);
  149. Matrix44<T> Ti;
  150. Ti.translate (-pi);
  151. return Mi * Ti * R * Tj;
  152. }
  153. else
  154. {
  155. Matrix44<T> Tr;
  156. Tr.translate (pj - pi);
  157. return Mi * Tr;
  158. }
  159. }
  160. ///
  161. /// Compute the last reference frame along a curve.
  162. ///
  163. /// This function returns the transformation matrix to the last reference
  164. /// frame defined by the previously computed transformation matrix and the
  165. /// last point along the curve.
  166. ///
  167. /// @param Mi
  168. /// The previous matrix
  169. /// @param pi
  170. /// The previous point
  171. /// @param pj
  172. /// The last point
  173. template <class T>
  174. Matrix44<T> constexpr lastFrame (const Matrix44<T>& Mi, // Previous matrix
  175. const Vec3<T>& pi, // Previous point
  176. const Vec3<T>& pj) IMATH_NOEXCEPT // Last point
  177. {
  178. Matrix44<T> Tr;
  179. Tr.translate (pj - pi);
  180. return Mi * Tr;
  181. }
  182. /// @}
  183. IMATH_INTERNAL_NAMESPACE_HEADER_EXIT
  184. #endif // INCLUDED_IMATHFRAME_H