1 /++
2 Matrix management module.
3
4 Macros:
5 LREF = <a href="#$1">$1</a>
6 HREF = <a href="$1">$2</a>
7 IDENTITY_IMG = <img src="https://latex.codecogs.com/svg.image?I_{n}&space;=&space;\begin{bmatrix}&space;1&&space;0&space;&&space;0&space;&&space;0&space;\\&space;0&&space;1&space;&&space;0&space;&&space;0&space;\\&space;0&&space;0&space;&&space;1&space;&&space;0&space;\\&space;0&&space;0&space;&&space;0&space;&&space;1&space;\\\end{bmatrix}" title="I_{n} = \begin{bmatrix} 1& 0 & 0 & 0 \\ 0& 1 & 0 & 0 \\ 0& 0 & 1 & 0 \\ 0& 0 & 0 & 1 \\\end{bmatrix}" />
8 TRANSLATE_IMG = <img src="https://latex.codecogs.com/svg.image?\begin{bmatrix}&space;1&space;&&space;0&space;&&space;0&space;&&space;x&space;\\&space;0&space;&&space;1&space;&&space;0&space;&&space;y&space;\\&space;0&space;&&space;0&space;&&space;1&space;&&space;z&space;\\&space;0&space;&&space;0&space;&&space;0&space;&&space;1&space;\\\end{bmatrix}" title="\begin{bmatrix} 1 & 0 & 0 & x \\ 0 & 1 & 0 & y \\ 0 & 0 & 1 & z \\ 0 & 0 & 0 & 1 \\\end{bmatrix}" />
9 SCALE_IMG = <img src="https://latex.codecogs.com/svg.image?\begin{bmatrix}&space;x&space;&&space;0&space;&&space;0&space;&&space;0&space;\\&space;0&space;&&space;y&space;&&space;0&space;&&space;0&space;\\&space;0&space;&&space;0&space;&&space;z&space;&&space;0&space;\\&space;0&space;&&space;0&space;&&space;0&space;&&space;1&space;\\\end{bmatrix}" title="\begin{bmatrix} x & 0 & 0 & 0 \\ 0 & y & 0 & 0 \\ 0 & 0 & z & 0 \\ 0 & 0 & 0 & 1 \\\end{bmatrix}" />
10 ROTATE_IMG = <img src="https://latex.codecogs.com/svg.image?xfactor&space;=&space;\begin{bmatrix}&space;1&space;&&space;0&space;&&space;0&space;&&space;0&space;\\&space;0&space;&&space;cos&space;\o&space;&&space;-sin&space;\o&space;&&space;0&space;\\&space;0&space;&&space;sin&space;\o&space;&&space;cos&space;\o&space;&&space;0&space;\\&space;0&space;&&space;0&space;&&space;0&space;&&space;1&space;\\\end{bmatrix},y-factor&space;=\begin{bmatrix}&space;cos\psi&space;&&space;0&space;&&space;sin\psi&space;&&space;0&space;\\&space;0&space;&&space;1&space;&&space;0&space;&&space;0&space;\\&space;-sin\psi&space;&&space;0&space;&&space;cos\psi&space;&space;&&space;0&space;\\&space;0&space;&&space;0&space;&&space;0&space;&&space;1&space;\\\end{bmatrix},z-factor=&space;\begin{bmatrix}&space;cos\chi&space;&space;&&space;-sin\chi&space;&&space;0&space;&&space;0&space;\\&space;sin\chi&space;&&space;cos\chi&space;&&space;0&space;&&space;0&space;\\&space;0&space;&&space;0&space;&&space;1&space;&&space;0&space;\\&space;0&space;&&space;0&space;&&space;0&space;&&space;1&space;\\\end{bmatrix}" title="xfactor = \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & cos \o & -sin \o & 0 \\ 0 & sin \o & cos \o & 0 \\ 0 & 0 & 0 & 1 \\\end{bmatrix},y-factor =\begin{bmatrix} cos\psi & 0 & sin\psi & 0 \\ 0 & 1 & 0 & 0 \\ -sin\psi & 0 & cos\psi & 0 \\ 0 & 0 & 0 & 1 \\\end{bmatrix},z-factor= \begin{bmatrix} cos\chi & -sin\chi & 0 & 0 \\ sin\chi & cos\chi & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 1 \\\end{bmatrix}" />
11
12 Authors: $(HREF https://github.com/TodNaz,TodNaz)
13 Copyright: Copyright (c) 2020 - 2021, TodNaz.
14 License: $(HREF https://github.com/TodNaz/Tida/blob/master/LICENSE,MIT)
15 +/
16 module tida.matrix;
17
18 alias mat4 = float[4][4]; /// Matrix alias
19
20 /++
21 A square matrix, the elements of the main diagonal of which are equal to one
22 of the field, and the rest are equal to zero.
23
24 $(IDENTITY_IMG)
25 +/
26 @property float[4][4] identity() @safe nothrow pure
27 {
28 return [
29 [1, 0, 0, 0],
30 [0, 1, 0, 0],
31 [0, 0, 1, 0],
32 [0, 0, 0, 1]
33 ];
34 }
35
36 /++
37 Increases the matrix by a specified factor along the specified axes.
38
39 Params:
40 x = X-axis scaling factor.
41 y = Y-axis scaling factor.
42 z = Z-axis scaling factor.
43
44 Returns:
45 Scaling matrix.
46
47 See_Also:
48 $(HREF https://en.wikipedia.org/wiki/Scaling_(geometry), Scaling (geometry) - Wikipedia.)
49
50 $(SCALE_IMG)
51 +/
52 float[4][4] scaleMat(float x, float y, float z = 1.0f) @safe nothrow pure
53 {
54 float[] v = [x, y, z, 1.0f];
55 float[4][4] mat = identity();
56
57 for (int i = 0; i < 4; ++i)
58 for (int j = 0; j + 1 < 4; ++j)
59 mat[i][j] *= v[j];
60
61 return mat;
62 }
63
64 /++
65 Increases the matrix by a specified factor along the specified axes.
66
67 Params:
68 mat = Matrix to be scaled.
69 x = X-axis scaling factor.
70 y = Y-axis scaling factor.
71 z = Z-axis scaling factor.
72
73 Returns:
74 Scaling matrix.
75
76 See_Also:
77 $(HREF https://en.wikipedia.org/wiki/Scaling_(geometry), Scaling (geometry) - Wikipedia.)
78
79 $(SCALE_IMG)
80 +/
81 float[4][4] scale(float[4][4] mat, float x, float y, float z = 1.0f) @safe nothrow pure
82 {
83 return mulmat(mat, scaleMat(x, y, z));
84 }
85
86 /++
87 Moves the matrix along the specified axes by the specified amount.
88
89 Params:
90 x = X-axis move factor.
91 y = Y-axis move factor.
92 z = Z-axis move factor.
93
94 Returns:
95 Moved matrix.
96
97 See_Also:
98 $(HREF https://en.wikipedia.org/wiki/Translation_(geometry), Translation (geometry) - Wikipedia)
99
100 $(TRANSLATE_IMG)
101 +/
102 float[4][4] translation(float x, float y, float z) @safe nothrow pure
103 {
104 auto mat = identity();
105
106 mat[3][0] = x;
107 mat[3][1] = y;
108 mat[3][2] = z;
109
110 return mat;
111 }
112
113 /++
114 Moves the matrix provided in the arguments along the given axes with the
115 given values.
116
117 Params:
118 mat = The matrix to be moved.
119 x = X-axis move factor.
120 y = Y-axis move factor.
121 z = Z-axis move factor.
122
123 Returns:
124 Matrix that was previously cast in the matrix and is now moved by the function.
125
126 See_Also:
127 $(HREF https://en.wikipedia.org/wiki/Translation_(geometry), Translation (geometry) - Wikipedia)
128
129 $(TRANSLATE_IMG)
130 +/
131 float[4][4] translate(float[4][4] mat, float x, float y, float z) @safe nothrow pure
132 {
133 return mulmat(mat, translation(x, y, z));
134 }
135
136 /++
137 Gives the rotation matrix.
138
139 Params:
140 angle = Angle rotation.
141 x = X-axis rotate factor.
142 y = Y-axis rotate factor.
143 z = Z-axis rotate factor.
144
145 Returns:
146 Rotation matrix.
147
148 Also_See:
149 $(HREF https://en.wikipedia.org/wiki/Rotation_matrix, Rotation matrix - Wikipedia)
150
151 $(ROTATE_IMG)
152 +/
153 float[4][4] rotateMat(float angle, float x, float y, float z) @safe nothrow pure
154 {
155 import std.math;
156
157 float[4][4] res = identity();
158
159 const float c = cos(angle);
160 const oneMinusC = 1 - c;
161 const float s = sin(angle);
162
163 res[0][0] = x * x * oneMinusC + c;
164 res[0][1] = x * y * oneMinusC - z * s;
165 res[0][2] = x * z * oneMinusC + y * s;
166 res[1][0] = y * x * oneMinusC + z * s;
167 res[1][1] = y * y * oneMinusC + c;
168 res[1][2] = y * z * oneMinusC - x * s;
169 res[2][0] = z * x * oneMinusC - y * s;
170 res[2][1] = z * y * oneMinusC + x * s;
171 res[2][2] = z * z * oneMinusC + c;
172
173 return res;
174 }
175
176 /++
177 Gives the rotation matrix.
178
179 Params:
180 mat = Rotation matrix.
181 angle = Angle rotation.
182 x = X-axis rotate factor.
183 y = Y-axis rotate factor.
184 z = Z-axis rotate factor.
185
186 Returns:
187 Rotation matrix.
188
189 Also_See:
190 $(HREF https://en.wikipedia.org/wiki/Rotation_matrix, Rotation matrix - Wikipedia)
191
192 $(ROTATE_IMG)
193 +/
194 float[4][4] rotateMat(float[4][4] mat, float angle, float x, float y, float z) @safe nothrow pure
195 {
196 return mulmat(mat, rotateMat(angle, x, y, z));
197 }
198
199 /++
200 Euler method rotation matrix.
201
202 Params:
203 roll = Roll-Axis.
204 pitch = Pitch-Axis.
205 yaw = Yaw-Axis.
206
207 Returns:
208 Rotated matrix.
209
210 See_Also:
211 $(HREF https://en.wikipedia.org/wiki/Rotation_matrix, Rotation matrix - Wikipedia)
212 +/
213 float[4][4] eulerRotateMat(float roll, float pitch, float yaw) @safe nothrow pure
214 {
215 import std.math;
216
217 float[4][4] xres = identity();
218 float[4][4] yres = identity();
219 float[4][4] zres = identity();
220
221 immutable ct = [cos(roll), cos(pitch), cos(yaw)];
222 immutable st = [sin(roll), sin(pitch), sin(yaw)];
223
224 xres[0][0] = ct[0];
225 xres[0][1] = st[0];
226 xres[1][0] = -st[0];
227 xres[1][1] = ct[0];
228
229 yres[0][0] = ct[1];
230 yres[0][2] = -st[1];
231 yres[2][0] = st[1];
232 yres[2][2] = ct[1];
233
234 zres[0][0] = ct[2];
235 zres[0][1] = st[2];
236 zres[1][0] = -st[2];
237 zres[1][1] = ct[2];
238
239 mat4 result = identity();
240
241 result = mulmat(result, xres);
242 result = mulmat(result, yres);
243 result = mulmat(result, zres);
244
245 return result;
246 }
247
248 /++
249 Euler method rotation matrix.
250
251 Params:
252 mat = Rotation matrix.
253 roll = Roll-Axis.
254 pitch = Pitch-Axis.
255 yaw = Yaw-Axis.
256
257 Returns:
258 Rotated matrix.
259
260 See_Also:
261 $(HREF https://en.wikipedia.org/wiki/Rotation_matrix, Rotation matrix - Wikipedia)
262 +/
263 float[4][4] eulerRotate(float[4][4] mat, float roll, float pitch, float yaw) @safe nothrow pure
264 {
265 return mulmat(mat, eulerRotateMat(roll, pitch, yaw));
266 }
267
268 /++
269 Multiply two matrices.
270
271 Params:
272 a = First matrix.
273 b = Second matrix.
274
275 Returns:
276 Multiple matrix.
277
278 See_Also:
279 $(HREF https://en.wikipedia.org/wiki/Matrix_multiplication, Matix multiplication - Wikipedia)
280 +/
281 float[4][4] mulmat(float[4][4] a, float[4][4] b) @safe nothrow pure
282 {
283 float[4][4] result = 0.0f;
284
285 for (int i = 0; i < 4; ++i)
286 {
287 for (int j = 0; j < 4; ++j)
288 {
289 float sum = 0.0f;
290
291 for (int k = 0; k < 4; ++k)
292 sum += a[i][k] * b[k][j];
293
294 result[i][j] = sum;
295 }
296 }
297
298 return result;
299 }
300
301 /// Ortho matrix generate
302 float[4][4] ortho(float left, float right, float bottom, float top, float zNear = -1.0f, float zFar = 0.0f)
303 @safe nothrow pure
304 {
305 immutable defl = 0.0f;
306
307 immutable mRL = right - left;
308 immutable mTB = top - bottom;
309 immutable mFN = zFar - zNear;
310
311 immutable tRL = -(right + left) / mRL;
312 immutable tTB = -(top + bottom) / mTB;
313 immutable tFN = -(zFar + zNear) / mFN;
314
315 return [
316 [2 / mRL, defl, defl, defl],
317 [defl, 2 / mTB, defl, defl],
318 [defl, defl, -2 / mFN, defl],
319 [ tRL, tTB, tFN, 1.0f]
320 ];
321 }
322
323 import tida.vector;
324
325 /++
326 Multiple matrix and vector.
327 +/
328 Vector!float transform(Vector!float v, mat4 m) @safe nothrow pure
329 {
330 Vector!float result = vec!(float)(0.0f, 0.0f);
331
332 for (size_t i = 0; i < 2; ++i)
333 {
334 float sum = 0.0f;
335
336 for (size_t j = 0; j < 2; ++j)
337 {
338 sum += m[i][j] * v[j];
339 }
340
341 result[i] = sum;
342 }
343
344 return result;
345 }