| //------------------------------------------------------------- |
| // ____ _ _ |
| // / ___|____ _ _ ____ ____| |__ | | |
| // | | / ___| | | | _ \/ ___| _ \| | |
| // | |___| | | |_| | | | | |___| | | ||_| |
| // \____|_| \_____|_| |_|\____|_| |_|(_) Media benchmarks |
| // |
| // © 2006, Intel Corporation, licensed under Apache 2.0 |
| // |
| // file : Dmatrix.h |
| // author : Scott Ettinger - scott.m.ettinger@intel.com |
| // description : Displacement matrix and vector math |
| // operations. |
| // modified : |
| //-------------------------------------------------------------- |
| |
| |
| #ifndef DMATRIX_H |
| #define DMATRIX_H |
| |
| #if defined(HAVE_CONFIG_H) |
| # include "config.h" |
| #endif |
| |
| #include <cstring> |
| #include <iostream> |
| #include "SmallVectors.h" |
| |
| typedef enum {X, Y, Z} DMAxis; |
| typedef enum {XYZ, ZYX, YXZ, ZXY} DMOrder; |
| |
| //simple 3D Displacement Matrix class |
| template<class T> |
| class DMatrix{ |
| protected: |
| T data[3][4]; |
| public: |
| |
| DMatrix() {}; |
| |
| //constructor to initialize diagonal elements |
| DMatrix(T d1, T d2, T d3); |
| |
| //constructor to initialize diagonal and translation elements |
| DMatrix(T d1, T d2, T d3, T t1, T t2, T t3); |
| |
| //constructor given a pointer to data (copies the data) |
| DMatrix(const T *p) { memcpy(data, p, 12 * sizeof(T)); }; |
| |
| //constructor given an orthogonal axis and an angle in radians |
| DMatrix(DMAxis axis, T angle); |
| |
| //constructor given a set of Euler angles in radians |
| DMatrix(float theta, float phi, float tau, DMOrder order); |
| |
| //destructor |
| ~DMatrix() {}; |
| |
| ///set to zero |
| void Clear() {memset(data, 0, sizeof(T) * 12); }; |
| |
| ///set to identity |
| void SetIdentity() {Clear(); data[0][0] = (T)1; data[1][1] = (T)1; data[2][2] = (T)1; }; |
| |
| ///element access |
| inline T &operator()(int r, int c) {return data[r][c]; }; |
| |
| ///set to given data |
| void Set(const T *p) { memcpy(data, p, 12 * sizeof(T)); }; |
| |
| ///set translation vector of Displacement matrix |
| void SetTranslation(const T t1, const T t2, const T t3) { data[0][3] = t1; data[1][3] = t2; data[2][3] = t3; }; |
| |
| ///display matrix |
| void Print(std::ostream &s) {s << data[0][0] << " " << data[0][1] << " " << data[0][2] << " " << data[0][3] << std::endl; |
| s << data[1][0] << " " << data[1][1] << " " << data[1][2] << " " << data[1][3] << std::endl; |
| s << data[2][0] << " " << data[2][1] << " " << data[2][2] << " " << data[2][3] << std::endl; }; |
| }; |
| |
| //------------- Operators Supported --------------- |
| |
| //between Dmatrices : + - * += |
| //between Dmatrix and scalar : * *= |
| //between Dmatrix and Vector3 : * |
| |
| |
| |
| //-------------- Related functions ---------------------------------------------------------- |
| |
| //Displacement matrix inverse |
| template<class T> |
| DMatrix<T> Inverse(const DMatrix<T> &m); |
| |
| //Frobenius norm squared of matrix |
| template<class T> |
| T FrobNorm2(const DMatrix<T> &m); |
| |
| //Create a rotation matrix around a given axis |
| template<class T> |
| void AxisRotation(DMatrix<T> &m, DMAxis axis, T angle); |
| |
| //Create a rotation matrix given Euler angles and axis order |
| template<class T> |
| void EulerRotation(DMatrix<T> &m, float theta, float phi, float tau, int order); |
| |
| |
| |
| |
| //--------------------------------- Implementation ------------------------------------------- |
| |
| //Constructor initializing diagonal elements |
| template<class T> |
| DMatrix<T>::DMatrix(T d1, T d2, T d3) |
| { Clear(); |
| data[0][0] = d1; data[1][1] = d2; data[2][2] = d3; |
| } |
| |
| //Constructor initializing diagonal elements and translation |
| template<class T> |
| DMatrix<T>::DMatrix(T d1, T d2, T d3, T t1, T t2, T t3) |
| { Clear(); |
| data[0][0] = d1; data[1][1] = d2; data[2][2] = d3; |
| data[0][3] = t1; data[1][3] = t2; data[2][3] = t3; |
| } |
| |
| //Constructor given an axis and an angle |
| template<class T> |
| DMatrix<T>::DMatrix(DMAxis axis, T angle) |
| { AxisRotation(*this, axis, angle); |
| } |
| |
| //Constructor given a set of Euler angles and rotation order |
| template<class T> |
| DMatrix<T>::DMatrix(float theta, float phi, float tau, DMOrder order) |
| { EulerRotation(*this, theta, phi, tau, order); |
| } |
| |
| //--------------------------------- Arithmetic Operators -------------------------------------- |
| |
| //Matrix-vector product with normalized coordinates (3x4 Matrix * 3x1 vector) |
| template<class T1, class T2> |
| inline Vector3<T1> operator*(const DMatrix<T2> &dm, const Vector3<T1> &v) |
| { |
| Vector3<T1> r; |
| DMatrix<T2> &m = *((DMatrix<T2> *)&dm); |
| r.x = m(0,0) * v.x + m(0,1) * v.y + m(0,2) * v.z + m(0,3); |
| r.y = m(1,0) * v.x + m(1,1) * v.y + m(1,2) * v.z + m(1,3); |
| r.z = m(2,0) * v.x + m(2,1) * v.y + m(2,2) * v.z + m(2,3); |
| return r; |
| } |
| |
| //Matrix Subtraction |
| template<class T> |
| inline DMatrix<T> operator-(const DMatrix<T> &m1, const DMatrix<T> &m2) |
| { |
| DMatrix<T> r; |
| T *pr = (T *)r.data, *p1 = (T *)m1.data, *p2 = (T *)m2.data; |
| for(int i = 0; i < 12; i++) |
| *(pr++) = *(p1++) - *(p2++); |
| return(r); |
| } |
| |
| //Matrix Addition |
| template<class T> |
| inline DMatrix<T> operator+(const DMatrix<T> &m1, const DMatrix<T> &m2) |
| { |
| DMatrix<T> r; |
| T *pr = (T *)r.data, *p1 = (T *)m1.data, *p2 = (T *)m2.data; |
| for(int i = 0; i < 12; i++) |
| *(pr++) = *(p1++) + *(p2++); |
| return(r); |
| } |
| |
| //Matrix Addition in place += |
| template<class T> |
| inline void operator+=(DMatrix<T> &m1, const DMatrix<T> &m2) |
| { |
| T *p1 = (T *)m1.data, *p2 = (T *)m2.data; |
| for(int i = 0; i < 12; i++) |
| *(p1++) += *(p2++); |
| } |
| |
| //Matrix Subtraction in place -= |
| template<class T> |
| inline void operator-=(DMatrix<T> &m1, const DMatrix<T> &m2) |
| { |
| T *p1 = (T *)m1.data, *p2 = (T *)m2.data; |
| for(int i = 0; i < 12; i++) |
| *(p1++) -= *(p2++); |
| } |
| |
| //Scalar multiplication in place |
| template<class T> |
| inline void operator*=(DMatrix<T> &m, T s) |
| { for(int i = 0; i < 12; i++) |
| ((T *)m.data)[i] *= s; |
| } |
| |
| //Scalar multiplication |
| template<class T> |
| inline DMatrix<T> operator*(DMatrix<T> m, T s) |
| { m *= s; |
| return m; |
| } |
| |
| //Matrix-Matrix product |
| template<class T> |
| inline DMatrix<T> operator*(const DMatrix<T> &dm1, const DMatrix<T> &dm2) |
| { |
| DMatrix<T> m3, &m1 = *((DMatrix<T> *)&dm1), &m2 = *((DMatrix<T> *)&dm2); //get non-const references to dm1 and dm2 to allow () operator |
| for(int r = 0; r < 3; r++) |
| for(int c = 0; c < 4; c++) |
| m3(r,c) = m1(r,0) * m2(0,c) + m1(r,1) * m2(1,c) + m1(r,2) * m2(2,c); |
| m3(0,3) += m1(0,3); m3(1,3) += m1(1,3); m3(2,3) += m1(2,3); |
| return m3; |
| } |
| |
| //---------------------------- Mathematical Functions ------------------------------------------ |
| |
| //Frobenius norm squared of matrix |
| template<class T> |
| T FrobNorm2(DMatrix<T> &m) |
| { T *p = (T *)m.data, r = 0; |
| for(int i = 0; i < 12; i++) |
| { r += *p * *p; |
| p++; |
| } |
| return r; |
| } |
| |
| //Displacement matrix inverse |
| template<class T> |
| DMatrix<T> Inverse(const DMatrix<T> &dm) |
| { |
| DMatrix<T> r, &m = *((DMatrix<T> *)&dm); |
| r.Clear(); |
| T k1 = m(1,1) * m(2,2) - m(1,2) * m(2,1); //calculate rotation matrix determinant |
| T k2 = m(1,0) * m(2,2) - m(1,2) * m(2,0); |
| T k3 = m(1,0) * m(2,1) - m(1,1) * m(2,0); |
| T c = (T)1.0 / (m(0,0) * k1 - m(0,1) * k2 + m(0,2) * k3); |
| r(0,0) = c * k1; //calculate inverse of rotation matrix |
| r(0,1) = c * (m(0,2) * m(2,1) - m(0,1) * m(2,2)); |
| r(0,2) = c * (m(0,1) * m(1,2) - m(0,2) * m(1,1)); |
| r(1,0) = c * -k2; |
| r(1,1) = c * (m(0,0) * m(2,2) - m(0,2) * m(2,0)); |
| r(1,2) = c * (m(0,2) * m(1,0) - m(0,0) * m(1,2)); |
| r(2,0) = c * k3; |
| r(2,1) = c * (m(0,1) * m(2,0) - m(0,0) * m(2,1)); |
| r(2,2) = c * (m(0,0) * m(1,1) - m(0,1) * m(1,0)); |
| Vector3<T> v(-m(0,3), -m(1,3), -m(2,3)); //calculate new translation vector |
| Vector3<T> t = r * v; |
| r(0,3) = t.x; r(1,3) = t.y; r(2,3) = t.z; |
| return r; |
| } |
| |
| //--------------------------------- Rotation Matrix functions ----------------------------------- |
| |
| //generate a rotation matrix about a given axis |
| template<class T> |
| inline void AxisRotation(DMatrix<T> &m, DMAxis axis, T angle) |
| { m.Clear(); |
| float c = cos(angle), s = sin(angle); |
| switch(axis) |
| { case X : m(0,0) = 1; m(1,1) = c; m(1,2) = -s; m(2,1) = s; m(2,2) = c; |
| break; |
| case Y : m(0,0) = c; m(0,2) = s; m(1,1) = 1; m(2,0) = -s; m(2,2) = c; |
| break; |
| case Z : m(0,0) = c; m(0,1) = -s; m(1,0) = s; m(1,1) = c; m(2,2) = 1; |
| break; |
| } |
| } |
| |
| //Constructor given a set of Euler angles |
| template<class T> |
| void EulerRotation(DMatrix<T> &m, float theta, float phi, float tau, DMOrder order) |
| { DMatrix<T> Rx(X, theta), Ry(Y, phi), Rz(Z, tau); |
| switch (order) |
| { case XYZ: |
| m = (Rx * Ry) * Rz; break; |
| case ZYX: |
| m = (Rz * Ry) * Rx; break; |
| case YXZ: |
| m = (Ry * Rx) * Rz; break; |
| case ZXY: |
| m = (Rz * Rx) * Ry; break; |
| default: |
| m = (Rx * Ry) * Rz; break; |
| } |
| } |
| |
| |
| |
| #endif |