/* * vec_mat.h - vector and matrix defination & calculation * * Copyright (c) 2017 Intel Corporation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Author: Zong Wei */ #ifndef XCAM_VECTOR_MATRIX_H #define XCAM_VECTOR_MATRIX_H #include #include namespace XCam { #ifndef PI #define PI 3.14159265358979323846 #endif #ifndef FLT_EPSILON #define FLT_EPSILON 1.19209290e-07F // float #endif #ifndef DBL_EPSILON #define DBL_EPSILON 2.2204460492503131e-16 // double #endif #ifndef DEGREE_2_RADIANS #define DEGREE_2_RADIANS(x) (((x) * PI) / 180.0) #endif #ifndef RADIANS_2_DEGREE #define RADIANS_2_DEGREE(x) (((x) * 180.0) / PI) #endif #define XCAM_VECT2_OPERATOR_VECT2(op) \ Vector2 operator op (const Vector2& b) const { \ return Vector2(x op b.x, y op b.y); \ } \ Vector2 &operator op##= (const Vector2& b) { \ x op##= b.x; y op##= b.y; return *this; \ } #define XCAM_VECT2_OPERATOR_SCALER(op) \ Vector2 operator op (const T& b) const { \ return Vector2(x op b, y op b); \ } \ Vector2 &operator op##= (const T& b) { \ x op##= b; y op##= b; return *this; \ } template class Vector2 { public: T x; T y; Vector2 () : x(0), y(0) {}; Vector2 (T _x, T _y) : x(_x), y(_y) {}; template Vector2 convert_to () const { Vector2 ret((New)(this->x), (New)(this->y)); return ret; } Vector2& operator = (const Vector2& rhs) { x = rhs.x; y = rhs.y; return *this; } template Vector2& operator = (const Vector2& rhs) { x = rhs.x; y = rhs.y; return *this; } Vector2 operator - () const { return Vector2(-x, -y); } XCAM_VECT2_OPERATOR_VECT2 (+) XCAM_VECT2_OPERATOR_VECT2 (-) XCAM_VECT2_OPERATOR_VECT2 (*) XCAM_VECT2_OPERATOR_VECT2 ( / ) XCAM_VECT2_OPERATOR_SCALER (+) XCAM_VECT2_OPERATOR_SCALER (-) XCAM_VECT2_OPERATOR_SCALER (*) XCAM_VECT2_OPERATOR_SCALER ( / ) bool operator == (const Vector2& rhs) const { return (x == rhs.x) && (y == rhs.y); } void reset () { this->x = (T) 0; this->y = (T) 0; } void set (T _x, T _y) { this->x = _x; this->y = _y; } T magnitude () const { return (T) sqrtf(x * x + y * y); } float distance (const Vector2& vec) const { return sqrtf((vec.x - x) * (vec.x - x) + (vec.y - y) * (vec.y - y)); } T dot (const Vector2& vec) const { return (x * vec.x + y * vec.y); } inline Vector2 lerp (T weight, const Vector2& vec) const { return (*this) + (vec - (*this)) * weight; } }; template class VectorN { public: VectorN (); VectorN (T x); VectorN (T x, T y); VectorN (T x, T y, T z); VectorN (T x, T y, T z, T w); VectorN (VectorN vec3, T w); inline VectorN& operator = (const VectorN& rhs); inline VectorN operator - () const; inline bool operator == (const VectorN& rhs) const; inline T& operator [] (uint32_t index) { XCAM_ASSERT(index >= 0 && index < N); return data[index]; } inline const T& operator [] (uint32_t index) const { XCAM_ASSERT(index >= 0 && index < N); return data[index]; } inline VectorN operator + (const T rhs) const; inline VectorN operator - (const T rhs) const; inline VectorN operator * (const T rhs) const; inline VectorN operator / (const T rhs) const; inline VectorN operator += (const T rhs); inline VectorN operator -= (const T rhs); inline VectorN operator *= (const T rhs); inline VectorN operator /= (const T rhs); inline VectorN operator + (const VectorN& rhs) const; inline VectorN operator - (const VectorN& rhs) const; inline VectorN operator * (const VectorN& rhs) const; inline VectorN operator / (const VectorN& rhs) const; inline VectorN operator += (const VectorN& rhs); inline VectorN operator -= (const VectorN& rhs); inline VectorN operator *= (const VectorN& rhs); inline VectorN operator /= (const VectorN& rhs); template inline VectorN convert_to () const; inline void zeros (); inline void set (T x, T y); inline void set (T x, T y, T z); inline void set (T x, T y, T z, T w); inline T magnitude () const; inline float distance (const VectorN& vec) const; inline T dot (const VectorN& vec) const; inline VectorN lerp (T weight, const VectorN& vec) const; private: T data[N]; }; template inline VectorN::VectorN () { for (uint32_t i = 0; i < N; i++) { data[i] = 0; } } template inline VectorN::VectorN (T x) { data[0] = x; } template inline VectorN::VectorN (T x, T y) { if (N >= 2) { data[0] = x; data[1] = y; } } template inline VectorN::VectorN (T x, T y, T z) { if (N >= 3) { data[0] = x; data[1] = y; data[2] = z; } } template inline VectorN::VectorN (T x, T y, T z, T w) { if (N >= 4) { data[0] = x; data[1] = y; data[2] = z; data[3] = w; } } template inline VectorN::VectorN (VectorN vec3, T w) { if (N >= 4) { data[0] = vec3.data[0]; data[1] = vec3.data[1]; data[2] = vec3.data[2]; data[3] = w; } } template inline VectorN& VectorN::operator = (const VectorN& rhs) { for (uint32_t i = 0; i < N; i++) { data[i] = rhs.data[i]; } return *this; } template inline VectorN VectorN::operator - () const { for (uint32_t i = 0; i < N; i++) { data[i] = -data[i]; } return *this; } template inline VectorN VectorN::operator + (const T rhs) const { VectorN result; for (uint32_t i = 0; i < N; i++) { result.data[i] = data[i] + rhs; } return result; } template inline VectorN VectorN::operator - (const T rhs) const { VectorN result; for (uint32_t i = 0; i < N; i++) { result.data[i] = data[i] - rhs; } return result; } template inline VectorN VectorN::operator * (const T rhs) const { VectorN result; for (uint32_t i = 0; i < N; i++) { result.data[i] = data[i] * rhs; } return result; } template inline VectorN VectorN::operator / (const T rhs) const { VectorN result; for (uint32_t i = 0; i < N; i++) { result.data[i] = data[i] / rhs; } return result; } template inline VectorN VectorN::operator += (const T rhs) { for (uint32_t i = 0; i < N; i++) { data[i] += rhs; } return *this; } template inline VectorN VectorN::operator -= (const T rhs) { for (uint32_t i = 0; i < N; i++) { data[i] -= rhs; } return *this; } template inline VectorN VectorN::operator *= (const T rhs) { for (uint32_t i = 0; i < N; i++) { data[i] *= rhs; } return *this; } template inline VectorN VectorN::operator /= (const T rhs) { for (uint32_t i = 0; i < N; i++) { data[i] /= rhs; } return *this; } template inline VectorN VectorN::operator + (const VectorN& rhs) const { VectorN result; for (uint32_t i = 0; i < N; i++) { result.data[i] = data[i] + rhs.data[i]; } return result; } template inline VectorN VectorN::operator - (const VectorN& rhs) const { VectorN result; for (uint32_t i = 0; i < N; i++) { result.data[i] = data[i] - rhs.data[i]; } return result; } template inline VectorN VectorN::operator * (const VectorN& rhs) const { VectorN result; for (uint32_t i = 0; i < N; i++) { result.data[i] = data[i] * rhs.data[i]; } return result; } template inline VectorN VectorN::operator / (const VectorN& rhs) const { VectorN result; for (uint32_t i = 0; i < N; i++) { result.data[i] = data[i] / rhs.data[i]; } return result; } template inline VectorN VectorN::operator += (const VectorN& rhs) { for (uint32_t i = 0; i < N; i++) { data[i] += rhs.data[i]; } return *this; } template inline VectorN VectorN::operator -= (const VectorN& rhs) { for (uint32_t i = 0; i < N; i++) { data[i] -= rhs.data[i]; } return *this; } template inline VectorN VectorN::operator *= (const VectorN& rhs) { for (uint32_t i = 0; i < N; i++) { data[i] *= rhs.data[i]; } return *this; } template inline VectorN VectorN::operator /= (const VectorN& rhs) { for (uint32_t i = 0; i < N; i++) { data[i] /= rhs.data[i]; } return *this; } template inline bool VectorN::operator == (const VectorN& rhs) const { for (uint32_t i = 0; i < N; i++) { if (data[i] != rhs[i]) { return false; } } return true; } template template VectorN VectorN::convert_to () const { VectorN result; for (uint32_t i = 0; i < N; i++) { result[i] = (NEW)(this->data[i]); } return result; } template inline void VectorN::zeros () { for (uint32_t i = 0; i < N; i++) { data[i] = (T)(0); } } template inline void VectorN::set (T x, T y) { if (N >= 2) { data[0] = x; data[1] = y; } } template inline void VectorN::set (T x, T y, T z) { if (N >= 3) { data[0] = x; data[1] = y; data[2] = z; } } template inline void VectorN::set (T x, T y, T z, T w) { if (N >= 4) { data[0] - x; data[1] = y; data[2] = z; data[3] = w; } } template inline T VectorN::magnitude () const { T result = 0; for (uint32_t i = 0; i < N; i++) { result += (data[i] * data[i]); } return (T) sqrtf(result); } template inline float VectorN::distance (const VectorN& vec) const { T result = 0; for (uint32_t i = 0; i < N; i++) { result += (vec.data[i] - data[i]) * (vec.data[i] - data[i]); } return sqrtf(result); } template inline T VectorN::dot (const VectorN& vec) const { T result = 0; for (uint32_t i = 0; i < N; i++) { result += (vec.data[i] * data[i]); } return result; } template inline VectorN VectorN::lerp (T weight, const VectorN& vec) const { return (*this) + (vec - (*this)) * weight; } // NxN matrix in row major order template class MatrixN { public: MatrixN (); MatrixN (VectorN a, VectorN b); MatrixN (VectorN a, VectorN b, VectorN c); MatrixN (VectorN a, VectorN b, VectorN c, VectorN d); inline void zeros (); inline void eye (); inline T& at (uint32_t row, uint32_t col) { XCAM_ASSERT(row >= 0 && row < N); XCAM_ASSERT(col >= 0 && col < N); return data[row * N + col]; }; inline const T& at (uint32_t row, uint32_t col) const { XCAM_ASSERT(row >= 0 && row < N); XCAM_ASSERT(col >= 0 && col < N); return data[row * N + col]; }; inline T& operator () (uint32_t row, uint32_t col) { return at (row, col); }; inline const T& operator () (uint32_t row, uint32_t col) const { return at (row, col); }; inline MatrixN& operator = (const MatrixN& rhs); inline MatrixN operator - () const; inline MatrixN operator + (const MatrixN& rhs) const; inline MatrixN operator - (const MatrixN& rhs) const; inline MatrixN operator * (const T a) const; inline MatrixN operator / (const T a) const; inline VectorN operator * (const VectorN& rhs) const; inline MatrixN operator * (const MatrixN& rhs) const; inline MatrixN transpose (); inline MatrixN inverse (); inline T trace (); private: inline MatrixN inverse (const MatrixN& mat); inline MatrixN inverse (const MatrixN& mat); inline MatrixN inverse (const MatrixN& mat); private: T data[N * N]; }; // NxN matrix in row major order template MatrixN::MatrixN () { eye (); } template MatrixN::MatrixN (VectorN a, VectorN b) { if (N == 2) { data[0] = a[0]; data[1] = a[1]; data[2] = b[0]; data[3] = b[1]; } else { eye (); } } template MatrixN::MatrixN (VectorN a, VectorN b, VectorN c) { if (N == 3) { data[0] = a[0]; data[1] = a[1]; data[2] = a[2]; data[3] = b[0]; data[4] = b[1]; data[5] = b[2]; data[6] = c[0]; data[7] = c[1]; data[8] = c[2]; } else { eye (); } } template MatrixN::MatrixN (VectorN a, VectorN b, VectorN c, VectorN d) { if (N == 4) { data[0] = a[0]; data[1] = a[1]; data[2] = a[2]; data[3] = a[3]; data[4] = b[0]; data[5] = b[1]; data[6] = b[2]; data[7] = b[3]; data[8] = c[0]; data[9] = c[1]; data[10] = c[2]; data[11] = c[3]; data[12] = d[0]; data[13] = d[1]; data[14] = d[2]; data[15] = d[3]; } else { eye (); } } template inline void MatrixN::zeros () { for (uint32_t i = 0; i < N * N; i++) { data[i] = 0; } } template inline void MatrixN::eye () { zeros (); for (uint32_t i = 0; i < N; i++) { data[i * N + i] = 1; } } template inline MatrixN& MatrixN::operator = (const MatrixN& rhs) { for (uint32_t i = 0; i < N * N; i++) { data[i] = rhs.data[i]; } return *this; } template inline MatrixN MatrixN::operator - () const { MatrixN result; for (uint32_t i = 0; i < N * N; i++) { result.data[i] = -data[i]; } return result; } template inline MatrixN MatrixN::operator + (const MatrixN& rhs) const { MatrixN result; for (uint32_t i = 0; i < N * N; i++) { result.data[i] = data[i] + rhs.data[i]; } return result; } template inline MatrixN MatrixN::operator - (const MatrixN& rhs) const { MatrixN result; for (uint32_t i = 0; i < N * N; i++) { result.data[i] = data[i] - rhs.data[i]; } return result; } template inline MatrixN MatrixN::operator * (const T a) const { MatrixN result; for (uint32_t i = 0; i < N * N; i++) { result.data[i] = data[i] * a; } return result; } template inline MatrixN MatrixN::operator / (const T a) const { MatrixN result; for (uint32_t i = 0; i < N * N; i++) { result.data[i] = data[i] / a; } return result; } template inline MatrixN MatrixN::operator * (const MatrixN& rhs) const { MatrixN result; result.zeros (); for (uint32_t i = 0; i < N; i++) { for (uint32_t j = 0; j < N; j++) { T element = 0; for (uint32_t k = 0; k < N; k++) { element += at(i, k) * rhs(k, j); } result(i, j) = element; } } return result; } template inline VectorN MatrixN::operator * (const VectorN& rhs) const { VectorN result; for (uint32_t i = 0; i < N; i++) { // row for (uint32_t j = 0; j < N; j++) { // col result.data[i] = data[i * N + j] * rhs.data[j]; } } return result; } template inline MatrixN MatrixN::transpose () { MatrixN result; for (uint32_t i = 0; i < N; i++) { for (uint32_t j = 0; j <= N; j++) { result.data[i * N + j] = data[j * N + i]; } } return result; } // if the matrix is non-invertible, return identity matrix template inline MatrixN MatrixN::inverse () { MatrixN result; result = inverse (*this); return result; } template inline T MatrixN::trace () { T t = 0; for ( uint32_t i = 0; i < N; i++ ) { t += data(i, i); } return t; } template inline MatrixN MatrixN::inverse (const MatrixN& mat) { MatrixN result; T det = mat(0, 0) * mat(1, 1) - mat(0, 1) * mat(1, 0); if (det == (T)0) { return result; } result(0, 0) = mat(1, 1); result(0, 1) = -mat(0, 1); result(1, 0) = -mat(1, 0); result(1, 1) = mat(0, 0); return result * (1.0f / det); } template inline MatrixN MatrixN::inverse (const MatrixN& mat) { MatrixN result; T det = mat(0, 0) * mat(1, 1) * mat(2, 2) + mat(1, 0) * mat(2, 1) * mat(0, 2) + mat(2, 0) * mat(0, 1) * mat(1, 2) - mat(0, 0) * mat(2, 1) * mat(1, 2) - mat(1, 0) * mat(0, 1) * mat(2, 2) - mat(2, 0) * mat(1, 1) * mat(0, 2); if (det == (T)0) { return result; } result(0, 0) = mat(1, 1) * mat(2, 2) - mat(1, 2) * mat(2, 1); result(1, 0) = mat(1, 2) * mat(2, 0) - mat(1, 0) * mat(2, 2); result(2, 0) = mat(1, 0) * mat(2, 1) - mat(1, 1) * mat(2, 0); result(0, 1) = mat(0, 2) * mat(2, 1) - mat(0, 1) * mat(2, 2); result(1, 1) = mat(0, 0) * mat(2, 2) - mat(0, 2) * mat(2, 0); result(2, 1) = mat(0, 1) * mat(2, 0) - mat(0, 0) * mat(2, 1); result(0, 2) = mat(0, 1) * mat(1, 2) - mat(0, 2) * mat(1, 1); result(1, 2) = mat(0, 2) * mat(1, 0) - mat(0, 0) * mat(1, 2); result(2, 2) = mat(0, 0) * mat(1, 1) - mat(0, 1) * mat(1, 0); return result * (1.0f / det); } template inline MatrixN MatrixN::inverse (const MatrixN& mat) { MatrixN result; T det = mat(0, 3) * mat(1, 2) * mat(2, 1) * mat(3, 1) - mat(0, 2) * mat(1, 3) * mat(2, 1) * mat(3, 1) - mat(0, 3) * mat(1, 1) * mat(2, 2) * mat(3, 1) + mat(0, 1) * mat(1, 3) * mat(2, 2) * mat(3, 1) + mat(0, 2) * mat(1, 1) * mat(2, 3) * mat(3, 1) - mat(0, 1) * mat(1, 2) * mat(2, 3) * mat(3, 1) - mat(0, 3) * mat(1, 2) * mat(2, 0) * mat(3, 1) + mat(0, 2) * mat(1, 3) * mat(2, 0) * mat(3, 1) + mat(0, 3) * mat(1, 0) * mat(2, 2) * mat(3, 1) - mat(0, 0) * mat(1, 3) * mat(2, 2) * mat(3, 1) - mat(0, 2) * mat(1, 0) * mat(2, 3) * mat(3, 1) + mat(0, 0) * mat(1, 2) * mat(2, 3) * mat(3, 1) + mat(0, 3) * mat(1, 1) * mat(2, 0) * mat(3, 2) - mat(0, 1) * mat(1, 3) * mat(2, 0) * mat(3, 2) - mat(0, 3) * mat(1, 0) * mat(2, 1) * mat(3, 2) + mat(0, 0) * mat(1, 3) * mat(2, 1) * mat(3, 2) + mat(0, 1) * mat(1, 0) * mat(2, 3) * mat(3, 2) - mat(0, 0) * mat(1, 1) * mat(2, 3) * mat(3, 2) - mat(0, 2) * mat(1, 1) * mat(2, 0) * mat(3, 3) + mat(0, 1) * mat(1, 2) * mat(2, 0) * mat(3, 3) + mat(0, 2) * mat(1, 0) * mat(2, 1) * mat(3, 3) - mat(0, 0) * mat(1, 2) * mat(2, 1) * mat(3, 3) - mat(0, 1) * mat(1, 0) * mat(2, 2) * mat(3, 3) + mat(0, 0) * mat(1, 1) * mat(2, 2) * mat(3, 3); if (det == (T)0) { return result; } result(0, 0) = mat(1, 2) * mat(2, 3) * mat(3, 1) - mat(1, 3) * mat(2, 2) * mat(3, 1) + mat(1, 3) * mat(2, 1) * mat(3, 2) - mat(1, 1) * mat(2, 3) * mat(3, 2) - mat(1, 2) * mat(2, 1) * mat(3, 3) + mat(1, 1) * mat(2, 2) * mat(3, 3); result(0, 1) = mat(0, 3) * mat(2, 2) * mat(3, 1) - mat(0, 2) * mat(2, 3) * mat(3, 1) - mat(0, 3) * mat(2, 1) * mat(3, 2) + mat(0, 1) * mat(2, 3) * mat(3, 2) + mat(0, 2) * mat(2, 1) * mat(3, 3) - mat(0, 1) * mat(2, 2) * mat(3, 3); result(0, 2) = mat(0, 2) * mat(1, 3) * mat(3, 1) - mat(0, 3) * mat(1, 2) * mat(3, 1) + mat(0, 3) * mat(1, 1) * mat(3, 2) - mat(0, 1) * mat(1, 3) * mat(3, 2) - mat(0, 2) * mat(1, 1) * mat(3, 3) + mat(0, 1) * mat(1, 2) * mat(3, 3); result(0, 3) = mat(0, 3) * mat(1, 2) * mat(2, 1) - mat(0, 2) * mat(1, 3) * mat(2, 1) - mat(0, 3) * mat(1, 1) * mat(2, 2) + mat(0, 1) * mat(1, 3) * mat(2, 2) + mat(0, 2) * mat(1, 1) * mat(2, 3) - mat(0, 1) * mat(1, 2) * mat(2, 3); result(1, 0) = mat(1, 3) * mat(2, 2) * mat(3, 0) - mat(1, 2) * mat(2, 3) * mat(3, 0) - mat(1, 3) * mat(2, 0) * mat(3, 2) + mat(1, 0) * mat(2, 3) * mat(3, 2) + mat(1, 2) * mat(2, 0) * mat(3, 3) - mat(1, 0) * mat(2, 2) * mat(3, 3); result(1, 1) = mat(0, 2) * mat(2, 3) * mat(3, 0) - mat(0, 3) * mat(2, 2) * mat(3, 0) + mat(0, 3) * mat(2, 0) * mat(3, 2) - mat(0, 0) * mat(2, 3) * mat(3, 2) - mat(0, 2) * mat(2, 0) * mat(3, 3) + mat(0, 0) * mat(2, 2) * mat(3, 3); result(1, 2) = mat(0, 3) * mat(1, 2) * mat(3, 0) - mat(0, 2) * mat(1, 3) * mat(3, 0) - mat(0, 3) * mat(1, 0) * mat(3, 2) + mat(0, 0) * mat(1, 3) * mat(3, 2) + mat(0, 2) * mat(1, 0) * mat(3, 3) - mat(0, 0) * mat(1, 2) * mat(3, 3); result(1, 3) = mat(0, 2) * mat(1, 3) * mat(2, 0) - mat(0, 3) * mat(1, 2) * mat(2, 0) + mat(0, 3) * mat(1, 0) * mat(2, 2) - mat(0, 0) * mat(1, 3) * mat(2, 2) - mat(0, 2) * mat(1, 0) * mat(2, 3) + mat(0, 0) * mat(1, 2) * mat(2, 3); result(2, 0) = mat(1, 1) * mat(2, 3) * mat(3, 0) - mat(1, 3) * mat(2, 1) * mat(3, 0) + mat(1, 3) * mat(2, 0) * mat(3, 1) - mat(1, 0) * mat(2, 3) * mat(3, 1) - mat(1, 1) * mat(2, 0) * mat(3, 3) + mat(1, 0) * mat(2, 1) * mat(3, 3); result(2, 1) = mat(0, 3) * mat(2, 1) * mat(3, 0) - mat(0, 1) * mat(2, 3) * mat(3, 0) - mat(0, 3) * mat(2, 0) * mat(3, 1) + mat(0, 0) * mat(2, 3) * mat(3, 1) + mat(0, 1) * mat(2, 0) * mat(3, 3) - mat(0, 0) * mat(2, 1) * mat(3, 3); result(2, 2) = mat(0, 1) * mat(1, 3) * mat(3, 0) - mat(0, 3) * mat(1, 1) * mat(3, 0) + mat(0, 3) * mat(1, 0) * mat(3, 1) - mat(0, 0) * mat(1, 3) * mat(3, 1) - mat(0, 1) * mat(1, 0) * mat(3, 3) + mat(0, 0) * mat(1, 1) * mat(3, 3); result(2, 3) = mat(0, 3) * mat(1, 1) * mat(2, 0) - mat(0, 1) * mat(1, 3) * mat(2, 0) - mat(0, 3) * mat(1, 0) * mat(2, 1) + mat(0, 0) * mat(1, 3) * mat(2, 1) + mat(0, 1) * mat(1, 0) * mat(2, 3) - mat(0, 0) * mat(1, 1) * mat(2, 3); result(3, 0) = mat(1, 2) * mat(2, 1) * mat(3, 0) - mat(1, 1) * mat(2, 2) * mat(3, 0) - mat(1, 2) * mat(2, 0) * mat(3, 1) + mat(1, 0) * mat(2, 2) * mat(3, 1) + mat(1, 1) * mat(2, 0) * mat(3, 2) - mat(1, 0) * mat(2, 1) * mat(3, 2); result(3, 1) = mat(1, 1) * mat(2, 2) * mat(3, 0) - mat(1, 2) * mat(2, 1) * mat(3, 0) + mat(1, 2) * mat(2, 0) * mat(3, 1) - mat(1, 0) * mat(2, 2) * mat(3, 1) - mat(1, 1) * mat(2, 0) * mat(3, 2) + mat(1, 0) * mat(2, 1) * mat(3, 2); result(3, 2) = mat(0, 2) * mat(1, 1) * mat(3, 0) - mat(0, 1) * mat(1, 2) * mat(3, 0) - mat(0, 2) * mat(1, 0) * mat(3, 1) + mat(0, 0) * mat(1, 2) * mat(3, 1) + mat(0, 1) * mat(1, 0) * mat(3, 2) - mat(0, 0) * mat(1, 1) * mat(3, 2); result(3, 3) = mat(0, 1) * mat(1, 2) * mat(2, 0) - mat(0, 2) * mat(1, 1) * mat(2, 0) + mat(0, 2) * mat(1, 0) * mat(2, 1) - mat(0, 0) * mat(1, 2) * mat(2, 1) - mat(0, 1) * mat(1, 0) * mat(2, 2) + mat(0, 0) * mat(1, 1) * mat(2, 2); return result * (1.0f / det); } typedef VectorN Vec2d; typedef VectorN Vec3d; typedef VectorN Vec4d; typedef MatrixN Mat2d; typedef MatrixN Mat3d; typedef MatrixN Mat4d; typedef VectorN Vec2f; typedef VectorN Vec3f; typedef VectorN Vec4f; typedef MatrixN Mat3f; typedef MatrixN Mat4f; template class Quaternion { public: Vec3d v; T w; Quaternion () : v(0, 0, 0), w(0) {}; Quaternion (const Quaternion& q) : v(q.v), w(q.w) {}; Quaternion (const Vec3d& vec, T _w) : v(vec), w(_w) {}; Quaternion (const Vec4d& vec) : v(vec[0], vec[1], vec[2]), w(vec[3]) {}; Quaternion (T _x, T _y, T _z, T _w) : v(_x, _y, _z), w(_w) {}; inline void reset () { v.zeros(); w = (T) 0; } inline Quaternion& operator = (const Quaternion& rhs) { v = rhs.v; w = rhs.w; return *this; } inline Quaternion operator + (const Quaternion& rhs) const { const Quaternion& lhs = *this; return Quaternion(lhs.v + rhs.v, lhs.w + rhs.w); } inline Quaternion operator - (const Quaternion& rhs) const { const Quaternion& lhs = *this; return Quaternion(lhs.v - rhs.v, lhs.w - rhs.w); } inline Quaternion operator * (T rhs) const { return Quaternion(v * rhs, w * rhs); } inline Quaternion operator * (const Quaternion& rhs) const { const Quaternion& lhs = *this; return Quaternion(lhs.w * rhs.v[0] + lhs.v[0] * rhs.w + lhs.v[1] * rhs.v[2] - lhs.v[2] * rhs.v[1], lhs.w * rhs.v[1] - lhs.v[0] * rhs.v[2] + lhs.v[1] * rhs.w + lhs.v[2] * rhs.v[0], lhs.w * rhs.v[2] + lhs.v[0] * rhs.v[1] - lhs.v[1] * rhs.v[0] + lhs.v[2] * rhs.w, lhs.w * rhs.w - lhs.v[0] * rhs.v[0] - lhs.v[1] * rhs.v[1] - lhs.v[2] * rhs.v[2]); } /* -------- / -- |Qr| = \/ Qr.Qr */ inline T magnitude () const { return (T) sqrtf(w * w + v[0] * v[0] + v[1] * v[1] + v[2] * v[2]); } inline void normalize () { T length = magnitude (); w = w / length; v = v / length; } inline Quaternion conjugate (const Quaternion& quat) const { return Quaternion(-quat.v, quat.w); } inline Quaternion inverse (const Quaternion& quat) const { return conjugate(quat) * ( 1.0f / magnitude(quat)); } inline Quaternion lerp (T weight, const Quaternion& quat) const { return Quaternion(v.lerp(weight, quat.v), (1 - weight) * w + weight * quat.w); } inline Quaternion slerp(T r, const Quaternion& quat) const { Quaternion ret; T cos_theta = w * quat.w + v[0] * quat.v[0] + v[1] * quat.v[1] + v[2] * quat.v[2]; T theta = (T) acos(cos_theta); if (fabs(theta) < FLT_EPSILON) { ret = *this; } else { T sin_theta = (T) sqrt(1.0 - cos_theta * cos_theta); if (fabs(sin_theta) < FLT_EPSILON) { ret.w = 0.5 * w + 0.5 * quat.w; ret.v = v.lerp(0.5, quat.v); } else { T r0 = (T) sin((1.0 - r) * theta) / sin_theta; T r1 = (T) sin(r * theta) / sin_theta; ret.w = w * r0 + quat.w * r1; ret.v[0] = v[0] * r0 + quat.v[0] * r1; ret.v[1] = v[1] * r0 + quat.v[1] * r1; ret.v[2] = v[2] * r0 + quat.v[2] * r1; } } return ret; } static Quaternion create_quaternion (Vec3d axis, T angle_rad) { T theta_over_two = angle_rad / (T) 2.0; T sin_theta_over_two = std::sin(theta_over_two); T cos_theta_over_two = std::cos(theta_over_two); return Quaternion(axis * sin_theta_over_two, cos_theta_over_two); } static Quaternion create_quaternion (Vec3d euler) { return create_quaternion(Vec3d(1, 0, 0), euler[0]) * create_quaternion(Vec3d(0, 1, 0), euler[1]) * create_quaternion(Vec3d(0, 0, 1), euler[2]); } static Quaternion create_quaternion (const Mat3d& mat) { Quaternion q; T trace, s; T diag1 = mat(0, 0); T diag2 = mat(1, 1); T diag3 = mat(2, 2); trace = diag1 + diag2 + diag3; if (trace >= FLT_EPSILON) { s = 2.0 * (T) sqrt(trace + 1.0); q.w = 0.25 * s; q.v[0] = (mat(2, 1) - mat(1, 2)) / s; q.v[1] = (mat(0, 2) - mat(2, 0)) / s; q.v[2] = (mat(1, 0) - mat(0, 1)) / s; } else { char max_diag = (diag1 > diag2) ? ((diag1 > diag3) ? 1 : 3) : ((diag2 > diag3) ? 2 : 3); if (max_diag == 1) { s = 2.0 * (T) sqrt(1.0 + mat(0, 0) - mat(1, 1) - mat(2, 2)); q.w = (mat(2, 1) - mat(1, 2)) / s; q.v[0] = 0.25 * s; q.v[1] = (mat(0, 1) + mat(1, 0)) / s; q.v[2] = (mat(0, 2) + mat(2, 0)) / s; } else if (max_diag == 2) { s = 2.0 * (T) sqrt(1.0 + mat(1, 1) - mat(0, 0) - mat(2, 2)); q.w = (mat(0, 2) - mat(2, 0)) / s; q.v[0] = (mat(0, 1) + mat(1, 0)) / s; q.v[1] = 0.25 * s; q.v[2] = (mat(1, 2) + mat(2, 1)) / s; } else { s = 2.0 * (T) sqrt(1.0 + mat(2, 2) - mat(0, 0) - mat(1, 1)); q.w = (mat(1, 0) - mat(0, 1)) / s; q.v[0] = (mat(0, 2) + mat(2, 0)) / s; q.v[1] = (mat(1, 2) + mat(2, 1)) / s; q.v[2] = 0.25 * s; } } return q; } inline Vec4d rotation_axis () { Vec4d rot_axis; T cos_theta_over_two = w; rot_axis[4] = (T) std::acos( cos_theta_over_two ) * 2.0f; T sin_theta_over_two = (T) sqrt( 1.0 - cos_theta_over_two * cos_theta_over_two ); if ( fabs( sin_theta_over_two ) < 0.0005 ) sin_theta_over_two = 1; rot_axis[0] = v[0] / sin_theta_over_two; rot_axis[1] = v[1] / sin_theta_over_two; rot_axis[2] = v[2] / sin_theta_over_two; return rot_axis; } /* psi=atan2(2.*(Q(:,1).*Q(:,4)-Q(:,2).*Q(:,3)),(Q(:,4).^2-Q(:,1).^2-Q(:,2).^2+Q(:,3).^2)); theta=asin(2.*(Q(:,1).*Q(:,3)+Q(:,2).*Q(:,4))); phi=atan2(2.*(Q(:,3).*Q(:,4)-Q(:,1).*Q(:,2)),(Q(:,4).^2+Q(:,1).^2-Q(:,2).^2-Q(:,3).^2)); */ inline Vec3d euler_angles () { Vec3d euler; // atan2(2*(qx*qw-qy*qz) , qw2-qx2-qy2+qz2) euler[0] = atan2(2 * (v[0] * w - v[1] * v[2]), w * w - v[0] * v[0] - v[1] * v[1] + v[2] * v[2]); // asin(2*(qx*qz + qy*qw) euler[1] = asin(2 * (v[0] * v[2] + v[1] * w)); // atan2(2*(qz*qw- qx*qy) , qw2 + qx2 - qy2 - qz2) euler[2] = atan2(2 * (v[2] * w - v[0] * v[1]), w * w + v[0] * v[0] - v[1] * v[1] - v[2] * v[2]); return euler; } inline Mat3d rotation_matrix () { Mat3d mat; T xx = v[0] * v[0]; T xy = v[0] * v[1]; T xz = v[0] * v[2]; T xw = v[0] * w; T yy = v[1] * v[1]; T yz = v[1] * v[2]; T yw = v[1] * w; T zz = v[2] * v[2]; T zw = v[2] * w; mat(0, 0) = 1 - 2 * (yy + zz); mat(0, 1) = 2 * (xy - zw); mat(0, 2) = 2 * (xz + yw); mat(1, 0) = 2 * (xy + zw); mat(1, 1) = 1 - 2 * (xx + zz); mat(1, 2) = 2 * (yz - xw); mat(2, 0) = 2 * (xz - yw); mat(2, 1) = 2 * (yz + xw); mat(2, 2) = 1 - 2 * (xx + yy); return mat; } }; typedef Quaternion Quaternd; } #endif //XCAM_VECTOR_MATRIX_H