#pragma once /** * @file Math3D.h * * @brief Fonctions pour l'intinialisation et la manipulation de matrices de * rotation, des matrices de transformations en coordonnées homogènes et les * vecteurs 3D. * * Nom: William Nolin * Code permanent : NOLW76060101 * Email : william.nolin.1@ens.etsmtl.ca * */ #include "Matrix.h" #include "Vector.h" #include "Operators.h" #ifndef _USE_MATH_DEFINES #define _USE_MATH_DEFINES #endif #include namespace gti320 { // Deux types de vecteurs 3D considérés ici typedef Vector Vector3d; typedef Vector Vector3f; // Dans le cadre de ce projet, nous considérons seulement deux // cas : // // - les rotations // - les translations // // Deux types de matrices en coordonnées homogèes : typedef Matrix Matrix4d; typedef Matrix Matrix4f; // // Deux types de matrices pour les rotations typedef Matrix Matrix3d; typedef Matrix Matrix3f; /** * Initialise et retourne la matrice identité */ template<> inline void Matrix4d::setIdentity() { this->setZero(); for (int i = 0; i < 4; i++) { (*this)(i, i) = 1; } } /** * Calcul de la matrice inverse, SPÉCIALISÉ pour le cas d'une matrice de * transformation en coordonnées homogènes. */ template<> inline Matrix4d Matrix4d::inverse() const { auto transposed_rotation = this->block(0, 0, 3, 3).transpose(); auto translation = Vector(); for (int i = 0; i < 3; i++) { translation(i) = (*this)(i, 3); } auto result = Matrix4d(); result(3, 3) = 1; // Applique la matrice de rotation result.block(0, 0, 3, 3) = transposed_rotation; // Applique le vecteur de translation auto inverted_translation = (-1.0 * transposed_rotation) * translation; auto trans_block = result.block(0, 3, 3, 1); trans_block(0, 0) = inverted_translation(0); trans_block(1, 0) = inverted_translation(1); trans_block(2, 0) = inverted_translation(2); return result; } /** * Calcul de la matrice inverse, SPÉCIALISÉ pour le cas d'une matrice de rotation. * * (vous pouvez supposer qu'il s'agit d'une matrice de rotation) */ template<> inline Matrix3d Matrix3d::inverse() const { return this->transpose(); } /** * Multiplication d'une matrice 4x4 avec un vecteur 3D où la matrice * représente une transformation en coordonnées homogène. */ template Vector<_Scalar, 3> operator*(const Matrix<_Scalar, 4, 4, ColumnStorage> &A, const Vector<_Scalar, 3> &v) { auto homogeneous = Vector<_Scalar, 4>(v); homogeneous(3) = 1; Vector<_Scalar, 4> transformed = A * homogeneous; return Vector<_Scalar, 3>(transformed); } /** * Initialise et retourne la matrice de rotation définie par les angles * d'Euler XYZ exprimés en radians. * * La matrice doit correspondre au produit : Rz*Ry*Rx. */ template static Matrix<_Scalar, 3, 3> makeRotation(_Scalar x, _Scalar y, _Scalar z) { double sin_theta = std::sin(x); double cos_theta = std::cos(x); double sin_phi = std::sin(y); double cos_phi = std::cos(y); double sin_psi = std::sin(z); double cos_psi = std::cos(z); auto m = Matrix<_Scalar, 3, 3>(); m(0, 0) = cos_phi * cos_psi; m(1, 0) = cos_phi * sin_psi; m(2, 0) = -sin_phi; m(0, 1) = sin_theta * sin_phi * cos_psi - cos_theta * sin_psi; m(1, 1) = sin_theta * sin_phi * sin_psi + cos_theta * cos_psi; m(2, 1) = sin_theta * cos_phi; m(0, 2) = cos_theta * sin_phi * cos_psi + sin_theta * sin_psi; m(1, 2) = cos_theta * sin_phi * sin_psi - sin_theta * cos_psi; m(2, 2) = cos_theta * cos_phi; return m; } }