1 | // Copyright 2016 The SwiftShader Authors. All Rights Reserved. |
2 | // |
3 | // Licensed under the Apache License, Version 2.0 (the "License"); |
4 | // you may not use this file except in compliance with the License. |
5 | // You may obtain a copy of the License at |
6 | // |
7 | // http://www.apache.org/licenses/LICENSE-2.0 |
8 | // |
9 | // Unless required by applicable law or agreed to in writing, software |
10 | // distributed under the License is distributed on an "AS IS" BASIS, |
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
12 | // See the License for the specific language governing permissions and |
13 | // limitations under the License. |
14 | |
15 | #include "MatrixStack.hpp" |
16 | |
17 | #include "Common/Math.hpp" |
18 | |
19 | namespace sw |
20 | { |
21 | MatrixStack::MatrixStack(int size) |
22 | { |
23 | stack = new Matrix[size]; |
24 | stack[0] = 1; |
25 | |
26 | top = 0; |
27 | this->size = size; |
28 | } |
29 | |
30 | MatrixStack::~MatrixStack() |
31 | { |
32 | delete[] stack; |
33 | stack = 0; |
34 | } |
35 | |
36 | void MatrixStack::identity() |
37 | { |
38 | stack[top] = 1; |
39 | } |
40 | |
41 | void MatrixStack::load(const Matrix &M) |
42 | { |
43 | stack[top] = M; |
44 | } |
45 | |
46 | void MatrixStack::load(const float *M) |
47 | { |
48 | stack[top] = Matrix(M[0], M[4], M[8], M[12], |
49 | M[1], M[5], M[9], M[13], |
50 | M[2], M[6], M[10], M[14], |
51 | M[3], M[7], M[11], M[15]); |
52 | } |
53 | |
54 | void MatrixStack::load(const double *M) |
55 | { |
56 | stack[top] = Matrix((float)M[0], (float)M[4], (float)M[8], (float)M[12], |
57 | (float)M[1], (float)M[5], (float)M[9], (float)M[13], |
58 | (float)M[2], (float)M[6], (float)M[10], (float)M[14], |
59 | (float)M[3], (float)M[7], (float)M[11], (float)M[15]); |
60 | } |
61 | |
62 | void MatrixStack::translate(float x, float y, float z) |
63 | { |
64 | stack[top] *= Matrix::translate(x, y, z); |
65 | } |
66 | |
67 | void MatrixStack::translate(double x, double y, double z) |
68 | { |
69 | translate((float)x, (float)y, (float)z); |
70 | } |
71 | |
72 | void MatrixStack::rotate(float angle, float x, float y, float z) |
73 | { |
74 | float n = 1.0f / sqrt(x*x + y*y + z*z); |
75 | |
76 | x *= n; |
77 | y *= n; |
78 | z *= n; |
79 | |
80 | float theta = angle * 0.0174532925f; // In radians |
81 | float c = cos(theta); |
82 | float _c = 1 - c; |
83 | float s = sin(theta); |
84 | |
85 | // Rodrigues' rotation formula |
86 | sw::Matrix rotate(c+x*x*_c, x*y*_c-z*s, x*z*_c+y*s, |
87 | x*y*_c+z*s, c+y*y*_c, y*z*_c-x*s, |
88 | x*z*_c-y*s, y*z*_c+x*s, c+z*z*_c); |
89 | |
90 | stack[top] *= rotate; |
91 | } |
92 | |
93 | void MatrixStack::rotate(double angle, double x, double y, double z) |
94 | { |
95 | rotate((float)angle, (float)x, (float)y, (float)z); |
96 | } |
97 | |
98 | void MatrixStack::scale(float x, float y, float z) |
99 | { |
100 | stack[top] *= Matrix::scale(x, y, z); |
101 | } |
102 | |
103 | void MatrixStack::scale(double x, double y, double z) |
104 | { |
105 | scale((float)x, (float)y, (float)z); |
106 | } |
107 | |
108 | void MatrixStack::multiply(const float *M) |
109 | { |
110 | stack[top] *= Matrix(M[0], M[4], M[8], M[12], |
111 | M[1], M[5], M[9], M[13], |
112 | M[2], M[6], M[10], M[14], |
113 | M[3], M[7], M[11], M[15]); |
114 | } |
115 | |
116 | void MatrixStack::multiply(const double *M) |
117 | { |
118 | stack[top] *= Matrix((float)M[0], (float)M[4], (float)M[8], (float)M[12], |
119 | (float)M[1], (float)M[5], (float)M[9], (float)M[13], |
120 | (float)M[2], (float)M[6], (float)M[10], (float)M[14], |
121 | (float)M[3], (float)M[7], (float)M[11], (float)M[15]); |
122 | } |
123 | |
124 | void MatrixStack::frustum(float left, float right, float bottom, float top, float zNear, float zFar) |
125 | { |
126 | float l = (float)left; |
127 | float r = (float)right; |
128 | float b = (float)bottom; |
129 | float t = (float)top; |
130 | float n = (float)zNear; |
131 | float f = (float)zFar; |
132 | |
133 | float A = (r + l) / (r - l); |
134 | float B = (t + b) / (t - b); |
135 | float C = -(f + n) / (f - n); |
136 | float D = -2 * f * n / (f - n); |
137 | |
138 | Matrix frustum(2 * n / (r - l), 0, A, 0, |
139 | 0, 2 * n / (t - b), B, 0, |
140 | 0, 0, C, D, |
141 | 0, 0, -1, 0); |
142 | |
143 | stack[this->top] *= frustum; |
144 | } |
145 | |
146 | void MatrixStack::ortho(double left, double right, double bottom, double top, double zNear, double zFar) |
147 | { |
148 | float l = (float)left; |
149 | float r = (float)right; |
150 | float b = (float)bottom; |
151 | float t = (float)top; |
152 | float n = (float)zNear; |
153 | float f = (float)zFar; |
154 | |
155 | float tx = -(r + l) / (r - l); |
156 | float ty = -(t + b) / (t - b); |
157 | float tz = -(f + n) / (f - n); |
158 | |
159 | Matrix ortho(2 / (r - l), 0, 0, tx, |
160 | 0, 2 / (t - b), 0, ty, |
161 | 0, 0, -2 / (f - n), tz, |
162 | 0, 0, 0, 1); |
163 | |
164 | stack[this->top] *= ortho; |
165 | } |
166 | |
167 | bool MatrixStack::push() |
168 | { |
169 | if(top >= size - 1) return false; |
170 | |
171 | stack[top + 1] = stack[top]; |
172 | top++; |
173 | |
174 | return true; |
175 | } |
176 | |
177 | bool MatrixStack::pop() |
178 | { |
179 | if(top <= 0) return false; |
180 | |
181 | top--; |
182 | |
183 | return true; |
184 | } |
185 | |
186 | const Matrix &MatrixStack::current() |
187 | { |
188 | return stack[top]; |
189 | } |
190 | |
191 | bool MatrixStack::isIdentity() const |
192 | { |
193 | const Matrix &m = stack[top]; |
194 | |
195 | if(m.m[0][0] != 1.0f) return false; |
196 | if(m.m[0][1] != 0.0f) return false; |
197 | if(m.m[0][2] != 0.0f) return false; |
198 | if(m.m[0][3] != 0.0f) return false; |
199 | |
200 | if(m.m[1][0] != 0.0f) return false; |
201 | if(m.m[1][1] != 1.0f) return false; |
202 | if(m.m[1][2] != 0.0f) return false; |
203 | if(m.m[1][3] != 0.0f) return false; |
204 | |
205 | if(m.m[2][0] != 0.0f) return false; |
206 | if(m.m[2][1] != 0.0f) return false; |
207 | if(m.m[2][2] != 1.0f) return false; |
208 | if(m.m[2][3] != 0.0f) return false; |
209 | |
210 | if(m.m[3][0] != 0.0f) return false; |
211 | if(m.m[3][1] != 0.0f) return false; |
212 | if(m.m[3][2] != 0.0f) return false; |
213 | if(m.m[3][3] != 1.0f) return false; |
214 | |
215 | return true; |
216 | } |
217 | } |
218 | |