]> git.tdb.fi Git - libs/gl.git/blob - source/matrix.cpp
Use a type registry to manage postprocessor types for pipeline templates
[libs/gl.git] / source / matrix.cpp
1 #include <algorithm>
2 #include <cmath>
3 #include <msp/geometry/affinetransformation.h>
4 #include <msp/gl/extensions/msp_legacy_features.h>
5 #include "error.h"
6 #include "matrix.h"
7
8 using namespace std;
9
10 namespace Msp {
11 namespace GL {
12
13 Matrix::Matrix():
14         Base(Base::identity())
15 { }
16
17 Matrix::Matrix(const float *m):
18         Base(m)
19 { }
20
21 Matrix::Matrix(const LinAl::Matrix<float, 4, 4> &other):
22         Base(other)
23 { }
24
25 Matrix &Matrix::translate(const Vector3 &t)
26 {
27         return multiply(translation(t));
28 }
29
30 Matrix &Matrix::rotate(const Angle &a, const Vector3 &x)
31 {
32         return multiply(rotation(a, x));
33 }
34
35 Matrix &Matrix::scale(const Vector3 &s)
36 {
37         return multiply(scaling(s));
38 }
39
40 float Matrix::operator[](unsigned i) const
41 {
42         if(i>=16)
43                 throw out_of_range("Matrix::operator[]");
44         return operator()(i%4, i/4);
45 }
46
47 Matrix Matrix::translation(const Vector3 &t)
48 {
49         return Geometry::AffineTransformation<float, 3>::translation(t).get_matrix();
50 }
51
52 Matrix Matrix::rotation(const Angle &a, const Vector3 &x)
53 {
54         return Geometry::AffineTransformation<float, 3>::rotation(a, x).get_matrix();
55 }
56
57 Matrix Matrix::scaling(const Vector3 &s)
58 {
59         return Geometry::AffineTransformation<float, 3>::scaling(s).get_matrix();
60 }
61
62 Matrix Matrix::ortho(float l, float r, float b, float t, float n, float f)
63 {
64         if(l==r || b==t || n==f)
65                 throw invalid_argument("Matrix::ortho");
66
67         Matrix result;
68         result(0, 0) = 2/(r-l);
69         result(1, 1) = 2/(t-b);
70         result(2, 2) = -2/(f-n);
71         result(0, 3) = -(r+l)/(r-l);
72         result(1, 3) = -(t+b)/(t-b);
73         result(2, 3) = -(f+n)/(f-n);
74         return result;
75 }
76
77 Matrix Matrix::ortho_centered(float w, float h)
78 {
79         return ortho(-w/2, w/2, -h/2, h/2, -1, 1);
80 }
81
82 Matrix Matrix::ortho_bottomleft(float w, float h)
83 {
84         return ortho(0, w, 0, h, -1, 1);
85 }
86
87 Matrix Matrix::ortho_topleft(float w, float h)
88 {
89         return ortho(0, w, h, 0, -1, 1);
90 }
91
92 Matrix Matrix::frustum(float l, float r, float b, float t, float n, float f)
93 {
94         if(l==r || b==t || n<=0 || f<=n)
95                 throw invalid_argument("Matrix::frustum");
96
97         Matrix result;
98         result(0, 0) = 2*n/(r-l);
99         result(1, 1) = 2*n/(t-b);
100         result(0, 2) = (r+l)/(r-l);
101         result(1, 2) = (t+b)/(t-b);
102         result(2, 2) = -(f+n)/(f-n);
103         result(3, 2) = -1;
104         result(2, 3) = -2*f*n/(f-n);
105         result(3, 3) = 0;
106         return result;
107 }
108
109 Matrix Matrix::frustum_centered(float w, float h, float n, float f)
110 {
111         return frustum(-w/2, w/2, -h/2, h/2, n, f);
112 }
113
114 Matrix Matrix::perspective(const Angle &h, float a, float n, float f)
115 {
116         float hh = tan(h/2.0f)*n;
117         return frustum(-hh*a, hh*a, -hh, hh, n, f);
118 }
119
120
121 GLenum MatrixStack::current_mode = GL_MODELVIEW;
122
123 MatrixStack::MatrixStack(GLenum m):
124         mode(m)
125 {
126         matrices.reserve(mode==GL_MODELVIEW ? 32 : 4);
127         matrices.push_back(Matrix());
128 }
129
130 MatrixStack::MatrixStack():
131         mode(0)
132 {
133         matrices.reserve(32);
134         matrices.push_back(Matrix());
135 }
136
137 const Matrix &MatrixStack::top() const
138 {
139         return matrices.back();
140 }
141
142 void MatrixStack::load(const Matrix &m)
143 {
144         matrices.back() = m;
145         update();
146 }
147
148 void MatrixStack::multiply(const Matrix &m)
149 {
150         matrices.back() *= m;
151         update();
152 }
153
154 void MatrixStack::push()
155 {
156         matrices.push_back(top());
157 }
158
159 void MatrixStack::pop()
160 {
161         if(matrices.size()==1)
162                 throw stack_underflow("MatrixStack::pop()");
163
164         matrices.pop_back();
165         update();
166 }
167
168 void MatrixStack::update()
169 {
170         if(!mode)
171                 return;
172
173         static Require _req(MSP_legacy_features);
174
175         if(mode!=current_mode)
176         {
177                 glMatrixMode(mode);
178                 current_mode = mode;
179         }
180
181         glLoadMatrixf(matrices.back().data());
182 }
183
184 MatrixStack &MatrixStack::operator=(const Matrix &m)
185 {
186         load(m);
187         return *this;
188 }
189
190 MatrixStack &MatrixStack::operator*=(const Matrix &m)
191 {
192         multiply(m);
193         return *this;
194 }
195
196 MatrixStack &MatrixStack::modelview()
197 {
198         static MatrixStack ms(GL_MODELVIEW);
199         return ms;
200 }
201
202 MatrixStack &MatrixStack::projection()
203 {
204         static MatrixStack ms(GL_PROJECTION);
205         return ms;
206 }
207
208 } // namespace GL
209 } // namespace Msp