diff --git a/etk/math/Matrix2.cpp b/etk/math/Matrix2.cpp index 0851420..282cffd 100644 --- a/etk/math/Matrix2.cpp +++ b/etk/math/Matrix2.cpp @@ -9,82 +9,77 @@ std::ostream& etk::operator <<(std::ostream& _os, const etk::Matrix2& _obj) { _os << "{"; _os << _obj.m_mat[0] << ","; - _os << _obj.m_mat[4] << ","; - _os << _obj.m_mat[1] << ","; - _os << _obj.m_mat[3] << ","; + _os << _obj.m_mat[1] << ";"; _os << _obj.m_mat[2] << ","; - _os << _obj.m_mat[5] << "}"; + _os << _obj.m_mat[3] << "}"; return _os; } -void etk::Matrix2::identity() { - m_mat[0] = 1.0; - m_mat[1] = 0.0; - m_mat[2] = 0.0; - m_mat[3] = 1.0; - m_mat[4] = 0.0; - m_mat[5] = 0.0; -} - etk::Matrix2::Matrix2() { - // TODO: Remove this ... - identity(); -} -etk::Matrix2::Matrix2(const etk::Matrix2& _obj) { - for(int32_t iii=0; iii<2*3 ; iii++) { - m_mat[iii] = _obj.m_mat[iii]; - } + m_mat[0] = 0.0f; + m_mat[1] = 0.0f; + m_mat[2] = 0.0f; + m_mat[3] = 0.0f; } -etk::Matrix2::Matrix2(float _sx, - float _shy, - float _shx, - float _sy, - float _tx, - float _ty) { - m_mat[0] = _sx; - m_mat[4] = _shy; - m_mat[1] = _shx; - m_mat[3] = _sy; - m_mat[2] = _tx; - m_mat[5] = _ty; +etk::Matrix2::Matrix2(float _value) { + m_mat[0] = _value; + m_mat[1] = _value; + m_mat[2] = _value; + m_mat[3] = _value; } -etk::Matrix2::Matrix2(const float* _values) { - if (_values == nullptr) { - identity(); - return; - } - m_mat[0] = _values[0]; - m_mat[4] = _values[1]; - m_mat[1] = _values[2]; - m_mat[3] = _values[3]; - m_mat[2] = _values[4]; - m_mat[5] = _values[5]; +etk::Matrix2::Matrix2(float _a1, float _a2,float _b1, float _b2) { + m_mat[0] = _a1; + m_mat[1] = _a2; + m_mat[2] = _b1; + m_mat[3] = _b2; } -etk::Matrix2::Matrix2(const double* _values) { - if (_values == nullptr) { - identity(); - return; +etk::Matrix2::Matrix2(const Matrix2& _obj) { + m_mat[0] = _obj.m_mat[0]; + m_mat[1] = _obj.m_mat[1]; + m_mat[2] = _obj.m_mat[2]; + m_mat[3] = _obj.m_mat[3]; +} + +void etk::Matrix2::setValue(float _a1, float _a2,float _b1, float _b2) { + m_mat[0] = _a1; + m_mat[1] = _a2; + m_mat[2] = _b1; + m_mat[3] = _b2; +} + +void etk::Matrix2::setZero() { + m_mat[0] = 0; + m_mat[1] = 0; + m_mat[2] = 0; + m_mat[3] = 0; +} + +vec2 etk::Matrix2::getColumn(uint32_t _iii) const { + if (_iii == 0) { + return vec2(m_mat[0], m_mat[2]); } - m_mat[0] = _values[0]; - m_mat[4] = _values[1]; - m_mat[1] = _values[2]; - m_mat[3] = _values[3]; - m_mat[2] = _values[4]; - m_mat[5] = _values[5]; + return vec2(m_mat[1], m_mat[3]); +} + +vec2 etk::Matrix2::getRow(uint32_t _iii) const { + if (_iii == 0) { + return vec2(m_mat[0], m_mat[1]); + } + return vec2(m_mat[2], m_mat[3]); } const etk::Matrix2& etk::Matrix2::operator= (const etk::Matrix2& _obj ) { - for(int32_t iii=0; iii<2*3 ; ++iii) { + for(int32_t iii=0; iii<2*2 ; ++iii) { m_mat[iii] = _obj.m_mat[iii]; } return *this; } bool etk::Matrix2::operator== (const etk::Matrix2& _obj) const { - for(int32_t iii=0; iii<2*3 ; ++iii) { + for(int32_t iii=0; iii<2*2 ; ++iii) { if(m_mat[iii] != _obj.m_mat[iii]) { return false; } @@ -93,7 +88,7 @@ bool etk::Matrix2::operator== (const etk::Matrix2& _obj) const { } bool etk::Matrix2::operator!= (const etk::Matrix2& _obj) const { - for(int32_t iii=0; iii<2*3 ; ++iii) { + for(int32_t iii=0; iii<2*2 ; ++iii) { if(m_mat[iii] != _obj.m_mat[iii]) { return true; } @@ -102,7 +97,7 @@ bool etk::Matrix2::operator!= (const etk::Matrix2& _obj) const { } const etk::Matrix2& etk::Matrix2::operator+= (const etk::Matrix2& _obj) { - for(int32_t iii=0; iii<2*3 ; ++iii) { + for(int32_t iii=0; iii<2*2 ; ++iii) { m_mat[iii] += _obj.m_mat[iii]; } return *this; @@ -115,7 +110,7 @@ etk::Matrix2 etk::Matrix2::operator+ (const etk::Matrix2& _obj) const { } const etk::Matrix2& etk::Matrix2::operator-= (const etk::Matrix2& _obj) { - for(int32_t iii=0; iii<2*3 ; ++iii) { + for(int32_t iii=0; iii<2*2 ; ++iii) { m_mat[iii] -= _obj.m_mat[iii]; } return *this; @@ -123,126 +118,119 @@ const etk::Matrix2& etk::Matrix2::operator-= (const etk::Matrix2& _obj) { etk::Matrix2 etk::Matrix2::operator- (const etk::Matrix2& _obj) const { etk::Matrix2 tmpp(*this); - tmpp += _obj; + tmpp -= _obj; return tmpp; } + const etk::Matrix2& etk::Matrix2::operator *= (const etk::Matrix2& _obj) { - float t0 = m_mat[0] * _obj.m_mat[0] + m_mat[4] * _obj.m_mat[1]; - float t2 = m_mat[1] * _obj.m_mat[0] + m_mat[3] * _obj.m_mat[1]; - float t4 = m_mat[2] * _obj.m_mat[0] + m_mat[5] * _obj.m_mat[1] + _obj.m_mat[2]; - m_mat[4] = m_mat[0] * _obj.m_mat[4] + m_mat[4] * _obj.m_mat[3]; - m_mat[3] = m_mat[1] * _obj.m_mat[4] + m_mat[3] * _obj.m_mat[3]; - m_mat[5] = m_mat[2] * _obj.m_mat[4] + m_mat[5] * _obj.m_mat[3] + _obj.m_mat[5]; + float t0 = m_mat[0] * _obj.m_mat[0] + m_mat[1] * _obj.m_mat[2]; + float t2 = m_mat[2] * _obj.m_mat[0] + m_mat[3] * _obj.m_mat[2]; + m_mat[1] = m_mat[0] * _obj.m_mat[1] + m_mat[1] * _obj.m_mat[3]; + m_mat[3] = m_mat[2] * _obj.m_mat[1] + m_mat[3] * _obj.m_mat[3]; m_mat[0] = t0; - m_mat[1] = t2; - m_mat[2] = t4; + m_mat[2] = t2; return *this; } -etk::Matrix2 etk::Matrix2::operator * (const etk::Matrix2& _obj) { +etk::Matrix2 etk::Matrix2::operator * (const etk::Matrix2& _obj) const { etk::Matrix2 tmp(*this); tmp *= _obj; return tmp; } vec2 etk::Matrix2::operator * (const vec2& _point) const { - return vec2(_point.x()*m_mat[0] + _point.y()*m_mat[1] + m_mat[2], - _point.x()*m_mat[4] + _point.y()*m_mat[3] + m_mat[5]); -} - -vec2 etk::Matrix2::applyScaleRotation(const vec2& _point) const { return vec2(_point.x()*m_mat[0] + _point.y()*m_mat[1], - _point.x()*m_mat[4] + _point.y()*m_mat[3]); + _point.x()*m_mat[2] + _point.y()*m_mat[3]); } -etk::Matrix2 etk::Matrix2::operator ~ () const { - etk::Matrix2 tmp(*this); - tmp.invert(); - return tmp; -} - -void etk::Matrix2::flipX() { - m_mat[0] = -m_mat[0]; - m_mat[4] = -m_mat[4]; - m_mat[2] = -m_mat[2]; -} - -void etk::Matrix2::flipY() { - m_mat[1] = -m_mat[1]; - m_mat[3] = -m_mat[3]; - m_mat[5] = -m_mat[5]; -} - -void etk::Matrix2::scale(const vec2& _vect) { - m_mat[0] *= _vect.x(); - m_mat[1] *= _vect.x(); - m_mat[2] *= _vect.x(); - m_mat[4] *= _vect.y(); - m_mat[3] *= _vect.y(); - m_mat[5] *= _vect.y(); -} - -void etk::Matrix2::scale(float _value) { +const etk::Matrix2& etk::Matrix2::operator *= (float _value) { m_mat[0] *= _value; m_mat[1] *= _value; m_mat[2] *= _value; - m_mat[4] *= _value; m_mat[3] *= _value; - m_mat[5] *= _value; + return *this; } -void etk::Matrix2::rotate(float _angleRad) { - float ca = cos(_angleRad); - float sa = sin(_angleRad); - float t0 = m_mat[0] * ca - m_mat[4] * sa; - float t2 = m_mat[1] * ca - m_mat[3] * sa; - float t4 = m_mat[2] * ca - m_mat[5] * sa; - m_mat[4] = m_mat[0] * sa + m_mat[4] * ca; - m_mat[3] = m_mat[1] * sa + m_mat[3] * ca; - m_mat[5] = m_mat[2] * sa + m_mat[5] * ca; - m_mat[0] = t0; - m_mat[1] = t2; - m_mat[2] = t4; +etk::Matrix2 etk::Matrix2::operator * (float _value) const { + etk::Matrix2 tmp(*this); + tmp *= _value; + return tmp; } -void etk::Matrix2::translate(const vec2& _vect) { - m_mat[2] += _vect.x(); - m_mat[5] += _vect.y(); +etk::Matrix2 etk::Matrix2::getTranspose() const { + return Matrix2(m_mat[0], m_mat[2], + m_mat[1], m_mat[3]); +} +void etk::Matrix2::transpose() { + float tmp = m_mat[2]; + m_mat[2] = m_mat[1]; + m_mat[1] = tmp; } float etk::Matrix2::determinant() const { - return m_mat[0] * m_mat[3] - m_mat[4] * m_mat[1]; + return m_mat[0] * m_mat[3] - m_mat[2] * m_mat[1]; } -void etk::Matrix2::invert() { - float det = 1.0f / determinant(); - float t0 = m_mat[3] * det; - m_mat[3] = m_mat[0] * det; - m_mat[4] = -m_mat[4] * det; - m_mat[1] = -m_mat[1] * det; - float t4 = -m_mat[2] * t0 - m_mat[5] * m_mat[1]; - m_mat[5] = -m_mat[2] * m_mat[4] - m_mat[5] * m_mat[3]; - m_mat[0] = t0; - m_mat[2] = t4; +float etk::Matrix2::getTrace() const { + return m_mat[0] + m_mat[3]; } +void etk::Matrix2::setIdentity() { + m_mat[0] = 1.0f; + m_mat[1] = 0.0f; + m_mat[2] = 0.0f; + m_mat[3] = 1.0f; +} + +etk::Matrix2 etk::Matrix2::identity() { + return etk::Matrix2(1.0f, 0.0f, 0.0f, 1.0f); +} + +etk::Matrix2 etk::Matrix2::zero() { + return etk::Matrix2(0.0f, 0.0f, 0.0f, 0.0f); +} + +etk::Matrix2 etk::Matrix2::getAbsolute() const { + return Matrix2(std::abs(m_mat[0]), std::abs(m_mat[1]), + std::abs(m_mat[2]), std::abs(m_mat[3])); +} +void etk::Matrix2::absolute() { + m_mat[0] = std::abs(m_mat[0]); + m_mat[1] = std::abs(m_mat[1]); + m_mat[2] = std::abs(m_mat[2]); + m_mat[3] = std::abs(m_mat[3]); +} + +void etk::Matrix2::inverse() { + *this = getInverse(); +} + +etk::Matrix2 etk::Matrix2::getInverse() const { + float det = determinant(); + //assert(std::abs(det) > MACHINE_EPSILON); + float invDet = 1.0f / det; + return etk::Matrix2(m_mat[3], -m_mat[1], -m_mat[2], m_mat[0]) * invDet; +} + + + etk::Matrix2 etk::mat2Rotate(float _angleRad) { - return Matrix2(cos(_angleRad), sin(_angleRad), -sin(_angleRad), cos(_angleRad), 0.0, 0.0); -}; + return Matrix2(cos(_angleRad), sin(_angleRad), -sin(_angleRad), cos(_angleRad)); +} etk::Matrix2 etk::mat2Scale(const vec2& _scale) { - return Matrix2(_scale.x(), 0.0, 0.0, _scale.y(), 0.0, 0.0); -}; + return Matrix2(_scale.x(), 0.0, 0.0, _scale.y()); +} etk::Matrix2 etk::mat2Scale(float _scale) { - return Matrix2(_scale, 0.0, 0.0, _scale, 0.0, 0.0); -}; - -etk::Matrix2 etk::mat2Translate(const vec2& _translate) { - return Matrix2(1.0, 0.0, 0.0, 1.0, _translate.x(), _translate.y()); -}; + return Matrix2(_scale, 0.0, 0.0, _scale); +} etk::Matrix2 etk::mat2Skew(const vec2& _skew) { - return Matrix2(1.0, tan(_skew.y()), tan(_skew.x()), 1.0, 0.0, 0.0); -}; + return Matrix2(1.0, tan(_skew.y()), tan(_skew.x()), 1.0); +} + +etk::Matrix2 operator-(const etk::Matrix2& _matrix) { + return etk::Matrix2(-_matrix.m_mat[0], -_matrix.m_mat[1], -_matrix.m_mat[2], -_matrix.m_mat[3]); +} \ No newline at end of file diff --git a/etk/math/Matrix2.hpp b/etk/math/Matrix2.hpp index 4b68285..6160a49 100644 --- a/etk/math/Matrix2.hpp +++ b/etk/math/Matrix2.hpp @@ -3,62 +3,123 @@ * @copyright 2011, Edouard DUPIN, all right reserved * @license MPL v2.0 (see license file) */ - #pragma once - -#include #include +#include +#include + namespace etk { /** - * @brief Transformation matrix for vector 2D. + * This class represents a 2x2 matrix. */ class Matrix2 { public: /** * @brief Internal data - * sx shx tx - * sy shy ty + * sx shx + * sy shy */ - float m_mat[2*3]; - public: + float m_mat[2*2]; + public : /** - * @brief Constructor that load identity + * @brief Constructor that load zero matrix */ Matrix2(); + /** + * @brief Configuration constructorwith single value. + * @param[in] _value single vamue + */ + Matrix2(float _value); + /** + * @brief Configuration constructor. + * @param[in] _a1 element 0x0 + * @param[in] _a2 element 0x1 + * @param[in] _b1 element 1x0 + * @param[in] _b2 element 1x1 + */ + Matrix2(float _a1, float _a2, float _b1, float _b2); /** * @brief Copy constructor. * @param[in] _obj Matrix object to copy */ - Matrix2(const Matrix2& _obj); + Matrix2(const Matrix2& _matrix); /** - * @brief Configuration constructor. - * @param[in] _sx Scale threw X axis - * @param[in] _shy Rotate in radian threw Y axis - * @param[in] _shx Rotate in radian threw X axis - * @param[in] _sy Scale threw Y axis - * @param[in] _tx Translate threw X axis - * @param[in] _ty translate threw Y axis + * @brief Set Value on the matrix + * @param[in] _a1 element 0x0 + * @param[in] _a2 element 0x1 + * @param[in] _b1 element 1x0 + * @param[in] _b2 element 1x1 */ - Matrix2(float _sx, - float _shy, - float _shx, - float _sy, - float _tx, - float _ty); + void setValue(float _a1, float _a2, float _b1, float _b2); /** - * @brief Configuration constructor. - * @param[in] _values vector of values in float + * @brief Load Zero matrix */ - Matrix2(const float* _values); + void setZero(); /** - * @brief Configuration constructor. - * @param[in] _values vector of values in double + * @brief get the colom id values + * @param[in] _iii Id of the colomn + * @return Vector 2D vith the values */ - Matrix2(const double* _values); + vec2 getColumn(uint32_t _iii) const; + /** + * @brief get the row id values + * @param[in] _iii Id of the row + * @return Vector 2D vith the values + */ + vec2 getRow(uint32_t _iii) const; + /** + * @brief get a transpose matrix of this one. + * @return the transpose matrix + */ + Matrix2 getTranspose() const; + /** + * @brief Transpose the current matrix. + */ + void transpose(); + /** + * @brief Computes the determinant of the matrix. + * @return The determinent Value. + */ + float determinant() const; + /** + * @brief Calculate the trace of the matrix + * @return value of addition of all element in the diagonal + */ + float getTrace() const; + /** + * @brief Inverts the matrix. + * @note The determinant must be != 0, otherwithe the matrix can't be inverted. + * @return The inverted matrix. + */ + Matrix2 getInverse() const; + /** + * @brief Inverts the current matrix. + * @note The determinant must be != 0, otherwithe the matrix can't be inverted. + */ + void inverse(); + /** + * @brief get the mathix with the absolute value + * @return matix in absolute + */ + Matrix2 getAbsolute() const; + /** + * @brief absolutise the matrix + */ + void absolute(); /** * @brief Load Identity matrix */ - void identity(); + void setIdentity(); + /** + * @brief create a Identity matrix + * @return created new matrix + */ + static etk::Matrix2 identity(); + /** + * @brief create a ZERO matrix + * @return created new matrix + */ + static Matrix2 zero(); /** * @brief Operator= Asign the current object with an other object * @param[in] _obj Reference on the external object @@ -78,7 +139,7 @@ namespace etk { * @return true The Objects are NOT identical * @return false The Objects are identical */ - bool operator!= (const Matrix2& _obj) const; + bool operator!= (const Matrix2& _obj) const; /** * @brief Operator+= Addition an other matrix with this one * @param[in] _obj Reference on the external object @@ -114,64 +175,27 @@ namespace etk { * @param[in] _obj Reference on the external object * @return New vector containing the value */ - Matrix2 operator * (const Matrix2& _obj); + Matrix2 operator * (const Matrix2& _obj) const; + /** + * @brief Operator*= Multiplication a value + * @param[in] _value value to multiply all the matrix + * @return Local reference of the vector multiplicated + */ + const Matrix2& operator *= (float _value); + /** + * @brief Operator*= Multiplication a value + * @param[in] _value value to multiply all the matrix + * @return Local reference of the vector multiplicated + */ + Matrix2 operator * (float _value) const; /** * @brief Operator* apply matrix on a vector * @param[in] _point Point value to apply the matrix * @return New vector containing the value */ vec2 operator * (const vec2& _point) const; - /** - * @brief Apply matrix on a vector Scale Rotate, but NOT the translation - * @param[in] _point Point value to apply the matrix - * @return New vector containing the value - */ - vec2 applyScaleRotation(const vec2& _point) const; - /** - * @brief Inverse the current Matrix - * @return New vector containing the value - */ - Matrix2 operator ~ () const; - /** - * @brief Flip the mathix threw the X axis - */ - void flipX(); - /** - * @brief Flip the mathix threw the Y axis - */ - void flipY(); - /** - * @brief Scale the current Matrix. - * @param[in] _vect Vector to scale matrix. - */ - void scale(const vec2& _vect); - /** - * @brief Scale the current Matrix. - * @param[in] _value Single value to scale in X andf Y. - */ - void scale(float _value); - /** - * @brief Makes a rotation matrix. - * @param[in] _angleRad angle to apply. - */ - void rotate(float _angleRad); - /** - * @brief Makes a translation of the matrix - * @param[in] _vect Translation to apply. - */ - void translate(const vec2& _vect); - /** - * @brief Computes the determinant of the matrix. - * @return The determinent Value. - */ - float determinant() const; - /** - * @brief Inverts the matrix. - * @note The determinant must be != 0, otherwithe the matrix can't be inverted. - * @return The inverted matrix. - */ - void invert(); }; + /** * @brief Create a matrix 2D with a simple rotation * @param[in] _angleRad Radian angle to set at the matrix @@ -190,12 +214,6 @@ namespace etk { * @return New matrix of the transformation requested */ Matrix2 mat2Scale(float _scale); - /** - * @brief Create a matrix 2D with a simple translation - * @param[in] _translate 2 dimention translation - * @return New matrix of the transformation requested - */ - Matrix2 mat2Translate(const vec2& _translate); /** * @brief Create a matrix 2D with a simple skew * @param[in] _skew 2 dimention skew @@ -205,6 +223,9 @@ namespace etk { //! @not_in_doc std::ostream& operator <<(std::ostream& _os, const etk::Matrix2& _obj); } + +etk::Matrix2 operator-(const etk::Matrix2& _matrix); + // simplify using of matrix ... using mat2 = etk::Matrix2; //!< Use simplification in upper application to use matrix like openGL shader diff --git a/etk/math/Matrix3.cpp b/etk/math/Matrix3.cpp new file mode 100644 index 0000000..70e40aa --- /dev/null +++ b/etk/math/Matrix3.cpp @@ -0,0 +1,298 @@ +/** @file + * @author Edouard DUPIN + * @copyright 2011, Edouard DUPIN, all right reserved + * @license MPL v2.0 (see license file) + */ + +#include + + +std::ostream& etk::operator <<(std::ostream& _os, const etk::Matrix3& _obj) { + _os << "{"; + _os << _obj.m_mat[0] << ","; + _os << _obj.m_mat[1] << ","; + _os << _obj.m_mat[2] << ";"; + _os << _obj.m_mat[3] << ","; + _os << _obj.m_mat[4] << ","; + _os << _obj.m_mat[5] << ";"; + _os << _obj.m_mat[6] << ","; + _os << _obj.m_mat[7] << ","; + _os << _obj.m_mat[8] << "}"; + return _os; +} + +etk::Matrix3::Matrix3() { + m_mat[0] = 0.0f; + m_mat[1] = 0.0f; + m_mat[2] = 0.0f; + m_mat[3] = 0.0f; + m_mat[4] = 0.0f; + m_mat[5] = 0.0f; + m_mat[6] = 0.0f; + m_mat[7] = 0.0f; + m_mat[8] = 0.0f; +} + +etk::Matrix3::Matrix3(float _value) { + m_mat[0] = _value; + m_mat[1] = _value; + m_mat[2] = _value; + m_mat[3] = _value; + m_mat[4] = _value; + m_mat[5] = _value; + m_mat[6] = _value; + m_mat[7] = _value; + m_mat[8] = _value; +} + +etk::Matrix3::Matrix3(float _a1, float _a2, float _a3, + float _b1, float _b2, float _b3, + float _c1, float _c2, float _c3) { + m_mat[0] = _a1; m_mat[1] = _a2; m_mat[2] = _a3; + m_mat[3] = _b1; m_mat[4] = _b2; m_mat[5] = _b3; + m_mat[6] = _c1; m_mat[7] = _c2; m_mat[8] = _c3; +} + +etk::Matrix3::Matrix3(const etk::Matrix3& _obj) { + m_mat[0] = _obj.m_mat[0]; + m_mat[1] = _obj.m_mat[1]; + m_mat[2] = _obj.m_mat[2]; + m_mat[3] = _obj.m_mat[3]; + m_mat[4] = _obj.m_mat[4]; + m_mat[5] = _obj.m_mat[5]; + m_mat[6] = _obj.m_mat[6]; + m_mat[7] = _obj.m_mat[7]; + m_mat[8] = _obj.m_mat[8]; +} + +void etk::Matrix3::setValue(float _a1, float _a2, float _a3, + float _b1, float _b2, float _b3, + float _c1, float _c2, float _c3) { + m_mat[0] = _a1; m_mat[1] = _a2; m_mat[2] = _a3; + m_mat[3] = _b1; m_mat[4] = _b2; m_mat[5] = _b3; + m_mat[6] = _c1; m_mat[7] = _c2; m_mat[8] = _c3; +} + +void etk::Matrix3::setZero() { + m_mat[0] = 0.0f; + m_mat[1] = 0.0f; + m_mat[2] = 0.0f; + m_mat[3] = 0.0f; + m_mat[4] = 0.0f; + m_mat[5] = 0.0f; + m_mat[6] = 0.0f; + m_mat[7] = 0.0f; + m_mat[8] = 0.0f; +} + +vec3 etk::Matrix3::getColumn(uint32_t _iii) const { + if (_iii == 0) { + return vec3(m_mat[0], m_mat[3], m_mat[6]); + } else if (_iii == 1) { + return vec3(m_mat[1], m_mat[4], m_mat[7]); + } + return vec3(m_mat[2], m_mat[5], m_mat[8]); +} + +vec3 etk::Matrix3::getRow(uint32_t _iii) const { + if (_iii == 0) { + return vec3(m_mat[0], m_mat[1], m_mat[2]); + } else if (_iii == 1) { + return vec3(m_mat[3], m_mat[4], m_mat[5]); + } + return vec3(m_mat[6], m_mat[7], m_mat[8]); +} + +etk::Matrix3 etk::Matrix3::getTranspose() const { + return etk::Matrix3(m_mat[0], m_mat[3], m_mat[6], + m_mat[1], m_mat[4], m_mat[7], + m_mat[2], m_mat[5], m_mat[8]); +} + +void etk::Matrix3::transpose() { + float tmp = m_mat[1]; + m_mat[1] = m_mat[3]; + m_mat[3] = tmp; + tmp = m_mat[2]; + m_mat[2] = m_mat[6]; + m_mat[6] = tmp; + tmp = m_mat[5]; + m_mat[5] = m_mat[7]; + m_mat[7] = tmp; +} + +float etk::Matrix3::determinant() const { + return m_mat[0]*(m_mat[4]*m_mat[8]-m_mat[7]*m_mat[5]) + - m_mat[1]*(m_mat[3]*m_mat[8]-m_mat[6]*m_mat[5]) + + m_mat[2]*(m_mat[3]*m_mat[7]-m_mat[6]*m_mat[4]); +} + +float etk::Matrix3::getTrace() const { + return (m_mat[0] + m_mat[4] + m_mat[8]); +} + +void etk::Matrix3::setIdentity() { + m_mat[0] = 1.0; m_mat[1] = 0.0; m_mat[2] = 0.0; + m_mat[3] = 0.0; m_mat[4] = 1.0; m_mat[5] = 0.0; + m_mat[6] = 0.0; m_mat[7] = 0.0; m_mat[8] = 1.0; +} + +etk::Matrix3 etk::Matrix3::identity() { + return etk::Matrix3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0); +} + +etk::Matrix3 etk::Matrix3::zero() { + return etk::Matrix3(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0); +} + +void etk::Matrix3::absolute() { + m_mat[0] = std::abs(m_mat[0]); + m_mat[1] = std::abs(m_mat[1]); + m_mat[2] = std::abs(m_mat[2]); + m_mat[3] = std::abs(m_mat[3]); + m_mat[4] = std::abs(m_mat[4]); + m_mat[5] = std::abs(m_mat[5]); + m_mat[6] = std::abs(m_mat[6]); + m_mat[7] = std::abs(m_mat[7]); + m_mat[8] = std::abs(m_mat[8]); +} + +etk::Matrix3 etk::Matrix3::getAbsolute() const { + return etk::Matrix3(std::abs(m_mat[0]), std::abs(m_mat[1]), std::abs(m_mat[2]), + std::abs(m_mat[3]), std::abs(m_mat[4]), std::abs(m_mat[5]), + std::abs(m_mat[6]), std::abs(m_mat[7]), std::abs(m_mat[8])); +} + + + +const etk::Matrix3& etk::Matrix3::operator= (const etk::Matrix3& _obj ) { + for(int32_t iii=0; iii<3*3 ; ++iii) { + m_mat[iii] = _obj.m_mat[iii]; + } + return *this; +} + +bool etk::Matrix3::operator== (const etk::Matrix3& _obj) const { + for(int32_t iii=0; iii<3*3 ; ++iii) { + if(m_mat[iii] != _obj.m_mat[iii]) { + return false; + } + } + return true; +} + +bool etk::Matrix3::operator!= (const etk::Matrix3& _obj) const { + for(int32_t iii=0; iii<3*3 ; ++iii) { + if(m_mat[iii] != _obj.m_mat[iii]) { + return true; + } + } + return false; +} + +const etk::Matrix3& etk::Matrix3::operator+= (const etk::Matrix3& _obj) { + for(int32_t iii=0; iii<3*3 ; ++iii) { + m_mat[iii] += _obj.m_mat[iii]; + } + return *this; +} + +etk::Matrix3 etk::Matrix3::operator+ (const etk::Matrix3& _obj) const { + etk::Matrix3 tmpp(*this); + tmpp += _obj; + return tmpp; +} + +const etk::Matrix3& etk::Matrix3::operator-= (const etk::Matrix3& _obj) { + for(int32_t iii=0; iii<3*3 ; ++iii) { + m_mat[iii] -= _obj.m_mat[iii]; + } + return *this; +} + +etk::Matrix3 etk::Matrix3::operator- (const etk::Matrix3& _obj) const { + etk::Matrix3 tmpp(*this); + tmpp -= _obj; + return tmpp; +} + +const etk::Matrix3& etk::Matrix3::operator *= (const etk::Matrix3& _obj) { + float a1 = m_mat[0]*_obj.m_mat[0] + m_mat[1]*_obj.m_mat[3] + m_mat[2]*_obj.m_mat[6]; + float b1 = m_mat[3]*_obj.m_mat[0] + m_mat[4]*_obj.m_mat[3] + m_mat[5]*_obj.m_mat[6]; + float c1 = m_mat[6]*_obj.m_mat[0] + m_mat[7]*_obj.m_mat[3] + m_mat[8]*_obj.m_mat[6]; + float a2 = m_mat[0]*_obj.m_mat[1] + m_mat[1]*_obj.m_mat[4] + m_mat[2]*_obj.m_mat[7]; + float b2 = m_mat[3]*_obj.m_mat[1] + m_mat[4]*_obj.m_mat[4] + m_mat[5]*_obj.m_mat[7]; + float c2 = m_mat[6]*_obj.m_mat[1] + m_mat[7]*_obj.m_mat[4] + m_mat[8]*_obj.m_mat[7]; + m_mat[2] = m_mat[0]*_obj.m_mat[2] + m_mat[1]*_obj.m_mat[5] + m_mat[2]*_obj.m_mat[8]; + m_mat[5] = m_mat[3]*_obj.m_mat[2] + m_mat[4]*_obj.m_mat[5] + m_mat[5]*_obj.m_mat[8]; + m_mat[8] = m_mat[6]*_obj.m_mat[2] + m_mat[7]*_obj.m_mat[5] + m_mat[8]*_obj.m_mat[8]; + m_mat[0] = a1; + m_mat[3] = b1; + m_mat[6] = c1; + m_mat[1] = a2; + m_mat[4] = b2; + m_mat[7] = c2; + return *this; +} + +etk::Matrix3 etk::Matrix3::operator * (const etk::Matrix3& _obj) const { + etk::Matrix3 tmp(*this); + tmp *= _obj; + return tmp; +} + +vec3 etk::Matrix3::operator * (const vec3& _point) const { + return vec3(_point.x()*m_mat[0] + _point.y()*m_mat[1] + _point.z()*m_mat[2], + _point.x()*m_mat[3] + _point.y()*m_mat[4] + _point.z()*m_mat[5], + _point.x()*m_mat[6] + _point.y()*m_mat[7] + _point.z()*m_mat[8]); +} + +const etk::Matrix3& etk::Matrix3::operator *= (float _value) { + m_mat[0] *= _value; + m_mat[1] *= _value; + m_mat[2] *= _value; + m_mat[3] *= _value; + m_mat[4] *= _value; + m_mat[5] *= _value; + m_mat[6] *= _value; + m_mat[7] *= _value; + m_mat[8] *= _value; + return *this; +} + +etk::Matrix3 etk::Matrix3::operator * (float _value) const { + etk::Matrix3 tmp(*this); + tmp *= _value; + return tmp; +} + +void etk::Matrix3::inverse() { + *this = getInverse(); +} + +etk::Matrix3 etk::Matrix3::getInverse() const { + float det = determinant(); + //assert(std::abs(det) > MACHINE_EPSILON); + float invDet = 1.0f / det; + return etk::Matrix3( (m_mat[4]*m_mat[8]-m_mat[7]*m_mat[5]), + -(m_mat[1]*m_mat[8]-m_mat[7]*m_mat[2]), + (m_mat[1]*m_mat[5]-m_mat[2]*m_mat[4]), + -(m_mat[3]*m_mat[8]-m_mat[6]*m_mat[5]), + (m_mat[0]*m_mat[8]-m_mat[6]*m_mat[2]), + -(m_mat[0]*m_mat[5]-m_mat[3]*m_mat[2]), + (m_mat[3]*m_mat[7]-m_mat[6]*m_mat[4]), + -(m_mat[0]*m_mat[7]-m_mat[6]*m_mat[1]), + (m_mat[0]*m_mat[4]-m_mat[1]*m_mat[3]))* invDet; +} + +etk::Matrix3 etk::Matrix3::computeSkewSymmetricMatrixForCrossProduct(const vec3& vector) { + return etk::Matrix3( 0.0f , -vector.z(), vector.y(), + vector.z(), 0.0f , -vector.x(), + -vector.y(), vector.x(), 0.0f); +} + +etk::Matrix3 operator-(const etk::Matrix3& _matrix) { + return etk::Matrix3(-_matrix.m_mat[0], -_matrix.m_mat[1], -_matrix.m_mat[2], + -_matrix.m_mat[3], -_matrix.m_mat[4], -_matrix.m_mat[5], + -_matrix.m_mat[6], -_matrix.m_mat[7], -_matrix.m_mat[8]); +} diff --git a/etk/math/Matrix3.hpp b/etk/math/Matrix3.hpp new file mode 100644 index 0000000..8592c53 --- /dev/null +++ b/etk/math/Matrix3.hpp @@ -0,0 +1,222 @@ +/** @file + * @author Edouard DUPIN + * @copyright 2011, Edouard DUPIN, all right reserved + * @license MPL v2.0 (see license file) + */ +#pragma once +#include +#include +#include + +namespace etk { + /** + * @brief This class represents a 3x3 matrix. + */ + class Matrix3 { + public: + float m_mat[3*3]; //!< matrix data + public : + /** + * @brief Constructor that load zero matrix + */ + Matrix3(); + /** + * @brief Configuration constructorwith single value. + * @param[in] _value single vamue + */ + Matrix3(float value); + /** + * @brief Configuration constructor. + * @param[in] _a1 element 0x0 + * @param[in] _a2 element 0x1 + * @param[in] _a3 element 0x2 + * @param[in] _b1 element 1x0 + * @param[in] _b2 element 1x1 + * @param[in] _b3 element 1x2 + * @param[in] _c1 element 2x0 + * @param[in] _c2 element 2x1 + * @param[in] _c3 element 2x2 + */ + Matrix3(float _a1, float _a2, float _a3, + float _b1, float _b2, float _b3, + float _c1, float _c2, float _c3); + /** + * @brief Copy constructor. + * @param[in] _obj Matrix object to copy + */ + Matrix3(const Matrix3& _obj); + /** + * @brief Set Value on the matrix + * @param[in] _a1 element 0x0 + * @param[in] _a2 element 0x1 + * @param[in] _a3 element 0x2 + * @param[in] _b1 element 1x0 + * @param[in] _b2 element 1x1 + * @param[in] _b3 element 1x2 + * @param[in] _c1 element 2x0 + * @param[in] _c2 element 2x1 + * @param[in] _c3 element 2x2 + */ + void setValue(float _a1, float _a2, float _a3, + float _b1, float _b2, float _b3, + float _c1, float _c2, float _c3); + /** + * @brief Load Zero matrix + */ + void setZero(); + /** + * @brief get the colom id values + * @param[in] _iii Id of the colomn + * @return Vector 3D vith the values + */ + vec3 getColumn(uint32_t _iii) const; + /** + * @brief get the row id values + * @param[in] _iii Id of the row + * @return Vector 3D vith the values + */ + vec3 getRow(uint32_t _iii) const; + /** + * @brief get a transpose matrix of this one. + * @return the transpose matrix + */ + Matrix3 getTranspose() const; + /** + * @brief Transpose the current matrix. + */ + void transpose(); + /** + * @brief Computes the determinant of the matrix. + * @return The determinent Value. + */ + float determinant() const; + /** + * @brief Calculate the trace of the matrix + * @return value of addition of all element in the diagonal + */ + float getTrace() const; + /** + * @brief Inverts the matrix. + * @note The determinant must be != 0, otherwithe the matrix can't be inverted. + * @return The inverted matrix. + */ + Matrix3 getInverse() const; + /** + * @brief Inverts the current matrix. + * @note The determinant must be != 0, otherwithe the matrix can't be inverted. + */ + void inverse(); + /** + * @brief get the matrix with the absolute value + * @return matix in absolute + */ + Matrix3 getAbsolute() const; + /** + * @brief absolutise the matrix + */ + void absolute(); + /** + * @brief Load Identity matrix + */ + void setIdentity(); + /** + * @brief create a Identity matrix + * @return created new matrix + */ + static Matrix3 identity(); + /** + * @brief create a ZERO matrix + * @return created new matrix + */ + static Matrix3 zero(); + /** + * @brief create a skew-symmetric matrix using a given vector that can be used to compute cross product with another vector using matrix multiplication + * @param[in] _vector Vector to comute + * @return Matrix to compute + */ + static Matrix3 computeSkewSymmetricMatrixForCrossProduct(const vec3& _vector); + /** + * @brief Operator= Asign the current object with an other object + * @param[in] _obj Reference on the external object + * @return Local reference of the vector asigned + */ + const Matrix3& operator= (const Matrix3& _obj ); + /** + * @brief Equality compare operator with an other object. + * @param[in] _obj Reference on the comparing object + * @return true The Objects are identical + * @return false The Objects are NOT identical + */ + bool operator== (const Matrix3& _obj) const; + /** + * @brief In-Equality compare operator with an other object. + * @param[in] _obj Reference on the comparing object + * @return true The Objects are NOT identical + * @return false The Objects are identical + */ + bool operator!= (const Matrix3& _obj) const; + /** + * @brief Operator+= Addition an other matrix with this one + * @param[in] _obj Reference on the external object + * @return Local reference of the vector additionned + */ + const Matrix3& operator+= (const Matrix3& _obj); + /** + * @brief Operator+ Addition an other matrix with this one + * @param[in] _obj Reference on the external object + * @return New vector containing the value + */ + Matrix3 operator+ (const Matrix3& _obj) const; + /** + * @brief Operator-= Decrement an other matrix with this one + * @param[in] _obj Reference on the external object + * @return Local reference of the vector decremented + */ + const Matrix3& operator-= (const Matrix3& _obj); + /** + * @brief Operator- Decrement an other matrix with this one + * @param[in] _obj Reference on the external object + * @return New vector containing the value + */ + Matrix3 operator- (const Matrix3& _obj) const; + /** + * @brief Operator*= Multiplication an other matrix with this one + * @param[in] _obj Reference on the external object + * @return Local reference of the vector multiplicated + */ + const Matrix3& operator *= (const Matrix3& _obj); + /** + * @brief Operator* Multiplication an other matrix with this one + * @param[in] _obj Reference on the external object + * @return New vector containing the value + */ + Matrix3 operator * (const Matrix3& _obj) const; + /** + * @brief Operator*= Multiplication a value + * @param[in] _value value to multiply all the matrix + * @return Local reference of the vector multiplicated + */ + const Matrix3& operator *= (float _value); + /** + * @brief Operator*= Multiplication a value + * @param[in] _value value to multiply all the matrix + * @return Local reference of the vector multiplicated + */ + Matrix3 operator * (float _value) const; + /** + * @brief Operator* apply matrix on a vector + * @param[in] _point Point value to apply the matrix + * @return New vector containing the value + */ + vec3 operator * (const vec3& _point) const; + }; + //! @not_in_doc + std::ostream& operator <<(std::ostream& _os, const etk::Matrix3& _obj); +} + +etk::Matrix3 operator-(const etk::Matrix3& _matrix); + +// simplify using of matrix ... +using mat3 = etk::Matrix3; //!< Use simplification in upper application to use matrix like openGL shader + + diff --git a/etk/math/Matrix4.cpp b/etk/math/Matrix4.cpp index 11428c2..95ff32f 100644 --- a/etk/math/Matrix4.cpp +++ b/etk/math/Matrix4.cpp @@ -346,7 +346,7 @@ float etk::Matrix4::determinant() const { etk::Matrix4 etk::Matrix4::invert() { float det = determinant(); - if(fabsf(det) < (1.0e-7f)) { + if(std::abs(det) < (1.0e-7f)) { // The matrix is not invertible! Singular case! return *this; } diff --git a/etk/math/Matrix4.hpp b/etk/math/Matrix4.hpp index 428a26c..1974871 100644 --- a/etk/math/Matrix4.hpp +++ b/etk/math/Matrix4.hpp @@ -32,7 +32,7 @@ namespace etk { return _val*T(180.0)/M_PI; } /** - * @brief Transformation matrix for vector 3D. + * @brief This class represents a 4x4 matrix. */ class Matrix4 { public: @@ -238,7 +238,8 @@ namespace etk { */ Matrix4 matRotate(vec3 _normal, float _angleRad=0.0); //! @not_in_doc - Matrix4 matRotate2(vec3 _vect); /** + Matrix4 matRotate2(vec3 _vect); + /** * @brief Create projection matrix with camera property (camera view in -z axis) * @param[in] _eye Optical center of the camera * @param[in] _target Point of where the camera is showing diff --git a/etk/math/Quaternion.cpp b/etk/math/Quaternion.cpp new file mode 100644 index 0000000..4f0638e --- /dev/null +++ b/etk/math/Quaternion.cpp @@ -0,0 +1,153 @@ +/** @file + * @author Edouard DUPIN + * @copyright 2011, Edouard DUPIN, all right reserved + * @license MPL v2.0 (see license file) + */ + +#include + +std::ostream& etk::operator <<(std::ostream &_os, const etk::Quaternion& _obj) { + _os << "("; + _os << _obj.x(); + _os << ","; + _os << _obj.y(); + _os << ","; + _os << _obj.z(); + _os << ","; + _os << _obj.w(); + _os << ")"; + return _os; +} + +etk::Quaternion::Quaternion(const etk::Matrix3& _matrix) { + float trace = _matrix.getTrace(); + if (trace < 0.0f) { + if (_matrix.m_mat[4] > _matrix.m_mat[0]) { + if(_matrix.m_mat[8] > _matrix.m_mat[4]) { + float rrr = sqrt(_matrix.m_mat[8] - _matrix.m_mat[0] - _matrix.m_mat[4] + 1.0f); + float sss = 0.5f / rrr; + m_floats[0] = (_matrix.m_mat[6] + _matrix.m_mat[2]) * sss; + m_floats[1] = (_matrix.m_mat[5] + _matrix.m_mat[7]) * sss; + m_floats[2] = 0.5f * rrr; + m_floats[3] = (_matrix.m_mat[3] - _matrix.m_mat[1]) * sss; + } else { + float rrr = sqrt(_matrix.m_mat[4] - _matrix.m_mat[8] - _matrix.m_mat[0] + 1.0f); + float sss = 0.5f / rrr; + m_floats[0] = (_matrix.m_mat[1] + _matrix.m_mat[3]) * sss; + m_floats[1] = 0.5f * rrr; + m_floats[2] = (_matrix.m_mat[5] + _matrix.m_mat[7]) * sss; + m_floats[3] = (_matrix.m_mat[2] - _matrix.m_mat[6]) * sss; + } + } else if (_matrix.m_mat[8] > _matrix.m_mat[0]) { + float rrr = sqrt(_matrix.m_mat[8] - _matrix.m_mat[0] - _matrix.m_mat[4] + 1.0f); + float sss = 0.5f / rrr; + m_floats[0] = (_matrix.m_mat[6] + _matrix.m_mat[2]) * sss; + m_floats[1] = (_matrix.m_mat[5] + _matrix.m_mat[7]) * sss; + m_floats[2] = 0.5f * rrr; + m_floats[3] = (_matrix.m_mat[3] - _matrix.m_mat[1]) * sss; + } else { + float rrr = sqrt(_matrix.m_mat[0] - _matrix.m_mat[4] - _matrix.m_mat[8] + 1.0f); + float sss = 0.5f / rrr; + m_floats[0] = 0.5f * rrr; + m_floats[1] = (_matrix.m_mat[1] + _matrix.m_mat[3]) * sss; + m_floats[2] = (_matrix.m_mat[6] - _matrix.m_mat[2]) * sss; + m_floats[3] = (_matrix.m_mat[7] - _matrix.m_mat[5]) * sss; + } + } else { + float rrr = sqrt(trace + 1.0f); + float sss = 0.5f / rrr; + m_floats[0] = (_matrix.m_mat[7] - _matrix.m_mat[5]) * sss; + m_floats[1] = (_matrix.m_mat[2] - _matrix.m_mat[6]) * sss; + m_floats[2] = (_matrix.m_mat[3] - _matrix.m_mat[1]) * sss; + m_floats[3] = 0.5f * rrr; + } +} + +void etk::Quaternion::getAngleAxis(float& _angle, vec3& _axis) const { + etk::Quaternion quaternion = getUnit(); + _angle = acos(quaternion.w()) * 2.0f; + vec3 rotationAxis(quaternion.x(), quaternion.y(), quaternion.z()); + rotationAxis = rotationAxis.normalized(); + _axis.setValue(rotationAxis.x(), rotationAxis.y(), rotationAxis.z()); +} + +etk::Matrix3 etk::Quaternion::getMatrix() const { + float nQ = m_floats[0]*m_floats[0] + + m_floats[1]*m_floats[1] + + m_floats[2]*m_floats[2] + + m_floats[3]*m_floats[3]; + float sss = 0.0f; + if (nQ > 0.0f) { + sss = 2.0f / nQ; + } + float xs = m_floats[0]*sss; + float ys = m_floats[1]*sss; + float zs = m_floats[2]*sss; + float wxs = m_floats[3]*xs; + float wys = m_floats[3]*ys; + float wzs = m_floats[3]*zs; + float xxs = m_floats[0]*xs; + float xys = m_floats[0]*ys; + float xzs = m_floats[0]*zs; + float yys = m_floats[1]*ys; + float yzs = m_floats[1]*zs; + float zzs = m_floats[2]*zs; + return etk::Matrix3(1.0f - yys - zzs, + xys - wzs, + xzs + wys, + xys + wzs, + 1.0f - xxs - zzs, + yzs - wxs, + xzs - wys, + yzs + wxs, + 1.0f - xxs - yys); +} + +etk::Quaternion etk::Quaternion::slerp(const Quaternion& _obj1, + const Quaternion& _obj2, + float _ttt) { + TK_ASSERT(_ttt >= 0.0f && _ttt <= 1.0f, "wrong intermolation"); + float invert = 1.0f; + float cosineTheta = _obj1.dot(_obj2); + if (cosineTheta < 0.0f) { + cosineTheta = -cosineTheta; + invert = -1.0f; + } + if(1-cosineTheta < 0.00001f) { + return _obj1 * (1.0f-_ttt) + _obj2 * (_ttt * invert); + } + float theta = acos(cosineTheta); + float sineTheta = sin(theta); + float coeff1 = sin((1.0f-_ttt)*theta) / sineTheta; + float coeff2 = sin(_ttt*theta) / sineTheta * invert; + return _obj1 * coeff1 + _obj2 * coeff2; +} + +void etk::Quaternion::setEulerAngles(const vec3& _angles) { + float angle = _angles.x() * 0.5f; + float sinX = std::sin(angle); + float cosX = std::cos(angle); + angle = _angles.y() * 0.5f; + float sinY = std::sin(angle); + float cosY = std::cos(angle); + angle = _angles.z() * 0.5f; + float sinZ = std::sin(angle); + float cosZ = std::cos(angle); + float cosYcosZ = cosY * cosZ; + float sinYcosZ = sinY * cosZ; + float cosYsinZ = cosY * sinZ; + float sinYsinZ = sinY * sinZ; + m_floats[0] = sinX * cosYcosZ - cosX * sinYsinZ; + m_floats[1] = cosX * sinYcosZ + sinX * cosYsinZ; + m_floats[2] = cosX * cosYsinZ - sinX * sinYcosZ; + m_floats[3] = cosX * cosYcosZ + sinX * sinYsinZ; + normalize(); +} + +etk::Quaternion etk::Quaternion::zero() { + return etk::Quaternion(0,0,0,0); +} + +etk::Quaternion etk::Quaternion::identity() { + return etk::Quaternion(0,0,0,1); +} diff --git a/etk/math/Quaternion.hpp b/etk/math/Quaternion.hpp new file mode 100644 index 0000000..e7f11ec --- /dev/null +++ b/etk/math/Quaternion.hpp @@ -0,0 +1,547 @@ +/** @file + * @author Edouard DUPIN + * @copyright 2011, Edouard DUPIN, all right reserved + * @license MPL v2.0 (see license file) + */ +#pragma once + +#include + +#include +#include +#include + +namespace etk { + /** + * @brief This class represents a quaternion. + */ + struct Quaternion { + public: + float m_floats[4]; //!< all internal values + public: + /** + * @brief No initialization constructor (faster ...) + */ + Quaternion() { + m_floats[0] = 0.0f; + m_floats[1] = 0.0f; + m_floats[2] = 0.0f; + m_floats[3] = 0.0f; + } + /** + * @brief Constructor from scalars. + * @param _xxx X value + * @param _yyy Y value + * @param _zzz Z value + * @param _www W value + */ + Quaternion(const float& _xxx, const float& _yyy, const float& _zzz, const float& _www) { + m_floats[0] = _xxx; + m_floats[1] = _yyy; + m_floats[2] = _zzz; + m_floats[3] = _www; + } + /** + * @brief Constructor with the component w and a vector 3D. + * @param _www W value + * @param _vec 3D vector value + */ + Quaternion(float _www, const vec3& _vec) { + m_floats[0] = _vec.x(); + m_floats[1] = _vec.y(); + m_floats[2] = _vec.z(); + m_floats[3] = _www; + } + /** + * @brief Constructor with Euler angles (in radians) to a quaternion + * @param _eulerAngles list of all euleu angle + */ + Quaternion(const vec3& _eulerAngles) { + setEulerAngles(_eulerAngles); + } + /** + * @brief Create a unit quaternion from a rotation matrix + * @param _matrix generic matrix + */ + Quaternion(const etk::Matrix3& _matrix); + /** + * @brief Add a vector to this one. + * @param[in] _obj The vector to add to this one + * @return Local reference of the vector + */ + Quaternion& operator+=(const Quaternion& _obj) { + m_floats[0] += _obj.m_floats[0]; + m_floats[1] += _obj.m_floats[1]; + m_floats[2] += _obj.m_floats[2]; + m_floats[3] += _obj.m_floats[3]; + return *this; + } + /** + * @brief Add a vector to this one. + * @param[in] _obj The vector to add to this one + * @return New vector containing the value + */ + Quaternion operator+(const Quaternion& _obj) { + return Quaternion(m_floats[0] + _obj.m_floats[0], + m_floats[1] + _obj.m_floats[1], + m_floats[2] + _obj.m_floats[2], + m_floats[3] + _obj.m_floats[3]); + } + /** + * @brief Subtract a vector from this one + * @param _obj The vector to subtract + * @return Local reference of the vector + */ + Quaternion& operator-=(const Quaternion& _obj) { + m_floats[0] -= _obj.m_floats[0]; + m_floats[1] -= _obj.m_floats[1]; + m_floats[2] -= _obj.m_floats[2]; + m_floats[3] -= _obj.m_floats[3]; + return *this; + } + /** + * @brief Subtract a vector from this one + * @param _obj The vector to subtract + * @return New quaternion containing the value + */ + Quaternion operator-(const Quaternion& _obj) { + return Quaternion(m_floats[0] - _obj.m_floats[0], + m_floats[1] - _obj.m_floats[1], + m_floats[2] - _obj.m_floats[2], + m_floats[3] - _obj.m_floats[3]); + } + /** + * @brief Scale the quaternion + * @param[in] _val Scale factor + * @return Local reference of the quaternion + */ + Quaternion& operator*=(const float& _val) { + m_floats[0] *= _val; + m_floats[1] *= _val; + m_floats[2] *= _val; + m_floats[3] *= _val; + return *this; + } + /** + * @brief Scale the quaternion + * @param[in] _val Scale factor + * @return New quaternion containing the value + */ + Quaternion operator*(const float& _val) const { + return Quaternion(m_floats[0] * _val, + m_floats[1] * _val, + m_floats[2] * _val, + m_floats[3] * _val); + } + /** + * @brief Inversely scale the quaternion + * @param[in] _val Scale factor to divide by. + * @return Local reference of the quaternion + */ + Quaternion& operator/=(const float& _val) { + if (_val != 0) { + m_floats[0] /= _val; + m_floats[1] /= _val; + m_floats[2] /= _val; + m_floats[3] /= _val; + return *this; + } + return *this; + } + /** + * @brief Inversely scale the quaternion + * @param[in] _val Scale factor to divide by. + * @return New quaternion containing the value + */ + Quaternion operator/(const float& _val) const { + if (_val != 0) { + return Quaternion(m_floats[0] / _val, + m_floats[1] / _val, + m_floats[2] / _val, + m_floats[3] / _val); + } + return *this; + } + /** + * @brief Return the dot product + * @param _obj The other quaternion in the dot product + * @return Dot result value + */ + float dot(const Quaternion& _obj) const { + return m_floats[0] * _obj.m_floats[0] + + m_floats[1] * _obj.m_floats[1] + + m_floats[2] * _obj.m_floats[2] + + m_floats[3] * _obj.m_floats[3]; + } + /** + * @brief Return the squared length of the quaternion. + * @return Squared length value. + */ + float length2() const { + return dot(*this); + } + /** + * @brief Return the length of the quaternion + * @return Length value + */ + float length() const { + #if __CPP_VERSION__ >= 2011 && !defined(__TARGET_OS__MacOs) && !defined(__TARGET_OS__IOs) + return std::sqrt(length2()); + #else + return sqrt(length2()); + #endif + } + /** + * @brief Return the distance squared between the ends of this and another quaternion + * This is symantically treating the quaternion like a point + * @param[in] _obj The other quaternion to compare distance + * @return the square distance of the 2 points + */ + /* + float distance2(const Quaternion& _obj) const { + return (_obj - *this).length2(); + } + */ + /** + * @brief Return the distance between the ends of this and another quaternion + * This is symantically treating the quaternion like a point + * @param[in] _obj The other quaternion to compare distance + * @return the distance of the 2 points + */ + /* + float distance(const Quaternion& _obj) const { + return (_obj - *this).length(); + } + */ + /** + * @brief Normalize this quaternion x^2 + y^2 + z^2 + w^2 = 1 + * @return Local reference of the quaternion normalized + */ + Quaternion& normalize() { + float invLength = 1.0f / length(); + m_floats[0] *= invLength; + m_floats[1] *= invLength; + m_floats[2] *= invLength; + m_floats[3] *= invLength; + return *this; + } + /** + * @brief Return a normalized version of this quaternion + * @return New quaternion containing the value + */ + Quaternion normalized() const { + etk::Quaternion tmp = *this; + tmp.normalize(); + return tmp; + } + /** + * @brief Return a quaternion will the absolute values of each element + * @return New quaternion with the absolute value + */ + Quaternion absolute() const { + return Quaternion( std::abs(m_floats[0]), + std::abs(m_floats[1]), + std::abs(m_floats[2]), + std::abs(m_floats[3])); + } + /** + * @brief Get X value + * @return the x value + */ + const float& getX() const { + return m_floats[0]; + } + /** + * @brief Get Y value + * @return the y value + */ + const float& getY() const { + return m_floats[1]; + } + /** + * @brief Get Z value + * @return the z value + */ + const float& getZ() const { + return m_floats[2]; + } + /** + * @brief Get W value + * @return the w value + */ + const float& getW() const { + return m_floats[3]; + } + /** + * @brief Set the x value + * @param[in] _x New value + */ + void setX(float _x) { + m_floats[0] = _x; + }; + /** + * @brief Set the y value + * @param[in] _y New value + */ + void setY(float _y) { + m_floats[1] = _y; + }; + /** + * @brief Set the z value + * @param[in] _z New value + */ + void setZ(float _z) { + m_floats[2] = _z; + }; + /** + * @brief Set the w value + * @param[in] _w New value + */ + void setW(float _w) { + m_floats[3] = _w; + }; + /** + * @brief Get X value + * @return the x value + */ + const float& x() const { + return m_floats[0]; + } + /** + * @brief Get Y value + * @return the y value + */ + const float& y() const { + return m_floats[1]; + } + /** + * @brief Get Z value + * @return the z value + */ + const float& z() const { + return m_floats[2]; + } + /** + * @brief Get W value + * @return the w value + */ + const float& w() const { + return m_floats[3]; + } + /** + * @brief Cast the quaternion in the type T* requested. + * @return Pointer on the data + */ + operator float *() { + return &m_floats[0]; + } + /** + * @brief Cast the quaternion in the type const float* requested. + * @return Pointer on the const data + */ + operator const float *() const { + return &m_floats[0]; + } + /** + * @brief Equality compare operator with an other object. + * @param[in] _obj Reference on the comparing object + * @return true The Objects are identical + * @return false The Objects are NOT identical + */ + bool operator==(const Quaternion& _obj) const { + return ( (m_floats[3] == _obj.m_floats[3]) + && (m_floats[2] == _obj.m_floats[2]) + && (m_floats[1] == _obj.m_floats[1]) + && (m_floats[0] == _obj.m_floats[0])); + } + /** + * @brief In-Equality compare operator with an other object. + * @param[in] _obj Reference on the comparing object + * @return true The Objects are NOT identical + * @return false The Objects are identical + */ + bool operator!=(const Quaternion& _obj) const { + return ( (m_floats[3] != _obj.m_floats[3]) + || (m_floats[2] != _obj.m_floats[2]) + || (m_floats[1] != _obj.m_floats[1]) + || (m_floats[0] != _obj.m_floats[0])); + } + /** + * @brief Multiply this quaternion by the other. + * @param _obj The other quaternion + * @return Local reference of the quaternion + */ + Quaternion& operator*=(const Quaternion& _obj) { + vec3 base = getVectorV(); + vec3 crossValue = base.cross(_obj.getVectorV()); + m_floats[0] = m_floats[3] * _obj.m_floats[0] + _obj.m_floats[3] * m_floats[0] + crossValue.x(); + m_floats[1] = m_floats[3] * _obj.m_floats[1] + _obj.m_floats[3] * m_floats[1] + crossValue.y(); + m_floats[2] = m_floats[3] * _obj.m_floats[2] + _obj.m_floats[3] * m_floats[2] + crossValue.z(); + m_floats[3] = m_floats[3] * _obj.m_floats[3] - base.dot(_obj.getVectorV()); + return *this; + } + /** + * @brief Multiply this quaternion by the other. + * @param _obj The other quaternion + * @return New quaternion containing the value + */ + Quaternion operator*(const Quaternion& _obj) const { + etk::Quaternion tmp = *this; + tmp *= _obj; + return tmp; + } + /** + * @brief Operator* with a vector. This methods rotates a point given the rotation of a quaternion + * @param[in] _point Point to move + * @return Point with the updated position + */ + vec3 operator*(const vec3& _point) const { + // TODO :Xheck this ==> if seams a little complicated ... + Quaternion p(0.0, _point); + return (((*this) * p) * getConjugate()).getVectorV(); + } + /** + * @brief Set each element to the max of the current values and the values of another Vector + * @param _obj The other Vector to compare with + */ + void setMax(const Quaternion& _obj) { + std::max(m_floats[0], _obj.m_floats[0]); + std::max(m_floats[1], _obj.m_floats[1]); + std::max(m_floats[2], _obj.m_floats[2]); + std::max(m_floats[3], _obj.m_floats[3]); + } + /** + * @brief Set each element to the min of the current values and the values of another Vector + * @param _obj The other Vector to compare with + */ + void setMin(const Quaternion& _obj) { + std::min(m_floats[0], _obj.m_floats[0]); + std::min(m_floats[1], _obj.m_floats[1]); + std::min(m_floats[2], _obj.m_floats[2]); + std::min(m_floats[3], _obj.m_floats[3]); + } + /** + * @brief Set Value on the quaternion + * @param[in] _xxx X value. + * @param[in] _yyy Y value. + * @param[in] _zzz Z value. + * @param[in] _www W value. + */ + void setValue(const float& _xxx, const float& _yyy, const float& _zzz, const float& _www) { + m_floats[0]=_xxx; + m_floats[1]=_yyy; + m_floats[2]=_zzz; + m_floats[3]=_www; + } + /** + * @brief Set 0 value on all the quaternion + */ + void setZero() { + setValue(0,0,0,0); + } + /** + * @brief get a 0 value on all a quaternion + * @return a zero quaternion + */ + static Quaternion zero(); + /** + * @brief Check if the quaternion is equal to (0,0,0,0) + * @return true The value is equal to (0,0,0,0) + * @return false The value is NOT equal to (0,0,0,0) + */ + bool isZero() const { + return m_floats[0] == 0 + && m_floats[1] == 0 + && m_floats[2] == 0 + && m_floats[3] == 0; + } + /** + * @brief Set identity value at the quaternion + */ + void setIdentity() { + setValue(0,0,0,1); + } + /** + * @brief get an identity quaternion + * @return an identity quaternion + */ + static Quaternion identity(); + /** + * @brief get x, y, z in a vec3 + */ + vec3 getVectorV() const { + return vec3(m_floats[0], + m_floats[1], + m_floats[2]); + } + /** + * @brief Inverse the quaternion + */ + void inverse() { + float invLengthSquare = 1.0f / length2(); + m_floats[0] *= -invLengthSquare; + m_floats[1] *= -invLengthSquare; + m_floats[2] *= -invLengthSquare; + m_floats[3] *= invLengthSquare; + } + /** + * @brief Return the inverse of the quaternion + * @return inverted quaternion + */ + Quaternion getInverse() const { + etk::Quaternion tmp = *this; + tmp.inverse(); + return tmp; + } + /** + * @brief Return the unit quaternion + * @return Quaternion unitarised + */ + Quaternion getUnit() const { + return normalized(); + } + /** + * @brief Conjugate the quaternion + */ + void conjugate() { + m_floats[0] *= -1.0f; + m_floats[1] *= -1.0f; + m_floats[2] *= -1.0f; + } + /** + * @brief Return the conjugate of the quaternion + * @return Conjugate quaternion + */ + Quaternion getConjugate() const { + etk::Quaternion tmp = *this; + tmp.conjugate(); + return tmp; + } + /** + * @brief Compute the rotation angle (in radians) and the rotation axis + * @param[out] _angle Angle of the quaternion + * @param[out] _axis Axis of the quaternion + */ + void getAngleAxis(float& _angle, vec3& _axis) const; + /** + * @brief Get the orientation matrix corresponding to this quaternion + * @return the 3x3 transformation matrix + */ + etk::Matrix3 getMatrix() const; + /** + * @brief Compute the spherical linear interpolation between two quaternions. + * @param[in] _obj1 First quaternion + * @param[in] _obj2 Second quaternion + * @param[in] _ttt linar coefficient interpolation to be such that [0..1] + */ + Quaternion slerp(const Quaternion& _obj1, const Quaternion& _obj2, float _ttt); + /** + * @brief Configure the quaternion with euler angles. + * @param[out] _angles Eular angle of the quaternion. + */ + void setEulerAngles(const vec3& _angles); + }; + //! @not_in_doc + std::ostream& operator <<(std::ostream& _os, const etk::Quaternion& _obj); +} + diff --git a/etk/math/Transform.cpp b/etk/math/Transform.cpp new file mode 100644 index 0000000..e69de29 diff --git a/etk/math/Transform.hpp b/etk/math/Transform.hpp new file mode 100644 index 0000000..73d7b26 --- /dev/null +++ b/etk/math/Transform.hpp @@ -0,0 +1,145 @@ +/** @file + * @author Edouard DUPIN + * @copyright 2011, Edouard DUPIN, all right reserved + * @license MPL v2.0 (see license file) + */ +#pragma once +#include + +// Libraries +#include +#include +#include + +namespace etk { + /** + * @brief This class represents a position and an orientation in 3D. It can also be seen as representing a translation and a rotation. + */ + class Transform { + public: + Transform(): + m_position(vec3(0.0, 0.0, 0.0)), + m_orientation(Quaternion::identity()) { + + } + Transform(const vec3& _position, const Matrix3x3& _orientation): + m_position(_position), + m_orientation(Quaternion(_orientation)) { + + } + Transform(const vec3& _position, const Quaternion& _orientation): + m_position(_position), + m_orientation(_orientation) { + + } + Transform(const Transform& _other): + m_position(_other.m_position), + m_orientation(_other.m_orientation) { + + } + protected: + vec3 m_position; //! Position + public: + /// Return the origin of the transform + const vec3& getPosition() const { + return m_position; + } + /// Set the origin of the transform + void setPosition(const vec3& _position) { + m_position = _position; + } + protected: + Quaternion m_orientation; //!< Orientation + public: + /// Return the orientation quaternion + const Quaternion& getOrientation() const { + return m_orientation; + } + /// Set the rotation quaternion + void setOrientation(const Quaternion& _orientation) { + m_orientation = _orientation; + } + public: + /// Set the transform to the identity transform + void setToIdentity() { + m_position = vec3(0.0, 0.0, 0.0); + m_orientation = Quaternion::identity(); + } + /// Set the transform from an OpenGL transform matrix + void setFromOpenGL(float* _matrix) { + Matrix3x3 matrix(_matrix[0], _matrix[4], _matrix[8], + _matrix[1], _matrix[5], _matrix[9], + _matrix[2], _matrix[6], _matrix[10]); + m_orientation = Quaternion(matrix); + m_position.setValue(_matrix[12], _matrix[13], _matrix[14]); + } + /// Get the OpenGL matrix of the transform + void getOpenGLMatrix(float* _matrix) const { + const Matrix3x3& matrix = m_orientation.getMatrix(); + _matrix[0] = matrix[0][0]; + _matrix[1] = matrix[1][0]; + _matrix[2] = matrix[2][0]; + _matrix[3] = 0.0; + _matrix[4] = matrix[0][1]; + _matrix[5] = matrix[1][1]; + _matrix[6] = matrix[2][1]; + _matrix[7] = 0.0; + _matrix[8] = matrix[0][2]; + _matrix[9] = matrix[1][2]; + _matrix[10] = matrix[2][2]; + _matrix[11] = 0.0; + _matrix[12] = m_position.x(); + _matrix[13] = m_position.y(); + _matrix[14] = m_position.z(); + _matrix[15] = 1.0; + } + /// Return the inverse of the transform + Transform getInverse() const { + const Quaternion& invQuaternion = m_orientation.getInverse(); + Matrix3x3 invMatrix = invQuaternion.getMatrix(); + return Transform(invMatrix * (-m_position), invQuaternion); + } + /// Return an interpolated transform + Transform interpolateTransforms(const Transform& _old, + const Transform& _new, + float _interpolationFactor) { + vec3 interPosition = _old.m_position * (decimal(1.0) - _interpolationFactor) + + _new.m_position * _interpolationFactor; + Quaternion interOrientation = Quaternion::slerp(_old.m_orientation, + _naw.m_orientation, + _interpolationFactor); + return Transform(interPosition, interOrientation); + } + /// Return the identity transform + Transform identity() { + return Transform(vec3(0, 0, 0), Quaternion::identity()); + } + /// Return the transformed vector + vec3 operator*(const vec3& _vector) const { + return (m_orientation.getMatrix() * _vector) + m_position; + } + /// Operator of multiplication of a transform with another one + Transform operator*(const Transform& _transform2) const { + return Transform(m_position + m_orientation.getMatrix() * _transform2.m_position, + m_orientation * _transform2.m_orientation); + } + /// Return true if the two transforms are equal + bool operator==(const Transform& _transform2) const { + return (m_position == _transform2.m_position) && (m_orientation == _transform2.m_orientation); + } + /// Return true if the two transforms are different + bool operator!=(const Transform& _transform2) const { + return !(*this == _transform2); + } + /// Assignment operator + Transform& operator=(const Transform& _transform) { + if (&_transform != this) { + m_position = _transform.m_position; + m_orientation = _transform.m_orientation; + } + return *this; + } + }; +} + + diff --git a/etk/math/Vector2D.hpp b/etk/math/Vector2D.hpp index 92c4729..7a6f10f 100644 --- a/etk/math/Vector2D.hpp +++ b/etk/math/Vector2D.hpp @@ -15,9 +15,9 @@ namespace etk { /** * @brief Vectorial 2-dimention vector (x/y) */ - template class Vector2D { + template class Vector2D { public: - T m_floats[2]; //!< all internal values + ETK_TYPE m_floats[2]; //!< all internal values public: /* **************************************************** * Constructor @@ -25,16 +25,18 @@ namespace etk { Vector2D() { #ifdef DEBUG // in debug mode we set supid value to prevent forget of the inits ... - m_floats[0] = (T)34673363; - m_floats[1] = (T)34523535; + m_floats[0] = (ETK_TYPE)34673363; + m_floats[1] = (ETK_TYPE)34523535; #endif + m_floats[0] = (ETK_TYPE)0; + m_floats[1] = (ETK_TYPE)0; } /** * @brief Constructor from scalars * @param[in] _xxx X value * @param[in] _yyy Y value */ - Vector2D(T _xxx, T _yyy) { + Vector2D(ETK_TYPE _xxx, ETK_TYPE _yyy) { m_floats[0] = _xxx; m_floats[1] = _yyy; } @@ -43,24 +45,24 @@ namespace etk { * @param[in] _obj The vector to add to this one */ Vector2D(const Vector2D& _obj) { - m_floats[0] = (T)_obj.x(); - m_floats[1] = (T)_obj.y(); + m_floats[0] = (ETK_TYPE)_obj.x(); + m_floats[1] = (ETK_TYPE)_obj.y(); } /** * @brief Constructor with external vector * @param[in] _obj The vector to add to this one */ Vector2D(const Vector2D& _obj) { - m_floats[0] = (T)_obj.x(); - m_floats[1] = (T)_obj.y(); + m_floats[0] = (ETK_TYPE)_obj.x(); + m_floats[1] = (ETK_TYPE)_obj.y(); } /** * @brief Constructor with external vector * @param[in] _obj The vector to add to this one */ Vector2D(const Vector2D& _obj) { - m_floats[0] = (T)_obj.x(); - m_floats[1] = (T)_obj.y(); + m_floats[0] = (ETK_TYPE)_obj.x(); + m_floats[1] = (ETK_TYPE)_obj.y(); } /** * @brief Constructor with string data @@ -75,7 +77,7 @@ namespace etk { * @param[in] _obj Reference on the external object * @return Local reference of the vector asigned */ - const Vector2D& operator= (const Vector2D& _obj ) { + const Vector2D& operator= (const Vector2D& _obj ) { m_floats[0] = _obj.m_floats[0]; m_floats[1] = _obj.m_floats[1]; return *this; @@ -85,7 +87,7 @@ namespace etk { * @param[in] _val Value to assign on the object * @return Local reference of the vector asigned */ - const Vector2D& operator= (const T _val ) { + const Vector2D& operator= (const ETK_TYPE _val ) { m_floats[0] = _val; m_floats[1] = _val; return *this; @@ -96,9 +98,9 @@ namespace etk { * @return true The Objects are identical * @return false The Objects are NOT identical */ - bool operator== (const Vector2D& _obj) const { - return ( (T)_obj.m_floats[0] == m_floats[0] - && (T)_obj.m_floats[1] == m_floats[1]); + bool operator== (const Vector2D& _obj) const { + return ( (ETK_TYPE)_obj.m_floats[0] == m_floats[0] + && (ETK_TYPE)_obj.m_floats[1] == m_floats[1]); } /** * @brief In-Equality compare operator with an other object. @@ -106,16 +108,16 @@ namespace etk { * @return true The Objects are NOT identical * @return false The Objects are identical */ - bool operator!= (const Vector2D& _obj) const { - return ( (T)_obj.m_floats[0] != m_floats[0] - || (T)_obj.m_floats[1] != m_floats[1]); + bool operator!= (const Vector2D& _obj) const { + return ( (ETK_TYPE)_obj.m_floats[0] != m_floats[0] + || (ETK_TYPE)_obj.m_floats[1] != m_floats[1]); } /** * @brief Operator+= Addition an other vertor with this one * @param[in] _obj Reference on the external object * @return Local reference of the vector additionned */ - const Vector2D& operator+= (const Vector2D& _obj) { + const Vector2D& operator+= (const Vector2D& _obj) { m_floats[0] += _obj.m_floats[0]; m_floats[1] += _obj.m_floats[1]; return *this; @@ -125,7 +127,7 @@ namespace etk { * @param[in] _val Value to addition at x/y * @return Local reference of the vector additionned */ - const Vector2D& operator+= (const T _val) { + const Vector2D& operator+= (const ETK_TYPE _val) { m_floats[0] += _val; m_floats[1] += _val; return *this; @@ -135,8 +137,8 @@ namespace etk { * @param[in] _obj Reference on the external object * @return New vector containing the value */ - Vector2D operator+ (const Vector2D& _obj) const { - Vector2D tmpp(m_floats[0],m_floats[1]); + Vector2D operator+ (const Vector2D& _obj) const { + Vector2D tmpp(m_floats[0],m_floats[1]); tmpp.m_floats[0] += _obj.m_floats[0]; tmpp.m_floats[1] += _obj.m_floats[1]; return tmpp; @@ -146,8 +148,8 @@ namespace etk { * @param[in] _val Value to addition at x/y * @return New vector containing the value */ - Vector2D operator+ (const T _val) const { - Vector2D tmpp(m_floats[0],m_floats[1]); + Vector2D operator+ (const ETK_TYPE _val) const { + Vector2D tmpp(m_floats[0],m_floats[1]); tmpp.m_floats[0] += _val; tmpp.m_floats[1] += _val; return tmpp; @@ -157,7 +159,7 @@ namespace etk { * @param[in] _obj Reference on the external object * @return Local reference of the vector decremented */ - const Vector2D& operator-= (const Vector2D& _obj) { + const Vector2D& operator-= (const Vector2D& _obj) { m_floats[0] -= _obj.m_floats[0]; m_floats[1] -= _obj.m_floats[1]; return *this; @@ -167,7 +169,7 @@ namespace etk { * @param[in] _val Value to addition at x/y * @return Local reference of the vector decremented */ - const Vector2D& operator-= (const T _val) { + const Vector2D& operator-= (const ETK_TYPE _val) { m_floats[0] -= _val; m_floats[1] -= _val; return *this; @@ -177,8 +179,8 @@ namespace etk { * @param[in] _obj Reference on the external object * @return New vector containing the value */ - Vector2D operator- (const Vector2D& _obj) const { - Vector2D tmpp(m_floats[0],m_floats[1]); + Vector2D operator- (const Vector2D& _obj) const { + Vector2D tmpp(m_floats[0],m_floats[1]); tmpp.m_floats[0] -= _obj.m_floats[0]; tmpp.m_floats[1] -= _obj.m_floats[1]; return tmpp; @@ -188,8 +190,8 @@ namespace etk { * @param[in] _val Value to addition at x/y * @return New vector containing the value */ - Vector2D operator- (const T _val) const { - Vector2D tmpp(m_floats[0],m_floats[1]); + Vector2D operator- (const ETK_TYPE _val) const { + Vector2D tmpp(m_floats[0],m_floats[1]); tmpp.m_floats[0] -= _val; tmpp.m_floats[1] -= _val; return tmpp; @@ -199,7 +201,7 @@ namespace etk { * @param[in] _obj Reference on the external object * @return Local reference of the vector multiplicated */ - const Vector2D& operator*= (const Vector2D& _obj) { + const Vector2D& operator*= (const Vector2D& _obj) { m_floats[0] *= _obj.m_floats[0]; m_floats[1] *= _obj.m_floats[1]; return *this; @@ -209,7 +211,7 @@ namespace etk { * @param[in] _val Value to addition at x/y * @return Local reference of the vector multiplicated */ - const Vector2D& operator*= (const T _val) { + const Vector2D& operator*= (const ETK_TYPE _val) { m_floats[0] *= _val; m_floats[1] *= _val; return *this; @@ -219,8 +221,8 @@ namespace etk { * @param[in] _obj Reference on the external object * @return New vector containing the value */ - Vector2D operator* (const Vector2D& _obj) const { - Vector2D tmpp(m_floats[0],m_floats[1]); + Vector2D operator* (const Vector2D& _obj) const { + Vector2D tmpp(m_floats[0],m_floats[1]); tmpp.m_floats[0] *= _obj.m_floats[0]; tmpp.m_floats[1] *= _obj.m_floats[1]; return tmpp; @@ -230,8 +232,8 @@ namespace etk { * @param[in] _val Value to addition at x/y * @return New vector containing the value */ - Vector2D operator* (const T _val) const { - Vector2D tmpp(m_floats[0],m_floats[1]); + Vector2D operator* (const ETK_TYPE _val) const { + Vector2D tmpp(m_floats[0],m_floats[1]); tmpp.m_floats[0] *= _val; tmpp.m_floats[1] *= _val; return tmpp; @@ -241,8 +243,8 @@ namespace etk { * @param[in] _obj Reference on the external object * @return Local reference of the vector divided */ - Vector2D operator/ (const Vector2D& _obj) const{ - Vector2D tmpp(m_floats[0], m_floats[1]); + Vector2D operator/ (const Vector2D& _obj) const{ + Vector2D tmpp(m_floats[0], m_floats[1]); tmpp.m_floats[0] /= _obj.m_floats[0]; tmpp.m_floats[1] /= _obj.m_floats[1]; return tmpp; @@ -252,8 +254,8 @@ namespace etk { * @param[in] _val Value to addition at x/y * @return Local reference of the vector divided */ - Vector2D operator/ (const T _val) const { - Vector2D tmpp(m_floats[0], m_floats[1]); + Vector2D operator/ (const ETK_TYPE _val) const { + Vector2D tmpp(m_floats[0], m_floats[1]); tmpp.m_floats[0] /= _val; tmpp.m_floats[1] /= _val; return tmpp; @@ -263,7 +265,7 @@ namespace etk { * @param[in] _obj Reference on the external object * @return New vector containing the value */ - const Vector2D& operator/= (const Vector2D& _obj) { + const Vector2D& operator/= (const Vector2D& _obj) { m_floats[0] /= _obj.m_floats[0]; m_floats[1] /= _obj.m_floats[1]; return *this; @@ -273,7 +275,7 @@ namespace etk { * @param[in] _val Value to addition at x/y * @return New vector containing the value */ - const Vector2D& operator/= (const T _val) { + const Vector2D& operator/= (const ETK_TYPE _val) { m_floats[0] /= _val; m_floats[1] /= _val; return *this; @@ -282,7 +284,7 @@ namespace etk { * @brief Operator++ Pre-incrementation of this vector * @return Local reference of the vector incremented */ - Vector2D& operator++() { + Vector2D& operator++() { ++m_floats[0]; ++m_floats[1]; return *this; @@ -291,8 +293,8 @@ namespace etk { * @brief Operator++ Post-incrementation of this vector * @return New vector containing the last value */ - Vector2D operator++(int) { - Vector2D result = *this; + Vector2D operator++(int) { + Vector2D result = *this; ++(*this); return result; } @@ -300,7 +302,7 @@ namespace etk { * @brief Operator++ Pre-decrementation of this vector * @return Local reference of the vector incremented */ - Vector2D& operator--() { + Vector2D& operator--() { --m_floats[0]; --m_floats[1]; return *this; @@ -309,8 +311,8 @@ namespace etk { * @brief Operator++ Post-decrementation of this vector * @return New vector containing the last value */ - Vector2D operator--(int) { - Vector2D result = *this; + Vector2D operator--(int) { + Vector2D result = *this; --(*this); return result; } @@ -319,7 +321,7 @@ namespace etk { * @param _obj The other vector in the cross product * @return cross product value */ - T cross(const Vector2D& _obj) const { + ETK_TYPE cross(const Vector2D& _obj) const { return m_floats[0] * _obj.m_floats[1] - m_floats[1] * _obj.m_floats[0]; } @@ -328,7 +330,7 @@ namespace etk { * @param _obj The other vector in the dot product * @return Dot product value */ - T dot(const Vector2D& _obj) const { + ETK_TYPE dot(const Vector2D& _obj) const { return m_floats[0] * _obj.m_floats[0] + m_floats[1] * _obj.m_floats[1]; } @@ -336,7 +338,7 @@ namespace etk { * @brief Get the length of the vector squared * @return Squared length value. */ - T length2() const { + ETK_TYPE length2() const { return dot(*this); } /** @@ -356,7 +358,7 @@ namespace etk { * @param[in] _obj The other vector to compare distance * @return the square distance of the 2 points */ - T distance2(const Vector2D& _obj) const { + ETK_TYPE distance2(const Vector2D& _obj) const { return (_obj - *this).length2(); } /** @@ -365,14 +367,14 @@ namespace etk { * @param[in] _obj The other vector to compare distance * @return the distance of the 2 points */ - float distance(const Vector2D& _obj) const { + float distance(const Vector2D& _obj) const { return (_obj - *this).length(); } /** * @brief Normalize this vector x^2 + y^2 = 1 * @return Local reference of the vector normalized */ - Vector2D& normalize() { + Vector2D& normalize() { *this /= length(); return *this; } @@ -380,8 +382,8 @@ namespace etk { * @brief Normalize this vector x^2 + y^2 = 1 (check if not deviding by 0, if it is the case ==> return (1,0)) * @return Local reference of the vector normalized */ - Vector2D& safeNormalize() { - T tmp = length(); + Vector2D& safeNormalize() { + ETK_TYPE tmp = length(); if (tmp != 0) { *this /= length(); return *this; @@ -393,16 +395,16 @@ namespace etk { * @brief Return a normalized version of this vector * @return New vector containing the value */ - Vector2D normalized() const { + Vector2D normalized() const { return *this / length(); } /** * @brief Return a vector will the absolute values of each element * @return New vector containing the value */ - Vector2D absolute() const { - return Vector2D( abs(m_floats[0]), - abs(m_floats[1])); + Vector2D absolute() const { + return Vector2D( std::abs(m_floats[0]), + std::abs(m_floats[1])); } /** * @brief Return the axis with the smallest value @@ -436,63 +438,63 @@ namespace etk { * @brief Get X value * @return the x value */ - const T& getX() const { + const ETK_TYPE& getX() const { return m_floats[0]; } /** * @brief Get Y value * @return the y value */ - const T& getY() const { + const ETK_TYPE& getY() const { return m_floats[1]; } /** * @brief Set the x value * @param[in] _xxx New value */ - void setX(T _xxx) { + void setX(ETK_TYPE _xxx) { m_floats[0] = _xxx; }; /** * @brief Set the y value * @param[in] _yyy New value */ - void setY(T _yyy) { + void setY(ETK_TYPE _yyy) { m_floats[1] = _yyy; }; /** * @brief Get X value * @return the x value */ - const T& x() const { + const ETK_TYPE& x() const { return m_floats[0]; } /** * @brief Get Y value * @return the y value */ - const T& y() const { + const ETK_TYPE& y() const { return m_floats[1]; } /** * @brief Cast the vector in the type T* requested. * @return Pointer on the data */ - operator T *() { + operator ETK_TYPE *() { return &m_floats[0]; } /** * @brief Cast the vector in the type const T* requested. * @return Pointer on the const data */ - operator const T *() const { + operator const ETK_TYPE *() const { return &m_floats[0]; } /** * @brief Set each element to the max of the current values and the values of another vector * @param _other The other vector to compare with */ - void setMax(const Vector2D& _other) { + void setMax(const Vector2D& _other) { m_floats[0] = std::max(m_floats[0], _other.m_floats[0]); m_floats[1] = std::max(m_floats[1], _other.m_floats[1]); } @@ -500,7 +502,7 @@ namespace etk { * @brief Set each element to the min of the current values and the values of another vector * @param _other The other vector to compare with */ - void setMin(const Vector2D& _other) { + void setMin(const Vector2D& _other) { m_floats[0] = std::min(m_floats[0], _other.m_floats[0]); m_floats[1] = std::min(m_floats[1], _other.m_floats[1]); } @@ -509,7 +511,7 @@ namespace etk { * @param[in] _xxx X value. * @param[in] _yyy Y value. */ - void setValue(const T& _xxx, const T& _yyy) { + void setValue(const ETK_TYPE& _xxx, const ETK_TYPE& _yyy) { m_floats[0] = _xxx; m_floats[1] = _yyy; } @@ -528,6 +530,17 @@ namespace etk { return m_floats[0] == 0 && m_floats[1] == 0; } + /* + // -------------------- Friends -------------------- // + friend Vector2D operator+(const Vector2D& _vect1, const Vector2D& _vect2); + friend Vector2D operator-(const Vector2D& _vect1, const Vector2D& _vect2); + friend Vector2D operator-(const Vector2D& _vect); + friend Vector2D operator*(const Vector2D& _vect, ETK_TYPE _value); + friend Vector2D operator*(ETK_TYPE _value, const Vector2D& _vect); + friend Vector2D operator*(const Vector2D& _vect1, const Vector2D& _vect2); + friend Vector2D operator/(const Vector2D& _vect, ETK_TYPE _value); + friend Vector2D operator/(const Vector2D& _vect1, const Vector2D& _vect2); + */ /** * @brief String caster of the object. * @return the Object cated in string (x.x,y.y) @@ -594,3 +607,45 @@ namespace etk { std::ostream& operator <<(std::ostream& _os, const std::vector& _obj); } +template +inline etk::Vector2D operator+(const etk::Vector2D& _vect1, const etk::Vector2D& _vect2) { + return etk::Vector2D(_vect1.x() + _vect2.x(), _vect1.y() + _vect2.y()); +} + +template +inline etk::Vector2D operator-(const etk::Vector2D& _vect1, const etk::Vector2D& _vect2) { + return etk::Vector2D(_vect1.x() - _vect2.x(), _vect1.y() - _vect2.y()); +} + +template +inline etk::Vector2D operator-(const etk::Vector2D& _vect) { + return etk::Vector2D(-_vect.x(), -_vect.y()); +} + +template +inline etk::Vector2D operator*(const etk::Vector2D& _vect, ETK_TYPE _value) { + return etk::Vector2D(_value * _vect.x(), _value * _vect.y()); +} + +template +inline etk::Vector2D operator*(const etk::Vector2D& _vect1, const etk::Vector2D& _vect2) { + return etk::Vector2D(_vect1.x() * _vect2.x(), _vect1.y() * _vect2.y()); +} + +template +inline etk::Vector2D operator/(const etk::Vector2D& _vect, ETK_TYPE _value) { + //assert(_value > MACHINE_EPSILON); + return etk::Vector2D(_vect.x() / _value, _vect.y() / _value); +} + +template +inline etk::Vector2D operator/(const etk::Vector2D& _vect1, const etk::Vector2D& _vect2) { + //assert(_vect2.x() > MACHINE_EPSILON); + //assert(_vect2.y() > MACHINE_EPSILON); + return etk::Vector2D(_vect1.x() / _vect2.x(), _vect1.y() / _vect2.y()); +} + +template +inline etk::Vector2D operator*(ETK_TYPE _value, const etk::Vector2D& _vect) { + return _vect * _value; +} diff --git a/etk/math/Vector3D.hpp b/etk/math/Vector3D.hpp index c232361..fd3784d 100644 --- a/etk/math/Vector3D.hpp +++ b/etk/math/Vector3D.hpp @@ -5,6 +5,7 @@ */ #include +#include #pragma once @@ -77,7 +78,7 @@ namespace etk { * @param[in] _obj The vector to add to this one * @return New vector containing the value */ - Vector3D operator+(const Vector3D& _obj) { + Vector3D operator+(const Vector3D& _obj) const { return Vector3D(m_floats[0] + _obj.m_floats[0], m_floats[1] + _obj.m_floats[1], m_floats[2] + _obj.m_floats[2]); @@ -98,7 +99,7 @@ namespace etk { * @param[in] _obj The vector to subtract * @return New vector containing the value */ - Vector3D operator-(const Vector3D& _obj) { + Vector3D operator-(const Vector3D& _obj) const { return Vector3D(m_floats[0] - _obj.m_floats[0], m_floats[1] - _obj.m_floats[1], m_floats[2] - _obj.m_floats[2]); @@ -119,7 +120,7 @@ namespace etk { * @param[in] _val Scale factor * @return New vector containing the value */ - Vector3D operator*(const T& _val) { + Vector3D operator*(const T& _val) const { return Vector3D(m_floats[0] * _val, m_floats[1] * _val, m_floats[2] * _val); @@ -200,10 +201,8 @@ namespace etk { * @return Local reference of the vector normalized */ Vector3D& safeNormalize() { - Vector3D absVec = this->absolute(); - int maxIndex = absVec.maxAxis(); - if (absVec[maxIndex]>0) { - *this /= absVec[maxIndex]; + float lenght = length(); + if (lenght != 0.0f) { return *this /= length(); } setValue(1,0,0); @@ -214,6 +213,7 @@ namespace etk { * @return Local reference of the vector normalized */ Vector3D& normalize() { + TK_ASSERT(length() != 0.0f, "Normalisation error"); return *this /= length(); } /** @@ -222,8 +222,7 @@ namespace etk { */ Vector3D normalized() const { Vector3D out = *this; - out /= length(); - return out; + return out.normalize(); } /** * @brief Return a rotated version of this vector @@ -255,9 +254,9 @@ namespace etk { * @return New vector containing the value */ Vector3D absolute() const { - return Vector3D( abs(m_floats[0]), - abs(m_floats[1]), - abs(m_floats[2])); + return Vector3D( std::abs(m_floats[0]), + std::abs(m_floats[1]), + std::abs(m_floats[2])); } /** * @brief Return the cross product between this and another vector @@ -344,7 +343,7 @@ namespace etk { * @return Local reference of the vector normalized */ Vector3D& operator*=(const Vector3D& _obj) { - m_floats[0] *= _obj.m_floats[0]; + m_floats[0] *= _obj.m_floats[0]; m_floats[1] *= _obj.m_floats[1]; m_floats[2] *= _obj.m_floats[2]; return *this; @@ -354,7 +353,7 @@ namespace etk { * @param _obj The other vector * @return New vector containing the value */ - Vector3D operator*(const Vector3D& _obj) { + Vector3D operator*(const Vector3D& _obj) const { return Vector3D(m_floats[0] * _obj.m_floats[0], m_floats[1] * _obj.m_floats[1], m_floats[2] * _obj.m_floats[2]); @@ -597,3 +596,47 @@ namespace etk { } + +template +inline etk::Vector3D operator+(const etk::Vector3D& _vect1, const etk::Vector3D& _vect2) { + return etk::Vector3D(_vect1.x() + _vect2.x(), _vect1.y() + _vect2.y(), _vect1.z() + _vect2.z()); +} + +template +inline etk::Vector3D operator-(const etk::Vector3D& _vect1, const etk::Vector3D& _vect2) { + return etk::Vector3D(_vect1.x() - _vect2.x(), _vect1.y() + _vect2.y(), _vect1.z() + _vect2.z()); +} + +template +inline etk::Vector3D operator-(const etk::Vector3D& _vect) { + return etk::Vector3D(-_vect.x(), -_vect.y(), -_vect.z()); +} + +template +inline etk::Vector3D operator*(const etk::Vector3D& _vect, ETK_TYPE _value) { + return etk::Vector3D(_value * _vect.x(), _value * _vect.y(), _value * _vect.z()); +} + +template +inline etk::Vector3D operator*(const etk::Vector3D& _vect1, const etk::Vector3D& _vect2) { + return etk::Vector3D(_vect1.x() * _vect2.x(), _vect1.y() * _vect2.y(), _vect1.z() * _vect2.z()); +} + +template +inline etk::Vector3D operator/(const etk::Vector3D& _vect, ETK_TYPE _value) { + //assert(_value > MACHINE_EPSILON); + return etk::Vector3D(_vect.x() / _value, _vect.y() / _value, _vect.z() / _value); +} + +template +inline etk::Vector3D operator/(const etk::Vector3D& _vect1, const etk::Vector3D& _vect2) { + //assert(_vect2.x() > MACHINE_EPSILON); + //assert(_vect2.y() > MACHINE_EPSILON); + //assert(_vect2.z() > MACHINE_EPSILON); + return etk::Vector3D(_vect1.x() / _vect2.x(), _vect1.y() / _vect2.y(), _vect1.z() / _vect2.z()); +} + +template +inline etk::Vector3D operator*(ETK_TYPE _value, const etk::Vector3D& _vect) { + return _vect * _value; +} diff --git a/etk/math/Vector4D.hpp b/etk/math/Vector4D.hpp index f61c071..85356b6 100644 --- a/etk/math/Vector4D.hpp +++ b/etk/math/Vector4D.hpp @@ -219,10 +219,10 @@ namespace etk { * @return New vector with the absolute value */ Vector4D absolute() const { - return Vector4D( abs(m_floats[0]), - abs(m_floats[1]), - abs(m_floats[2]), - abs(m_floats[3])); + return Vector4D( std::abs(m_floats[0]), + std::abs(m_floats[1]), + std::abs(m_floats[2]), + std::abs(m_floats[3])); } /** * @brief Multiply this vector by the other. diff --git a/lutin_etk-test.py b/lutin_etk-test.py index b83c9db..36d104f 100644 --- a/lutin_etk-test.py +++ b/lutin_etk-test.py @@ -26,7 +26,19 @@ def get_maintainer(): def configure(target, my_module): my_module.add_src_file([ - 'test/main.cpp' + 'test/main.cpp', + 'test/testColor.cpp', + 'test/testHash.cpp', + 'test/testMatrix3x3.cpp', + 'test/testRegExp.cpp', + 'test/testTransform.cpp', + 'test/testVector3_f.cpp', + 'test/testArchive.cpp', + 'test/testFSNode.cpp', + 'test/testMatrix2x2.cpp', + 'test/testQuaternion.cpp', + 'test/testStdShared.cpp', + 'test/testVector2_f.cpp', ]) my_module.add_depend([ 'etk', diff --git a/lutin_etk.py b/lutin_etk.py index e2bc720..f9bbc4b 100644 --- a/lutin_etk.py +++ b/lutin_etk.py @@ -36,10 +36,13 @@ def configure(target, my_module): 'etk/Color.cpp', 'etk/RegExp.cpp', 'etk/math/Matrix2.cpp', + 'etk/math/Matrix3.cpp', 'etk/math/Matrix4.cpp', 'etk/math/Vector2D.cpp', 'etk/math/Vector3D.cpp', 'etk/math/Vector4D.cpp', + 'etk/math/Quaternion.cpp', + 'etk/math/Transform.cpp', 'etk/os/FSNode.cpp', 'etk/os/FSNodeRight.cpp', 'etk/archive/Archive.cpp', @@ -57,10 +60,13 @@ def configure(target, my_module): 'etk/Buffer.hpp', 'etk/Hash.hpp', 'etk/math/Matrix2.hpp', + 'etk/math/Matrix3.hpp', 'etk/math/Matrix4.hpp', 'etk/math/Vector2D.hpp', 'etk/math/Vector3D.hpp', 'etk/math/Vector4D.hpp', + 'etk/math/Quaternion.hpp', + 'etk/math/Transform.hpp', 'etk/os/Fifo.hpp', 'etk/os/FSNode.hpp', 'etk/os/FSNodeRight.hpp', diff --git a/test/main.cpp b/test/main.cpp index 683b755..654693c 100644 --- a/test/main.cpp +++ b/test/main.cpp @@ -8,22 +8,12 @@ #include #include #include -#include -#include -#include #include -#include #include #include -#define NAME "Empty" +#include #include -#include "testArchive.hpp" -#include "testColor.hpp" -#include "testFSNode.hpp" -#include "testHash.hpp" -#include "testRegExp.hpp" -#include "testStdShared.hpp" int main(int argc, const char *argv[]) { // init Google test : diff --git a/test/testArchive.hpp b/test/testArchive.cpp similarity index 88% rename from test/testArchive.hpp rename to test/testArchive.cpp index b5e82d0..2931a9d 100644 --- a/test/testArchive.hpp +++ b/test/testArchive.cpp @@ -7,8 +7,9 @@ */ #include -#undef NAME #define NAME "Archive" +#include +#include #ifdef ETK_BUILD_MINIZIP diff --git a/test/testColor.hpp b/test/testColor.cpp similarity index 98% rename from test/testColor.hpp rename to test/testColor.cpp index 5eb2ff0..603a093 100644 --- a/test/testColor.hpp +++ b/test/testColor.cpp @@ -7,7 +7,8 @@ */ #include -#undef NAME +#include +#include #define NAME "Color" TEST(TestEtkColor, RGBA8) { diff --git a/test/testFSNode.hpp b/test/testFSNode.cpp similarity index 98% rename from test/testFSNode.hpp rename to test/testFSNode.cpp index 1bd32a4..9b96586 100644 --- a/test/testFSNode.hpp +++ b/test/testFSNode.cpp @@ -7,7 +7,8 @@ */ #include -#undef NAME +#include +#include #define NAME "FSNode" TEST(TestEtkFSNode, checkType) { diff --git a/test/testHash.hpp b/test/testHash.cpp similarity index 97% rename from test/testHash.hpp rename to test/testHash.cpp index 9605094..0174823 100644 --- a/test/testHash.hpp +++ b/test/testHash.cpp @@ -8,7 +8,8 @@ #include -#undef NAME +#include +#include #define NAME "Hash" TEST(TestEtkHash, Creation) { diff --git a/test/testMatrix2x2.cpp b/test/testMatrix2x2.cpp new file mode 100644 index 0000000..415b41d --- /dev/null +++ b/test/testMatrix2x2.cpp @@ -0,0 +1,258 @@ +/** + * @author Edouard DUPIN + * + * @copyright 2011, Edouard DUPIN, all right reserved + * + * @license MPL v2.0 (see license file) + */ + +#include +#include +#include + +#define NAME "etk::Matrix2x2" + +TEST(TestMatrix2x2, constructor) { + // Test contructor value + etk::Matrix2 test1(99.0); + EXPECT_FLOAT_EQ(test1.m_mat[0], 99.0); + EXPECT_FLOAT_EQ(test1.m_mat[1], 99.0); + EXPECT_FLOAT_EQ(test1.m_mat[2], 99.0); + EXPECT_FLOAT_EQ(test1.m_mat[3], 99.0); + etk::Matrix2 test2(11,22,33,44); + EXPECT_FLOAT_EQ(test2.m_mat[0], 11.0); + EXPECT_FLOAT_EQ(test2.m_mat[1], 22.0); + EXPECT_FLOAT_EQ(test2.m_mat[2], 33.0); + EXPECT_FLOAT_EQ(test2.m_mat[3], 44.0); + etk::Matrix2 test3(test2); + EXPECT_FLOAT_EQ(test3.m_mat[0], 11.0); + EXPECT_FLOAT_EQ(test3.m_mat[1], 22.0); + EXPECT_FLOAT_EQ(test3.m_mat[2], 33.0); + EXPECT_FLOAT_EQ(test3.m_mat[3], 44.0); + etk::Matrix2 test4 = test1; + EXPECT_FLOAT_EQ(test4.m_mat[0], 99.0); + EXPECT_FLOAT_EQ(test4.m_mat[1], 99.0); + EXPECT_FLOAT_EQ(test4.m_mat[2], 99.0); + EXPECT_FLOAT_EQ(test4.m_mat[3], 99.0); + test1 = test3; + EXPECT_FLOAT_EQ(test1.m_mat[0], 11.0); + EXPECT_FLOAT_EQ(test1.m_mat[1], 22.0); + EXPECT_FLOAT_EQ(test1.m_mat[2], 33.0); + EXPECT_FLOAT_EQ(test1.m_mat[3], 44.0); +} + +TEST(TestMatrix2x2, equity) { + etk::Matrix2 test1(99,32,56,92); + etk::Matrix2 test2(11,22,33,44); + etk::Matrix2 test3(11,22,33,44); + EXPECT_EQ(test1 == test2, false); + EXPECT_EQ(test1 != test2, true); + EXPECT_EQ(test3 == test2, true); + EXPECT_EQ(test3 != test2, false); +} + +TEST(TestMatrix2x2, set) { + etk::Matrix2 test; + test.setValue(22, 54, 45, 985); + EXPECT_FLOAT_EQ(test.m_mat[0], 22.0); + EXPECT_FLOAT_EQ(test.m_mat[1], 54.0); + EXPECT_FLOAT_EQ(test.m_mat[2], 45.0); + EXPECT_FLOAT_EQ(test.m_mat[3], 985.0); + test.setZero(); + EXPECT_FLOAT_EQ(test.m_mat[0], 0.0); + EXPECT_FLOAT_EQ(test.m_mat[1], 0.0); + EXPECT_FLOAT_EQ(test.m_mat[2], 0.0); + EXPECT_FLOAT_EQ(test.m_mat[3], 0.0); + test.setIdentity(); + EXPECT_FLOAT_EQ(test.m_mat[0], 1.0); + EXPECT_FLOAT_EQ(test.m_mat[1], 0.0); + EXPECT_FLOAT_EQ(test.m_mat[2], 0.0); + EXPECT_FLOAT_EQ(test.m_mat[3], 1.0); + test = etk::Matrix2::zero(); + EXPECT_FLOAT_EQ(test.m_mat[0], 0.0); + EXPECT_FLOAT_EQ(test.m_mat[1], 0.0); + EXPECT_FLOAT_EQ(test.m_mat[2], 0.0); + EXPECT_FLOAT_EQ(test.m_mat[3], 0.0); + test = etk::Matrix2::identity(); + EXPECT_FLOAT_EQ(test.m_mat[0], 1.0); + EXPECT_FLOAT_EQ(test.m_mat[1], 0.0); + EXPECT_FLOAT_EQ(test.m_mat[2], 0.0); + EXPECT_FLOAT_EQ(test.m_mat[3], 1.0); +} + +TEST(TestMatrix2x2, getRowColomn) { + etk::Matrix2 test(11, 22, 33, 44); + EXPECT_FLOAT_EQ(test.getColumn(0).x(), 11.0); + EXPECT_FLOAT_EQ(test.getColumn(0).y(), 33.0); + EXPECT_FLOAT_EQ(test.getColumn(1).x(), 22.0); + EXPECT_FLOAT_EQ(test.getColumn(1).y(), 44.0); + EXPECT_FLOAT_EQ(test.getColumn(999).x(), 22.0); + EXPECT_FLOAT_EQ(test.getColumn(999).y(), 44.0); + EXPECT_FLOAT_EQ(test.getRow(0).x(), 11.0); + EXPECT_FLOAT_EQ(test.getRow(0).y(), 22.0); + EXPECT_FLOAT_EQ(test.getRow(1).x(), 33.0); + EXPECT_FLOAT_EQ(test.getRow(1).y(), 44.0); + EXPECT_FLOAT_EQ(test.getRow(999).x(), 33.0); + EXPECT_FLOAT_EQ(test.getRow(999).y(), 44.0); +} + +TEST(TestMatrix2x2, transpose) { + etk::Matrix2 test(11, 22, 33, 44); + etk::Matrix2 test2 = test.getTranspose(); + EXPECT_FLOAT_EQ(test2.m_mat[0], 11.0); + EXPECT_FLOAT_EQ(test2.m_mat[1], 33.0); + EXPECT_FLOAT_EQ(test2.m_mat[2], 22.0); + EXPECT_FLOAT_EQ(test2.m_mat[3], 44.0); + // check if original matrix is not transposed + EXPECT_FLOAT_EQ(test.m_mat[0], 11.0); + EXPECT_FLOAT_EQ(test.m_mat[1], 22.0); + EXPECT_FLOAT_EQ(test.m_mat[2], 33.0); + EXPECT_FLOAT_EQ(test.m_mat[3], 44.0); + test.transpose(); + EXPECT_FLOAT_EQ(test.m_mat[0], 11.0); + EXPECT_FLOAT_EQ(test.m_mat[1], 33.0); + EXPECT_FLOAT_EQ(test.m_mat[2], 22.0); + EXPECT_FLOAT_EQ(test.m_mat[3], 44.0); +} + +TEST(TestMatrix2x2, determinant) { + etk::Matrix2 test(11, 22, 33, 44); + EXPECT_FLOAT_EQ(test.determinant(), -242.0); + EXPECT_FLOAT_EQ(etk::Matrix2::identity().determinant(), 1.0); +} + +TEST(TestMatrix2x2, trace) { + etk::Matrix2 test(11, 22, 33, 44); + EXPECT_FLOAT_EQ(test.getTrace(), 55.0); +} + +TEST(TestMatrix2x2, inverse) { + etk::Matrix2 test(1, 2, 3, 4); + etk::Matrix2 test2 = test.getInverse(); + // check if original matrix is not inversed + EXPECT_FLOAT_EQ(test.m_mat[0], 1.0); + EXPECT_FLOAT_EQ(test.m_mat[1], 2.0); + EXPECT_FLOAT_EQ(test.m_mat[2], 3.0); + EXPECT_FLOAT_EQ(test.m_mat[3], 4.0); + EXPECT_FLOAT_EQ(test2.m_mat[0], -2.0); + EXPECT_FLOAT_EQ(test2.m_mat[1], 1.0); + EXPECT_FLOAT_EQ(test2.m_mat[2], 1.5); + EXPECT_FLOAT_EQ(test2.m_mat[3], -0.5); + test.inverse(); + EXPECT_FLOAT_EQ(test.m_mat[0], -2.0); + EXPECT_FLOAT_EQ(test.m_mat[1], 1.0); + EXPECT_FLOAT_EQ(test.m_mat[2], 1.5); + EXPECT_FLOAT_EQ(test.m_mat[3], -0.5); +} + +TEST(TestMatrix2x2, absolute) { + etk::Matrix2 test(-1, -2, -3, -4); + etk::Matrix2 test2 = test.getAbsolute(); + // check if original matrix is not inversed + EXPECT_FLOAT_EQ(test.m_mat[0], -1.0); + EXPECT_FLOAT_EQ(test.m_mat[1], -2.0); + EXPECT_FLOAT_EQ(test.m_mat[2], -3.0); + EXPECT_FLOAT_EQ(test.m_mat[3], -4.0); + EXPECT_FLOAT_EQ(test2.m_mat[0], 1.0); + EXPECT_FLOAT_EQ(test2.m_mat[1], 2.0); + EXPECT_FLOAT_EQ(test2.m_mat[2], 3.0); + EXPECT_FLOAT_EQ(test2.m_mat[3], 4.0); + test.absolute(); + EXPECT_FLOAT_EQ(test.m_mat[0], 1.0); + EXPECT_FLOAT_EQ(test.m_mat[1], 2.0); + EXPECT_FLOAT_EQ(test.m_mat[2], 3.0); + EXPECT_FLOAT_EQ(test.m_mat[3], 4.0); +} + +TEST(TestMatrix2x2, operatorAddition) { + etk::Matrix2 test1(-1, -2, -3, -4); + etk::Matrix2 test2(1, 2, 3, 4); + etk::Matrix2 test3 = test1 + test2; + // check no change + EXPECT_FLOAT_EQ(test1.m_mat[0], -1.0); + EXPECT_FLOAT_EQ(test1.m_mat[1], -2.0); + EXPECT_FLOAT_EQ(test1.m_mat[2], -3.0); + EXPECT_FLOAT_EQ(test1.m_mat[3], -4.0); + EXPECT_FLOAT_EQ(test2.m_mat[0], 1.0); + EXPECT_FLOAT_EQ(test2.m_mat[1], 2.0); + EXPECT_FLOAT_EQ(test2.m_mat[2], 3.0); + EXPECT_FLOAT_EQ(test2.m_mat[3], 4.0); + EXPECT_FLOAT_EQ(test3.m_mat[0], 0.0); + EXPECT_FLOAT_EQ(test3.m_mat[1], 0.0); + EXPECT_FLOAT_EQ(test3.m_mat[2], 0.0); + EXPECT_FLOAT_EQ(test3.m_mat[3], 0.0); + + test1 += test2; + EXPECT_FLOAT_EQ(test1.m_mat[0], 0.0); + EXPECT_FLOAT_EQ(test1.m_mat[1], 0.0); + EXPECT_FLOAT_EQ(test1.m_mat[2], 0.0); + EXPECT_FLOAT_EQ(test1.m_mat[3], 0.0); +} + +TEST(TestMatrix2x2, operatorSubstraction) { + etk::Matrix2 test1(-1, -2, -3, -4); + etk::Matrix2 test2(1, 2, 3, 4); + etk::Matrix2 test3 = test1 - test2; + // check no change + EXPECT_FLOAT_EQ(test1.m_mat[0], -1.0); + EXPECT_FLOAT_EQ(test1.m_mat[1], -2.0); + EXPECT_FLOAT_EQ(test1.m_mat[2], -3.0); + EXPECT_FLOAT_EQ(test1.m_mat[3], -4.0); + EXPECT_FLOAT_EQ(test2.m_mat[0], 1.0); + EXPECT_FLOAT_EQ(test2.m_mat[1], 2.0); + EXPECT_FLOAT_EQ(test2.m_mat[2], 3.0); + EXPECT_FLOAT_EQ(test2.m_mat[3], 4.0); + EXPECT_FLOAT_EQ(test3.m_mat[0], -2.0); + EXPECT_FLOAT_EQ(test3.m_mat[1], -4.0); + EXPECT_FLOAT_EQ(test3.m_mat[2], -6.0); + EXPECT_FLOAT_EQ(test3.m_mat[3], -8.0); + test1 -= test2; + EXPECT_FLOAT_EQ(test1.m_mat[0], -2.0); + EXPECT_FLOAT_EQ(test1.m_mat[1], -4.0); + EXPECT_FLOAT_EQ(test1.m_mat[2], -6.0); + EXPECT_FLOAT_EQ(test1.m_mat[3], -8.0); +} + +TEST(TestMatrix2x2, operatorNegation) { + etk::Matrix2 test1(-1, -2, -3, -4); + etk::Matrix2 test2 = -test1; + EXPECT_FLOAT_EQ(test1.m_mat[0], -1.0); + EXPECT_FLOAT_EQ(test1.m_mat[1], -2.0); + EXPECT_FLOAT_EQ(test1.m_mat[2], -3.0); + EXPECT_FLOAT_EQ(test1.m_mat[3], -4.0); + EXPECT_FLOAT_EQ(test2.m_mat[0], 1.0); + EXPECT_FLOAT_EQ(test2.m_mat[1], 2.0); + EXPECT_FLOAT_EQ(test2.m_mat[2], 3.0); + EXPECT_FLOAT_EQ(test2.m_mat[3], 4.0); +} + +TEST(TestMatrix2x2, operatorMultiplicationMatrix) { + etk::Matrix2 test1(1, 2, 3, 4); + etk::Matrix2 test2(5, 6, 7, 10); + etk::Matrix2 test3 = test1 * test2; + EXPECT_FLOAT_EQ(test1.m_mat[0], 1.0); + EXPECT_FLOAT_EQ(test1.m_mat[1], 2.0); + EXPECT_FLOAT_EQ(test1.m_mat[2], 3.0); + EXPECT_FLOAT_EQ(test1.m_mat[3], 4.0); + EXPECT_FLOAT_EQ(test2.m_mat[0], 5.0); + EXPECT_FLOAT_EQ(test2.m_mat[1], 6.0); + EXPECT_FLOAT_EQ(test2.m_mat[2], 7.0); + EXPECT_FLOAT_EQ(test2.m_mat[3], 10.0); + EXPECT_FLOAT_EQ(test3.m_mat[0], 19.0); + EXPECT_FLOAT_EQ(test3.m_mat[1], 26.0); + EXPECT_FLOAT_EQ(test3.m_mat[2], 43.0); + EXPECT_FLOAT_EQ(test3.m_mat[3], 58.0); + test1 *= test2; + EXPECT_FLOAT_EQ(test1.m_mat[0], 19.0); + EXPECT_FLOAT_EQ(test1.m_mat[1], 26.0); + EXPECT_FLOAT_EQ(test1.m_mat[2], 43.0); + EXPECT_FLOAT_EQ(test1.m_mat[3], 58.0); +} + +TEST(TestMatrix2x2, operatorMultiplicationVector) { + etk::Matrix2 test1(1, 2, 3, 4); + vec2 result = test1 * vec2(1,2); + EXPECT_FLOAT_EQ(result.x(), 5.0); + EXPECT_FLOAT_EQ(result.y(), 11.0); +} + diff --git a/test/testMatrix3x3.cpp b/test/testMatrix3x3.cpp new file mode 100644 index 0000000..0259c0c --- /dev/null +++ b/test/testMatrix3x3.cpp @@ -0,0 +1,437 @@ +/** + * @author Edouard DUPIN + * + * @copyright 2011, Edouard DUPIN, all right reserved + * + * @license MPL v2.0 (see license file) + */ + +#include +#include +#include +#include + +#define NAME "etk::Matrix3" + +TEST(TestMatrix3x3, constructor) { + // Test contructor value + etk::Matrix3 test1(99.0); + EXPECT_FLOAT_EQ(test1.m_mat[0], 99.0); + EXPECT_FLOAT_EQ(test1.m_mat[1], 99.0); + EXPECT_FLOAT_EQ(test1.m_mat[2], 99.0); + EXPECT_FLOAT_EQ(test1.m_mat[3], 99.0); + EXPECT_FLOAT_EQ(test1.m_mat[4], 99.0); + EXPECT_FLOAT_EQ(test1.m_mat[5], 99.0); + EXPECT_FLOAT_EQ(test1.m_mat[6], 99.0); + EXPECT_FLOAT_EQ(test1.m_mat[7], 99.0); + EXPECT_FLOAT_EQ(test1.m_mat[8], 99.0); + etk::Matrix3 test2(11,22,33,44,55,66,77,88,99); + EXPECT_FLOAT_EQ(test2.m_mat[0], 11.0); + EXPECT_FLOAT_EQ(test2.m_mat[1], 22.0); + EXPECT_FLOAT_EQ(test2.m_mat[2], 33.0); + EXPECT_FLOAT_EQ(test2.m_mat[3], 44.0); + EXPECT_FLOAT_EQ(test2.m_mat[4], 55.0); + EXPECT_FLOAT_EQ(test2.m_mat[5], 66.0); + EXPECT_FLOAT_EQ(test2.m_mat[6], 77.0); + EXPECT_FLOAT_EQ(test2.m_mat[7], 88.0); + EXPECT_FLOAT_EQ(test2.m_mat[8], 99.0); + etk::Matrix3 test3(test2); + EXPECT_FLOAT_EQ(test3.m_mat[0], 11.0); + EXPECT_FLOAT_EQ(test3.m_mat[1], 22.0); + EXPECT_FLOAT_EQ(test3.m_mat[2], 33.0); + EXPECT_FLOAT_EQ(test3.m_mat[3], 44.0); + EXPECT_FLOAT_EQ(test3.m_mat[4], 55.0); + EXPECT_FLOAT_EQ(test3.m_mat[5], 66.0); + EXPECT_FLOAT_EQ(test3.m_mat[6], 77.0); + EXPECT_FLOAT_EQ(test3.m_mat[7], 88.0); + EXPECT_FLOAT_EQ(test3.m_mat[8], 99.0); + etk::Matrix3 test4 = test1; + EXPECT_FLOAT_EQ(test4.m_mat[0], 99.0); + EXPECT_FLOAT_EQ(test4.m_mat[1], 99.0); + EXPECT_FLOAT_EQ(test4.m_mat[2], 99.0); + EXPECT_FLOAT_EQ(test4.m_mat[3], 99.0); + EXPECT_FLOAT_EQ(test4.m_mat[4], 99.0); + EXPECT_FLOAT_EQ(test4.m_mat[5], 99.0); + EXPECT_FLOAT_EQ(test4.m_mat[6], 99.0); + EXPECT_FLOAT_EQ(test4.m_mat[7], 99.0); + EXPECT_FLOAT_EQ(test4.m_mat[8], 99.0); + test1 = test3; + EXPECT_FLOAT_EQ(test1.m_mat[0], 11.0); + EXPECT_FLOAT_EQ(test1.m_mat[1], 22.0); + EXPECT_FLOAT_EQ(test1.m_mat[2], 33.0); + EXPECT_FLOAT_EQ(test1.m_mat[3], 44.0); + EXPECT_FLOAT_EQ(test1.m_mat[4], 55.0); + EXPECT_FLOAT_EQ(test1.m_mat[5], 66.0); + EXPECT_FLOAT_EQ(test1.m_mat[6], 77.0); + EXPECT_FLOAT_EQ(test1.m_mat[7], 88.0); + EXPECT_FLOAT_EQ(test1.m_mat[8], 99.0); +} + +TEST(TestMatrix3x3, equity) { + etk::Matrix3 test1(99,32,56,92,56,32,45,12,54); + etk::Matrix3 test2(11,22,33,44,55,66,77,88,99); + etk::Matrix3 test3(11,22,33,44,55,66,77,88,99); + EXPECT_EQ(test1 == test2, false); + EXPECT_EQ(test1 != test2, true); + EXPECT_EQ(test3 == test2, true); + EXPECT_EQ(test3 != test2, false); +} + +TEST(TestMatrix3x3, set) { + etk::Matrix3 test; + test.setValue(22, 54, 45, 985, 54, 87, 98, 6532, -8652); + EXPECT_FLOAT_EQ(test.m_mat[0], 22.0); + EXPECT_FLOAT_EQ(test.m_mat[1], 54.0); + EXPECT_FLOAT_EQ(test.m_mat[2], 45.0); + EXPECT_FLOAT_EQ(test.m_mat[3], 985.0); + EXPECT_FLOAT_EQ(test.m_mat[4], 54.0); + EXPECT_FLOAT_EQ(test.m_mat[5], 87.0); + EXPECT_FLOAT_EQ(test.m_mat[6], 98.0); + EXPECT_FLOAT_EQ(test.m_mat[7], 6532.0); + EXPECT_FLOAT_EQ(test.m_mat[8], -8652.0); + test.setZero(); + EXPECT_FLOAT_EQ(test.m_mat[0], 0.0); + EXPECT_FLOAT_EQ(test.m_mat[1], 0.0); + EXPECT_FLOAT_EQ(test.m_mat[2], 0.0); + EXPECT_FLOAT_EQ(test.m_mat[3], 0.0); + EXPECT_FLOAT_EQ(test.m_mat[4], 0.0); + EXPECT_FLOAT_EQ(test.m_mat[5], 0.0); + EXPECT_FLOAT_EQ(test.m_mat[6], 0.0); + EXPECT_FLOAT_EQ(test.m_mat[7], 0.0); + EXPECT_FLOAT_EQ(test.m_mat[8], 0.0); + test.setIdentity(); + EXPECT_FLOAT_EQ(test.m_mat[0], 1.0); + EXPECT_FLOAT_EQ(test.m_mat[1], 0.0); + EXPECT_FLOAT_EQ(test.m_mat[2], 0.0); + EXPECT_FLOAT_EQ(test.m_mat[3], 0.0); + EXPECT_FLOAT_EQ(test.m_mat[4], 1.0); + EXPECT_FLOAT_EQ(test.m_mat[5], 0.0); + EXPECT_FLOAT_EQ(test.m_mat[6], 0.0); + EXPECT_FLOAT_EQ(test.m_mat[7], 0.0); + EXPECT_FLOAT_EQ(test.m_mat[8], 1.0); + test = etk::Matrix3::zero(); + EXPECT_FLOAT_EQ(test.m_mat[0], 0.0); + EXPECT_FLOAT_EQ(test.m_mat[1], 0.0); + EXPECT_FLOAT_EQ(test.m_mat[2], 0.0); + EXPECT_FLOAT_EQ(test.m_mat[3], 0.0); + EXPECT_FLOAT_EQ(test.m_mat[4], 0.0); + EXPECT_FLOAT_EQ(test.m_mat[5], 0.0); + EXPECT_FLOAT_EQ(test.m_mat[6], 0.0); + EXPECT_FLOAT_EQ(test.m_mat[7], 0.0); + EXPECT_FLOAT_EQ(test.m_mat[8], 0.0); + test = etk::Matrix3::identity(); + EXPECT_FLOAT_EQ(test.m_mat[0], 1.0); + EXPECT_FLOAT_EQ(test.m_mat[1], 0.0); + EXPECT_FLOAT_EQ(test.m_mat[2], 0.0); + EXPECT_FLOAT_EQ(test.m_mat[3], 0.0); + EXPECT_FLOAT_EQ(test.m_mat[4], 1.0); + EXPECT_FLOAT_EQ(test.m_mat[5], 0.0); + EXPECT_FLOAT_EQ(test.m_mat[6], 0.0); + EXPECT_FLOAT_EQ(test.m_mat[7], 0.0); + EXPECT_FLOAT_EQ(test.m_mat[8], 1.0); +} + +TEST(TestMatrix3x3, getRowColomn) { + etk::Matrix3 test(11, 22, 33, 44, 55, 66, 77, 88, 99); + EXPECT_FLOAT_EQ(test.getColumn(0).x(), 11.0); + EXPECT_FLOAT_EQ(test.getColumn(0).y(), 44.0); + EXPECT_FLOAT_EQ(test.getColumn(0).z(), 77.0); + EXPECT_FLOAT_EQ(test.getColumn(1).x(), 22.0); + EXPECT_FLOAT_EQ(test.getColumn(1).y(), 55.0); + EXPECT_FLOAT_EQ(test.getColumn(1).z(), 88.0); + EXPECT_FLOAT_EQ(test.getColumn(2).x(), 33.0); + EXPECT_FLOAT_EQ(test.getColumn(2).y(), 66.0); + EXPECT_FLOAT_EQ(test.getColumn(2).z(), 99.0); + EXPECT_FLOAT_EQ(test.getColumn(999).x(), 33.0); + EXPECT_FLOAT_EQ(test.getColumn(999).y(), 66.0); + EXPECT_FLOAT_EQ(test.getColumn(999).z(), 99.0); + EXPECT_FLOAT_EQ(test.getRow(0).x(), 11.0); + EXPECT_FLOAT_EQ(test.getRow(0).y(), 22.0); + EXPECT_FLOAT_EQ(test.getRow(0).z(), 33.0); + EXPECT_FLOAT_EQ(test.getRow(1).x(), 44.0); + EXPECT_FLOAT_EQ(test.getRow(1).y(), 55.0); + EXPECT_FLOAT_EQ(test.getRow(1).z(), 66.0); + EXPECT_FLOAT_EQ(test.getRow(2).x(), 77.0); + EXPECT_FLOAT_EQ(test.getRow(2).y(), 88.0); + EXPECT_FLOAT_EQ(test.getRow(2).z(), 99.0); + EXPECT_FLOAT_EQ(test.getRow(999).x(), 77.0); + EXPECT_FLOAT_EQ(test.getRow(999).y(), 88.0); + EXPECT_FLOAT_EQ(test.getRow(999).z(), 99.0); +} + +TEST(TestMatrix3x3, transpose) { + etk::Matrix3 test(11, 22, 33, 44, 55, 66, 77, 88, 99); + etk::Matrix3 test2 = test.getTranspose(); + EXPECT_FLOAT_EQ(test2.m_mat[0], 11.0); + EXPECT_FLOAT_EQ(test2.m_mat[1], 44.0); + EXPECT_FLOAT_EQ(test2.m_mat[2], 77.0); + EXPECT_FLOAT_EQ(test2.m_mat[3], 22.0); + EXPECT_FLOAT_EQ(test2.m_mat[4], 55.0); + EXPECT_FLOAT_EQ(test2.m_mat[5], 88.0); + EXPECT_FLOAT_EQ(test2.m_mat[6], 33.0); + EXPECT_FLOAT_EQ(test2.m_mat[7], 66.0); + EXPECT_FLOAT_EQ(test2.m_mat[8], 99.0); + // check if original matrix is not transposed + EXPECT_FLOAT_EQ(test.m_mat[0], 11.0); + EXPECT_FLOAT_EQ(test.m_mat[1], 22.0); + EXPECT_FLOAT_EQ(test.m_mat[2], 33.0); + EXPECT_FLOAT_EQ(test.m_mat[3], 44.0); + EXPECT_FLOAT_EQ(test.m_mat[4], 55.0); + EXPECT_FLOAT_EQ(test.m_mat[5], 66.0); + EXPECT_FLOAT_EQ(test.m_mat[6], 77.0); + EXPECT_FLOAT_EQ(test.m_mat[7], 88.0); + EXPECT_FLOAT_EQ(test.m_mat[8], 99.0); + test.transpose(); + EXPECT_FLOAT_EQ(test.m_mat[0], 11.0); + EXPECT_FLOAT_EQ(test.m_mat[1], 44.0); + EXPECT_FLOAT_EQ(test.m_mat[2], 77.0); + EXPECT_FLOAT_EQ(test.m_mat[3], 22.0); + EXPECT_FLOAT_EQ(test.m_mat[4], 55.0); + EXPECT_FLOAT_EQ(test.m_mat[5], 88.0); + EXPECT_FLOAT_EQ(test.m_mat[6], 33.0); + EXPECT_FLOAT_EQ(test.m_mat[7], 66.0); + EXPECT_FLOAT_EQ(test.m_mat[8], 99.0); +} + +TEST(TestMatrix3x3, determinant) { + etk::Matrix3 test(11, -6, 6, 4, -5, 1, 8, -9, -6); + EXPECT_FLOAT_EQ(test.determinant(), 261.0); + EXPECT_FLOAT_EQ(etk::Matrix3::identity().determinant(), 1.0); +} + +TEST(TestMatrix3x3, trace) { + etk::Matrix3 test(11, 22, 33, 44, 55, 66, 77, 88, 99); + EXPECT_FLOAT_EQ(test.getTrace(), 165.0); +} + +TEST(TestMatrix3x3, inverse) { + etk::Matrix3 test(1, -4, 3, -6, 5, 6, 7, 8, 9); + etk::Matrix3 test2 = test.getInverse(); + // check if original matrix is not inversed + EXPECT_FLOAT_EQ(test.m_mat[0], 1.0); + EXPECT_FLOAT_EQ(test.m_mat[1], -4.0); + EXPECT_FLOAT_EQ(test.m_mat[2], 3.0); + EXPECT_FLOAT_EQ(test.m_mat[3], -6.0); + EXPECT_FLOAT_EQ(test.m_mat[4], 5.0); + EXPECT_FLOAT_EQ(test.m_mat[5], 6.0); + EXPECT_FLOAT_EQ(test.m_mat[6], 7.0); + EXPECT_FLOAT_EQ(test.m_mat[7], 8.0); + EXPECT_FLOAT_EQ(test.m_mat[8], 9.0); + EXPECT_FLOAT_EQ(test2.m_mat[0], 0.0047169812); + EXPECT_FLOAT_EQ(test2.m_mat[1], -0.094339617); + EXPECT_FLOAT_EQ(test2.m_mat[2], 0.061320752); + EXPECT_FLOAT_EQ(test2.m_mat[3], -0.1509434); + EXPECT_FLOAT_EQ(test2.m_mat[4], 0.018867925); + EXPECT_FLOAT_EQ(test2.m_mat[5], 0.03773585); + EXPECT_FLOAT_EQ(test2.m_mat[6], 0.13050313); + EXPECT_FLOAT_EQ(test2.m_mat[7], 0.056603771); + EXPECT_FLOAT_EQ(test2.m_mat[8], 0.029874213); + test.inverse(); + EXPECT_FLOAT_EQ(test.m_mat[0], 0.0047169812); + EXPECT_FLOAT_EQ(test.m_mat[1], -0.094339617); + EXPECT_FLOAT_EQ(test.m_mat[2], 0.061320752); + EXPECT_FLOAT_EQ(test.m_mat[3], -0.1509434); + EXPECT_FLOAT_EQ(test.m_mat[4], 0.018867925); + EXPECT_FLOAT_EQ(test.m_mat[5], 0.03773585); + EXPECT_FLOAT_EQ(test.m_mat[6], 0.13050313); + EXPECT_FLOAT_EQ(test.m_mat[7], 0.056603771); + EXPECT_FLOAT_EQ(test.m_mat[8], 0.029874213); +} + +TEST(TestMatrix3x3, absolute) { + etk::Matrix3 test(-1, -2, -3, -4, -5, -6, -7, -8, -9); + etk::Matrix3 test2 = test.getAbsolute(); + // check if original matrix is not inversed + EXPECT_FLOAT_EQ(test.m_mat[0], -1.0); + EXPECT_FLOAT_EQ(test.m_mat[1], -2.0); + EXPECT_FLOAT_EQ(test.m_mat[2], -3.0); + EXPECT_FLOAT_EQ(test.m_mat[3], -4.0); + EXPECT_FLOAT_EQ(test.m_mat[4], -5.0); + EXPECT_FLOAT_EQ(test.m_mat[5], -6.0); + EXPECT_FLOAT_EQ(test.m_mat[6], -7.0); + EXPECT_FLOAT_EQ(test.m_mat[7], -8.0); + EXPECT_FLOAT_EQ(test.m_mat[8], -9.0); + EXPECT_FLOAT_EQ(test2.m_mat[0], 1.0); + EXPECT_FLOAT_EQ(test2.m_mat[1], 2.0); + EXPECT_FLOAT_EQ(test2.m_mat[2], 3.0); + EXPECT_FLOAT_EQ(test2.m_mat[3], 4.0); + EXPECT_FLOAT_EQ(test2.m_mat[4], 5.0); + EXPECT_FLOAT_EQ(test2.m_mat[5], 6.0); + EXPECT_FLOAT_EQ(test2.m_mat[6], 7.0); + EXPECT_FLOAT_EQ(test2.m_mat[7], 8.0); + EXPECT_FLOAT_EQ(test2.m_mat[8], 9.0); + test.absolute(); + EXPECT_FLOAT_EQ(test.m_mat[0], 1.0); + EXPECT_FLOAT_EQ(test.m_mat[1], 2.0); + EXPECT_FLOAT_EQ(test.m_mat[2], 3.0); + EXPECT_FLOAT_EQ(test.m_mat[3], 4.0); + EXPECT_FLOAT_EQ(test.m_mat[4], 5.0); + EXPECT_FLOAT_EQ(test.m_mat[5], 6.0); + EXPECT_FLOAT_EQ(test.m_mat[6], 7.0); + EXPECT_FLOAT_EQ(test.m_mat[7], 8.0); + EXPECT_FLOAT_EQ(test.m_mat[8], 9.0); +} + +TEST(TestMatrix3x3, operatorAddition) { + etk::Matrix3 test1(-1, -2, -3, -4, -5, -6, -7, -8, -9); + etk::Matrix3 test2(1, 2, 3, 4, 5, 6, 7, 8, 9); + etk::Matrix3 test3 = test1 + test2; + // check no change + EXPECT_FLOAT_EQ(test1.m_mat[0], -1.0); + EXPECT_FLOAT_EQ(test1.m_mat[1], -2.0); + EXPECT_FLOAT_EQ(test1.m_mat[2], -3.0); + EXPECT_FLOAT_EQ(test1.m_mat[3], -4.0); + EXPECT_FLOAT_EQ(test1.m_mat[4], -5.0); + EXPECT_FLOAT_EQ(test1.m_mat[5], -6.0); + EXPECT_FLOAT_EQ(test1.m_mat[6], -7.0); + EXPECT_FLOAT_EQ(test1.m_mat[7], -8.0); + EXPECT_FLOAT_EQ(test1.m_mat[8], -9.0); + EXPECT_FLOAT_EQ(test2.m_mat[0], 1.0); + EXPECT_FLOAT_EQ(test2.m_mat[1], 2.0); + EXPECT_FLOAT_EQ(test2.m_mat[2], 3.0); + EXPECT_FLOAT_EQ(test2.m_mat[3], 4.0); + EXPECT_FLOAT_EQ(test2.m_mat[4], 5.0); + EXPECT_FLOAT_EQ(test2.m_mat[5], 6.0); + EXPECT_FLOAT_EQ(test2.m_mat[6], 7.0); + EXPECT_FLOAT_EQ(test2.m_mat[7], 8.0); + EXPECT_FLOAT_EQ(test2.m_mat[8], 9.0); + EXPECT_FLOAT_EQ(test3.m_mat[0], 0.0); + EXPECT_FLOAT_EQ(test3.m_mat[1], 0.0); + EXPECT_FLOAT_EQ(test3.m_mat[2], 0.0); + EXPECT_FLOAT_EQ(test3.m_mat[3], 0.0); + EXPECT_FLOAT_EQ(test3.m_mat[4], 0.0); + EXPECT_FLOAT_EQ(test3.m_mat[5], 0.0); + EXPECT_FLOAT_EQ(test3.m_mat[6], 0.0); + EXPECT_FLOAT_EQ(test3.m_mat[7], 0.0); + EXPECT_FLOAT_EQ(test3.m_mat[8], 0.0); + test1 += test2; + EXPECT_FLOAT_EQ(test1.m_mat[0], 0.0); + EXPECT_FLOAT_EQ(test1.m_mat[1], 0.0); + EXPECT_FLOAT_EQ(test1.m_mat[2], 0.0); + EXPECT_FLOAT_EQ(test1.m_mat[3], 0.0); + EXPECT_FLOAT_EQ(test1.m_mat[4], 0.0); + EXPECT_FLOAT_EQ(test1.m_mat[5], 0.0); + EXPECT_FLOAT_EQ(test1.m_mat[6], 0.0); + EXPECT_FLOAT_EQ(test1.m_mat[7], 0.0); + EXPECT_FLOAT_EQ(test1.m_mat[8], 0.0); +} + +TEST(TestMatrix3x3, operatorSubstraction) { + etk::Matrix3 test1(-1, -2, -3, -4, -5, -6, -7, -8, -9); + etk::Matrix3 test2(1, 2, 3, 4, 5, 6, 7, 8, 9); + etk::Matrix3 test3 = test1 - test2; + // check no change + EXPECT_FLOAT_EQ(test1.m_mat[0], -1.0); + EXPECT_FLOAT_EQ(test1.m_mat[1], -2.0); + EXPECT_FLOAT_EQ(test1.m_mat[2], -3.0); + EXPECT_FLOAT_EQ(test1.m_mat[3], -4.0); + EXPECT_FLOAT_EQ(test1.m_mat[4], -5.0); + EXPECT_FLOAT_EQ(test1.m_mat[5], -6.0); + EXPECT_FLOAT_EQ(test1.m_mat[6], -7.0); + EXPECT_FLOAT_EQ(test1.m_mat[7], -8.0); + EXPECT_FLOAT_EQ(test1.m_mat[8], -9.0); + EXPECT_FLOAT_EQ(test2.m_mat[0], 1.0); + EXPECT_FLOAT_EQ(test2.m_mat[1], 2.0); + EXPECT_FLOAT_EQ(test2.m_mat[2], 3.0); + EXPECT_FLOAT_EQ(test2.m_mat[3], 4.0); + EXPECT_FLOAT_EQ(test2.m_mat[4], 5.0); + EXPECT_FLOAT_EQ(test2.m_mat[5], 6.0); + EXPECT_FLOAT_EQ(test2.m_mat[6], 7.0); + EXPECT_FLOAT_EQ(test2.m_mat[7], 8.0); + EXPECT_FLOAT_EQ(test2.m_mat[8], 9.0); + EXPECT_FLOAT_EQ(test3.m_mat[0], -2.0); + EXPECT_FLOAT_EQ(test3.m_mat[1], -4.0); + EXPECT_FLOAT_EQ(test3.m_mat[2], -6.0); + EXPECT_FLOAT_EQ(test3.m_mat[3], -8.0); + EXPECT_FLOAT_EQ(test3.m_mat[4], -10.0); + EXPECT_FLOAT_EQ(test3.m_mat[5], -12.0); + EXPECT_FLOAT_EQ(test3.m_mat[6], -14.0); + EXPECT_FLOAT_EQ(test3.m_mat[7], -16.0); + EXPECT_FLOAT_EQ(test3.m_mat[8], -18.0); + test1 -= test2; + EXPECT_FLOAT_EQ(test1.m_mat[0], -2.0); + EXPECT_FLOAT_EQ(test1.m_mat[1], -4.0); + EXPECT_FLOAT_EQ(test1.m_mat[2], -6.0); + EXPECT_FLOAT_EQ(test1.m_mat[3], -8.0); + EXPECT_FLOAT_EQ(test1.m_mat[4], -10.0); + EXPECT_FLOAT_EQ(test1.m_mat[5], -12.0); + EXPECT_FLOAT_EQ(test1.m_mat[6], -14.0); + EXPECT_FLOAT_EQ(test1.m_mat[7], -16.0); + EXPECT_FLOAT_EQ(test1.m_mat[8], -18.0); +} + +TEST(TestMatrix3x3, operatorNegation) { + etk::Matrix3 test1(-1, -2, -3, -4, -5, -6, -7, -8, -9); + etk::Matrix3 test2 = -test1; + // check no change + EXPECT_FLOAT_EQ(test1.m_mat[0], -1.0); + EXPECT_FLOAT_EQ(test1.m_mat[1], -2.0); + EXPECT_FLOAT_EQ(test1.m_mat[2], -3.0); + EXPECT_FLOAT_EQ(test1.m_mat[3], -4.0); + EXPECT_FLOAT_EQ(test1.m_mat[4], -5.0); + EXPECT_FLOAT_EQ(test1.m_mat[5], -6.0); + EXPECT_FLOAT_EQ(test1.m_mat[6], -7.0); + EXPECT_FLOAT_EQ(test1.m_mat[7], -8.0); + EXPECT_FLOAT_EQ(test1.m_mat[8], -9.0); + EXPECT_FLOAT_EQ(test2.m_mat[0], 1.0); + EXPECT_FLOAT_EQ(test2.m_mat[1], 2.0); + EXPECT_FLOAT_EQ(test2.m_mat[2], 3.0); + EXPECT_FLOAT_EQ(test2.m_mat[3], 4.0); + EXPECT_FLOAT_EQ(test2.m_mat[4], 5.0); + EXPECT_FLOAT_EQ(test2.m_mat[5], 6.0); + EXPECT_FLOAT_EQ(test2.m_mat[6], 7.0); + EXPECT_FLOAT_EQ(test2.m_mat[7], 8.0); + EXPECT_FLOAT_EQ(test2.m_mat[8], 9.0); +} + +TEST(TestMatrix3x3, operatorMultiplicationMatrix) { + etk::Matrix3 test1(-1, -2, -3, -4, -5, -6, -7, -8, -9); + etk::Matrix3 test2(1, 2, 3, 4, 5, 6, 7, 8, 9); + etk::Matrix3 test3 = test1 * test2; + EXPECT_FLOAT_EQ(test1.m_mat[0], -1.0); + EXPECT_FLOAT_EQ(test1.m_mat[1], -2.0); + EXPECT_FLOAT_EQ(test1.m_mat[2], -3.0); + EXPECT_FLOAT_EQ(test1.m_mat[3], -4.0); + EXPECT_FLOAT_EQ(test1.m_mat[4], -5.0); + EXPECT_FLOAT_EQ(test1.m_mat[5], -6.0); + EXPECT_FLOAT_EQ(test1.m_mat[6], -7.0); + EXPECT_FLOAT_EQ(test1.m_mat[7], -8.0); + EXPECT_FLOAT_EQ(test1.m_mat[8], -9.0); + EXPECT_FLOAT_EQ(test2.m_mat[0], 1.0); + EXPECT_FLOAT_EQ(test2.m_mat[1], 2.0); + EXPECT_FLOAT_EQ(test2.m_mat[2], 3.0); + EXPECT_FLOAT_EQ(test2.m_mat[3], 4.0); + EXPECT_FLOAT_EQ(test2.m_mat[4], 5.0); + EXPECT_FLOAT_EQ(test2.m_mat[5], 6.0); + EXPECT_FLOAT_EQ(test2.m_mat[6], 7.0); + EXPECT_FLOAT_EQ(test2.m_mat[7], 8.0); + EXPECT_FLOAT_EQ(test2.m_mat[8], 9.0); + EXPECT_FLOAT_EQ(test3.m_mat[0], -30); + EXPECT_FLOAT_EQ(test3.m_mat[1], -36); + EXPECT_FLOAT_EQ(test3.m_mat[2], -42); + EXPECT_FLOAT_EQ(test3.m_mat[3], -66); + EXPECT_FLOAT_EQ(test3.m_mat[4], -81); + EXPECT_FLOAT_EQ(test3.m_mat[5], -96); + EXPECT_FLOAT_EQ(test3.m_mat[6], -102); + EXPECT_FLOAT_EQ(test3.m_mat[7], -126); + EXPECT_FLOAT_EQ(test3.m_mat[8], -150); + test1 *= test2; + EXPECT_FLOAT_EQ(test1.m_mat[0], -30); + EXPECT_FLOAT_EQ(test1.m_mat[1], -36); + EXPECT_FLOAT_EQ(test1.m_mat[2], -42); + EXPECT_FLOAT_EQ(test1.m_mat[3], -66); + EXPECT_FLOAT_EQ(test1.m_mat[4], -81); + EXPECT_FLOAT_EQ(test1.m_mat[5], -96); + EXPECT_FLOAT_EQ(test1.m_mat[6], -102); + EXPECT_FLOAT_EQ(test1.m_mat[7], -126); + EXPECT_FLOAT_EQ(test1.m_mat[8], -150); +} + +TEST(TestMatrix3x3, operatorMultiplicationVector) { + etk::Matrix3 test1(1, 2, 3, 4, 5, 6, 7, 8, 9); + vec3 result = test1 * vec3(1,2,3); + EXPECT_FLOAT_EQ(result.x(), 14.0); + EXPECT_FLOAT_EQ(result.y(), 32.0); + EXPECT_FLOAT_EQ(result.z(), 50.0); +} + diff --git a/test/testQuaternion.cpp b/test/testQuaternion.cpp new file mode 100644 index 0000000..5b156cd --- /dev/null +++ b/test/testQuaternion.cpp @@ -0,0 +1,161 @@ +/** + * @author Edouard DUPIN + * @copyright 2011, Edouard DUPIN, all right reserved + * @license MPL v2.0 (see license file) + */ + +#include +#include +#include + +#define NAME "etk::Quaternion" + +TEST(TestQuaternion, constructor) { + etk::Quaternion test0(1,2,3,4); + EXPECT_FLOAT_EQ(test0.x(), 1.0); + EXPECT_FLOAT_EQ(test0.y(), 2.0); + EXPECT_FLOAT_EQ(test0.z(), 3.0); + EXPECT_FLOAT_EQ(test0.w(), 4.0); + etk::Quaternion test1(4, etk::Vector3D(1,2,3)); + EXPECT_FLOAT_EQ(test1.x(), 1.0); + EXPECT_FLOAT_EQ(test1.y(), 2.0); + EXPECT_FLOAT_EQ(test1.z(), 3.0); + EXPECT_FLOAT_EQ(test1.w(), 4.0); + etk::Quaternion test2; + EXPECT_FLOAT_EQ(test2.x(), 0.0); + EXPECT_FLOAT_EQ(test2.y(), 0.0); + EXPECT_FLOAT_EQ(test2.z(), 0.0); + EXPECT_FLOAT_EQ(test2.w(), 0.0); + etk::Quaternion test3(test0); + EXPECT_FLOAT_EQ(test3.x(), 1.0); + EXPECT_FLOAT_EQ(test3.y(), 2.0); + EXPECT_FLOAT_EQ(test3.z(), 3.0); + EXPECT_FLOAT_EQ(test3.w(), 4.0); + etk::Quaternion test4 = test0; + EXPECT_FLOAT_EQ(test4.x(), 1.0); + EXPECT_FLOAT_EQ(test4.y(), 2.0); + EXPECT_FLOAT_EQ(test4.z(), 3.0); + EXPECT_FLOAT_EQ(test4.w(), 4.0); + test2 = test0; + EXPECT_FLOAT_EQ(test2.x(), 1.0); + EXPECT_FLOAT_EQ(test2.y(), 2.0); + EXPECT_FLOAT_EQ(test2.z(), 3.0); + EXPECT_FLOAT_EQ(test2.w(), 4.0); +} + +TEST(TestQuaternion, constructorMatrix) { + etk::Quaternion test1(0.18257423, 0.3651484, 0.54772264, 0.73029673); + etk::Quaternion test2(test1.getMatrix()); + EXPECT_FLOAT_EQ(test2.x(), 0.18257423); + EXPECT_FLOAT_EQ(test2.y(), 0.3651484); + EXPECT_FLOAT_EQ(test2.z(), 0.54772264); + EXPECT_FLOAT_EQ(test2.w(), 0.73029673); +} + +TEST(TestQuaternion, constructorEuler) { + etk::Quaternion test0(etk::Vector3D(M_PI*0.5f, 0, 0)); + etk::Quaternion test01(std::sin(M_PI*0.25f), 0, 0, std::cos(M_PI*0.25f)); + test01.normalize(); + EXPECT_FLOAT_EQ(test0.x(), test01.x()); + EXPECT_FLOAT_EQ(test0.y(), test01.y()); + EXPECT_FLOAT_EQ(test0.z(), test01.z()); + EXPECT_FLOAT_EQ(test0.w(), test01.w()); + + etk::Quaternion test1(etk::Vector3D(0, M_PI*0.5f, 0)); + etk::Quaternion test11(0, std::sin(M_PI*0.25f), 0, std::cos(M_PI*0.25f)); + test11.normalize(); + EXPECT_FLOAT_EQ(test1.x(), test11.x()); + EXPECT_FLOAT_EQ(test1.y(), test11.y()); + EXPECT_FLOAT_EQ(test1.z(), test11.z()); + EXPECT_FLOAT_EQ(test1.w(), test11.w()); + + etk::Quaternion test2(etk::Vector3D(0, 0, M_PI*0.5f)); + etk::Quaternion test21(0, 0, std::sin(M_PI*0.25f), std::cos(M_PI*0.25f)); + test21.normalize(); + EXPECT_FLOAT_EQ(test2.x(), test21.x()); + EXPECT_FLOAT_EQ(test2.y(), test21.y()); + EXPECT_FLOAT_EQ(test2.z(), test21.z()); + EXPECT_FLOAT_EQ(test2.w(), test21.w()); +} + +TEST(TestQuaternion, normalize) { + etk::Quaternion test1(5, 3, 8, 2); + etk::Quaternion test2 = test1.normalized(); + // check if other quaternion does not change + EXPECT_FLOAT_EQ(test1.x(), 5.0); + EXPECT_FLOAT_EQ(test1.y(), 3.0); + EXPECT_FLOAT_EQ(test1.z(), 8.0); + EXPECT_FLOAT_EQ(test1.w(), 2.0); + EXPECT_FLOAT_EQ(test2.x(), 0.4950738); + EXPECT_FLOAT_EQ(test2.y(), 0.29704428); + EXPECT_FLOAT_EQ(test2.z(), 0.79211807); + EXPECT_FLOAT_EQ(test2.w(), 0.19802952); + test1.normalize(); + EXPECT_FLOAT_EQ(test1.x(), 0.4950738); + EXPECT_FLOAT_EQ(test1.y(), 0.29704428); + EXPECT_FLOAT_EQ(test1.z(), 0.79211807); + EXPECT_FLOAT_EQ(test1.w(), 0.19802952); +} + +TEST(TestQuaternion, length) { + etk::Quaternion test1(5, 3, 8, 2); + EXPECT_FLOAT_EQ(test1.length2(), 102.0); + EXPECT_FLOAT_EQ(test1.length(), 10.099504); + EXPECT_FLOAT_EQ(test1.normalized().length(), 1.0); +} + +TEST(TestQuaternion, set) { + etk::Quaternion test1(5, 3, 8, 2); + test1.setValue(12, 15, 22, 13); + EXPECT_FLOAT_EQ(test1.x(), 12.0); + EXPECT_FLOAT_EQ(test1.y(), 15.0); + EXPECT_FLOAT_EQ(test1.z(), 22.0); + EXPECT_FLOAT_EQ(test1.w(), 13.0); + test1.setZero(); + EXPECT_FLOAT_EQ(test1.x(), 0.0); + EXPECT_FLOAT_EQ(test1.y(), 0.0); + EXPECT_FLOAT_EQ(test1.z(), 0.0); + EXPECT_FLOAT_EQ(test1.w(), 0.0); + test1.setIdentity(); + EXPECT_FLOAT_EQ(test1.x(), 0.0); + EXPECT_FLOAT_EQ(test1.y(), 0.0); + EXPECT_FLOAT_EQ(test1.z(), 0.0); + EXPECT_FLOAT_EQ(test1.w(), 1.0); + test1 = etk::Quaternion::zero(); + EXPECT_FLOAT_EQ(test1.x(), 0.0); + EXPECT_FLOAT_EQ(test1.y(), 0.0); + EXPECT_FLOAT_EQ(test1.z(), 0.0); + EXPECT_FLOAT_EQ(test1.w(), 0.0); + test1 = etk::Quaternion::identity(); + EXPECT_FLOAT_EQ(test1.x(), 0.0); + EXPECT_FLOAT_EQ(test1.y(), 0.0); + EXPECT_FLOAT_EQ(test1.z(), 0.0); + EXPECT_FLOAT_EQ(test1.w(), 1.0); +} + +TEST(TestQuaternion, getVector) { + etk::Quaternion test1(5, 3, 8, 2); + etk::Vector3D test2 = test1.getVectorV(); + EXPECT_FLOAT_EQ(test2.x(), 5.0); + EXPECT_FLOAT_EQ(test2.y(), 3.0); + EXPECT_FLOAT_EQ(test2.z(), 8.0); +} + +TEST(TestQuaternion, conjugate) { + etk::Quaternion test1(5, 3, 8, 2); + etk::Quaternion test2 = test1.getConjugate(); + // check if other quaternion does not change + EXPECT_FLOAT_EQ(test1.x(), 5.0); + EXPECT_FLOAT_EQ(test1.y(), 3.0); + EXPECT_FLOAT_EQ(test1.z(), 8.0); + EXPECT_FLOAT_EQ(test1.w(), 2.0); + EXPECT_FLOAT_EQ(test2.x(), -5.0); + EXPECT_FLOAT_EQ(test2.y(), -3.0); + EXPECT_FLOAT_EQ(test2.z(), -8.0); + EXPECT_FLOAT_EQ(test2.w(), 2.0); + test1.conjugate(); + EXPECT_FLOAT_EQ(test1.x(), -5.0); + EXPECT_FLOAT_EQ(test1.y(), -3.0); + EXPECT_FLOAT_EQ(test1.z(), -8.0); + EXPECT_FLOAT_EQ(test1.w(), 2.0); +} diff --git a/test/testRegExp.hpp b/test/testRegExp.cpp similarity index 99% rename from test/testRegExp.hpp rename to test/testRegExp.cpp index 1270f3a..ba34975 100644 --- a/test/testRegExp.hpp +++ b/test/testRegExp.cpp @@ -8,8 +8,8 @@ #include #include +#include -#undef NAME #define NAME "Hash" std::pair testRegExpSingle(const std::string& _expression, const std::string& _search) { diff --git a/test/testStdShared.hpp b/test/testStdShared.cpp similarity index 96% rename from test/testStdShared.hpp rename to test/testStdShared.cpp index fbb4598..44e9a67 100644 --- a/test/testStdShared.hpp +++ b/test/testStdShared.cpp @@ -8,7 +8,7 @@ #include #include -#undef NAME +#include #define NAME "Shared_ptr" class Example : public ememory::EnableSharedFromThis { diff --git a/test/testTransform.cpp b/test/testTransform.cpp new file mode 100644 index 0000000..e69de29 diff --git a/test/testVector2_f.cpp b/test/testVector2_f.cpp new file mode 100644 index 0000000..ff94898 --- /dev/null +++ b/test/testVector2_f.cpp @@ -0,0 +1,109 @@ +/** + * @author Edouard DUPIN + * @copyright 2011, Edouard DUPIN, all right reserved + * @license MPL v2.0 (see license file) + */ + +#include +#include +#include + +#define NAME "etk:Vector2D" + +TEST(TestVector2D_f, constructor) { + // Test contructor value + etk::Vector2D test0(0,0); + EXPECT_FLOAT_EQ(test0.x(), 0.0); + EXPECT_FLOAT_EQ(test0.y(), 0.0); + etk::Vector2D vect1(4,5); + EXPECT_FLOAT_EQ(vect1.x(), 4.0); + EXPECT_FLOAT_EQ(vect1.y(), 5.0); + etk::Vector2D vect2(vect1); + EXPECT_FLOAT_EQ(vect2.x(), 4.0); + EXPECT_FLOAT_EQ(vect2.y(), 5.0); + etk::Vector2D vect3 = vect1; + EXPECT_FLOAT_EQ(vect3.x(), 4.0); + EXPECT_FLOAT_EQ(vect3.y(), 5.0); + test0 = vect2; + EXPECT_FLOAT_EQ(test0.x(), 4.0); + EXPECT_FLOAT_EQ(test0.y(), 5.0); +} + +TEST(TestVector2D_f, constructorString) { + etk::Vector2D vect1("(4,-8.5)"); + EXPECT_FLOAT_EQ(vect1.x(), 4.0); + EXPECT_FLOAT_EQ(vect1.y(), -8.5); + etk::Vector2D vect2("-6,5.5"); + EXPECT_FLOAT_EQ(vect2.x(), -6.0); + EXPECT_FLOAT_EQ(vect2.y(), 5.5); + etk::Vector2D vect3("256.38"); + EXPECT_FLOAT_EQ(vect3.x(), 256.38); + EXPECT_FLOAT_EQ(vect3.y(), 256.38); +} + +TEST(TestVector2D_f, equity) { + etk::Vector2D test1(99,32); + etk::Vector2D test2(11,22); + etk::Vector2D test3(11,22); + EXPECT_EQ(test1 == test2, false); + EXPECT_EQ(test1 != test2, true); + EXPECT_EQ(test3 == test2, true); + EXPECT_EQ(test3 != test2, false); +} + +TEST(TestVector2D_f, set) { + // Test contructor value + etk::Vector2D test1(0,0); + EXPECT_FLOAT_EQ(test1.x(), 0.0); + EXPECT_FLOAT_EQ(test1.y(), 0.0); + test1.setValue(1,2); + EXPECT_FLOAT_EQ(test1.x(), 1.0); + EXPECT_FLOAT_EQ(test1.y(), 2.0); +} + + +TEST(TestVector2D_f, setSetZero) { + // Test contructor value + etk::Vector2D test1(4,5); + EXPECT_FLOAT_EQ(test1.x(), 4.0); + EXPECT_FLOAT_EQ(test1.y(), 5.0); + test1.setZero(); + EXPECT_FLOAT_EQ(test1.x(), 0.0); + EXPECT_FLOAT_EQ(test1.y(), 0.0); +} + + +TEST(TestVector2D_f, length) { + // Test contructor value + etk::Vector2D test1(0,0); + EXPECT_FLOAT_EQ(test1.length(), 0.0); + EXPECT_FLOAT_EQ(test1.length2(), 0.0); + test1.setValue(2,0); + EXPECT_FLOAT_EQ(test1.length(), 2.0); + test1.setValue(0,3); + EXPECT_FLOAT_EQ(test1.length(), 3.0); + test1.setValue(3,4); + EXPECT_FLOAT_EQ(test1.length2(), 25.0); +} + +TEST(TestVector2D_f, normalize) { + etk::Vector2D test1(11,22); + etk::Vector2D test2 = test1.normalized(); + EXPECT_FLOAT_EQ(test1.x(), 11.0); + EXPECT_FLOAT_EQ(test1.y(), 22.0); + EXPECT_FLOAT_EQ(test2.x(), 0.44721359); + EXPECT_FLOAT_EQ(test2.y(), 0.89442718); + test1.normalize(); + EXPECT_FLOAT_EQ(test1.x(), 0.44721359); + EXPECT_FLOAT_EQ(test1.y(), 0.89442718); +} + +TEST(TestVector2D_f, dot) { + etk::Vector2D test1(11,0); + etk::Vector2D test2(0,88); + EXPECT_FLOAT_EQ(test1.dot(test1), 121.0); + EXPECT_FLOAT_EQ(test1.dot(test2), 0.0); + test1.setValue(2,3); + test2.setValue(9,7); + EXPECT_FLOAT_EQ(test1.dot(test2), 39.0); +} diff --git a/test/testVector3_f.cpp b/test/testVector3_f.cpp new file mode 100644 index 0000000..d0c928b --- /dev/null +++ b/test/testVector3_f.cpp @@ -0,0 +1,127 @@ +/** + * @author Edouard DUPIN + * @copyright 2011, Edouard DUPIN, all right reserved + * @license MPL v2.0 (see license file) + */ + +#include +#include +#include + +#define NAME "etk:Vector3D" + +TEST(TestVector3D_f, constructor) { + // Test contructor value + etk::Vector3D test0(0,0,0); + EXPECT_FLOAT_EQ(test0.x(), 0.0); + EXPECT_FLOAT_EQ(test0.y(), 0.0); + EXPECT_FLOAT_EQ(test0.z(), 0.0); + etk::Vector3D vect1(4,5,8); + EXPECT_FLOAT_EQ(vect1.x(), 4.0); + EXPECT_FLOAT_EQ(vect1.y(), 5.0); + EXPECT_FLOAT_EQ(vect1.z(), 8.0); + etk::Vector3D vect2(vect1); + EXPECT_FLOAT_EQ(vect2.x(), 4.0); + EXPECT_FLOAT_EQ(vect2.y(), 5.0); + EXPECT_FLOAT_EQ(vect2.z(), 8.0); + etk::Vector3D vect3 = vect1; + EXPECT_FLOAT_EQ(vect3.x(), 4.0); + EXPECT_FLOAT_EQ(vect3.y(), 5.0); + EXPECT_FLOAT_EQ(vect3.z(), 8.0); + test0 = vect2; + EXPECT_FLOAT_EQ(test0.x(), 4.0); + EXPECT_FLOAT_EQ(test0.y(), 5.0); + EXPECT_FLOAT_EQ(test0.z(), 8.0); +} + +TEST(TestVector3D_f, equity) { + etk::Vector3D test1(99,32,56); + etk::Vector3D test2(11,22,33); + etk::Vector3D test3(11,22,33); + EXPECT_EQ(test1 == test2, false); + EXPECT_EQ(test1 != test2, true); + EXPECT_EQ(test3 == test2, true); + EXPECT_EQ(test3 != test2, false); +} + +TEST(TestVector3D_f, set) { + // Test contructor value + etk::Vector3D test1(0,0,0); + EXPECT_FLOAT_EQ(test1.x(), 0.0); + EXPECT_FLOAT_EQ(test1.y(), 0.0); + EXPECT_FLOAT_EQ(test1.z(), 0.0); + test1.setValue(1,2,3); + EXPECT_FLOAT_EQ(test1.x(), 1.0); + EXPECT_FLOAT_EQ(test1.y(), 2.0); + EXPECT_FLOAT_EQ(test1.z(), 3.0); +} + +TEST(TestVector3D_f, setSetZero) { + // Test contructor value + etk::Vector3D test1(4,5,6); + EXPECT_FLOAT_EQ(test1.x(), 4.0); + EXPECT_FLOAT_EQ(test1.y(), 5.0); + EXPECT_FLOAT_EQ(test1.z(), 6.0); + test1.setZero(); + EXPECT_FLOAT_EQ(test1.x(), 0.0); + EXPECT_FLOAT_EQ(test1.y(), 0.0); + EXPECT_FLOAT_EQ(test1.z(), 0.0); +} + + +TEST(TestVector3D_f, length) { + // Test contructor value + etk::Vector3D test1(0,0,0); + EXPECT_FLOAT_EQ(test1.length(), 0.0); + EXPECT_FLOAT_EQ(test1.length2(), 0.0); + test1.setValue(2,0,0); + EXPECT_FLOAT_EQ(test1.length(), 2.0); + test1.setValue(0,3,0); + EXPECT_FLOAT_EQ(test1.length(), 3.0); + test1.setValue(0,0,4); + EXPECT_FLOAT_EQ(test1.length(), 4.0); + test1.setValue(3,4,5); + EXPECT_FLOAT_EQ(test1.length2(), 50.0); +} + +TEST(TestVector3D_f, normalize) { + etk::Vector3D test1(11,22,33); + etk::Vector3D test2 = test1.normalized(); + EXPECT_FLOAT_EQ(test1.x(), 11.0); + EXPECT_FLOAT_EQ(test1.y(), 22.0); + EXPECT_FLOAT_EQ(test1.z(), 33.0); + EXPECT_FLOAT_EQ(test2.x(), 0.26726124); + EXPECT_FLOAT_EQ(test2.y(), 0.53452247); + EXPECT_FLOAT_EQ(test2.z(), 0.80178374); + test1.normalize(); + EXPECT_FLOAT_EQ(test1.x(), 0.26726124); + EXPECT_FLOAT_EQ(test1.y(), 0.53452247); + EXPECT_FLOAT_EQ(test1.z(), 0.80178374); +} + +TEST(TestVector3D_f, dot) { + etk::Vector3D test1(11,0,0); + etk::Vector3D test2(0,88,66); + EXPECT_FLOAT_EQ(test1.dot(test1), 121.0); + EXPECT_FLOAT_EQ(test1.dot(test2), 0.0); + test1.setValue(2,3,5); + test2.setValue(9,7,6); + EXPECT_FLOAT_EQ(test1.dot(test2), 69.0); // ???? +} + +TEST(TestVector3D_f, cross) { + etk::Vector3D test1(0,0,0); + etk::Vector3D test2(-55,88,66); + EXPECT_EQ(test1.cross(test1), vec3(0,0,0)); + EXPECT_EQ(test2.cross(test2), vec3(0,0,0)); + test1.setValue(1,0,0); + test2.setValue(0,1,0); + EXPECT_EQ(test1.cross(test2), vec3(0,0,1)); + test2.setValue(0,0,1); + EXPECT_EQ(test1.cross(test2), vec3(0,-1,0)); + test1.setValue(0,1,0); + EXPECT_EQ(test1.cross(test2), vec3(1,0,0)); + test1.setValue(8,9,-10); + test2.setValue(2,-3,5); + EXPECT_EQ(test1.cross(test2), vec3(15,-60,-42)); +}