7 #ifndef OPENVDB_MATH_MAT_HAS_BEEN_INCLUDED 8 #define OPENVDB_MATH_MAT_HAS_BEEN_INCLUDED 25 template<
unsigned SIZE,
typename T>
33 #if OPENVDB_ABI_VERSION_NUMBER >= 8 45 for (
unsigned i(0); i < numElements(); ++i) {
50 Mat& operator=(
Mat const& src) {
52 for (
unsigned i = 0; i < numElements(); ++i) {
61 static unsigned numRows() {
return SIZE; }
75 str(
unsigned indentation = 0)
const {
81 indent.append(indentation+1,
' ');
86 for (
unsigned i(0); i < SIZE; i++) {
91 for (
unsigned j(0); j < SIZE; j++) {
94 if (j) ret.append(
", ");
95 ret.append(std::to_string(mm[(i*SIZE)+j]));
132 void write(std::ostream& os)
const {
133 os.write(reinterpret_cast<const char*>(&mm),
sizeof(T)*SIZE*SIZE);
137 is.read(reinterpret_cast<char*>(&mm),
sizeof(T)*SIZE*SIZE);
142 T x =
static_cast<T
>(std::fabs(mm[0]));
143 for (
unsigned i = 1; i < numElements(); ++i) {
144 x =
std::max(x, static_cast<T>(std::fabs(mm[i])));
151 for (
unsigned i = 0; i < numElements(); ++i) {
159 for (
unsigned i = 0; i < numElements(); ++i) {
167 for (
unsigned i = 0; i < numElements(); ++i) {
175 for (
unsigned i = 0; i < numElements(); ++i) {
186 template<
typename T>
class Quat;
187 template<
typename T>
class Vec3;
192 template<
class MatType>
195 typename MatType::value_type eps = static_cast<typename MatType::value_type>(1.0e-8))
197 using T =
typename MatType::value_type;
220 r[0][0]=T(1) - (yy+zz); r[0][1]=xy + wz; r[0][2]=xz - wy;
221 r[1][0]=xy - wz; r[1][1]=T(1) - (xx+zz); r[1][2]=yz + wx;
222 r[2][0]=xz + wy; r[2][1]=yz - wx; r[2][2]=T(1) - (xx+yy);
224 if(MatType::numColumns() == 4)
padMat4(r);
233 template<
class MatType>
237 using T =
typename MatType::value_type;
238 T c =
static_cast<T
>(cos(angle));
239 T s =
static_cast<T
>(sin(angle));
242 result.setIdentity();
264 throw ValueError(
"Unrecognized rotation axis");
271 template<
class MatType>
275 using T =
typename MatType::value_type;
276 T txy, txz, tyz, sx, sy, sz;
281 T c(cos(
double(angle)));
282 T s(sin(
double(angle)));
287 result[0][0] = axis[0]*axis[0] * t + c;
288 result[1][1] = axis[1]*axis[1] * t + c;
289 result[2][2] = axis[2]*axis[2] * t + c;
291 txy = axis[0]*axis[1] * t;
294 txz = axis[0]*axis[2] * t;
297 tyz = axis[1]*axis[2] * t;
302 result[0][1] = txy + sz;
303 result[1][0] = txy - sz;
305 result[0][2] = txz - sy;
306 result[2][0] = txz + sy;
308 result[1][2] = tyz + sx;
309 result[2][1] = tyz - sx;
311 if(MatType::numColumns() == 4)
padMat4(result);
312 return MatType(result);
353 template<
class MatType>
358 typename MatType::value_type eps = static_cast<typename MatType::value_type>(1.0e-8))
360 using ValueType =
typename MatType::value_type;
362 ValueType phi, theta, psi;
364 switch(rotationOrder)
368 theta = ValueType(M_PI_2);
369 phi = ValueType(0.5 * atan2(mat[1][2], mat[1][1]));
372 theta = ValueType(-M_PI_2);
373 phi = ValueType(0.5 * atan2(mat[1][2], mat[1][1]));
376 psi = ValueType(atan2(-mat[1][0],mat[0][0]));
377 phi = ValueType(atan2(-mat[2][1],mat[2][2]));
378 theta = ValueType(atan2(mat[2][0],
379 sqrt( mat[2][1]*mat[2][1] +
380 mat[2][2]*mat[2][2])));
382 return V(phi, theta, psi);
385 theta = ValueType(M_PI_2);
386 phi = ValueType(0.5 * atan2(mat[0][1], mat[0][0]));
389 theta = ValueType(-M_PI/2);
390 phi = ValueType(0.5 * atan2(mat[0][1],mat[2][1]));
393 psi = ValueType(atan2(-mat[0][2], mat[2][2]));
394 phi = ValueType(atan2(-mat[1][0], mat[1][1]));
395 theta = ValueType(atan2(mat[1][2],
396 sqrt(mat[0][2] * mat[0][2] +
397 mat[2][2] * mat[2][2])));
399 return V(theta, psi, phi);
403 theta = ValueType(M_PI_2);
404 phi = ValueType(0.5 * atan2(mat[2][0], mat[2][2]));
407 theta = ValueType(-M_PI/2);
408 phi = ValueType(0.5 * atan2(mat[2][0], mat[1][0]));
411 psi = ValueType(atan2(-mat[2][1], mat[1][1]));
412 phi = ValueType(atan2(-mat[0][2], mat[0][0]));
413 theta = ValueType(atan2(mat[0][1],
414 sqrt(mat[0][0] * mat[0][0] +
415 mat[0][2] * mat[0][2])));
417 return V(psi, phi, theta);
422 theta = ValueType(0.0);
423 phi = ValueType(0.5 * atan2(mat[1][2], mat[1][1]));
426 theta = ValueType(M_PI);
427 psi = ValueType(0.5 * atan2(mat[2][1], -mat[1][1]));
430 psi = ValueType(atan2(mat[2][0], -mat[1][0]));
431 phi = ValueType(atan2(mat[0][2], mat[0][1]));
432 theta = ValueType(atan2(sqrt(mat[0][1] * mat[0][1] +
433 mat[0][2] * mat[0][2]),
436 return V(phi, psi, theta);
441 theta = ValueType(0.0);
442 phi = ValueType(0.5 * atan2(mat[0][1], mat[0][0]));
445 theta = ValueType(M_PI);
446 phi = ValueType(0.5 * atan2(mat[0][1], mat[0][0]));
449 psi = ValueType(atan2(mat[0][2], mat[1][2]));
450 phi = ValueType(atan2(mat[2][0], -mat[2][1]));
451 theta = ValueType(atan2(sqrt(mat[0][2] * mat[0][2] +
452 mat[1][2] * mat[1][2]),
455 return V(theta, psi, phi);
460 theta = ValueType(-M_PI_2);
461 phi = ValueType(0.5 * atan2(-mat[1][0], mat[0][0]));
464 theta = ValueType(M_PI_2);
465 phi = ValueType(0.5 * atan2(mat[1][0], mat[0][0]));
468 psi = ValueType(atan2(mat[0][1], mat[1][1]));
469 phi = ValueType(atan2(mat[2][0], mat[2][2]));
470 theta = ValueType(atan2(-mat[2][1],
471 sqrt(mat[0][1] * mat[0][1] +
472 mat[1][1] * mat[1][1])));
474 return V(theta, phi, psi);
479 theta = ValueType(-M_PI_2);
480 phi = ValueType(0.5 * atan2(-mat[1][0], mat[1][1]));
483 theta = ValueType(M_PI_2);
484 phi = ValueType(0.5 * atan2(mat[2][1], mat[2][0]));
487 psi = ValueType(atan2(mat[1][2], mat[2][2]));
488 phi = ValueType(atan2(mat[0][1], mat[0][0]));
489 theta = ValueType(atan2(-mat[0][2],
490 sqrt(mat[0][1] * mat[0][1] +
491 mat[0][0] * mat[0][0])));
493 return V(psi, theta, phi);
498 theta = ValueType(M_PI_2);
499 psi = ValueType(0.5 * atan2(mat[2][1], mat[2][2]));
502 theta = ValueType(-M_PI_2);
503 psi = ValueType(0.5 * atan2(- mat[2][1], mat[2][2]));
506 psi = ValueType(atan2(mat[2][0], mat[0][0]));
507 phi = ValueType(atan2(mat[1][2], mat[1][1]));
508 theta = ValueType(atan2(- mat[1][0],
509 sqrt(mat[1][1] * mat[1][1] +
510 mat[1][2] * mat[1][2])));
512 return V(phi, psi, theta);
522 template<
typename MatType,
typename ValueType1,
typename ValueType2>
527 typename MatType::value_type eps = static_cast<typename MatType::value_type>(1.0e-8))
529 using T =
typename MatType::value_type;
559 Vec3<T> u, v, p(0.0, 0.0, 0.0);
561 double x =
Abs(v1[0]);
562 double y =
Abs(v1[1]);
563 double z =
Abs(v1[2]);
581 double udot = u.
dot(u);
582 double vdot = v.
dot(v);
584 double a = -2 / udot;
585 double b = -2 / vdot;
586 double c = 4 * u.
dot(v) / (udot * vdot);
589 result.setIdentity();
591 for (
int j = 0; j < 3; j++) {
592 for (
int i = 0; i < 3; i++)
593 result[i][j] = static_cast<T>(
594 a * u[i] * u[j] + b * v[i] * v[j] + c * v[j] * u[i]);
600 if(MatType::numColumns() == 4)
padMat4(result);
604 double c = v1.
dot(v2);
605 double a = (1.0 - c) / cross.
dot(cross);
607 double a0 = a * cross[0];
608 double a1 = a * cross[1];
609 double a2 = a * cross[2];
611 double a01 = a0 * cross[1];
612 double a02 = a0 * cross[2];
613 double a12 = a1 * cross[2];
617 r[0][0] =
static_cast<T
>(c + a0 * cross[0]);
618 r[0][1] =
static_cast<T
>(a01 + cross[2]);
619 r[0][2] =
static_cast<T
>(a02 - cross[1]);
620 r[1][0] =
static_cast<T
>(a01 - cross[2]);
621 r[1][1] =
static_cast<T
>(c + a1 * cross[1]);
622 r[1][2] =
static_cast<T
>(a12 + cross[0]);
623 r[2][0] =
static_cast<T
>(a02 + cross[1]);
624 r[2][1] =
static_cast<T
>(a12 - cross[0]);
625 r[2][2] =
static_cast<T
>(c + a2 * cross[2]);
627 if(MatType::numColumns() == 4)
padMat4(r);
635 template<
class MatType>
643 result.setIdentity();
653 template<
class MatType>
659 V(mat[0][0], mat[0][1], mat[0][2]).length(),
660 V(mat[1][0], mat[1][1], mat[1][2]).length(),
661 V(mat[2][0], mat[2][1], mat[2][2]).length());
668 template<
class MatType>
670 unit(
const MatType &mat,
typename MatType::value_type eps = 1.0e-8)
673 return unit(mat, eps, dud);
681 template<
class MatType>
685 typename MatType::value_type eps,
688 using T =
typename MatType::value_type;
691 for (
int i(0); i < 3; i++) {
694 Vec3<T>(in[i][0], in[i][1], in[i][2]).
unit(eps, scaling[i]));
695 for (
int j=0; j<3; j++) result[i][j] = u[j];
697 for (
int j=0; j<3; j++) result[i][j] = 0;
708 template <
class MatType>
712 int index0 =
static_cast<int>(axis0);
713 int index1 =
static_cast<int>(axis1);
716 result.setIdentity();
717 if (axis0 == axis1) {
718 result[index1][index0] = shear + 1;
720 result[index1][index0] =
shear;
728 template<
class MatType>
732 using T =
typename MatType::value_type;
735 r[0][0] = T(0); r[0][1] = skew.
z(); r[0][2] = -skew.
y();
736 r[1][0] = -skew.
z(); r[1][1] = T(0); r[2][1] = skew.
x();
737 r[2][0] = skew.
y(); r[2][1] = -skew.
x(); r[2][2] = T(0);
739 if(MatType::numColumns() == 4)
padMat4(r);
746 template<
class MatType>
751 using T =
typename MatType::value_type;
753 Vec3<T> horizontal(vertical.
unit().cross(forward).unit());
754 Vec3<T> up(forward.cross(horizontal).unit());
758 r[0][0]=horizontal.
x(); r[0][1]=horizontal.
y(); r[0][2]=horizontal.
z();
759 r[1][0]=up.
x(); r[1][1]=up.
y(); r[1][2]=up.
z();
760 r[2][0]=forward.
x(); r[2][1]=forward.
y(); r[2][2]=forward.
z();
762 if(MatType::numColumns() == 4)
padMat4(r);
771 template<
class MatType>
775 using T =
typename MatType::value_type;
778 Vec3<T> ourUnitAxis(source.row(axis).unit());
781 T parallel = unitDir.
dot(ourUnitAxis);
791 T angleBetween(
angle(unitDir, ourUnitAxis));
796 rotation.setToRotation(rotationAxis, angleBetween);
803 template<
class MatType>
807 dest[0][3] = dest[1][3] = dest[2][3] = 0;
808 dest[3][2] = dest[3][1] = dest[3][0] = 0;
817 template<
typename MatType>
819 sqrtSolve(
const MatType& aA, MatType& aB,
double aTol=0.01)
821 unsigned int iterations =
static_cast<unsigned int>(log(aTol)/log(0.5));
825 Z[0] = MatType::identity();
827 unsigned int current = 0;
828 for (
unsigned int iteration=0; iteration < iterations; iteration++) {
829 unsigned int last = current;
832 MatType invY = Y[last].inverse();
833 MatType invZ = Z[last].inverse();
835 Y[current] = 0.5 * (Y[last] + invZ);
836 Z[current] = 0.5 * (Z[last] + invY);
842 template<
typename MatType>
844 powSolve(
const MatType& aA, MatType& aB,
double aPower,
double aTol=0.01)
846 unsigned int iterations =
static_cast<unsigned int>(log(aTol)/log(0.5));
848 const bool inverted = (aPower < 0.0);
849 if (inverted) { aPower = -aPower; }
851 unsigned int whole =
static_cast<unsigned int>(aPower);
852 double fraction = aPower - whole;
854 MatType R = MatType::identity();
855 MatType partial = aA;
857 double contribution = 1.0;
858 for (
unsigned int iteration = 0; iteration < iterations; iteration++) {
861 if (fraction >= contribution) {
863 fraction -= contribution;
869 if (whole & 1) { R *= partial; }
871 if (whole) { partial *= partial; }
874 if (inverted) { aB = R.inverse(); }
880 template<
typename MatType>
884 return m.eq(MatType::identity());
889 template<
typename MatType>
893 using ValueType =
typename MatType::ValueType;
900 template<
typename MatType>
904 return m.eq(m.transpose());
909 template<
typename MatType>
913 using ValueType =
typename MatType::ValueType;
914 if (!
isApproxEqual(std::abs(m.det()), ValueType(1.0)))
return false;
916 MatType temp = m * m.transpose();
917 return temp.eq(MatType::identity());
922 template<
typename MatType>
926 int n = MatType::size;
927 typename MatType::ValueType temp(0);
928 for (
int i = 0; i < n; ++i) {
929 for (
int j = 0; j < n; ++j) {
931 temp += std::abs(mat(i,j));
935 return isApproxEqual(temp,
typename MatType::ValueType(0.0));
940 template<
typename MatType>
941 typename MatType::ValueType
944 int n = MatType::size;
945 typename MatType::ValueType norm = 0;
947 for(
int j = 0; j<n; ++j) {
948 typename MatType::ValueType column_sum = 0;
950 for (
int i = 0; i<n; ++i) {
951 column_sum += std::fabs(matrix(i,j));
961 template<
typename MatType>
962 typename MatType::ValueType
965 int n = MatType::size;
966 typename MatType::ValueType norm = 0;
968 for(
int i = 0; i<n; ++i) {
969 typename MatType::ValueType row_sum = 0;
971 for (
int j = 0; j<n; ++j) {
972 row_sum += std::fabs(matrix(i,j));
988 template<
typename MatType>
991 MatType& positive_hermitian,
unsigned int MAX_ITERATIONS=100)
994 MatType new_unitary(input);
999 unsigned int iteration(0);
1001 typename MatType::ValueType linf_of_u;
1002 typename MatType::ValueType l1nm_of_u;
1003 typename MatType::ValueType linf_of_u_inv;
1004 typename MatType::ValueType l1nm_of_u_inv;
1005 typename MatType::ValueType l1_error = 100;
1009 unitary_inv = unitary.inverse();
1014 l1nm_of_u_inv =
lOneNorm(unitary_inv);
1016 gamma = sqrt( sqrt( (l1nm_of_u_inv * linf_of_u_inv ) / (l1nm_of_u * linf_of_u) ));
1018 new_unitary = 0.5*(gamma * unitary + (1./gamma) * unitary_inv.transpose() );
1021 unitary = new_unitary;
1024 if (iteration > MAX_ITERATIONS)
return false;
1028 positive_hermitian = unitary.transpose() * input;
1035 template<
unsigned SIZE,
typename T>
1041 constexpr
unsigned size = SIZE*SIZE;
1042 for (
unsigned i = 0; i < size-1; ++i, ++m0p, ++m1p) {
1049 template<
unsigned SIZE,
typename T>
1055 constexpr
unsigned size = SIZE*SIZE;
1056 for (
unsigned i = 0; i < size-1; ++i, ++m0p, ++m1p) {
1066 #endif // OPENVDB_MATH_MAT_HAS_BEEN_INCLUDED bool isInfinite(const float x)
Return true if x is an infinity value (either positive infinity or negative infinity).
Definition: Math.h:386
Definition: Exceptions.h:56
Definition: Exceptions.h:61
void powSolve(const MatType &aA, MatType &aB, double aPower, double aTol=0.01)
Definition: Mat.h:844
bool isNan(const float x)
Return true if x is a NaN (Not-A-Number) value.
Definition: Math.h:396
bool isExactlyEqual(const T0 &a, const T1 &b)
Return true if a is exactly equal to b.
Definition: Math.h:444
T mm[SIZE *SIZE]
Definition: Mat.h:182
T & x()
Reference to the component, e.g. q.x() = 4.5f;.
Definition: Quat.h:218
#define OPENVDB_THROW(exception, message)
Definition: Exceptions.h:74
bool isFinite(const float x)
Return true if x is finite.
Definition: Math.h:376
General-purpose arithmetic and comparison routines, most of which accept arbitrary value types (or at...
void sqrtSolve(const MatType &aA, MatType &aB, double aTol=0.01)
Solve for A=B*B, given A.
Definition: Mat.h:819
void read(std::istream &is)
Definition: Mat.h:136
static unsigned numElements()
Definition: Mat.h:63
Vec3< T > cross(const Vec3< T > &v) const
Return the cross product of "this" vector and v;.
Definition: Vec3.h:224
MatType rotation(const Vec3< ValueType1 > &_v1, const Vec3< ValueType2 > &_v2, typename MatType::value_type eps=static_cast< typename MatType::value_type >(1.0e-8))
Return a rotation matrix that maps v1 onto v2 about the cross product of v1 and v2.
Definition: Mat.h:524
const T * operator[](int i) const
Array style reference to ith row.
Definition: Mat.h:129
T & z()
Definition: Vec3.h:91
T * operator[](int i)
Array style reference to ith row.
Definition: Mat.h:128
bool cwiseLessThan(const Mat< SIZE, T > &m0, const Mat< SIZE, T > &m1)
Definition: Mat.h:1037
T & y()
Definition: Vec3.h:90
bool isIdentity(const MatType &m)
Determine if a matrix is an identity matrix.
Definition: Mat.h:882
RotationOrder
Definition: Math.h:911
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.
Definition: Mat.h:773
Vec3< T > unit(T eps=0) const
return normalized this, throws if null vector
Definition: Vec3.h:378
bool isUnitary(const MatType &m)
Determine if a matrix is unitary (i.e., rotation or reflection).
Definition: Mat.h:911
Tolerance for floating-point comparison.
Definition: Math.h:147
Definition: Exceptions.h:65
T dot(const Quat &q) const
Dot product.
Definition: Quat.h:476
MatType skew(const Vec3< typename MatType::value_type > &skew)
Return a matrix as the cross product of the given vector.
Definition: Mat.h:730
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...
Definition: Mat.h:990
T ValueType
Definition: Mat.h:30
bool isDiagonal(const MatType &mat)
Determine if a matrix is diagonal.
Definition: Mat.h:924
Axis
Definition: Math.h:904
T * asPointer()
Direct access to the internal data.
Definition: Mat.h:123
MatType & padMat4(MatType &dest)
Write 0s along Mat4's last row and column, and a 1 on its diagonal.
Definition: Mat.h:805
static unsigned numColumns()
Definition: Mat.h:62
static unsigned numRows()
Definition: Mat.h:61
bool isSymmetric(const MatType &m)
Determine if a matrix is symmetric.
Definition: Mat.h:902
T & w()
Definition: Quat.h:221
bool isFinite() const
True if no Nan or Inf values are present.
Definition: Mat.h:166
bool cwiseGreaterThan(const Mat< SIZE, T > &m0, const Mat< SIZE, T > &m1)
Definition: Mat.h:1051
T dot(const Vec3< T > &v) const
Dot product.
Definition: Vec3.h:195
T angle(const Vec2< T > &v1, const Vec2< T > &v2)
Definition: Vec2.h:450
Definition: Exceptions.h:13
void write(std::ostream &os) const
Definition: Mat.h:132
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.
Definition: Mat.h:355
MatType scale(const Vec3< typename MatType::value_type > &s)
Return a matrix that scales by s.
Definition: Mat.h:637
bool isZero() const
True if all elements are exactly zero.
Definition: Mat.h:174
bool isNan() const
True if a Nan is present in this matrix.
Definition: Mat.h:150
std::string str(unsigned indentation=0) const
Definition: Mat.h:75
bool isInfinite() const
True if an Inf is present in this matrix.
Definition: Mat.h:158
T & z()
Definition: Quat.h:220
bool isApproxEqual(const Type &a, const Type &b, const Type &tolerance)
Return true if a is equal to b to within the given tolerance.
Definition: Math.h:407
T & y()
Definition: Quat.h:219
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.
Definition: Mat.h:655
T & x()
Reference to the component, e.g. v.x() = 4.5f;.
Definition: Vec3.h:89
MatType::ValueType lInfinityNorm(const MatType &matrix)
Return the L∞ norm of an N×N matrix.
Definition: Mat.h:942
bool normalize(T eps=T(1.0e-7))
this = normalized this
Definition: Vec3.h:366
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...
Definition: Mat.h:748
const T * asPointer() const
Definition: Mat.h:124
MatType::ValueType lOneNorm(const MatType &matrix)
Return the L1 norm of an N×N matrix.
Definition: Mat.h:963
SIZE_
Definition: Mat.h:31
Coord Abs(const Coord &xyz)
Definition: Coord.h:514
MatType unit(const MatType &in, typename MatType::value_type eps, Vec3< typename MatType::value_type > &scaling)
Return a copy of the given matrix with its upper 3×3 rows normalized, and return the length of each o...
Definition: Mat.h:683
bool isZero(const Type &x)
Return true if x is exactly equal to zero.
Definition: Math.h:338
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h.in:116
T absMax() const
Return the maximum of the absolute of all elements in this matrix.
Definition: Mat.h:141
T value_type
Definition: Mat.h:29
bool isInvertible(const MatType &m)
Determine if a matrix is invertible.
Definition: Mat.h:891
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h.in:202
MatType shear(Axis axis0, Axis axis1, typename MatType::value_type shear)
Set the matrix to a shear along axis0 by a fraction of axis1.
Definition: Mat.h:710
friend std::ostream & operator<<(std::ostream &ostr, const Mat< SIZE, T > &m)
Write a Mat to an output stream.
Definition: Mat.h:114