X-Git-Url: http://git.tdb.fi/?p=libs%2Fgl.git;a=blobdiff_plain;f=source%2Fmatrix.cpp;h=a4c36a022a9ecb338406a496760f12c1d0655540;hp=7a91078621e647d293af0628d06044c95e719fcd;hb=9d1fa012a23693768bbe287371e97751c03acc50;hpb=4c89817d6e060323ec1ddd275f3265cea688c650 diff --git a/source/matrix.cpp b/source/matrix.cpp index 7a910786..a4c36a02 100644 --- a/source/matrix.cpp +++ b/source/matrix.cpp @@ -1,43 +1,208 @@ -/* $Id$ - -This file is part of libmspgl -Copyright © 2007 Mikko Rasa, Mikkosoft Productions -Distributed under the LGPL -*/ - +#include +#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(m) +{ } + +Matrix::Matrix(const LinAl::Matrix &other): + Base(other) +{ } + +Matrix &Matrix::translate(const Vector3 &t) +{ + return multiply(translation(t)); +} + +Matrix &Matrix::rotate(const Angle &a, const Vector3 &x) +{ + return multiply(rotation(a, x)); +} + +Matrix &Matrix::scale(const Vector3 &s) +{ + return multiply(scaling(s)); +} + +float Matrix::operator[](unsigned i) const +{ + 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(float l, float r, float b, float t, float n, float 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(float w, float h) +{ + return ortho(-w/2, w/2, -h/2, h/2, -1, 1); +} + +Matrix Matrix::ortho_bottomleft(float w, float h) +{ + return ortho(0, w, 0, h, -1, 1); +} + +Matrix Matrix::ortho_topleft(float w, float h) { - glMatrixMode(m); + return ortho(0, w, h, 0, -1, 1); } -void load_identity() +Matrix Matrix::frustum(float l, float r, float b, float t, float n, float f) { - glLoadIdentity(); + 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(float w, float h, float n, float f) +{ + return frustum(-w/2, w/2, -h/2, h/2, n, f); +} + +Matrix Matrix::perspective(const Angle &h, float a, float n, float f) +{ + float hh = tan(h/2.0f)*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; + + static Require _req(MSP_legacy_features); + + if(mode!=current_mode) + { + glMatrixMode(mode); + current_mode = mode; + } + + glLoadMatrixf(matrices.back().data()); } -void mult_matrix(const float *matrix) +MatrixStack &MatrixStack::operator=(const Matrix &m) { - glMultMatrixf(matrix); + load(m); + return *this; } -void mult_matrix(const double *matrix) +MatrixStack &MatrixStack::operator*=(const Matrix &m) { - glMultMatrixd(matrix); + multiply(m); + return *this; } -void push_matrix() +MatrixStack &MatrixStack::modelview() { - glPushMatrix(); + static MatrixStack ms(GL_MODELVIEW); + return ms; } -void pop_matrix() +MatrixStack &MatrixStack::projection() { - glPopMatrix(); + static MatrixStack ms(GL_PROJECTION); + return ms; } } // namespace GL