1 | // |
2 | // Copyright 2018 The ANGLE Project Authors. All rights reserved. |
3 | // Use of this source code is governed by a BSD-style license that can be |
4 | // found in the LICENSE file. |
5 | // |
6 | |
7 | // matrix_utils.cpp: Contains implementations for Mat4 methods. |
8 | |
9 | #include "common/matrix_utils.h" |
10 | |
11 | namespace angle |
12 | { |
13 | |
14 | Mat4::Mat4() : Mat4(1.f, 0.f, 0.f, 0.f, 0.f, 1.f, 0.f, 0.f, 0.f, 0.f, 1.f, 0.f, 0.f, 0.f, 0.f, 1.f) |
15 | {} |
16 | |
17 | Mat4::Mat4(const Matrix<float> generalMatrix) : Matrix(std::vector<float>(16, 0), 4, 4) |
18 | { |
19 | unsigned int minCols = std::min((unsigned int)4, generalMatrix.columns()); |
20 | unsigned int minRows = std::min((unsigned int)4, generalMatrix.rows()); |
21 | for (unsigned int i = 0; i < minCols; i++) |
22 | { |
23 | for (unsigned int j = 0; j < minRows; j++) |
24 | { |
25 | mElements[j * minCols + i] = generalMatrix.at(j, i); |
26 | } |
27 | } |
28 | } |
29 | |
30 | Mat4::Mat4(const std::vector<float> &elements) : Matrix(elements, 4) {} |
31 | |
32 | Mat4::Mat4(const float *elements) : Matrix(elements, 4) {} |
33 | |
34 | Mat4::Mat4(float m00, |
35 | float m01, |
36 | float m02, |
37 | float m03, |
38 | float m10, |
39 | float m11, |
40 | float m12, |
41 | float m13, |
42 | float m20, |
43 | float m21, |
44 | float m22, |
45 | float m23, |
46 | float m30, |
47 | float m31, |
48 | float m32, |
49 | float m33) |
50 | : Matrix(std::vector<float>(16, 0), 4, 4) |
51 | { |
52 | mElements[0] = m00; |
53 | mElements[1] = m01; |
54 | mElements[2] = m02; |
55 | mElements[3] = m03; |
56 | mElements[4] = m10; |
57 | mElements[5] = m11; |
58 | mElements[6] = m12; |
59 | mElements[7] = m13; |
60 | mElements[8] = m20; |
61 | mElements[9] = m21; |
62 | mElements[10] = m22; |
63 | mElements[11] = m23; |
64 | mElements[12] = m30; |
65 | mElements[13] = m31; |
66 | mElements[14] = m32; |
67 | mElements[15] = m33; |
68 | } |
69 | |
70 | // static |
71 | Mat4 Mat4::Rotate(float angle, const Vector3 &axis) |
72 | { |
73 | auto axis_normalized = axis.normalized(); |
74 | float angle_radians = angle * (3.14159265358979323f / 180.0f); |
75 | float c = cos(angle_radians); |
76 | float ci = 1.f - c; |
77 | float s = sin(angle_radians); |
78 | |
79 | float x = axis_normalized.x(); |
80 | float y = axis_normalized.y(); |
81 | float z = axis_normalized.z(); |
82 | |
83 | float x2 = x * x; |
84 | float y2 = y * y; |
85 | float z2 = z * z; |
86 | |
87 | float xy = x * y; |
88 | float yz = y * z; |
89 | float zx = z * x; |
90 | |
91 | float r00 = c + ci * x2; |
92 | float r01 = ci * xy + s * z; |
93 | float r02 = ci * zx - s * y; |
94 | float r03 = 0.f; |
95 | |
96 | float r10 = ci * xy - s * z; |
97 | float r11 = c + ci * y2; |
98 | float r12 = ci * yz + s * x; |
99 | float r13 = 0.f; |
100 | |
101 | float r20 = ci * zx + s * y; |
102 | float r21 = ci * yz - s * x; |
103 | float r22 = c + ci * z2; |
104 | float r23 = 0.f; |
105 | |
106 | float r30 = 0.f; |
107 | float r31 = 0.f; |
108 | float r32 = 0.f; |
109 | float r33 = 1.f; |
110 | |
111 | return Mat4(r00, r01, r02, r03, r10, r11, r12, r13, r20, r21, r22, r23, r30, r31, r32, r33); |
112 | } |
113 | |
114 | // static |
115 | Mat4 Mat4::Translate(const Vector3 &t) |
116 | { |
117 | float r00 = 1.f; |
118 | float r01 = 0.f; |
119 | float r02 = 0.f; |
120 | float r03 = 0.f; |
121 | |
122 | float r10 = 0.f; |
123 | float r11 = 1.f; |
124 | float r12 = 0.f; |
125 | float r13 = 0.f; |
126 | |
127 | float r20 = 0.f; |
128 | float r21 = 0.f; |
129 | float r22 = 1.f; |
130 | float r23 = 0.f; |
131 | |
132 | float r30 = t.x(); |
133 | float r31 = t.y(); |
134 | float r32 = t.z(); |
135 | float r33 = 1.f; |
136 | |
137 | return Mat4(r00, r01, r02, r03, r10, r11, r12, r13, r20, r21, r22, r23, r30, r31, r32, r33); |
138 | } |
139 | |
140 | // static |
141 | Mat4 Mat4::Scale(const Vector3 &s) |
142 | { |
143 | float r00 = s.x(); |
144 | float r01 = 0.f; |
145 | float r02 = 0.f; |
146 | float r03 = 0.f; |
147 | |
148 | float r10 = 0.f; |
149 | float r11 = s.y(); |
150 | float r12 = 0.f; |
151 | float r13 = 0.f; |
152 | |
153 | float r20 = 0.f; |
154 | float r21 = 0.f; |
155 | float r22 = s.z(); |
156 | float r23 = 0.f; |
157 | |
158 | float r30 = 0.f; |
159 | float r31 = 0.f; |
160 | float r32 = 0.f; |
161 | float r33 = 1.f; |
162 | |
163 | return Mat4(r00, r01, r02, r03, r10, r11, r12, r13, r20, r21, r22, r23, r30, r31, r32, r33); |
164 | } |
165 | |
166 | // static |
167 | Mat4 Mat4::Frustum(float l, float r, float b, float t, float n, float f) |
168 | { |
169 | float nn = 2.f * n; |
170 | float fpn = f + n; |
171 | float fmn = f - n; |
172 | float tpb = t + b; |
173 | float tmb = t - b; |
174 | float rpl = r + l; |
175 | float rml = r - l; |
176 | |
177 | float r00 = nn / rml; |
178 | float r01 = 0.f; |
179 | float r02 = 0.f; |
180 | float r03 = 0.f; |
181 | |
182 | float r10 = 0.f; |
183 | float r11 = nn / tmb; |
184 | float r12 = 0.f; |
185 | float r13 = 0.f; |
186 | |
187 | float r20 = rpl / rml; |
188 | float r21 = tpb / tmb; |
189 | float r22 = -fpn / fmn; |
190 | float r23 = -1.f; |
191 | |
192 | float r30 = 0.f; |
193 | float r31 = 0.f; |
194 | float r32 = -nn * f / fmn; |
195 | float r33 = 0.f; |
196 | |
197 | return Mat4(r00, r01, r02, r03, r10, r11, r12, r13, r20, r21, r22, r23, r30, r31, r32, r33); |
198 | } |
199 | |
200 | // static |
201 | Mat4 Mat4::Perspective(float fov, float aspectRatio, float n, float f) |
202 | { |
203 | const float frustumHeight = tanf(static_cast<float>(fov / 360.0f * 3.14159265358979323)) * n; |
204 | const float frustumWidth = frustumHeight * aspectRatio; |
205 | return Frustum(-frustumWidth, frustumWidth, -frustumHeight, frustumHeight, n, f); |
206 | } |
207 | |
208 | // static |
209 | Mat4 Mat4::Ortho(float l, float r, float b, float t, float n, float f) |
210 | { |
211 | float fpn = f + n; |
212 | float fmn = f - n; |
213 | float tpb = t + b; |
214 | float tmb = t - b; |
215 | float rpl = r + l; |
216 | float rml = r - l; |
217 | |
218 | float r00 = 2.f / rml; |
219 | float r01 = 0.f; |
220 | float r02 = 0.f; |
221 | float r03 = 0.f; |
222 | |
223 | float r10 = 0.f; |
224 | float r11 = 2.f / tmb; |
225 | float r12 = 0.f; |
226 | float r13 = 0.f; |
227 | |
228 | float r20 = 0.f; |
229 | float r21 = 0.f; |
230 | float r22 = -2.f / fmn; |
231 | float r23 = 0.f; |
232 | |
233 | float r30 = -rpl / rml; |
234 | float r31 = -tpb / tmb; |
235 | float r32 = -fpn / fmn; |
236 | float r33 = 1.f; |
237 | |
238 | return Mat4(r00, r01, r02, r03, r10, r11, r12, r13, r20, r21, r22, r23, r30, r31, r32, r33); |
239 | } |
240 | |
241 | Mat4 Mat4::product(const Mat4 &m) |
242 | { |
243 | const float *a = mElements.data(); |
244 | const float *b = m.mElements.data(); |
245 | |
246 | return Mat4(a[0] * b[0] + a[4] * b[1] + a[8] * b[2] + a[12] * b[3], |
247 | a[1] * b[0] + a[5] * b[1] + a[9] * b[2] + a[13] * b[3], |
248 | a[2] * b[0] + a[6] * b[1] + a[10] * b[2] + a[14] * b[3], |
249 | a[3] * b[0] + a[7] * b[1] + a[11] * b[2] + a[15] * b[3], |
250 | |
251 | a[0] * b[4] + a[4] * b[5] + a[8] * b[6] + a[12] * b[7], |
252 | a[1] * b[4] + a[5] * b[5] + a[9] * b[6] + a[13] * b[7], |
253 | a[2] * b[4] + a[6] * b[5] + a[10] * b[6] + a[14] * b[7], |
254 | a[3] * b[4] + a[7] * b[5] + a[11] * b[6] + a[15] * b[7], |
255 | |
256 | a[0] * b[8] + a[4] * b[9] + a[8] * b[10] + a[12] * b[11], |
257 | a[1] * b[8] + a[5] * b[9] + a[9] * b[10] + a[13] * b[11], |
258 | a[2] * b[8] + a[6] * b[9] + a[10] * b[10] + a[14] * b[11], |
259 | a[3] * b[8] + a[7] * b[9] + a[11] * b[10] + a[15] * b[11], |
260 | |
261 | a[0] * b[12] + a[4] * b[13] + a[8] * b[14] + a[12] * b[15], |
262 | a[1] * b[12] + a[5] * b[13] + a[9] * b[14] + a[13] * b[15], |
263 | a[2] * b[12] + a[6] * b[13] + a[10] * b[14] + a[14] * b[15], |
264 | a[3] * b[12] + a[7] * b[13] + a[11] * b[14] + a[15] * b[15]); |
265 | } |
266 | |
267 | Vector4 Mat4::product(const Vector4 &b) |
268 | { |
269 | return Vector4( |
270 | mElements[0] * b.x() + mElements[4] * b.y() + mElements[8] * b.z() + mElements[12] * b.w(), |
271 | mElements[1] * b.x() + mElements[5] * b.y() + mElements[9] * b.z() + mElements[13] * b.w(), |
272 | mElements[2] * b.x() + mElements[6] * b.y() + mElements[10] * b.z() + mElements[14] * b.w(), |
273 | mElements[3] * b.x() + mElements[7] * b.y() + mElements[11] * b.z() + |
274 | mElements[15] * b.w()); |
275 | } |
276 | |
277 | void Mat4::dump() |
278 | { |
279 | printf("[ %f %f %f %f ]\n" , mElements[0], mElements[4], mElements[8], mElements[12]); |
280 | printf("[ %f %f %f %f ]\n" , mElements[1], mElements[5], mElements[9], mElements[13]); |
281 | printf("[ %f %f %f %f ]\n" , mElements[2], mElements[6], mElements[10], mElements[14]); |
282 | printf("[ %f %f %f %f ]\n" , mElements[3], mElements[7], mElements[11], mElements[15]); |
283 | } |
284 | |
285 | } // namespace angle |
286 | |