]> git.tdb.fi Git - libs/gl.git/blobdiff - source/matrix.cpp
Use libmspmath to provide vector and matrix operations
[libs/gl.git] / source / matrix.cpp
index 6ff3b603002f3a43a59cee50f3a4d75508efdae2..8cc9dcba3a513e49b5b7d9367bd3dae733e371ee 100644 (file)
@@ -1,5 +1,6 @@
 #include <algorithm>
 #include <cmath>
+#include <msp/geometry/affinetransformation.h>
 #include "error.h"
 #include "matrix.h"
 
@@ -9,116 +10,44 @@ namespace Msp {
 namespace GL {
 
 Matrix::Matrix():
-       flags(IDENTITY)
-{
-       for(unsigned i=0; i<16; ++i)
-               matrix[i] = (i%5 ? 0 : 1);
-}
+       Base(Base::identity())
+{ }
 
 Matrix::Matrix(const float *m):
-       flags(IDENTITY)
-{
-       copy(m, m+16, matrix);
-       check_flags();
-}
+       Base(LinAl::SquareMatrix<float, 4>(m))
+{ }
 
 Matrix::Matrix(const double *m):
-       flags(IDENTITY)
-{
-       copy(m, m+16, matrix);
-       check_flags();
-}
+       Base(m)
+{ }
 
-void Matrix::check_flags()
-{
-       const double *m = matrix;
-       if(m[12]!=0 || m[13]!=0 || m[14]!=0)
-               flags |= TRANSLATE;
-       if(m[0]!=1)
-       {
-               flags |= SCALE;
-               if(m[5]!=m[0] || m[10]!=m[0])
-                       flags |= ARBITARY;
-       }
-       if(m[1]!=0 || m[2]!=0 || m[4]!=0 || m[6]!=0 || m[8]!=0 || m[9]!=0)
-       {
-               flags |= ROTATE;
-               double x_dot_y = m[0]*m[1]+m[4]*m[5]+m[8]*m[9];
-               double x_dot_z = m[0]*m[2]+m[4]*m[6]+m[8]*m[10];
-               double y_dot_z = m[1]*m[2]+m[5]*m[6]+m[9]*m[10];
-               if(x_dot_y!=0 || x_dot_z!=0 || y_dot_z!=0)
-                       flags |= ARBITARY;
-       }
-       if(m[3]!=0 || m[7]!=0 || m[11]!=0 || m[15]!=1)
-               flags |= ARBITARY;
-}
+Matrix::Matrix(const LinAl::Matrix<double, 4, 4> &other):
+       Base(other)
+{ }
 
 void Matrix::multiply(const Matrix &other)
 {
        *this = *this*other;
 }
 
-void Matrix::translate(double x, double y, double z)
-{
-       multiply(translation(x, y, z));
-}
-
-void Matrix::rotate(double a, double x, double y, double z)
+void Matrix::translate(const Vector3 &t)
 {
-       multiply(rotation(a, x, y, z));
+       multiply(translation(t));
 }
 
-void Matrix::rotate_deg(double a, double x, double y, double z)
+void Matrix::rotate(const Angle &a, const Vector3 &x)
 {
-       multiply(rotation_deg(a, x, y, z));
+       multiply(rotation(a, x));
 }
 
-void Matrix::scale(double s)
+void Matrix::scale(const Vector3 &s)
 {
        multiply(scaling(s));
 }
 
-void Matrix::scale(double x, double y, double z)
-{
-       multiply(scaling(x, y, z));
-}
-
 Matrix Matrix::operator*(const Matrix &other) const
 {
-       if(flags==IDENTITY)
-               return other;
-       else if(other.flags==IDENTITY)
-               return *this;
-       else if(flags==TRANSLATE && !(other.flags&ARBITARY))
-       {
-               Matrix result = other;
-               result.matrix[12] += matrix[12];
-               result.matrix[13] += matrix[13];
-               result.matrix[14] += matrix[14];
-               result.flags |= flags;
-               return result;
-       }
-       else if(!(flags&ARBITARY) && other.flags==TRANSLATE)
-       {
-               Matrix result = *this;
-               const double *m = other.matrix;
-               result.matrix[12] += matrix[0]*m[12]+matrix[4]*m[13]+matrix[8]*m[14];
-               result.matrix[13] += matrix[1]*m[12]+matrix[5]*m[13]+matrix[9]*m[14];
-               result.matrix[14] += matrix[2]*m[12]+matrix[6]*m[13]+matrix[10]*m[14];
-               result.flags |= other.flags;
-               return result;
-       }
-       else
-       {
-               Matrix result;
-               fill(result.matrix, result.matrix+16, 0.0);
-               for(unsigned i=0; i<4; ++i)
-                       for(unsigned j=0; j<4; ++j)
-                               for(unsigned k=0; k<4; ++k)
-                                       result.matrix[i+j*4] += matrix[i+k*4]*other.matrix[k+j*4];
-               result.flags = flags|other.flags;
-               return result;
-       }
+       return static_cast<const Base &>(*this)*static_cast<const Base &>(other);
 }
 
 Matrix &Matrix::operator*=(const Matrix &other)
@@ -129,87 +58,34 @@ Matrix &Matrix::operator*=(const Matrix &other)
 
 Vector4 Matrix::operator*(const Vector4 &vec) const
 {
-       if(flags==IDENTITY)
-               return vec;
-       else if(flags==TRANSLATE)
-               return Vector4(vec.x+vec.w*matrix[12], vec.y+vec.w*matrix[13], vec.z+vec.w*matrix[14], vec.w);
-       else if(flags==SCALE)
-               return Vector4(vec.x*matrix[0], vec.y*matrix[5], vec.z*matrix[10], vec.w);
-       else
-       {
-               Vector4 result;
-               result.x = vec.x*matrix[0]+vec.y*matrix[4]+vec.z*matrix[8]+vec.w*matrix[12];
-               result.y = vec.x*matrix[1]+vec.y*matrix[5]+vec.z*matrix[9]+vec.w*matrix[13];
-               result.z = vec.x*matrix[2]+vec.y*matrix[6]+vec.z*matrix[10]+vec.w*matrix[14];
-               result.w = vec.x*matrix[3]+vec.y*matrix[7]+vec.z*matrix[11]+vec.w*matrix[15];
-               return result;
-       }
+       return static_cast<const Base &>(*this)*LinAl::Vector<double, 4>(vec);
 }
 
-double Matrix::operator[](unsigned i) const
+Vector3 Matrix::operator*(const Vector3 &vec) const
 {
-       if(i>=16)
-               throw out_of_range("Matrix::operator[]");
-       return matrix[i];
+       return Geometry::reduce_vector((*this)*Geometry::augment_vector(vec, 1.0f));
 }
 
-Matrix Matrix::translation(double x, double y, double z)
-{
-       Matrix result;
-       result.matrix[12] = x;
-       result.matrix[13] = y;
-       result.matrix[14] = z;
-       result.flags |= TRANSLATE;
-       return result;
-}
-
-Matrix Matrix::rotation(double a, double x, double y, double z)
+double Matrix::operator[](unsigned i) const
 {
-       double l = sqrt(x*x+y*y+z*z);
-       x /= l;
-       y /= l;
-       z /= l;
-       double c = cos(a);
-       double s = sin(a);
-
-       // http://en.wikipedia.org/wiki/Rotation_matrix#Rotation_matrix_given_an_axis_and_an_angle
-       Matrix result;
-       result.matrix[0] = c+x*x*(1-c);
-       result.matrix[1] = y*x*(1-c)+z*s;
-       result.matrix[2] = z*x*(1-c)-y*s;
-       result.matrix[4] = x*y*(1-c)-z*s;
-       result.matrix[5] = c+y*y*(1-c);
-       result.matrix[6] = z*y*(1-c)+x*s;
-       result.matrix[8] = x*z*(1-c)+y*s;
-       result.matrix[9] = y*z*(1-c)-x*s;
-       result.matrix[10] = c+z*z*(1-c);
-       result.flags |= ROTATE;
-       return result;
+       if(i>=16)
+               throw out_of_range("Matrix::operator[]");
+       return operator()(i%4, i/4);
 }
 
-Matrix Matrix::rotation_deg(double a, double x, double y, double z)
+Matrix Matrix::translation(const Vector3 &t)
 {
-       return rotation(a*M_PI/180, x, y, z);
+       return Geometry::AffineTransformation<double, 3>::translation(t).get_matrix();
 }
 
-Matrix Matrix::scaling(double s)
+Matrix Matrix::rotation(const Angle &a, const Vector3 &x)
 {
-       Matrix result;
-       result.matrix[0] = s;
-       result.matrix[5] = s;
-       result.matrix[10] = s;
-       result.flags |= SCALE;
-       return result;
+       return Geometry::AffineTransformation<double, 3>::rotation(a, x).get_matrix();
 }
 
-Matrix Matrix::scaling(double x, double y, double z)
+Matrix Matrix::scaling(const Vector3 &s)
 {
-       Matrix result;
-       result.matrix[0] = x;
-       result.matrix[5] = y;
-       result.matrix[10] = z;
-       result.flags |= SCALE|ARBITARY;
-       return result;
+       return Geometry::AffineTransformation<double, 3>::scaling(s).get_matrix();
 }
 
 Matrix Matrix::ortho(double l, double r, double b, double t, double n, double f)
@@ -218,13 +94,12 @@ Matrix Matrix::ortho(double l, double r, double b, double t, double n, double f)
                throw invalid_argument("Matrix::ortho");
 
        Matrix result;
-       result.matrix[0] = 2/(r-l);
-       result.matrix[5] = 2/(t-b);
-       result.matrix[10] = -2/(f-n);
-       result.matrix[12] = -(r+l)/(r-l);
-       result.matrix[13] = -(t+b)/(t-b);
-       result.matrix[14] = -(f+n)/(f-n);
-       result.flags = TRANSLATE|SCALE|ARBITARY;
+       result(0, 0) = 2/(r-l);
+       result(1, 1) = 2/(t-b);
+       result(2, 2) = -2/(f-n);
+       result(0, 3) = -(r+l)/(r-l);
+       result(1, 3) = -(t+b)/(t-b);
+       result(2, 3) = -(f+n)/(f-n);
        return result;
 }
 
@@ -249,15 +124,14 @@ Matrix Matrix::frustum(double l, double r, double b, double t, double n, double
                throw invalid_argument("Matrix::frustum");
 
        Matrix result;
-       result.matrix[0] = 2*n/(r-l);
-       result.matrix[5] = 2*n/(t-b);
-       result.matrix[8] = (r+l)/(r-l);
-       result.matrix[9] = (t+b)/(t-b);
-       result.matrix[10] = -(f+n)/(f-n);
-       result.matrix[11] = -1;
-       result.matrix[14] = -2*f*n/(f-n);
-       result.matrix[15] = 0;
-       result.flags = ARBITARY;
+       result(0, 0) = 2*n/(r-l);
+       result(1, 1) = 2*n/(t-b);
+       result(0, 2) = (r+l)/(r-l);
+       result(1, 2) = (t+b)/(t-b);
+       result(2, 2) = -(f+n)/(f-n);
+       result(3, 2) = -1;
+       result(2, 3) = -2*f*n/(f-n);
+       result(3 ,3) = 0;
        return result;
 }