// // SPDX-License-Identifier: BSD-3-Clause // Copyright Contributors to the OpenEXR Project. // // // Functions for computing reference frames. // #ifndef INCLUDED_IMATHFRAME_H #define INCLUDED_IMATHFRAME_H #include "ImathNamespace.h" IMATH_INTERNAL_NAMESPACE_HEADER_ENTER /// @cond Doxygen_Suppress template class Vec3; template class Matrix44; /// @endcond /// /// @{ /// @name Functions for computing reference frames /// /// These methods compute a set of reference frames, defined by their /// transformation matrix, along a curve. It is designed so that the /// array of points and the array of matrices used to fetch these /// routines don't need to be ordered as the curve. /// /// A typical usage would be : /// /// m[0] = IMATH_INTERNAL_NAMESPACE::firstFrame( p[0], p[1], p[2] ); /// for( int i = 1; i < n - 1; i++ ) /// { /// m[i] = IMATH_INTERNAL_NAMESPACE::nextFrame( m[i-1], p[i-1], p[i], t[i-1], t[i] ); /// } /// m[n-1] = IMATH_INTERNAL_NAMESPACE::lastFrame( m[n-2], p[n-2], p[n-1] ); /// /// See Graphics Gems I for the underlying algorithm. template Matrix44 constexpr firstFrame (const Vec3&, // First point const Vec3&, // Second point const Vec3&) IMATH_NOEXCEPT; // Third point template Matrix44 constexpr nextFrame (const Matrix44&, // Previous matrix const Vec3&, // Previous point const Vec3&, // Current point Vec3&, // Previous tangent Vec3&) IMATH_NOEXCEPT; // Current tangent template Matrix44 constexpr lastFrame (const Matrix44&, // Previous matrix const Vec3&, // Previous point const Vec3&) IMATH_NOEXCEPT; // Last point /// /// Compute the first reference frame along a curve. /// /// This function returns the transformation matrix to the reference /// frame defined by the three points `pi`, `pj` and `pk`. Note that /// if the two vectors <`pi`,`pj`> and <`pi`,`pk`> are colinears, an /// arbitrary twist value will be choosen. /// /// Throw `std::domain_error` if `pi` and `pj` are equal. /// /// @param pi /// First point /// @param pj /// Second point /// @param pk /// Third point /// template Matrix44 constexpr firstFrame (const Vec3& pi, // first point const Vec3& pj, // secont point const Vec3& pk) IMATH_NOEXCEPT // third point { Vec3 t = pj - pi; t.normalizeExc(); Vec3 n = t.cross (pk - pi); n.normalize(); if (n.length() == 0.0f) { int i = fabs (t[0]) < fabs (t[1]) ? 0 : 1; if (fabs (t[2]) < fabs (t[i])) i = 2; Vec3 v (0.0, 0.0, 0.0); v[i] = 1.0; n = t.cross (v); n.normalize(); } Vec3 b = t.cross (n); Matrix44 M; M[0][0] = t[0]; M[0][1] = t[1]; M[0][2] = t[2]; M[0][3] = 0.0, M[1][0] = n[0]; M[1][1] = n[1]; M[1][2] = n[2]; M[1][3] = 0.0, M[2][0] = b[0]; M[2][1] = b[1]; M[2][2] = b[2]; M[2][3] = 0.0, M[3][0] = pi[0]; M[3][1] = pi[1]; M[3][2] = pi[2]; M[3][3] = 1.0; return M; } /// /// Compute the next reference frame along a curve. /// /// This function returns the transformation matrix to the next reference /// frame defined by the previously computed transformation matrix and the /// new point and tangent vector along the curve. /// /// @param Mi /// The previous matrix /// @param pi /// The previous point /// @param pj /// The current point /// @param ti /// The previous tangent vector /// @param tj /// The current tangent vector template Matrix44 constexpr nextFrame (const Matrix44& Mi, // Previous matrix const Vec3& pi, // Previous point const Vec3& pj, // Current point Vec3& ti, // Previous tangent vector Vec3& tj) IMATH_NOEXCEPT // Current tangent vector { Vec3 a (0.0, 0.0, 0.0); /// Rotation axis. T r = 0.0; // Rotation angle. if (ti.length() != 0.0 && tj.length() != 0.0) { ti.normalize(); tj.normalize(); T dot = ti.dot (tj); // // This is *really* necessary : // if (dot > 1.0) dot = 1.0; else if (dot < -1.0) dot = -1.0; r = acosf (dot); a = ti.cross (tj); } if (a.length() != 0.0 && r != 0.0) { Matrix44 R; R.setAxisAngle (a, r); Matrix44 Tj; Tj.translate (pj); Matrix44 Ti; Ti.translate (-pi); return Mi * Ti * R * Tj; } else { Matrix44 Tr; Tr.translate (pj - pi); return Mi * Tr; } } /// /// Compute the last reference frame along a curve. /// /// This function returns the transformation matrix to the last reference /// frame defined by the previously computed transformation matrix and the /// last point along the curve. /// /// @param Mi /// The previous matrix /// @param pi /// The previous point /// @param pj /// The last point template Matrix44 constexpr lastFrame (const Matrix44& Mi, // Previous matrix const Vec3& pi, // Previous point const Vec3& pj) IMATH_NOEXCEPT // Last point { Matrix44 Tr; Tr.translate (pj - pi); return Mi * Tr; } /// @} IMATH_INTERNAL_NAMESPACE_HEADER_EXIT #endif // INCLUDED_IMATHFRAME_H