]> git.tdb.fi Git - libs/gl.git/blobdiff - source/matrix.cpp
Better naming algorithm for objects in scene export
[libs/gl.git] / source / matrix.cpp
index dc855d2b0899f638782b1e2bc44cf52d157948d7..a4c36a022a9ecb338406a496760f12c1d0655540 100644 (file)
+#include <algorithm>
+#include <cmath>
+#include <msp/geometry/affinetransformation.h>
+#include <msp/gl/extensions/msp_legacy_features.h>
+#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<float, 4, 4> &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<float, 3>::translation(t).get_matrix();
+}
+
+Matrix Matrix::rotation(const Angle &a, const Vector3 &x)
+{
+       return Geometry::AffineTransformation<float, 3>::rotation(a, x).get_matrix();
+}
+
+Matrix Matrix::scaling(const Vector3 &s)
+{
+       return Geometry::AffineTransformation<float, 3>::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)
+{
+       return ortho(0, w, h, 0, -1, 1);
+}
+
+Matrix Matrix::frustum(float l, float r, float b, float t, float n, float 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(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()
 {
-       glMatrixMode(m);
+       matrices.push_back(top());
 }
 
-void load_identity()
+void MatrixStack::pop()
 {
-       glLoadIdentity();
+       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