7 #ifndef OPENVDB_MATH_MAT_HAS_BEEN_INCLUDED
8 #define OPENVDB_MATH_MAT_HAS_BEEN_INCLUDED
25 template<
unsigned SIZE,
typename T>
53 str(
unsigned indentation = 0)
const {
59 indent.append(indentation+1,
' ');
64 for (
unsigned i(0); i <
SIZE; i++) {
69 for (
unsigned j(0);
j < SIZE;
j++) {
72 if (
j) ret.append(
", ");
110 void write(std::ostream& os)
const {
111 os.write(reinterpret_cast<const char*>(&
mm),
sizeof(
T)*
SIZE*
SIZE);
115 is.read(reinterpret_cast<char*>(&
mm),
sizeof(
T)*
SIZE*
SIZE);
120 T x =
static_cast<T>(std::fabs(
mm[0]));
122 x =
std::max(x, static_cast<T>(std::fabs(
mm[i])));
164 template<
typename T>
class Quat;
165 template<
typename T>
class Vec3;
170 template<
class MatType>
198 r[0][0]=
T(1) - (yy+zz); r[0][1]=xy + wz; r[0][2]=xz - wy;
199 r[1][0]=xy - wz; r[1][1]=
T(1) - (xx+zz); r[1][2]=yz + wx;
200 r[2][0]=xz + wy; r[2][1]=yz - wx; r[2][2]=
T(1) - (xx+yy);
202 if(MatType::numColumns() == 4)
padMat4(r);
211 template<
class MatType>
216 T c =
static_cast<T>(
cos(angle));
217 T s =
static_cast<T>(
sin(angle));
220 result.setIdentity();
242 throw ValueError(
"Unrecognized rotation axis");
249 template<
class MatType>
254 T txy, txz, tyz, sx, sy, sz;
259 T c(
cos(
double(angle)));
260 T s(
sin(
double(angle)));
265 result[0][0] = axis[0]*axis[0] * t +
c;
266 result[1][1] = axis[1]*axis[1] * t +
c;
267 result[2][2] = axis[2]*axis[2] * t +
c;
269 txy = axis[0]*axis[1] *
t;
272 txz = axis[0]*axis[2] *
t;
275 tyz = axis[1]*axis[2] *
t;
280 result[0][1] = txy + sz;
281 result[1][0] = txy - sz;
283 result[0][2] = txz - sy;
284 result[2][0] = txz + sy;
286 result[1][2] = tyz + sx;
287 result[2][1] = tyz - sx;
289 if(MatType::numColumns() == 4)
padMat4(result);
290 return MatType(result);
331 template<
class MatType>
342 switch(rotationOrder)
346 theta =
ValueType(math::pi<double>() / 2.0);
350 theta =
ValueType(-math::pi<double>() / 2.0);
357 sqrt( mat[2][1]*mat[2][1] +
358 mat[2][2]*mat[2][2])));
360 return V(phi, theta, psi);
363 theta =
ValueType(math::pi<double>() / 2.0);
367 theta =
ValueType(-math::pi<double>() / 2.0);
374 sqrt(mat[0][2] * mat[0][2] +
375 mat[2][2] * mat[2][2])));
377 return V(theta, psi, phi);
381 theta =
ValueType(math::pi<double>() / 2.0);
385 theta =
ValueType(-math::pi<double>() / 2.0);
392 sqrt(mat[0][0] * mat[0][0] +
393 mat[0][2] * mat[0][2])));
395 return V(psi, phi, theta);
411 mat[0][2] * mat[0][2]),
414 return V(phi, psi, theta);
430 mat[1][2] * mat[1][2]),
433 return V(theta, psi, phi);
438 theta =
ValueType(-math::pi<double>() / 2.0);
442 theta =
ValueType(math::pi<double>() / 2.0);
449 sqrt(mat[0][1] * mat[0][1] +
450 mat[1][1] * mat[1][1])));
452 return V(theta, phi, psi);
457 theta =
ValueType(-math::pi<double>() / 2.0);
461 theta =
ValueType(math::pi<double>() / 2.0);
468 sqrt(mat[0][1] * mat[0][1] +
469 mat[0][0] * mat[0][0])));
471 return V(psi, theta, phi);
476 theta =
ValueType(math::pi<double>() / 2.0);
480 theta =
ValueType(-math::pi<double>() / 2.0);
487 sqrt(mat[1][1] * mat[1][1] +
488 mat[1][2] * mat[1][2])));
490 return V(phi, psi, theta);
493 OPENVDB_THROW(NotImplementedError,
"Euler extraction sequence not implemented");
500 template<
typename MatType,
typename ValueType1,
typename ValueType2>
539 double x =
Abs(v1[0]);
540 double y =
Abs(v1[1]);
541 double z =
Abs(v1[2]);
559 double udot = u.
dot(u);
562 double a = -2 / udot;
563 double b = -2 /
vdot;
564 double c = 4 * u.
dot(v) / (udot *
vdot);
567 result.setIdentity();
569 for (
int j = 0;
j < 3;
j++) {
570 for (
int i = 0; i < 3; i++)
571 result[i][
j] = static_cast<T>(
572 a * u[i] * u[
j] + b * v[i] * v[
j] + c * v[
j] * u[i]);
578 if(MatType::numColumns() == 4)
padMat4(result);
582 double c = v1.
dot(v2);
583 double a = (1.0 -
c) / cross.
dot(cross);
585 double a0 = a * cross[0];
586 double a1 = a * cross[1];
587 double a2 = a * cross[2];
589 double a01 = a0 * cross[1];
590 double a02 = a0 * cross[2];
591 double a12 = a1 * cross[2];
595 r[0][0] =
static_cast<T>(c + a0 * cross[0]);
596 r[0][1] =
static_cast<T>(a01 + cross[2]);
597 r[0][2] =
static_cast<T>(a02 - cross[1]);
598 r[1][0] =
static_cast<T>(a01 - cross[2]);
599 r[1][1] =
static_cast<T>(c + a1 * cross[1]);
600 r[1][2] =
static_cast<T>(a12 + cross[0]);
601 r[2][0] =
static_cast<T>(a02 + cross[1]);
602 r[2][1] =
static_cast<T>(a12 - cross[0]);
603 r[2][2] =
static_cast<T>(c + a2 * cross[2]);
605 if(MatType::numColumns() == 4)
padMat4(r);
613 template<
class MatType>
621 result.setIdentity();
631 template<
class MatType>
637 V(mat[0][0], mat[0][1], mat[0][2]).
length(),
638 V(mat[1][0], mat[1][1], mat[1][2]).
length(),
639 V(mat[2][0], mat[2][1], mat[2][2]).
length());
646 template<
class MatType>
651 return unit(mat, eps, dud);
659 template<
class MatType>
669 for (
int i(0); i < 3; i++) {
672 Vec3<T>(in[i][0], in[i][1], in[i][2]).
unit(eps, scaling[i]));
673 for (
int j=0;
j<3;
j++) result[i][
j] = u[
j];
674 }
catch (ArithmeticError&) {
675 for (
int j=0;
j<3;
j++) result[i][
j] = 0;
686 template <
class MatType>
690 int index0 =
static_cast<int>(axis0);
691 int index1 =
static_cast<int>(axis1);
694 result.setIdentity();
695 if (axis0 == axis1) {
696 result[index1][index0] = shear + 1;
698 result[index1][index0] =
shear;
706 template<
class MatType>
713 r[0][0] =
T(0); r[0][1] = skew.
z(); r[0][2] = -skew.
y();
714 r[1][0] = -skew.
z(); r[1][1] =
T(0); r[2][1] = skew.
x();
715 r[2][0] = skew.
y(); r[2][1] = -skew.
x(); r[2][2] =
T(0);
717 if(MatType::numColumns() == 4)
padMat4(r);
724 template<
class MatType>
731 Vec3<T> horizontal(vertical.
unit().cross(forward).unit());
732 Vec3<T> up(forward.cross(horizontal).unit());
736 r[0][0]=horizontal.
x(); r[0][1]=horizontal.
y(); r[0][2]=horizontal.
z();
737 r[1][0]=
up.x(); r[1][1]=
up.y(); r[1][2]=
up.z();
738 r[2][0]=forward.
x(); r[2][1]=forward.
y(); r[2][2]=forward.
z();
740 if(MatType::numColumns() == 4)
padMat4(r);
749 template<
class MatType>
756 Vec3<T> ourUnitAxis(source.row(axis).unit());
759 T parallel = unitDir.dot(ourUnitAxis);
769 T angleBetween(
angle(unitDir, ourUnitAxis));
774 rotation.setToRotation(rotationAxis, angleBetween);
781 template<
class MatType>
785 dest[0][3] = dest[1][3] = dest[2][3] = 0;
786 dest[3][2] = dest[3][1] = dest[3][0] = 0;
795 template<
typename MatType>
797 sqrtSolve(
const MatType& aA, MatType& aB,
double aTol=0.01)
799 unsigned int iterations =
static_cast<unsigned int>(
log(aTol)/
log(0.5));
803 Z[0] = MatType::identity();
805 unsigned int current = 0;
806 for (
unsigned int iteration=0; iteration < iterations; iteration++) {
807 unsigned int last = current;
810 MatType invY = Y[
last].inverse();
811 MatType invZ = Z[
last].inverse();
813 Y[current] = 0.5 * (Y[
last] + invZ);
814 Z[current] = 0.5 * (Z[
last] + invY);
820 template<
typename MatType>
822 powSolve(
const MatType& aA, MatType& aB,
double aPower,
double aTol=0.01)
824 unsigned int iterations =
static_cast<unsigned int>(
log(aTol)/
log(0.5));
826 const bool inverted = (aPower < 0.0);
827 if (inverted) { aPower = -aPower; }
829 unsigned int whole =
static_cast<unsigned int>(aPower);
830 double fraction = aPower - whole;
832 MatType
R = MatType::identity();
833 MatType partial = aA;
835 double contribution = 1.0;
836 for (
unsigned int iteration = 0; iteration < iterations; iteration++) {
839 if (fraction >= contribution) {
841 fraction -= contribution;
847 if (whole & 1) { R *= partial; }
849 if (whole) { partial *= partial; }
852 if (inverted) { aB = R.inverse(); }
858 template<
typename MatType>
862 return m.eq(MatType::identity());
867 template<
typename MatType>
878 template<
typename MatType>
882 return m.eq(m.transpose());
887 template<
typename MatType>
894 MatType temp = m * m.transpose();
895 return temp.eq(MatType::identity());
900 template<
typename MatType>
906 for (
int i = 0; i <
n; ++i) {
907 for (
int j = 0;
j <
n; ++
j) {
918 template<
typename MatType>
925 for(
int j = 0;
j<
n; ++
j) {
928 for (
int i = 0; i<
n; ++i) {
929 column_sum += std::fabs(matrix(i,
j));
939 template<
typename MatType>
946 for(
int i = 0; i<
n; ++i) {
949 for (
int j = 0;
j<
n; ++
j) {
950 row_sum += std::fabs(matrix(i,
j));
966 template<
typename MatType>
969 MatType& positive_hermitian,
unsigned int MAX_ITERATIONS=100)
972 MatType new_unitary(input);
977 unsigned int iteration(0);
987 unitary_inv = unitary.inverse();
992 l1nm_of_u_inv =
lOneNorm(unitary_inv);
994 gamma =
sqrt(
sqrt( (l1nm_of_u_inv * linf_of_u_inv ) / (l1nm_of_u * linf_of_u) ));
996 new_unitary = 0.5*(gamma * unitary + (1./gamma) * unitary_inv.transpose() );
999 unitary = new_unitary;
1002 if (iteration > MAX_ITERATIONS)
return false;
1006 positive_hermitian = unitary.transpose() * input;
1013 template<
unsigned SIZE,
typename T>
1020 for (
unsigned i = 0; i < size-1; ++i, ++m0p, ++m1p) {
1027 template<
unsigned SIZE,
typename T>
1034 for (
unsigned i = 0; i < size-1; ++i, ++m0p, ++m1p) {
1044 #endif // OPENVDB_MATH_MAT_HAS_BEEN_INCLUDED
SYS_API double cos(double x)
bool isInvertible(const MatType &m)
Determine if a matrix is invertible.
bool isFinite() const
True if no Nan or Inf values are present.
SYS_API double atan2(double y, double x)
bool polarDecomposition(const MatType &input, MatType &unitary, MatType &positive_hermitian, unsigned int MAX_ITERATIONS=100)
Decompose an invertible 3×3 matrix into a unitary matrix followed by a symmetric matrix (positive sem...
bool cwiseGreaterThan(const Mat< SIZE, T > &m0, const Mat< SIZE, T > &m1)
bool isExactlyEqual(const T0 &a, const T1 &b)
Return true if a is exactly equal to b.
bool normalize(T eps=T(1.0e-7))
this = normalized this
MatType shear(Axis axis0, Axis axis1, typename MatType::value_type shear)
Set the matrix to a shear along axis0 by a fraction of axis1.
void write(std::ostream &os) const
IMF_EXPORT IMATH_NAMESPACE::V3f direction(const IMATH_NAMESPACE::Box2i &dataWindow, const IMATH_NAMESPACE::V2f &pixelPosition)
GLsizei const GLchar *const * string
bool isZero() const
True if all elements are exactly zero.
vfloat4 sqrt(const vfloat4 &a)
GLdouble GLdouble GLdouble z
const T * asPointer() const
MatType aim(const Vec3< typename MatType::value_type > &direction, const Vec3< typename MatType::value_type > &vertical)
Return an orientation matrix such that z points along direction, and y is along the direction / verti...
bool isIdentity(const MatType &m)
Determine if a matrix is an identity matrix.
GLboolean GLboolean GLboolean GLboolean a
GLuint GLsizei GLsizei * length
#define OPENVDB_USE_VERSION_NAMESPACE
**But if you need a result
GLfloat GLfloat GLfloat v2
GLdouble GLdouble GLdouble q
MatType unit(const MatType &mat, typename MatType::value_type eps=1.0e-8)
Return a copy of the given matrix with its upper 3×3 rows normalized.
T dot(const Vec3< T > &v) const
Dot product.
Tolerance for floating-point comparison.
Vec3< typename MatType::value_type > eulerAngles(const MatType &mat, RotationOrder rotationOrder, typename MatType::value_type eps=static_cast< typename MatType::value_type >(1.0e-8))
Return the Euler angles composing the given rotation matrix.
bool isNan() const
True if a Nan is present in this matrix.
bool isApproxEqual(const Type &a, const Type &b, const Type &tolerance)
Return true if a is equal to b to within the given tolerance.
static unsigned numColumns()
Coord Abs(const Coord &xyz)
bool isDiagonal(const MatType &mat)
Determine if a matrix is diagonal.
void read(std::istream &is)
friend std::ostream & operator<<(std::ostream &ostr, const Mat< SIZE, T > &m)
Write a Mat to an output stream.
General-purpose arithmetic and comparison routines, most of which accept arbitrary value types (or at...
bool isInfinite(const float x)
Return true if x is an infinity value (either positive infinity or negative infinity).
GLsizei GLsizei GLchar * source
Vec3< T > cross(const Vec3< T > &v) const
Return the cross product of "this" vector and v;.
bool isNan(const float x)
Return true if x is a NaN (Not-A-Number) value.
T angle(const Vec2< T > &v1, const Vec2< T > &v2)
T * operator[](int i)
Array style reference to ith row.
bool cwiseLessThan(const Mat< SIZE, T > &m0, const Mat< SIZE, T > &m1)
bool isUnitary(const MatType &m)
Determine if a matrix is unitary (i.e., rotation or reflection).
Vec3< T > unit(T eps=0) const
return normalized this, throws if null vector
GLboolean GLboolean GLboolean b
std::string str(unsigned indentation=0) const
vfloat4 vdot(const vfloat4 &a, const vfloat4 &b)
Return the float dot (inner) product of a and b in every component.
static unsigned numRows()
const T * operator[](int i) const
Array style reference to ith row.
__hostdev__ uint64_t last(uint32_t i) const
MatType scale(const Vec3< typename MatType::value_type > &s)
Return a matrix that scales by s.
T dot(const Quat &q) const
Dot product.
MatType & padMat4(MatType &dest)
Write 0s along Mat4's last row and column, and a 1 on its diagonal.
GA_API const UT_StringHolder up
T & x()
Reference to the component, e.g. v.x() = 4.5f;.
T * asPointer()
Direct access to the internal data.
bool isSymmetric(const MatType &m)
Determine if a matrix is symmetric.
bool isInfinite() const
True if an Inf is present in this matrix.
T & x()
Reference to the component, e.g. q.x() = 4.5f;.
ImageBuf OIIO_API max(Image_or_Const A, Image_or_Const B, ROI roi={}, int nthreads=0)
Vec3< typename MatType::value_type > getScale(const MatType &mat)
Return a Vec3 representing the lengths of the passed matrix's upper 3×3's rows.
static unsigned numElements()
IMATH_INTERNAL_NAMESPACE_HEADER_ENTER IMATH_HOSTDEVICE constexpr T abs(T a) IMATH_NOEXCEPT
MatType::ValueType lOneNorm(const MatType &matrix)
Return the L1 norm of an N×N matrix.
OIIO_FORCEINLINE T log(const T &v)
T absMax() const
Return the maximum of the absolute of all elements in this matrix.
void sqrtSolve(const MatType &aA, MatType &aB, double aTol=0.01)
Solve for A=B*B, given A.
MatType snapMatBasis(const MatType &source, Axis axis, const Vec3< typename MatType::value_type > &direction)
This function snaps a specific axis to a specific direction, preserving scaling.
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
MatType::ValueType lInfinityNorm(const MatType &matrix)
Return the L∞ norm of an N×N matrix.
SIM_DerVector3 cross(const SIM_DerVector3 &lhs, const SIM_DerVector3 &rhs)
MatType skew(const Vec3< typename MatType::value_type > &skew)
Return a matrix as the cross product of the given vector.
SYS_API double sin(double x)
bool isZero(const Type &x)
Return true if x is exactly equal to zero.
#define OPENVDB_THROW(exception, message)
bool isFinite(const float x)
Return true if x is finite.
void powSolve(const MatType &aA, MatType &aB, double aPower, double aTol=0.01)
MatType rotation(const Quat< typename MatType::value_type > &q, typename MatType::value_type eps=static_cast< typename MatType::value_type >(1.0e-8))
Return the rotation matrix specified by the given quaternion.