1 | /** |
2 | * Copyright (c) 2006-2023 LOVE Development Team |
3 | * |
4 | * This software is provided 'as-is', without any express or implied |
5 | * warranty. In no event will the authors be held liable for any damages |
6 | * arising from the use of this software. |
7 | * |
8 | * Permission is granted to anyone to use this software for any purpose, |
9 | * including commercial applications, and to alter it and redistribute it |
10 | * freely, subject to the following restrictions: |
11 | * |
12 | * 1. The origin of this software must not be misrepresented; you must not |
13 | * claim that you wrote the original software. If you use this software |
14 | * in a product, an acknowledgment in the product documentation would be |
15 | * appreciated but is not required. |
16 | * 2. Altered source versions must be plainly marked as such, and must not be |
17 | * misrepresented as being the original software. |
18 | * 3. This notice may not be removed or altered from any source distribution. |
19 | **/ |
20 | |
21 | #ifndef LOVE_MATRIX_H |
22 | #define LOVE_MATRIX_H |
23 | |
24 | // LOVE |
25 | #include "math.h" |
26 | |
27 | namespace love |
28 | { |
29 | |
30 | /** |
31 | * This class is the basis for all transformations in LOVE. Although not really |
32 | * needed for 2D, it contains 4x4 elements to be compatible with OpenGL without |
33 | * conversions. |
34 | **/ |
35 | class Matrix4 |
36 | { |
37 | private: |
38 | |
39 | static void multiply(const Matrix4 &a, const Matrix4 &b, float t[16]); |
40 | |
41 | public: |
42 | |
43 | static void multiply(const Matrix4 &a, const Matrix4 &b, Matrix4 &result); |
44 | |
45 | /** |
46 | * Creates a new identity matrix. |
47 | **/ |
48 | Matrix4(); |
49 | |
50 | /** |
51 | * Creates a new matrix with the transform values set. |
52 | **/ |
53 | Matrix4(float t00, float t10, float t01, float t11, float x, float y); |
54 | |
55 | /** |
56 | * Creates a new matrix from the specified elements. Be sure to pass |
57 | * exactly 16 elements in! |
58 | **/ |
59 | Matrix4(const float elements[16]); |
60 | |
61 | /** |
62 | * Creates a new matrix from the result of multiplying the two specified |
63 | * matrices. |
64 | **/ |
65 | Matrix4(const Matrix4 &a, const Matrix4 &b); |
66 | |
67 | /** |
68 | * Creates a new matrix set to a transformation. |
69 | **/ |
70 | Matrix4(float x, float y, float angle, float sx, float sy, float ox, float oy, float kx, float ky); |
71 | |
72 | /** |
73 | * Multiplies this Matrix with another Matrix, changing neither. |
74 | * @param m The Matrix to multiply with this Matrix. |
75 | * @return The combined matrix. |
76 | **/ |
77 | Matrix4 operator * (const Matrix4 &m) const; |
78 | |
79 | /** |
80 | * Multiplies a Matrix into this Matrix. |
81 | * @param m The Matrix to combine into this Matrix. |
82 | **/ |
83 | void operator *= (const Matrix4 &m); |
84 | |
85 | /** |
86 | * Gets a pointer to the 16 array elements. |
87 | * @return The array elements. |
88 | **/ |
89 | const float *getElements() const; |
90 | |
91 | /** |
92 | * Resets this Matrix to the identity matrix. |
93 | **/ |
94 | void setIdentity(); |
95 | |
96 | /** |
97 | * Resets this Matrix to a translation. |
98 | * @param x Translation along x-axis. |
99 | * @param y Translation along y-axis. |
100 | **/ |
101 | void setTranslation(float x, float y); |
102 | |
103 | /** |
104 | * Resets this Matrix to a rotation. |
105 | * @param r The angle in radians. |
106 | **/ |
107 | void setRotation(float r); |
108 | |
109 | /** |
110 | * Resets this Matrix to a scale transformation. |
111 | * @param sx Scale factor along the x-axis. |
112 | * @param sy Scale factor along the y-axis. |
113 | **/ |
114 | void setScale(float sx, float sy); |
115 | |
116 | /** |
117 | * Resets this Matrix to a shear transformation. |
118 | * @param kx Shear along x-axis. |
119 | * @param ky Shear along y-axis. |
120 | **/ |
121 | void setShear(float kx, float ky); |
122 | |
123 | /** |
124 | * Calculates the scale factors for a 2D affine transform. The output values |
125 | * are absolute (not signed). |
126 | **/ |
127 | void getApproximateScale(float &sx, float &sy) const; |
128 | |
129 | /** |
130 | * Sets a transformation's values directly. Useful if you want to modify them inplace, |
131 | * or if you want to create a transformation that's not buildable with setTransformation() |
132 | * i.e. the inverse of setTransformation() is not easily built with another call |
133 | * to setTransformation() with tweaked values. |
134 | * |
135 | * @param t00 The sx*cos(angle) component of the transformation. |
136 | * @param t10 The sx*sin(angle) component of the transformation. |
137 | * @param t01 The sy*(-sin(angle)) component of the transformation. |
138 | * @param t11 The sy*cos(angle) component of the transformation. |
139 | * @param x The x translation component of the transformation. |
140 | * @param y The y translation component of the transformation. |
141 | **/ |
142 | void setRawTransformation(float t00, float t10, float t01, float t11, float x, float y); |
143 | |
144 | /** |
145 | * Creates a transformation with a certain position, orientation, scale |
146 | * and offset. Perfect for Drawables -- what a coincidence! |
147 | * |
148 | * @param x The translation along the x-axis. |
149 | * @param y The translation along the y-axis. |
150 | * @param angle The rotation (rad) around the center with offset (ox,oy). |
151 | * @param sx Scale along x-axis. |
152 | * @param sy Scale along y-axis. |
153 | * @param ox The offset for rotation along the x-axis. |
154 | * @param oy The offset for rotation along the y-axis. |
155 | * @param kx Shear along x-axis |
156 | * @param ky Shear along y-axis |
157 | **/ |
158 | void setTransformation(float x, float y, float angle, float sx, float sy, float ox, float oy, float kx, float ky); |
159 | |
160 | /** |
161 | * Multiplies this Matrix with a translation. |
162 | * @param x Translation along x-axis. |
163 | * @param y Translation along y-axis. |
164 | **/ |
165 | void translate(float x, float y); |
166 | |
167 | /** |
168 | * Multiplies this Matrix with a rotation. |
169 | * @param r Angle in radians. |
170 | **/ |
171 | void rotate(float r); |
172 | |
173 | /** |
174 | * Multiplies this Matrix with a scale transformation. |
175 | * @param sx Scale factor along the x-axis. |
176 | * @param sy Scale factor along the y-axis. |
177 | **/ |
178 | void scale(float sx, float sy); |
179 | |
180 | /** |
181 | * Multiplies this Matrix with a shear transformation. |
182 | * @param kx Shear along the x-axis. |
183 | * @param ky Shear along the y-axis. |
184 | **/ |
185 | void shear(float kx, float ky); |
186 | |
187 | /** |
188 | * Transforms an array of 2-component vertices by this Matrix. The source |
189 | * and destination arrays may be the same. |
190 | **/ |
191 | template <typename Vdst, typename Vsrc> |
192 | void transformXY(Vdst *dst, const Vsrc *src, int size) const; |
193 | |
194 | /** |
195 | * Transforms an array of 2-component vertices by this Matrix, and stores |
196 | * them in an array of 3-component vertices. |
197 | **/ |
198 | template <typename Vdst, typename Vsrc> |
199 | void transformXY0(Vdst *dst, const Vsrc *src, int size) const; |
200 | |
201 | /** |
202 | * Transforms an array of 3-component vertices by this Matrix. The source |
203 | * and destination arrays may be the same. |
204 | **/ |
205 | template <typename Vdst, typename Vsrc> |
206 | void transformXYZ(Vdst *dst, const Vsrc *src, int size) const; |
207 | |
208 | /** |
209 | * Gets whether this matrix is an affine 2D transform (if the only non- |
210 | * identity elements are the upper-left 2x2 and 2 translation values in the |
211 | * 4th column). |
212 | **/ |
213 | bool isAffine2DTransform() const; |
214 | |
215 | /** |
216 | * Computes and returns the inverse of the matrix. |
217 | **/ |
218 | Matrix4 inverse() const; |
219 | |
220 | /** |
221 | * Creates a new orthographic projection matrix. |
222 | **/ |
223 | static Matrix4 ortho(float left, float right, float bottom, float top, float near, float far); |
224 | |
225 | private: |
226 | |
227 | /** |
228 | * | e0 e4 e8 e12 | |
229 | * | e1 e5 e9 e13 | |
230 | * | e2 e6 e10 e14 | |
231 | * | e3 e7 e11 e15 | |
232 | **/ |
233 | float e[16]; |
234 | |
235 | }; // Matrix4 |
236 | |
237 | class Matrix3 |
238 | { |
239 | public: |
240 | |
241 | Matrix3(); |
242 | |
243 | /** |
244 | * Constructs a 3x3 matrix from the upper left section of a 4x4 matrix. |
245 | **/ |
246 | Matrix3(const Matrix4 &mat4); |
247 | |
248 | /** |
249 | * Creates a new matrix set to a transformation. |
250 | **/ |
251 | Matrix3(float x, float y, float angle, float sx, float sy, float ox, float oy, float kx, float ky); |
252 | |
253 | ~Matrix3(); |
254 | |
255 | /** |
256 | * Resets this matrix to the identity matrix. |
257 | **/ |
258 | void setIdentity(); |
259 | |
260 | Matrix3 operator * (const Matrix3 &m) const; |
261 | void operator *= (const Matrix3 &m); |
262 | |
263 | /** |
264 | * Gets a pointer to the 9 array elements. |
265 | **/ |
266 | const float *getElements() const; |
267 | |
268 | /** |
269 | * Calculates the inverse of the transpose of this matrix. |
270 | **/ |
271 | Matrix3 transposedInverse() const; |
272 | |
273 | /** |
274 | * Creates a transformation with a certain position, orientation, scale |
275 | * and offset. |
276 | * |
277 | * @param x The translation along the x-axis. |
278 | * @param y The translation along the y-axis. |
279 | * @param angle The rotation (rad) around the center with offset (ox,oy). |
280 | * @param sx Scale along x-axis. |
281 | * @param sy Scale along y-axis. |
282 | * @param ox The offset for rotation along the x-axis. |
283 | * @param oy The offset for rotation along the y-axis. |
284 | * @param kx Shear along x-axis |
285 | * @param ky Shear along y-axis |
286 | **/ |
287 | void setTransformation(float x, float y, float angle, float sx, float sy, float ox, float oy, float kx, float ky); |
288 | |
289 | /** |
290 | * Transforms an array of vertices by this matrix. |
291 | **/ |
292 | template <typename Vdst, typename Vsrc> |
293 | void transformXY(Vdst *dst, const Vsrc *src, int size) const; |
294 | |
295 | private: |
296 | |
297 | /** |
298 | * | e0 e3 e6 |
299 | * | e1 e4 e7 |
300 | * | e2 e5 e8 |
301 | **/ |
302 | float e[9]; |
303 | |
304 | }; // Matrix3 |
305 | |
306 | // | x | |
307 | // | y | |
308 | // | 0 | |
309 | // | 1 | |
310 | // | e0 e4 e8 e12 | |
311 | // | e1 e5 e9 e13 | |
312 | // | e2 e6 e10 e14 | |
313 | // | e3 e7 e11 e15 | |
314 | |
315 | template <typename Vdst, typename Vsrc> |
316 | void Matrix4::transformXY(Vdst *dst, const Vsrc *src, int size) const |
317 | { |
318 | for (int i = 0; i < size; i++) |
319 | { |
320 | // Store in temp variables in case src = dst |
321 | float x = (e[0]*src[i].x) + (e[4]*src[i].y) + (0) + (e[12]); |
322 | float y = (e[1]*src[i].x) + (e[5]*src[i].y) + (0) + (e[13]); |
323 | |
324 | dst[i].x = x; |
325 | dst[i].y = y; |
326 | } |
327 | } |
328 | |
329 | template <typename Vdst, typename Vsrc> |
330 | void Matrix4::transformXY0(Vdst *dst, const Vsrc *src, int size) const |
331 | { |
332 | for (int i = 0; i < size; i++) |
333 | { |
334 | // Store in temp variables in case src = dst |
335 | float x = (e[0]*src[i].x) + (e[4]*src[i].y) + (0) + (e[12]); |
336 | float y = (e[1]*src[i].x) + (e[5]*src[i].y) + (0) + (e[13]); |
337 | float z = (e[2]*src[i].x) + (e[6]*src[i].y) + (0) + (e[14]); |
338 | |
339 | dst[i].x = x; |
340 | dst[i].y = y; |
341 | dst[i].z = z; |
342 | } |
343 | } |
344 | |
345 | // | x | |
346 | // | y | |
347 | // | z | |
348 | // | 1 | |
349 | // | e0 e4 e8 e12 | |
350 | // | e1 e5 e9 e13 | |
351 | // | e2 e6 e10 e14 | |
352 | // | e3 e7 e11 e15 | |
353 | |
354 | template <typename Vdst, typename Vsrc> |
355 | void Matrix4::transformXYZ(Vdst *dst, const Vsrc *src, int size) const |
356 | { |
357 | for (int i = 0; i < size; i++) |
358 | { |
359 | // Store in temp variables in case src = dst |
360 | float x = (e[0]*src[i].x) + (e[4]*src[i].y) + (e[ 8]*src[i].z) + (e[12]); |
361 | float y = (e[1]*src[i].x) + (e[5]*src[i].y) + (e[ 9]*src[i].z) + (e[13]); |
362 | float z = (e[2]*src[i].x) + (e[6]*src[i].y) + (e[10]*src[i].z) + (e[14]); |
363 | |
364 | dst[i].x = x; |
365 | dst[i].y = y; |
366 | dst[i].z = z; |
367 | } |
368 | } |
369 | |
370 | // | x | |
371 | // | y | |
372 | // | 1 | |
373 | // | e0 e3 e6 | |
374 | // | e1 e4 e7 | |
375 | // | e2 e5 e8 | |
376 | template <typename Vdst, typename Vsrc> |
377 | void Matrix3::transformXY(Vdst *dst, const Vsrc *src, int size) const |
378 | { |
379 | for (int i = 0; i < size; i++) |
380 | { |
381 | float x = (e[0]*src[i].x) + (e[3]*src[i].y) + (e[6]); |
382 | float y = (e[1]*src[i].x) + (e[4]*src[i].y) + (e[7]); |
383 | |
384 | dst[i].x = x; |
385 | dst[i].y = y; |
386 | } |
387 | } |
388 | |
389 | } //love |
390 | |
391 | #endif// LOVE_MATRIX_H |
392 | |