X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=source%2Fmatrix.cpp;h=cac4a4fcd99afe6d2e110c80030aad39dd9352c1;hb=ae9abd6be3e556d0a202cc5ab05668da715382c9;hp=9af850d2dfa68956037be0e4854716813fdc79a6;hpb=41339bc44d076569c680b2c24c75b30ef1254c1b;p=libs%2Fgl.git diff --git a/source/matrix.cpp b/source/matrix.cpp index 9af850d2..cac4a4fc 100644 --- a/source/matrix.cpp +++ b/source/matrix.cpp @@ -1,73 +1,235 @@ -/* $Id$ - -This file is part of libmspgl -Copyright © 2007 Mikko Rasa, Mikkosoft Productions -Distributed under the LGPL -*/ - +#include +#include +#include +#include "error.h" #include "matrix.h" +using namespace std; + namespace Msp { namespace GL { -void matrix_mode(MatrixMode m) +Matrix::Matrix(): + Base(Base::identity()) +{ } + +Matrix::Matrix(const float *m): + Base(LinAl::SquareMatrix(m)) +{ } + +Matrix::Matrix(const double *m): + Base(m) +{ } + +Matrix::Matrix(const LinAl::Matrix &other): + Base(other) +{ } + +void Matrix::multiply(const Matrix &other) +{ + *this = *this*other; +} + +void Matrix::translate(const Vector3 &t) { - glMatrixMode(m); + multiply(translation(t)); } -void load_identity() +void Matrix::rotate(const Angle &a, const Vector3 &x) { - glLoadIdentity(); + multiply(rotation(a, x)); } -void load_matrix(const float *matrix) +void Matrix::scale(const Vector3 &s) { - glLoadMatrixf(matrix); + multiply(scaling(s)); } -void load_matrix(const double *matrix) +Matrix Matrix::operator*(const Matrix &other) const { - glLoadMatrixd(matrix); + return static_cast(*this)*static_cast(other); } -void mult_matrix(const float *matrix) +Matrix &Matrix::operator*=(const Matrix &other) { - glMultMatrixf(matrix); + multiply(other); + return *this; } -void mult_matrix(const double *matrix) +Vector4 Matrix::operator*(const Vector4 &vec) const { - glMultMatrixd(matrix); + return static_cast(*this)*LinAl::Vector(vec); } -void push_matrix() +Vector3 Matrix::operator*(const Vector3 &vec) const { - glPushMatrix(); + return Vector3((*this)*Vector4(vec, 1.0f)); } -void pop_matrix() +double Matrix::operator[](unsigned i) const { - glPopMatrix(); + if(i>=16) + throw out_of_range("Matrix::operator[]"); + return operator()(i%4, i/4); +} + +Matrix Matrix::translation(const Vector3 &t) +{ + return Geometry::AffineTransformation::translation(t).get_matrix(); +} + +Matrix Matrix::rotation(const Angle &a, const Vector3 &x) +{ + return Geometry::AffineTransformation::rotation(a, x).get_matrix(); +} + +Matrix Matrix::scaling(const Vector3 &s) +{ + return Geometry::AffineTransformation::scaling(s).get_matrix(); +} + +Matrix Matrix::ortho(double l, double r, double b, double t, double n, double f) +{ + if(l==r || b==t || n==f) + throw invalid_argument("Matrix::ortho"); + + Matrix result; + 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; +} + +Matrix Matrix::ortho_centered(double w, double h) +{ + return ortho(-w/2, w/2, -h/2, h/2, -1, 1); +} + +Matrix Matrix::ortho_bottomleft(double w, double h) +{ + return ortho(0, w, 0, h, -1, 1); +} + +Matrix Matrix::ortho_topleft(double w, double h) +{ + return ortho(0, w, h, 0, -1, 1); +} + +Matrix Matrix::frustum(double l, double r, double b, double t, double n, double f) +{ + if(l==r || b==t || n<=0 || f<=n) + throw invalid_argument("Matrix::frustum"); + + Matrix result; + 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; +} + +Matrix Matrix::frustum_centered(double w, double h, double n, double f) +{ + return frustum(-w/2, w/2, -h/2, h/2, n, f); +} + +Matrix Matrix::perspective(const Angle &h, double a, double n, double f) +{ + double hh = tan(h/2.0)*n; + return frustum(-hh*a, hh*a, -hh, hh, n, f); +} + + +GLenum MatrixStack::current_mode = GL_MODELVIEW; + +MatrixStack::MatrixStack(GLenum m): + mode(m) +{ + matrices.reserve(mode==GL_MODELVIEW ? 32 : 4); + matrices.push_back(Matrix()); +} + +MatrixStack::MatrixStack(): + mode(0) +{ + matrices.reserve(32); + matrices.push_back(Matrix()); +} + +const Matrix &MatrixStack::top() const +{ + return matrices.back(); +} + +void MatrixStack::load(const Matrix &m) +{ + matrices.back() = m; + update(); +} + +void MatrixStack::multiply(const Matrix &m) +{ + matrices.back() *= m; + update(); +} + +void MatrixStack::push() +{ + matrices.push_back(top()); +} + +void MatrixStack::pop() +{ + if(matrices.size()==1) + throw stack_underflow("MatrixStack::pop()"); + + matrices.pop_back(); + update(); +} + +void MatrixStack::update() +{ + if(!mode) + return; + + if(mode!=current_mode) + { + glMatrixMode(mode); + current_mode = mode; + } + + glLoadMatrixd(matrices.back().data()); } -void translate(float x, float y, float z) +MatrixStack &MatrixStack::operator=(const Matrix &m) { - glTranslatef(x, y, z); + load(m); + return *this; } -void rotate(float a, float x, float y, float z) +MatrixStack &MatrixStack::operator*=(const Matrix &m) { - glRotatef(a, x, y, z); + multiply(m); + return *this; } -void scale(float x, float y, float z) +MatrixStack &MatrixStack::modelview() { - glScalef(x, y, z); + static MatrixStack ms(GL_MODELVIEW); + return ms; } -void scale_uniform(float s) +MatrixStack &MatrixStack::projection() { - scale(s, s, s); + static MatrixStack ms(GL_PROJECTION); + return ms; } } // namespace GL