34 #ifndef OPENVDB_MATH_MAT_HAS_BEEN_INCLUDED
35 #define OPENVDB_MATH_MAT_HAS_BEEN_INCLUDED
39 #include <boost/format.hpp>
40 #include <openvdb/Exceptions.h>
51 template<
unsigned SIZE,
typename T>
60 static unsigned numRows() {
return SIZE; }
70 for (
unsigned i(0); i < numElements(); ++i) {
85 str(
unsigned indentation = 0)
const {
91 indent.append(indentation+1,
' ');
96 for (
unsigned i(0); i < SIZE; i++) {
101 for (
unsigned j(0); j < SIZE; j++) {
104 if (j) ret.append(
", ");
105 ret.append((boost::format(
"%1%") % mm[(i*SIZE)+j]).str());
114 ret.append((boost::format(
",\n%1%") % indent).str());
131 void write(std::ostream& os)
const {
132 os.write(reinterpret_cast<const char*>(&mm),
sizeof(T)*SIZE*SIZE);
136 is.read(reinterpret_cast<char*>(&mm),
sizeof(T)*SIZE*SIZE);
145 template<
typename T>
class Quat;
146 template<
typename T>
class Vec3;
151 template<
class MatType>
155 typedef typename MatType::value_type T;
178 r[0][0]=T(1) - (yy+zz); r[0][1]=xy + wz; r[0][2]=xz - wy;
179 r[1][0]=xy - wz; r[1][1]=T(1) - (xx+zz); r[1][2]=yz + wx;
180 r[2][0]=xz + wy; r[2][1]=yz - wx; r[2][2]=T(1) - (xx+yy);
182 if(MatType::numColumns() == 4)
padMat4(r);
191 template<
class MatType>
195 typedef typename MatType::value_type T;
196 T c =
static_cast<T
>(cos(angle));
197 T s =
static_cast<T
>(sin(angle));
200 result.setIdentity();
222 throw ValueError(
"Unrecognized rotation axis");
229 template<
class MatType>
233 typedef typename MatType::value_type T;
234 T txy, txz, tyz, sx, sy, sz;
239 T c(cos(
double(angle)));
240 T s(sin(
double(angle)));
245 result[0][0] = axis[0]*axis[0] * t + c;
246 result[1][1] = axis[1]*axis[1] * t + c;
247 result[2][2] = axis[2]*axis[2] * t + c;
249 txy = axis[0]*axis[1] * t;
252 txz = axis[0]*axis[2] * t;
255 tyz = axis[1]*axis[2] * t;
260 result[0][1] = txy + sz;
261 result[1][0] = txy - sz;
263 result[0][2] = txz - sy;
264 result[2][0] = txz + sy;
266 result[1][2] = tyz + sx;
267 result[2][1] = tyz - sx;
269 if(MatType::numColumns() == 4)
padMat4(result);
270 return MatType(result);
311 template<
class MatType>
312 Vec3<typename MatType::value_type>
316 typename MatType::value_type eps=1.0e-8)
318 typedef typename MatType::value_type ValueType;
320 ValueType phi, theta, psi;
322 switch(rotationOrder)
327 phi = 0.5 * atan2(mat[1][2], mat[1][1]);
331 phi = 0.5 * atan2(mat[1][2], mat[1][1]);
334 psi = atan2(-mat[1][0],mat[0][0]);
335 phi = atan2(-mat[2][1],mat[2][2]);
336 theta = atan2(mat[2][0],
337 sqrt( mat[2][1]*mat[2][1] +
338 mat[2][2]*mat[2][2]));
340 return V(phi, theta, psi);
344 phi = 0.5 * atan2(mat[0][1], mat[0][0]);
348 phi = 0.5 * atan2(mat[0][1],mat[2][1]);
351 psi = atan2(-mat[0][2], mat[2][2]);
352 phi = atan2(-mat[1][0], mat[1][1]);
353 theta = atan2(mat[1][2],
354 sqrt(mat[0][2] * mat[0][2] +
355 mat[2][2] * mat[2][2]));
357 return V(theta, psi, phi);
362 phi = 0.5 * atan2(mat[2][0], mat[2][2]);
366 phi = 0.5 * atan2(mat[2][0], mat[1][0]);
369 psi = atan2(-mat[2][1], mat[1][1]);
370 phi = atan2(-mat[0][2], mat[0][0]);
371 theta = atan2(mat[0][1],
372 sqrt(mat[0][0] * mat[0][0] +
373 mat[0][2] * mat[0][2]));
375 return V(psi, phi, theta);
381 phi = 0.5 * atan2(mat[1][2], mat[1][1]);
385 psi = 0.5 * atan2(mat[2][1], -mat[1][1]);
388 psi = atan2(mat[2][0], -mat[1][0]);
389 phi = atan2(mat[0][2], mat[0][1]);
390 theta = atan2(sqrt(mat[0][1] * mat[0][1] +
391 mat[0][2] * mat[0][2]),
394 return V(phi, psi, theta);
400 phi = 0.5 * atan2(mat[0][1], mat[0][0]);
404 phi = 0.5 * atan2(mat[0][1], mat[0][0]);
407 psi = atan2(mat[0][2], mat[1][2]);
408 phi = atan2(mat[2][0], -mat[2][1]);
409 theta = atan2(sqrt(mat[0][2] * mat[0][2] +
410 mat[1][2] * mat[1][2]),
413 return V(theta, psi, phi);
419 phi = 0.5 * atan2(-mat[1][0], mat[0][0]);
423 phi = 0.5 * atan2(mat[1][0], mat[0][0]);
426 psi = atan2(mat[0][1], mat[1][1]);
427 phi = atan2(mat[2][0], mat[2][2]);
428 theta = atan2(-mat[2][1],
429 sqrt(mat[0][1] * mat[0][1] +
430 mat[1][1] * mat[1][1]));
432 return V(theta, phi, psi);
438 phi = 0.5 * atan2(-mat[1][0], mat[1][1]);
442 phi = 0.5 * atan2(mat[2][1], mat[2][0]);
445 psi = atan2(mat[1][2], mat[2][2]);
446 phi = atan2(mat[0][1], mat[0][0]);
447 theta = atan2(-mat[0][2],
448 sqrt(mat[0][1] * mat[0][1] +
449 mat[0][0] * mat[0][0]));
451 return V(psi, theta, phi);
457 psi = 0.5 * atan2(mat[2][1], mat[2][2]);
461 psi = 0.5 * atan2(- mat[2][1], mat[2][2]);
464 psi = atan2(mat[2][0], mat[0][0]);
465 phi = atan2(mat[1][2], mat[1][1]);
466 theta = atan2(- mat[1][0],
467 sqrt(mat[1][1] * mat[1][1] +
468 mat[1][2] * mat[1][2]));
470 return V(phi, psi, theta);
479 template<
class MatType>
484 typename MatType::value_type eps=1.0e-8)
486 typedef typename MatType::value_type T;
515 Vec3<T> u, v, p(0.0, 0.0, 0.0);
517 double x =
Abs(v1[0]);
518 double y =
Abs(v1[1]);
519 double z =
Abs(v1[2]);
537 double udot = u.
dot(u);
538 double vdot = v.
dot(v);
540 double a = -2 / udot;
541 double b = -2 / vdot;
542 double c = 4 * u.
dot(v) / (udot * vdot);
545 result.setIdentity();
547 for (
int j = 0; j < 3; j++) {
548 for (
int i = 0; i < 3; i++)
550 a * u[i] * u[j] + b * v[i] * v[j] + c * v[j] * u[i];
556 if(MatType::numColumns() == 4)
padMat4(result);
560 double c = v1.
dot(v2);
561 double a = (1.0 - c) / cross.
dot(cross);
563 double a0 = a * cross[0];
564 double a1 = a * cross[1];
565 double a2 = a * cross[2];
567 double a01 = a0 * cross[1];
568 double a02 = a0 * cross[2];
569 double a12 = a1 * cross[2];
573 r[0][0] = c + a0 * cross[0];
574 r[0][1] = a01 + cross[2];
575 r[0][2] = a02 - cross[1],
576 r[1][0] = a01 - cross[2];
577 r[1][1] = c + a1 * cross[1];
578 r[1][2] = a12 + cross[0];
579 r[2][0] = a02 + cross[1];
580 r[2][1] = a12 - cross[0];
581 r[2][2] = c + a2 * cross[2];
583 if(MatType::numColumns() == 4)
padMat4(r);
591 template<
class MatType>
599 result.setIdentity();
609 template<
class MatType>
610 Vec3<typename MatType::value_type>
615 V(mat[0][0], mat[0][1], mat[0][2]).length(),
616 V(mat[1][0], mat[1][1], mat[1][2]).length(),
617 V(mat[2][0], mat[2][1], mat[2][2]).length());
624 template<
class MatType>
626 unit(
const MatType &mat,
typename MatType::value_type eps = 1.0e-8)
629 return unit(mat, eps, dud);
637 template<
class MatType>
641 typename MatType::value_type eps,
644 typedef typename MatType::value_type T;
647 for (
int i(0); i < 3; i++) {
650 Vec3<T>(in[i][0], in[i][1], in[i][2]).
unit(eps, scaling[i]));
651 for (
int j=0; j<3; j++) result[i][j] = u[j];
653 for (
int j=0; j<3; j++) result[i][j] = 0;
664 template <
class MatType>
668 int index0 =
static_cast<int>(axis0);
669 int index1 =
static_cast<int>(axis1);
672 result.setIdentity();
673 if (axis0 == axis1) {
674 result[index1][index0] = shear + 1;
676 result[index1][index0] =
shear;
684 template<
class MatType>
688 typedef typename MatType::value_type T;
691 r[0][0] = T(0); r[0][1] = skew.
z(); r[0][2] = -skew.
y();
692 r[1][0] = -skew.
z(); r[1][1] = T(0); r[2][1] = skew.
x();
693 r[2][0] = skew.
y(); r[2][1] = -skew.
x(); r[2][2] = T(0);
695 if(MatType::numColumns() == 4)
padMat4(r);
702 template<
class MatType>
707 typedef typename MatType::value_type T;
709 Vec3<T> horizontal(vertical.
unit().cross(forward).unit());
710 Vec3<T> up(forward.cross(horizontal).unit());
714 r[0][0]=horizontal.
x(); r[0][1]=horizontal.
y(); r[0][2]=horizontal.
z();
715 r[1][0]=up.
x(); r[1][1]=up.
y(); r[1][2]=up.
z();
716 r[2][0]=forward.
x(); r[2][1]=forward.
y(); r[2][2]=forward.
z();
718 if(MatType::numColumns() == 4)
padMat4(r);
725 template<
class MatType>
729 dest[0][3] = dest[1][3] = dest[2][3] = 0;
730 dest[3][2] = dest[3][1] = dest[3][0] = 0;
739 template <
typename MatType>
741 sqrtSolve(
const MatType &aA, MatType &aB,
double aTol=0.01)
743 unsigned int iterations = (
unsigned int)(log(aTol)/log(0.5));
749 unsigned int current = 0;
752 Z[0] = MatType::identity();
754 unsigned int iteration;
755 for (iteration=0; iteration<iterations; iteration++)
757 unsigned int last = current;
760 invY = Y[last].inverse();
761 invZ = Z[last].inverse();
763 Y[current]=0.5*(Y[last]+invZ);
764 Z[current]=0.5*(Z[last]+invY);
767 MatType &R = Y[current];
773 template <
typename MatType>
775 powSolve(
const MatType &aA, MatType &aB,
double aPower,
double aTol=0.01)
777 unsigned int iterations = (
unsigned int)(log(aTol)/log(0.5));
779 const bool inverted = ( aPower < 0.0 );
785 unsigned int whole = (
unsigned int)aPower;
786 double fraction = aPower - whole;
789 R = MatType::identity();
791 MatType partial = aA;
793 double contribution = 1.0;
795 unsigned int iteration;
797 for (iteration=0; iteration< iterations; iteration++)
802 if (fraction>=contribution)
805 fraction-=contribution;
831 template<
typename MatType>
835 return m.eq(MatType::identity());
840 template<
typename MatType>
844 typedef typename MatType::ValueType value_type;
851 template<
typename MatType>
855 return m.eq(m.transpose());
860 template<
typename MatType>
864 typedef typename MatType::ValueType value_type;
865 if (!
isApproxEqual(std::abs(m.det()), value_type(1.0)))
return false;
867 MatType temp = m * m.transpose();
868 return temp.eq(MatType::identity());
873 template<
typename MatType>
877 int n = MatType::size;
878 typename MatType::ValueType temp(0);
879 for (
int i = 0; i < n; ++i) {
880 for (
int j = 0; j < n; ++j) {
882 temp+=std::abs(mat(i,j));
886 return isApproxEqual(temp,
typename MatType::ValueType(0.0));
891 template<
typename MatType>
892 typename MatType::ValueType
895 int n = MatType::size;
896 typename MatType::ValueType norm = 0;
898 for(
int j = 0; j<n; ++j) {
899 typename MatType::ValueType column_sum = 0;
901 for (
int i = 0; i<n; ++i) {
902 column_sum += fabs(matrix(i,j));
912 template<
typename MatType>
913 typename MatType::ValueType
916 int n = MatType::size;
917 typename MatType::ValueType norm = 0;
919 for(
int i = 0; i<n; ++i) {
920 typename MatType::ValueType row_sum = 0;
922 for (
int j = 0; j<n; ++j) {
923 row_sum += fabs(matrix(i,j));
939 template<
typename MatType>
942 MatType& positive_hermitian,
unsigned int MAX_ITERATIONS=100)
945 MatType new_unitary(input);
950 unsigned int iteration(0);
952 typename MatType::ValueType linf_of_u;
953 typename MatType::ValueType l1nm_of_u;
954 typename MatType::ValueType linf_of_u_inv;
955 typename MatType::ValueType l1nm_of_u_inv;
956 typename MatType::ValueType l1_error = 100;
960 unitary_inv = unitary.inverse();
965 l1nm_of_u_inv =
lOneNorm(unitary_inv);
967 gamma = sqrt( sqrt( (l1nm_of_u_inv * linf_of_u_inv ) / (l1nm_of_u * linf_of_u) ));
969 new_unitary = 0.5*(gamma * unitary + (1./gamma) * unitary_inv.transpose() );
972 unitary = new_unitary;
975 if (iteration > MAX_ITERATIONS)
return false;
979 positive_hermitian = unitary.transpose() * input;
987 #endif // OPENVDB_MATH_MAT_HAS_BEEN_INCLUDED
static unsigned numElements()
Definition: Mat.h:62
MatType rotation(const Vec3< typename MatType::value_type > &_v1, const Vec3< typename MatType::value_type > &_v2, typename MatType::value_type eps=1.0e-8)
Return a rotation matrix that maps v1 onto v2 about the cross product of v1 and v2.
Definition: Mat.h:481
General-purpose arithmetic and comparison routines, most of which accept arbitrary value types (or at...
T & z()
Definition: Vec3.h:96
bool polarDecomposition(const MatType &input, MatType &unitary, MatType &positive_hermitian, unsigned int MAX_ITERATIONS=100)
Decompose an invertible 3x3 matrix into a unitary matrix followed by a symmetric matrix (positive sem...
Definition: Mat.h:941
Definition: Exceptions.h:78
friend std::ostream & operator<<(std::ostream &ostr, const Mat< SIZE, T > &m)
Write a Mat to an output stream.
Definition: Mat.h:123
#define OPENVDB_THROW(exception, message)
Definition: Exceptions.h:97
bool normalize(T eps=T(1.0e-7))
this = normalized this
Definition: Vec3.h:344
int32_t Abs(int32_t i)
Return the absolute value of the given quantity.
Definition: Math.h:244
T angle(const Vec2< T > &v1, const Vec2< T > &v2)
Definition: Vec2.h:446
Mat(Mat const &src)
Copy constructor. Used when the class signature matches exactly.
Definition: Mat.h:69
static unsigned numRows()
Definition: Mat.h:60
bool isSymmetric(const MatType &m)
Determine if a matrix is symmetric.
Definition: Mat.h:853
Definition: Exceptions.h:88
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 3x3 rows normalized, and return the length of each o...
Definition: Mat.h:639
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:704
T & y()
Definition: Vec3.h:95
MatType skew(const Vec3< typename MatType::value_type > &skew)
Return a matrix as the cross product of the given vector.
Definition: Mat.h:686
Mat()
Definition: Mat.h:66
Vec3< typename MatType::value_type > eulerAngles(const MatType &mat, RotationOrder rotationOrder, typename MatType::value_type eps=1.0e-8)
Return the Euler angles composing the given rotation matrix.
Definition: Mat.h:313
void write(std::ostream &os) const
Definition: Mat.h:131
bool isUnitary(const MatType &m)
Determine if a matrix is unitary (i.e., rotation or reflection).
Definition: Mat.h:862
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:666
Vec3< T > cross(const Vec3< T > &v) const
Return the cross product of "this" vector and v;.
Definition: Vec3.h:228
T & z()
Definition: Quat.h:225
#define OPENVDB_VERSION_NAME
Definition: version.h:45
void powSolve(const MatType &aA, MatType &aB, double aPower, double aTol=0.01)
Definition: Mat.h:775
T dot(const Vec3< T > &v) const
Dot product.
Definition: Vec3.h:199
RotationOrder
Definition: Math.h:774
static MatType & padMat4(MatType &dest)
Write 0s along Mat4's last row and column, and a 1 on its diagonal.
Definition: Mat.h:727
bool isInvertible(const MatType &m)
Determine if a matrix is invertible.
Definition: Mat.h:842
OPENVDB_API Hermite max(const Hermite &, const Hermite &)
min and max operations done directly on the compressed data.
T dot(const Quat &q) const
Dot product.
Definition: Quat.h:492
T ValueType
Definition: Mat.h:56
SIZE_
Definition: Mat.h:57
MatType scale(const Vec3< typename MatType::value_type > &s)
Return a matrix that scales by s.
Definition: Mat.h:593
void read(std::istream &is)
Definition: Mat.h:135
T & y()
Definition: Quat.h:224
T & w()
Definition: Quat.h:226
Definition: Exceptions.h:84
T value_type
Definition: Mat.h:55
void sqrtSolve(const MatType &aA, MatType &aB, double aTol=0.01)
Solve for A=B*B, given A.
Definition: Mat.h:741
Vec3< T > unit(T eps=0) const
return normalized this, throws if null vector
Definition: Vec3.h:356
bool isIdentity(const MatType &m)
Determine if a matrix is an identity matrix.
Definition: Mat.h:833
bool isApproxEqual(const Hermite &lhs, const Hermite &rhs)
Definition: Hermite.h:470
Axis
Definition: Math.h:767
Vec3< typename MatType::value_type > getScale(const MatType &mat)
Return a Vec3 representing the lengths of the passed matrix's upper 3x3's rows.
Definition: Mat.h:611
static unsigned numColumns()
Definition: Mat.h:61
MatType::ValueType lOneNorm(const MatType &matrix)
Return the norm of an N x N matrix.
Definition: Mat.h:914
T mm[SIZE *SIZE]
Definition: Mat.h:141
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:67
T & x()
Reference to the component, e.g. q.x() = 4.5f;.
Definition: Quat.h:223
Tolerance for floating-point comparison.
Definition: Math.h:116
T & x()
Reference to the component, e.g. v.x() = 4.5f;.
Definition: Vec3.h:94
bool isDiagonal(const MatType &mat)
Determine if a matrix is diagonal.
Definition: Mat.h:875
MatType::ValueType lInfinityNorm(const MatType &matrix)
Return the norm of an N x N matrix.
Definition: Mat.h:893
std::string str(unsigned indentation=0) const
Definition: Mat.h:85