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 }