1 /* EINA - Drawing Library
2 * Copyright (C) 2007-2014 Jorge Luis Zapata
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library.
16 * If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 #ifdef HAVE_CONFIG_H
20 # include "config.h"
21 #endif
22
23 #include "eina_private.h"
24
25 #include <math.h>
26 #include <float.h>
27 #include <string.h>
28
29 #include "eina_fp.h"
30 #include "eina_rectangle.h"
31 #include "eina_quad.h"
32 #include "eina_matrix.h"
33 #include "eina_util.h"
34
35 #define MATRIX_XX(m) (m)->xx
36 #define MATRIX_XY(m) (m)->xy
37 #define MATRIX_XZ(m) (m)->xz
38 #define MATRIX_XW(m) (m)->xw
39 #define MATRIX_YX(m) (m)->yx
40 #define MATRIX_YY(m) (m)->yy
41 #define MATRIX_YZ(m) (m)->yz
42 #define MATRIX_YW(m) (m)->yw
43 #define MATRIX_ZX(m) (m)->zx
44 #define MATRIX_ZY(m) (m)->zy
45 #define MATRIX_ZZ(m) (m)->zz
46 #define MATRIX_ZW(m) (m)->zw
47 #define MATRIX_WX(m) (m)->wx
48 #define MATRIX_WY(m) (m)->wy
49 #define MATRIX_WZ(m) (m)->wz
50 #define MATRIX_WW(m) (m)->ww
51 #define MATRIX_SIZE 9
52
53 #define QUAD_X0(q) q->x0
54 #define QUAD_Y0(q) q->y0
55 #define QUAD_X1(q) q->x1
56 #define QUAD_Y1(q) q->y1
57 #define QUAD_X2(q) q->x2
58 #define QUAD_Y2(q) q->y2
59 #define QUAD_X3(q) q->x3
60 #define QUAD_Y3(q) q->y3
61
62 /*============================================================================*
63 * Local *
64 *============================================================================*/
65
66 /*============================================================================*
67 * API *
68 *============================================================================*/
69 EAPI Eina_Matrix_Type
eina_matrix3_type_get(const Eina_Matrix3 * m)70 eina_matrix3_type_get(const Eina_Matrix3 *m)
71 {
72 if (!EINA_DBL_EQ(MATRIX_ZX(m), 0.0) ||
73 !EINA_DBL_EQ(MATRIX_ZY(m), 0.0) ||
74 !EINA_DBL_EQ(MATRIX_ZZ(m), 1.0))
75 return EINA_MATRIX_TYPE_PROJECTIVE;
76 else
77 {
78 if (EINA_DBL_EQ(MATRIX_XX(m), 1.0) &&
79 EINA_DBL_EQ(MATRIX_XY(m), 0.0) &&
80 EINA_DBL_EQ(MATRIX_XZ(m), 0.0) &&
81 EINA_DBL_EQ(MATRIX_YX(m), 0.0) &&
82 EINA_DBL_EQ(MATRIX_YY(m), 1.0) &&
83 EINA_DBL_EQ(MATRIX_YZ(m), 0.0))
84 return EINA_MATRIX_TYPE_IDENTITY;
85 else
86 return EINA_MATRIX_TYPE_AFFINE;
87 }
88 }
89
90 EAPI Eina_Matrix_Type
eina_matrix4_type_get(const Eina_Matrix4 * m)91 eina_matrix4_type_get(const Eina_Matrix4 *m)
92 {
93 if (EINA_DBL_EQ(MATRIX_XX(m), 1.0) &&
94 EINA_DBL_EQ(MATRIX_XY(m), 0.0) &&
95 EINA_DBL_EQ(MATRIX_XZ(m), 0.0) &&
96 EINA_DBL_EQ(MATRIX_XW(m), 0.0) &&
97 EINA_DBL_EQ(MATRIX_YX(m), 0.0) &&
98 EINA_DBL_EQ(MATRIX_YY(m), 1.0) &&
99 EINA_DBL_EQ(MATRIX_YZ(m), 0.0) &&
100 EINA_DBL_EQ(MATRIX_YW(m), 0.0) &&
101 EINA_DBL_EQ(MATRIX_ZX(m), 0.0) &&
102 EINA_DBL_EQ(MATRIX_ZY(m), 0.0) &&
103 EINA_DBL_EQ(MATRIX_ZZ(m), 1.0) &&
104 EINA_DBL_EQ(MATRIX_ZW(m), 0.0) &&
105 EINA_DBL_EQ(MATRIX_WX(m), 0.0) &&
106 EINA_DBL_EQ(MATRIX_WY(m), 0.0) &&
107 EINA_DBL_EQ(MATRIX_WZ(m), 0.0) &&
108 EINA_DBL_EQ(MATRIX_WW(m), 1.0))
109 return EINA_MATRIX_TYPE_IDENTITY;
110 return EINA_MATRIX_TYPE_AFFINE;
111 }
112
113 EAPI Eina_Matrix_Type
eina_matrix3_f16p16_type_get(const Eina_Matrix3_F16p16 * m)114 eina_matrix3_f16p16_type_get(const Eina_Matrix3_F16p16 *m)
115 {
116 if ((MATRIX_ZX(m) != 0) || (MATRIX_ZY(m) != 0) || (MATRIX_ZZ(m) != 65536))
117 return EINA_MATRIX_TYPE_PROJECTIVE;
118 else
119 {
120 if ((MATRIX_XX(m) == 65536) && (MATRIX_XY(m) == 0) && (MATRIX_XZ(m) == 0) &&
121 (MATRIX_YX(m) == 0) && (MATRIX_YY(m) == 65536) && (MATRIX_YZ(m) == 0))
122 return EINA_MATRIX_TYPE_IDENTITY;
123 else
124 return EINA_MATRIX_TYPE_AFFINE;
125 }
126 }
127
128 EAPI void
eina_matrix3_values_set(Eina_Matrix3 * m,double xx,double xy,double xz,double yx,double yy,double yz,double zx,double zy,double zz)129 eina_matrix3_values_set(Eina_Matrix3 *m,
130 double xx, double xy, double xz,
131 double yx, double yy, double yz,
132 double zx, double zy, double zz)
133 {
134 MATRIX_XX(m) = xx;
135 MATRIX_XY(m) = xy;
136 MATRIX_XZ(m) = xz;
137 MATRIX_YX(m) = yx;
138 MATRIX_YY(m) = yy;
139 MATRIX_YZ(m) = yz;
140 MATRIX_ZX(m) = zx;
141 MATRIX_ZY(m) = zy;
142 MATRIX_ZZ(m) = zz;
143 }
144
145 EAPI void
eina_matrix3_values_get(const Eina_Matrix3 * m,double * xx,double * xy,double * xz,double * yx,double * yy,double * yz,double * zx,double * zy,double * zz)146 eina_matrix3_values_get(const Eina_Matrix3 *m,
147 double *xx, double *xy, double *xz,
148 double *yx, double *yy, double *yz,
149 double *zx, double *zy, double *zz)
150 {
151 if (xx) *xx = MATRIX_XX(m);
152 if (xy) *xy = MATRIX_XY(m);
153 if (xz) *xz = MATRIX_XZ(m);
154 if (yx) *yx = MATRIX_YX(m);
155 if (yy) *yy = MATRIX_YY(m);
156 if (yz) *yz = MATRIX_YZ(m);
157 if (zx) *zx = MATRIX_ZX(m);
158 if (zy) *zy = MATRIX_ZY(m);
159 if (zz) *zz = MATRIX_ZZ(m);
160 }
161
162 EAPI void
eina_matrix4_values_set(Eina_Matrix4 * m,double xx,double xy,double xz,double xw,double yx,double yy,double yz,double yw,double zx,double zy,double zz,double zw,double wx,double wy,double wz,double ww)163 eina_matrix4_values_set(Eina_Matrix4 *m,
164 double xx, double xy, double xz, double xw,
165 double yx, double yy, double yz, double yw,
166 double zx, double zy, double zz, double zw,
167 double wx, double wy, double wz, double ww)
168 {
169 MATRIX_XX(m) = xx;
170 MATRIX_XY(m) = xy;
171 MATRIX_XZ(m) = xz;
172 MATRIX_XW(m) = xw;
173 MATRIX_YX(m) = yx;
174 MATRIX_YY(m) = yy;
175 MATRIX_YZ(m) = yz;
176 MATRIX_YW(m) = yw;
177 MATRIX_ZX(m) = zx;
178 MATRIX_ZY(m) = zy;
179 MATRIX_ZZ(m) = zz;
180 MATRIX_ZW(m) = zw;
181 MATRIX_WX(m) = wx;
182 MATRIX_WY(m) = wy;
183 MATRIX_WZ(m) = wz;
184 MATRIX_WW(m) = ww;
185 }
186
187 EAPI void
eina_matrix4_values_get(const Eina_Matrix4 * m,double * xx,double * xy,double * xz,double * xw,double * yx,double * yy,double * yz,double * yw,double * zx,double * zy,double * zz,double * zw,double * wx,double * wy,double * wz,double * ww)188 eina_matrix4_values_get(const Eina_Matrix4 *m,
189 double *xx, double *xy, double *xz, double *xw,
190 double *yx, double *yy, double *yz, double *yw,
191 double *zx, double *zy, double *zz, double *zw,
192 double *wx, double *wy, double *wz, double *ww)
193 {
194 if (xx) *xx = MATRIX_XX(m);
195 if (xy) *xy = MATRIX_XY(m);
196 if (xz) *xz = MATRIX_XZ(m);
197 if (xw) *xw = MATRIX_XW(m);
198 if (yx) *yx = MATRIX_YX(m);
199 if (yy) *yy = MATRIX_YY(m);
200 if (yz) *yz = MATRIX_YZ(m);
201 if (yw) *yw = MATRIX_YW(m);
202 if (zx) *zx = MATRIX_ZX(m);
203 if (zy) *zy = MATRIX_ZY(m);
204 if (zz) *zz = MATRIX_ZZ(m);
205 if (zw) *zw = MATRIX_ZW(m);
206 if (wx) *wx = MATRIX_WX(m);
207 if (wy) *wy = MATRIX_WY(m);
208 if (wz) *wz = MATRIX_WZ(m);
209 if (ww) *ww = MATRIX_WW(m);
210 }
211
212 EAPI void
eina_matrix3_fixed_values_get(const Eina_Matrix3 * m,Eina_F16p16 * xx,Eina_F16p16 * xy,Eina_F16p16 * xz,Eina_F16p16 * yx,Eina_F16p16 * yy,Eina_F16p16 * yz,Eina_F16p16 * zx,Eina_F16p16 * zy,Eina_F16p16 * zz)213 eina_matrix3_fixed_values_get(const Eina_Matrix3 *m,
214 Eina_F16p16 *xx, Eina_F16p16 *xy, Eina_F16p16 *xz,
215 Eina_F16p16 *yx, Eina_F16p16 *yy, Eina_F16p16 *yz,
216 Eina_F16p16 *zx, Eina_F16p16 *zy, Eina_F16p16 *zz)
217 {
218 if (xx) *xx = eina_f16p16_double_from(MATRIX_XX(m));
219 if (xy) *xy = eina_f16p16_double_from(MATRIX_XY(m));
220 if (xz) *xz = eina_f16p16_double_from(MATRIX_XZ(m));
221 if (yx) *yx = eina_f16p16_double_from(MATRIX_YX(m));
222 if (yy) *yy = eina_f16p16_double_from(MATRIX_YY(m));
223 if (yz) *yz = eina_f16p16_double_from(MATRIX_YZ(m));
224 if (zx) *zx = eina_f16p16_double_from(MATRIX_ZX(m));
225 if (zy) *zy = eina_f16p16_double_from(MATRIX_ZY(m));
226 if (zz) *zz = eina_f16p16_double_from(MATRIX_ZZ(m));
227 }
228
229 EAPI void
eina_matrix3_matrix3_f16p16_to(const Eina_Matrix3 * m,Eina_Matrix3_F16p16 * fm)230 eina_matrix3_matrix3_f16p16_to(const Eina_Matrix3 *m,
231 Eina_Matrix3_F16p16 *fm)
232 {
233 eina_matrix3_fixed_values_get(m,
234 &fm->xx, &fm->xy, &fm->xz,
235 &fm->yx, &fm->yy, &fm->yz,
236 &fm->zx, &fm->zy, &fm->zz);
237 }
238
239 EAPI void
eina_matrix3_point_transform(const Eina_Matrix3 * m,double x,double y,double * xr,double * yr)240 eina_matrix3_point_transform(const Eina_Matrix3 *m,
241 double x, double y,
242 double *xr, double *yr)
243 {
244 double xrr, yrr;
245
246 if (!EINA_DBL_EQ(MATRIX_ZX(m), 0.0) &&
247 !EINA_DBL_EQ(MATRIX_ZY(m), 0.0))
248 {
249 xrr = (x * MATRIX_XX(m) + y * MATRIX_XY(m) + MATRIX_XZ(m));
250 yrr = (x * MATRIX_YX(m) + y * MATRIX_YY(m) + MATRIX_YZ(m));
251 }
252 else
253 {
254 xrr = (x * MATRIX_XX(m) + y * MATRIX_XY(m) + MATRIX_XZ(m)) /
255 (x * MATRIX_ZX(m) + y * MATRIX_ZY(m) + MATRIX_ZZ(m));
256 yrr = (x * MATRIX_YX(m) + y * MATRIX_YY(m) + MATRIX_YZ(m)) /
257 (x * MATRIX_ZX(m) + y * MATRIX_ZY(m) + MATRIX_ZZ(m));
258 }
259
260 if (xr) *xr = xrr;
261 if (yr) *yr = yrr;
262 }
263
264 EAPI void
eina_matrix3_rectangle_transform(const Eina_Matrix3 * m,const Eina_Rectangle * r,const Eina_Quad * q)265 eina_matrix3_rectangle_transform(const Eina_Matrix3 *m,
266 const Eina_Rectangle *r,
267 const Eina_Quad *q)
268 {
269 eina_matrix3_point_transform(m, r->x, r->y, &((Eina_Quad *)q)->x0, &((Eina_Quad *)q)->y0);
270 eina_matrix3_point_transform(m, r->x + r->w, r->y, &((Eina_Quad *)q)->x1, &((Eina_Quad *)q)->y1);
271 eina_matrix3_point_transform(m, r->x + r->w, r->y + r->h, &((Eina_Quad *)q)->x2, &((Eina_Quad *)q)->y2);
272 eina_matrix3_point_transform(m, r->x, r->y + r->h, &((Eina_Quad *)q)->x3, &((Eina_Quad *)q)->y3);
273 }
274
275 EAPI void
eina_matrix3_cofactor(const Eina_Matrix3 * m,Eina_Matrix3 * a)276 eina_matrix3_cofactor(const Eina_Matrix3 *m, Eina_Matrix3 *a)
277 {
278 double a11, a12, a13, a21, a22, a23, a31, a32, a33;
279
280 a11 = (MATRIX_YY(m) * MATRIX_ZZ(m)) - (MATRIX_YZ(m) * MATRIX_ZY(m));
281 a12 = -1 * ((MATRIX_YX(m) * MATRIX_ZZ(m)) - (MATRIX_YZ(m) * MATRIX_ZX(m)));
282 a13 = (MATRIX_YX(m) * MATRIX_ZY(m)) - (MATRIX_YY(m) * MATRIX_ZX(m));
283
284 a21 = -1 * ((MATRIX_XY(m) * MATRIX_ZZ(m)) - (MATRIX_XZ(m) * MATRIX_ZY(m)));
285 a22 = (MATRIX_XX(m) * MATRIX_ZZ(m)) - (MATRIX_XZ(m) * MATRIX_ZX(m));
286 a23 = -1 * ((MATRIX_XX(m) * MATRIX_ZY(m)) - (MATRIX_XY(m) * MATRIX_ZX(m)));
287
288 a31 = (MATRIX_XY(m) * MATRIX_YZ(m)) - (MATRIX_XZ(m) * MATRIX_YY(m));
289 a32 = -1 * ((MATRIX_XX(m) * MATRIX_YZ(m)) - (MATRIX_XZ(m) * MATRIX_YX(m)));
290 a33 = (MATRIX_XX(m) * MATRIX_YY(m)) - (MATRIX_XY(m) * MATRIX_YX(m));
291
292 MATRIX_XX(a) = a11;
293 MATRIX_XY(a) = a12;
294 MATRIX_XZ(a) = a13;
295
296 MATRIX_YX(a) = a21;
297 MATRIX_YY(a) = a22;
298 MATRIX_YZ(a) = a23;
299
300 MATRIX_ZX(a) = a31;
301 MATRIX_ZY(a) = a32;
302 MATRIX_ZZ(a) = a33;
303 }
304
305 EAPI void
eina_matrix3_transpose(const Eina_Matrix3 * m,Eina_Matrix3 * a)306 eina_matrix3_transpose(const Eina_Matrix3 *m, Eina_Matrix3 *a)
307 {
308 MATRIX_XX(a) = MATRIX_XX(m);
309 MATRIX_XY(a) = MATRIX_YX(m);
310 MATRIX_XZ(a) = MATRIX_ZX(m);
311
312 MATRIX_YX(a) = MATRIX_XY(m);
313 MATRIX_YY(a) = MATRIX_YY(m);
314 MATRIX_YZ(a) = MATRIX_ZY(m);
315
316 MATRIX_ZX(a) = MATRIX_XZ(m);
317 MATRIX_ZY(a) = MATRIX_YZ(m);
318 MATRIX_ZZ(a) = MATRIX_ZZ(m);
319 }
320
321 EAPI void
eina_matrix3_adjoint(const Eina_Matrix3 * m,Eina_Matrix3 * a)322 eina_matrix3_adjoint(const Eina_Matrix3 *m, Eina_Matrix3 *a)
323 {
324 Eina_Matrix3 cofactor;
325
326 /* cofactor */
327 eina_matrix3_cofactor(m, &cofactor);
328 /* transpose */
329 eina_matrix3_transpose(&cofactor, a);
330 }
331
332 EAPI double
eina_matrix3_determinant(const Eina_Matrix3 * m)333 eina_matrix3_determinant(const Eina_Matrix3 *m)
334 {
335 double det;
336
337 det = MATRIX_XX(m) * ((MATRIX_YY(m) * MATRIX_ZZ(m)) - (MATRIX_YZ(m) * MATRIX_ZY(m)));
338 det -= MATRIX_XY(m) * ((MATRIX_YX(m) * MATRIX_ZZ(m)) - (MATRIX_YZ(m) * MATRIX_ZX(m)));
339 det += MATRIX_XZ(m) * ((MATRIX_YX(m) * MATRIX_ZY(m)) - (MATRIX_YY(m) * MATRIX_ZX(m)));
340
341 return det;
342 }
343
344 EAPI void
eina_matrix3_divide(Eina_Matrix3 * m,double scalar)345 eina_matrix3_divide(Eina_Matrix3 *m, double scalar)
346 {
347 MATRIX_XX(m) /= scalar;
348 MATRIX_XY(m) /= scalar;
349 MATRIX_XZ(m) /= scalar;
350
351 MATRIX_YX(m) /= scalar;
352 MATRIX_YY(m) /= scalar;
353 MATRIX_YZ(m) /= scalar;
354
355 MATRIX_ZX(m) /= scalar;
356 MATRIX_ZY(m) /= scalar;
357 MATRIX_ZZ(m) /= scalar;
358 }
359
360 EAPI void
eina_matrix3_inverse(const Eina_Matrix3 * m,Eina_Matrix3 * m2)361 eina_matrix3_inverse(const Eina_Matrix3 *m, Eina_Matrix3 *m2)
362 {
363 double scalar;
364
365 /* determinant */
366 scalar = eina_matrix3_determinant(m);
367 if (EINA_DBL_EQ(scalar, 0.0))
368 {
369 eina_matrix3_identity(m2);
370 return;
371 }
372 /* do its adjoint */
373 eina_matrix3_adjoint(m, m2);
374 /* divide */
375 eina_matrix3_divide(m2, scalar);
376 }
377
378 EAPI void
eina_matrix3_compose(const Eina_Matrix3 * m1,const Eina_Matrix3 * m2,Eina_Matrix3 * dst)379 eina_matrix3_compose(const Eina_Matrix3 *m1,
380 const Eina_Matrix3 *m2,
381 Eina_Matrix3 *dst)
382 {
383 double a11, a12, a13, a21, a22, a23, a31, a32, a33;
384
385 a11 = (MATRIX_XX(m1) * MATRIX_XX(m2)) + (MATRIX_XY(m1) * MATRIX_YX(m2)) + (MATRIX_XZ(m1) * MATRIX_ZX(m2));
386 a12 = (MATRIX_XX(m1) * MATRIX_XY(m2)) + (MATRIX_XY(m1) * MATRIX_YY(m2)) + (MATRIX_XZ(m1) * MATRIX_ZY(m2));
387 a13 = (MATRIX_XX(m1) * MATRIX_XZ(m2)) + (MATRIX_XY(m1) * MATRIX_YZ(m2)) + (MATRIX_XZ(m1) * MATRIX_ZZ(m2));
388
389 a21 = (MATRIX_YX(m1) * MATRIX_XX(m2)) + (MATRIX_YY(m1) * MATRIX_YX(m2)) + (MATRIX_YZ(m1) * MATRIX_ZX(m2));
390 a22 = (MATRIX_YX(m1) * MATRIX_XY(m2)) + (MATRIX_YY(m1) * MATRIX_YY(m2)) + (MATRIX_YZ(m1) * MATRIX_ZY(m2));
391 a23 = (MATRIX_YX(m1) * MATRIX_XZ(m2)) + (MATRIX_YY(m1) * MATRIX_YZ(m2)) + (MATRIX_YZ(m1) * MATRIX_ZZ(m2));
392
393 a31 = (MATRIX_ZX(m1) * MATRIX_XX(m2)) + (MATRIX_ZY(m1) * MATRIX_YX(m2)) + (MATRIX_ZZ(m1) * MATRIX_ZX(m2));
394 a32 = (MATRIX_ZX(m1) * MATRIX_XY(m2)) + (MATRIX_ZY(m1) * MATRIX_YY(m2)) + (MATRIX_ZZ(m1) * MATRIX_ZY(m2));
395 a33 = (MATRIX_ZX(m1) * MATRIX_XZ(m2)) + (MATRIX_ZY(m1) * MATRIX_YZ(m2)) + (MATRIX_ZZ(m1) * MATRIX_ZZ(m2));
396
397 MATRIX_XX(dst) = a11;
398 MATRIX_XY(dst) = a12;
399 MATRIX_XZ(dst) = a13;
400 MATRIX_YX(dst) = a21;
401 MATRIX_YY(dst) = a22;
402 MATRIX_YZ(dst) = a23;
403 MATRIX_ZX(dst) = a31;
404 MATRIX_ZY(dst) = a32;
405 MATRIX_ZZ(dst) = a33;
406 }
407
408 EAPI Eina_Bool
eina_matrix3_equal(const Eina_Matrix3 * m1,const Eina_Matrix3 * m2)409 eina_matrix3_equal(const Eina_Matrix3 *m1, const Eina_Matrix3 *m2)
410 {
411 if (!EINA_DBL_EQ(m1->xx, m2->xx) ||
412 !EINA_DBL_EQ(m1->xy, m2->xy) ||
413 !EINA_DBL_EQ(m1->xz, m2->xz) ||
414 !EINA_DBL_EQ(m1->yx, m2->yx) ||
415 !EINA_DBL_EQ(m1->yy, m2->yy) ||
416 !EINA_DBL_EQ(m1->yz, m2->yz) ||
417 !EINA_DBL_EQ(m1->zx, m2->zx) ||
418 !EINA_DBL_EQ(m1->zy, m2->zy) ||
419 !EINA_DBL_EQ(m1->zz, m2->zz))
420 return EINA_FALSE;
421 return EINA_TRUE;
422 }
423
424 EAPI void
eina_matrix3_f16p16_compose(const Eina_Matrix3_F16p16 * m1,const Eina_Matrix3_F16p16 * m2,Eina_Matrix3_F16p16 * dst)425 eina_matrix3_f16p16_compose(const Eina_Matrix3_F16p16 *m1,
426 const Eina_Matrix3_F16p16 *m2,
427 Eina_Matrix3_F16p16 *dst)
428 {
429 Eina_F16p16 a11, a12, a13, a21, a22, a23, a31, a32, a33;
430
431 a11 = eina_f16p16_mul(MATRIX_XX(m1), MATRIX_XX(m2)) +
432 eina_f16p16_mul(MATRIX_XY(m1), MATRIX_YX(m2)) +
433 eina_f16p16_mul(MATRIX_XZ(m1), MATRIX_ZX(m2));
434 a12 = eina_f16p16_mul(MATRIX_XX(m1), MATRIX_XY(m2)) +
435 eina_f16p16_mul(MATRIX_XY(m1), MATRIX_YY(m2)) +
436 eina_f16p16_mul(MATRIX_XZ(m1), MATRIX_ZY(m2));
437 a13 = eina_f16p16_mul(MATRIX_XX(m1), MATRIX_XZ(m2)) +
438 eina_f16p16_mul(MATRIX_XY(m1), MATRIX_YZ(m2)) +
439 eina_f16p16_mul(MATRIX_XZ(m1), MATRIX_ZZ(m2));
440
441 a21 = eina_f16p16_mul(MATRIX_YX(m1), MATRIX_XX(m2)) +
442 eina_f16p16_mul(MATRIX_YY(m1), MATRIX_YX(m2)) +
443 eina_f16p16_mul(MATRIX_YZ(m1), MATRIX_ZX(m2));
444 a22 = eina_f16p16_mul(MATRIX_YX(m1), MATRIX_XY(m2)) +
445 eina_f16p16_mul(MATRIX_YY(m1), MATRIX_YY(m2)) +
446 eina_f16p16_mul(MATRIX_YZ(m1), MATRIX_ZY(m2));
447 a23 = eina_f16p16_mul(MATRIX_YX(m1), MATRIX_XZ(m2)) +
448 eina_f16p16_mul(MATRIX_YY(m1), MATRIX_YZ(m2)) +
449 eina_f16p16_mul(MATRIX_YZ(m1), MATRIX_ZZ(m2));
450
451 a31 = eina_f16p16_mul(MATRIX_ZX(m1), MATRIX_XX(m2)) +
452 eina_f16p16_mul(MATRIX_ZY(m1), MATRIX_YX(m2)) +
453 eina_f16p16_mul(MATRIX_ZZ(m1), MATRIX_ZX(m2));
454 a32 = eina_f16p16_mul(MATRIX_ZX(m1), MATRIX_XY(m2)) +
455 eina_f16p16_mul(MATRIX_ZY(m1), MATRIX_YY(m2)) +
456 eina_f16p16_mul(MATRIX_ZZ(m1), MATRIX_ZY(m2));
457 a33 = eina_f16p16_mul(MATRIX_ZX(m1), MATRIX_XZ(m2)) +
458 eina_f16p16_mul(MATRIX_ZY(m1), MATRIX_YZ(m2)) +
459 eina_f16p16_mul(MATRIX_ZZ(m1), MATRIX_ZZ(m2));
460
461 MATRIX_XX(dst) = a11;
462 MATRIX_XY(dst) = a12;
463 MATRIX_XZ(dst) = a13;
464 MATRIX_YX(dst) = a21;
465 MATRIX_YY(dst) = a22;
466 MATRIX_YZ(dst) = a23;
467 MATRIX_ZX(dst) = a31;
468 MATRIX_ZY(dst) = a32;
469 MATRIX_ZZ(dst) = a33;
470 }
471
472 EAPI void
eina_matrix3_translate(Eina_Matrix3 * m,double tx,double ty)473 eina_matrix3_translate(Eina_Matrix3 *m, double tx, double ty)
474 {
475 Eina_Matrix3 tmp;
476 MATRIX_XX(&tmp) = 1;
477 MATRIX_XY(&tmp) = 0;
478 MATRIX_XZ(&tmp) = tx;
479 MATRIX_YX(&tmp) = 0;
480 MATRIX_YY(&tmp) = 1;
481 MATRIX_YZ(&tmp) = ty;
482 MATRIX_ZX(&tmp) = 0;
483 MATRIX_ZY(&tmp) = 0;
484 MATRIX_ZZ(&tmp) = 1;
485 eina_matrix3_compose(m, &tmp, m);
486 }
487
488 EAPI void
eina_matrix3_scale(Eina_Matrix3 * m,double sx,double sy)489 eina_matrix3_scale(Eina_Matrix3 *m, double sx, double sy)
490 {
491 Eina_Matrix3 tmp;
492 MATRIX_XX(&tmp) = sx;
493 MATRIX_XY(&tmp) = 0;
494 MATRIX_XZ(&tmp) = 0;
495 MATRIX_YX(&tmp) = 0;
496 MATRIX_YY(&tmp) = sy;
497 MATRIX_YZ(&tmp) = 0;
498 MATRIX_ZX(&tmp) = 0;
499 MATRIX_ZY(&tmp) = 0;
500 MATRIX_ZZ(&tmp) = 1;
501 eina_matrix3_compose(m, &tmp, m);
502 }
503
504 EAPI void
eina_matrix3_rotate(Eina_Matrix3 * m,double rad)505 eina_matrix3_rotate(Eina_Matrix3 *m, double rad)
506 {
507 double c, s;
508
509 /* Note: Local functions do not guarantee accuracy.
510 * Errors occur in the calculation of very small or very large numbers.
511 * Local cos and sin functions differ from the math header cosf and sinf functions
512 * by result values. The 4th decimal place is different.
513 * But local functions are certainly faster than functions in math library.
514 * Later we would want someone to look at this and improve accuracy.
515 */
516 #if 1
517 c = cos(rad);
518 s = sin(rad);
519 #else
520 /* normalize the angle between -pi,pi */
521 rad = fmod(rad + M_PI, 2 * M_PI) - M_PI;
522 c = _cos(rad);
523 s = _sin(rad);
524 #endif
525
526 Eina_Matrix3 tmp;
527 MATRIX_XX(&tmp) = c;
528 MATRIX_XY(&tmp) = -s;
529 MATRIX_XZ(&tmp) = 0;
530 MATRIX_YX(&tmp) = s;
531 MATRIX_YY(&tmp) = c;
532 MATRIX_YZ(&tmp) = 0;
533 MATRIX_ZX(&tmp) = 0;
534 MATRIX_ZY(&tmp) = 0;
535 MATRIX_ZZ(&tmp) = 1;
536 eina_matrix3_compose(m, &tmp, m);
537 }
538
539 EAPI void
eina_matrix3_identity(Eina_Matrix3 * m)540 eina_matrix3_identity(Eina_Matrix3 *m)
541 {
542 MATRIX_XX(m) = 1;
543 MATRIX_XY(m) = 0;
544 MATRIX_XZ(m) = 0;
545 MATRIX_YX(m) = 0;
546 MATRIX_YY(m) = 1;
547 MATRIX_YZ(m) = 0;
548 MATRIX_ZX(m) = 0;
549 MATRIX_ZY(m) = 0;
550 MATRIX_ZZ(m) = 1;
551 }
552
553 EAPI void
eina_matrix3_f16p16_identity(Eina_Matrix3_F16p16 * m)554 eina_matrix3_f16p16_identity(Eina_Matrix3_F16p16 *m)
555 {
556 MATRIX_XX(m) = 65536;
557 MATRIX_XY(m) = 0;
558 MATRIX_XZ(m) = 0;
559 MATRIX_YX(m) = 0;
560 MATRIX_YY(m) = 65536;
561 MATRIX_YZ(m) = 0;
562 MATRIX_ZX(m) = 0;
563 MATRIX_ZY(m) = 0;
564 MATRIX_ZZ(m) = 65536;
565 }
566
567 EAPI Eina_Bool
eina_matrix3_square_quad_map(Eina_Matrix3 * m,const Eina_Quad * q)568 eina_matrix3_square_quad_map(Eina_Matrix3 *m, const Eina_Quad *q)
569 {
570 // x0 - x1 + x2 - x3
571 double ex = QUAD_X0(q) - QUAD_X1(q) + QUAD_X2(q) - QUAD_X3(q);
572 // y0 - y1 + y2 - y3
573 double ey = QUAD_Y0(q) - QUAD_Y1(q) + QUAD_Y2(q) - QUAD_Y3(q);
574
575 /* parallelogram */
576 if (EINA_DBL_EQ(ex, 0.0) && EINA_DBL_EQ(ey, 0.0))
577 {
578 /* create the affine matrix */
579 MATRIX_XX(m) = QUAD_X1(q) - QUAD_X0(q);
580 MATRIX_XY(m) = QUAD_X2(q) - QUAD_X1(q);
581 MATRIX_XZ(m) = QUAD_X0(q);
582
583 MATRIX_YX(m) = QUAD_Y1(q) - QUAD_Y0(q);
584 MATRIX_YY(m) = QUAD_Y2(q) - QUAD_Y1(q);
585 MATRIX_YZ(m) = QUAD_Y0(q);
586
587 MATRIX_ZX(m) = 0;
588 MATRIX_ZY(m) = 0;
589 MATRIX_ZZ(m) = 1;
590
591 return EINA_TRUE;
592 }
593 else
594 {
595 double dx1 = QUAD_X1(q) - QUAD_X2(q); // x1 - x2
596 double dx2 = QUAD_X3(q) - QUAD_X2(q); // x3 - x2
597 double dy1 = QUAD_Y1(q) - QUAD_Y2(q); // y1 - y2
598 double dy2 = QUAD_Y3(q) - QUAD_Y2(q); // y3 - y2
599 double den = (dx1 * dy2) - (dx2 * dy1);
600
601 if (EINA_DBL_EQ(den, 0.0))
602 return EINA_FALSE;
603
604 MATRIX_ZX(m) = ((ex * dy2) - (dx2 * ey)) / den;
605 MATRIX_ZY(m) = ((dx1 * ey) - (ex * dy1)) / den;
606 MATRIX_ZZ(m) = 1;
607 MATRIX_XX(m) = QUAD_X1(q) - QUAD_X0(q) + (MATRIX_ZX(m) * QUAD_X1(q));
608 MATRIX_XY(m) = QUAD_X3(q) - QUAD_X0(q) + (MATRIX_ZY(m) * QUAD_X3(q));
609 MATRIX_XZ(m) = QUAD_X0(q);
610 MATRIX_YX(m) = QUAD_Y1(q) - QUAD_Y0(q) + (MATRIX_ZX(m) * QUAD_Y1(q));
611 MATRIX_YY(m) = QUAD_Y3(q) - QUAD_Y0(q) + (MATRIX_ZY(m) * QUAD_Y3(q));
612 MATRIX_YZ(m) = QUAD_Y0(q);
613
614 return EINA_TRUE;
615 }
616 }
617
618 EAPI Eina_Bool
eina_matrix3_quad_square_map(Eina_Matrix3 * m,const Eina_Quad * q)619 eina_matrix3_quad_square_map(Eina_Matrix3 *m,
620 const Eina_Quad *q)
621 {
622 Eina_Matrix3 tmp;
623
624 /* compute square to quad */
625 if (!eina_matrix3_square_quad_map(&tmp, q))
626 return EINA_FALSE;
627
628 eina_matrix3_inverse(&tmp, m);
629 /* make the projective matrix3 always have 1 on zz */
630 if (!EINA_DBL_EQ(MATRIX_ZZ(m), 1.0))
631 {
632 eina_matrix3_divide(m, MATRIX_ZZ(m));
633 }
634
635 return EINA_TRUE;
636 }
637
638 EAPI Eina_Bool
eina_matrix3_quad_quad_map(Eina_Matrix3 * m,const Eina_Quad * src,const Eina_Quad * dst)639 eina_matrix3_quad_quad_map(Eina_Matrix3 *m,
640 const Eina_Quad *src,
641 const Eina_Quad *dst)
642 {
643 Eina_Matrix3 tmp;
644
645 /* TODO check that both are actually quadrangles */
646 if (!eina_matrix3_quad_square_map(m, src))
647 return EINA_FALSE;
648 if (!eina_matrix3_square_quad_map(&tmp, dst))
649 return EINA_FALSE;
650 eina_matrix3_compose(&tmp, m, m);
651
652 return EINA_TRUE;
653 }
654
655 EAPI void
eina_matrix4_matrix3_to(Eina_Matrix3 * m3,const Eina_Matrix4 * m4)656 eina_matrix4_matrix3_to(Eina_Matrix3 *m3, const Eina_Matrix4 *m4)
657 {
658 MATRIX_XX(m3) = MATRIX_XX(m4);
659 MATRIX_XY(m3) = MATRIX_XY(m4);
660 MATRIX_XZ(m3) = MATRIX_XW(m4);
661 MATRIX_YX(m3) = MATRIX_YX(m4);
662 MATRIX_YY(m3) = MATRIX_YY(m4);
663 MATRIX_YZ(m3) = MATRIX_YW(m4);
664 MATRIX_ZX(m3) = MATRIX_WX(m4);
665 MATRIX_ZY(m3) = MATRIX_WY(m4);
666 MATRIX_ZZ(m3) = MATRIX_WW(m4);
667 }
668
669 EAPI void
eina_matrix3_matrix4_to(Eina_Matrix4 * m4,const Eina_Matrix3 * m3)670 eina_matrix3_matrix4_to(Eina_Matrix4 *m4, const Eina_Matrix3 *m3)
671 {
672 MATRIX_XX(m4) = MATRIX_XX(m3);
673 MATRIX_XY(m4) = MATRIX_XY(m3);
674 MATRIX_XZ(m4) = 0;
675 MATRIX_XW(m4) = MATRIX_XZ(m3);
676 MATRIX_YX(m4) = MATRIX_YX(m3);
677 MATRIX_YY(m4) = MATRIX_YY(m3);
678 MATRIX_YZ(m4) = 0;
679 MATRIX_YW(m4) = MATRIX_YZ(m3);
680 MATRIX_ZX(m4) = 0;
681 MATRIX_ZY(m4) = 0;
682 MATRIX_ZZ(m4) = 1;
683 MATRIX_ZW(m4) = 0;
684 MATRIX_WX(m4) = MATRIX_ZX(m3);
685 MATRIX_WY(m4) = MATRIX_ZY(m3);
686 MATRIX_WZ(m4) = 0;
687 MATRIX_WW(m4) = MATRIX_ZZ(m3);
688 }
689
690 EAPI double
eina_matrix4_determinant(const Eina_Matrix4 * m)691 eina_matrix4_determinant(const Eina_Matrix4 *m)
692 {
693 return
694 MATRIX_XW(m) * MATRIX_YZ(m) * MATRIX_ZY(m) * MATRIX_WX(m)
695 - MATRIX_XZ(m) * MATRIX_YW(m) * MATRIX_ZY(m) * MATRIX_WX(m)
696 - MATRIX_XW(m) * MATRIX_YY(m) * MATRIX_ZZ(m) * MATRIX_WX(m)
697 + MATRIX_XY(m) * MATRIX_YW(m) * MATRIX_ZZ(m) * MATRIX_WX(m)
698 + MATRIX_XZ(m) * MATRIX_YY(m) * MATRIX_ZW(m) * MATRIX_WX(m)
699 - MATRIX_XY(m) * MATRIX_YZ(m) * MATRIX_ZW(m) * MATRIX_WX(m)
700 - MATRIX_XW(m) * MATRIX_YZ(m) * MATRIX_ZX(m) * MATRIX_WY(m)
701 + MATRIX_XZ(m) * MATRIX_YW(m) * MATRIX_ZX(m) * MATRIX_WY(m)
702 + MATRIX_XW(m) * MATRIX_YX(m) * MATRIX_ZZ(m) * MATRIX_WY(m)
703 - MATRIX_XX(m) * MATRIX_YW(m) * MATRIX_ZZ(m) * MATRIX_WY(m)
704 - MATRIX_XZ(m) * MATRIX_YX(m) * MATRIX_ZW(m) * MATRIX_WY(m)
705 + MATRIX_XX(m) * MATRIX_YZ(m) * MATRIX_ZW(m) * MATRIX_WY(m)
706 + MATRIX_XW(m) * MATRIX_YY(m) * MATRIX_ZX(m) * MATRIX_WZ(m)
707 - MATRIX_XY(m) * MATRIX_YW(m) * MATRIX_ZX(m) * MATRIX_WZ(m)
708 - MATRIX_XW(m) * MATRIX_YX(m) * MATRIX_ZY(m) * MATRIX_WZ(m)
709 + MATRIX_XX(m) * MATRIX_YW(m) * MATRIX_ZY(m) * MATRIX_WZ(m)
710 + MATRIX_XY(m) * MATRIX_YX(m) * MATRIX_ZW(m) * MATRIX_WZ(m)
711 - MATRIX_XX(m) * MATRIX_YY(m) * MATRIX_ZW(m) * MATRIX_WZ(m)
712 - MATRIX_XZ(m) * MATRIX_YY(m) * MATRIX_ZX(m) * MATRIX_WW(m)
713 + MATRIX_XY(m) * MATRIX_YZ(m) * MATRIX_ZX(m) * MATRIX_WW(m)
714 + MATRIX_XZ(m) * MATRIX_YX(m) * MATRIX_ZY(m) * MATRIX_WW(m)
715 - MATRIX_XX(m) * MATRIX_YZ(m) * MATRIX_ZY(m) * MATRIX_WW(m)
716 - MATRIX_XY(m) * MATRIX_YX(m) * MATRIX_ZZ(m) * MATRIX_WW(m)
717 + MATRIX_XX(m) * MATRIX_YY(m) * MATRIX_ZZ(m) * MATRIX_WW(m);
718 }
719
720 EAPI Eina_Bool
eina_matrix4_normalized(Eina_Matrix4 * out,const Eina_Matrix4 * in)721 eina_matrix4_normalized(Eina_Matrix4 *out, const Eina_Matrix4 *in)
722 {
723 double det;
724
725 det = eina_matrix4_determinant(in);
726 if (fabs(det) < DBL_EPSILON) return EINA_FALSE;
727
728 MATRIX_XX(out) = MATRIX_XX(in) / det;
729 MATRIX_XY(out) = MATRIX_XY(in) / det;
730 MATRIX_XZ(out) = MATRIX_XZ(in) / det;
731 MATRIX_XW(out) = MATRIX_XW(in) / det;
732 MATRIX_YX(out) = MATRIX_YX(in) / det;
733 MATRIX_YY(out) = MATRIX_YY(in) / det;
734 MATRIX_YZ(out) = MATRIX_YZ(in) / det;
735 MATRIX_YW(out) = MATRIX_YW(in) / det;
736 MATRIX_ZX(out) = MATRIX_ZX(in) / det;
737 MATRIX_ZY(out) = MATRIX_ZY(in) / det;
738 MATRIX_ZZ(out) = MATRIX_ZZ(in) / det;
739 MATRIX_ZW(out) = MATRIX_ZW(in) / det;
740 MATRIX_WX(out) = MATRIX_WX(in) / det;
741 MATRIX_WY(out) = MATRIX_WY(in) / det;
742 MATRIX_WZ(out) = MATRIX_WZ(in) / det;
743 MATRIX_WW(out) = MATRIX_WW(in) / det;
744
745 return EINA_TRUE;
746 }
747
748 EAPI Eina_Bool
eina_matrix4_inverse(Eina_Matrix4 * out,const Eina_Matrix4 * in)749 eina_matrix4_inverse(Eina_Matrix4 *out, const Eina_Matrix4 *in)
750 {
751 double det;
752
753 MATRIX_XX(out) =
754 MATRIX_YY(in) * MATRIX_ZZ(in) * MATRIX_WW(in)
755 - MATRIX_YY(in) * MATRIX_ZW(in) * MATRIX_WZ(in)
756 - MATRIX_ZY(in) * MATRIX_YZ(in) * MATRIX_WW(in)
757 + MATRIX_ZY(in) * MATRIX_YW(in) * MATRIX_WZ(in)
758 + MATRIX_WY(in) * MATRIX_YZ(in) * MATRIX_ZW(in)
759 - MATRIX_WY(in) * MATRIX_YW(in) * MATRIX_ZZ(in);
760
761 MATRIX_YX(out) =
762 - MATRIX_YX(in) * MATRIX_ZZ(in) * MATRIX_WW(in)
763 + MATRIX_YX(in) * MATRIX_ZW(in) * MATRIX_WZ(in)
764 + MATRIX_ZX(in) * MATRIX_YZ(in) * MATRIX_WW(in)
765 - MATRIX_ZX(in) * MATRIX_YW(in) * MATRIX_WZ(in)
766 - MATRIX_WX(in) * MATRIX_YZ(in) * MATRIX_ZW(in)
767 + MATRIX_WX(in) * MATRIX_YW(in) * MATRIX_ZZ(in);
768
769 MATRIX_ZX(out) =
770 MATRIX_YX(in) * MATRIX_ZY(in) * MATRIX_WW(in)
771 - MATRIX_YX(in) * MATRIX_ZW(in) * MATRIX_WY(in)
772 - MATRIX_ZX(in) * MATRIX_YY(in) * MATRIX_WW(in)
773 + MATRIX_ZX(in) * MATRIX_YW(in) * MATRIX_WY(in)
774 + MATRIX_WX(in) * MATRIX_YY(in) * MATRIX_ZW(in)
775 - MATRIX_WX(in) * MATRIX_YW(in) * MATRIX_ZY(in);
776
777 MATRIX_WX(out) =
778 - MATRIX_YX(in) * MATRIX_ZY(in) * MATRIX_WZ(in)
779 + MATRIX_YX(in) * MATRIX_ZZ(in) * MATRIX_WY(in)
780 + MATRIX_ZX(in) * MATRIX_YY(in) * MATRIX_WZ(in)
781 - MATRIX_ZX(in) * MATRIX_YZ(in) * MATRIX_WY(in)
782 - MATRIX_WX(in) * MATRIX_YY(in) * MATRIX_ZZ(in)
783 + MATRIX_WX(in) * MATRIX_YZ(in) * MATRIX_ZY(in);
784
785 MATRIX_XY(out) =
786 - MATRIX_XY(in) * MATRIX_ZZ(in) * MATRIX_WW(in)
787 + MATRIX_XY(in) * MATRIX_ZW(in) * MATRIX_WZ(in)
788 + MATRIX_ZY(in) * MATRIX_XZ(in) * MATRIX_WW(in)
789 - MATRIX_ZY(in) * MATRIX_XW(in) * MATRIX_WZ(in)
790 - MATRIX_WY(in) * MATRIX_XZ(in) * MATRIX_ZW(in)
791 + MATRIX_WY(in) * MATRIX_XW(in) * MATRIX_ZZ(in);
792
793 MATRIX_YY(out) =
794 MATRIX_XX(in) * MATRIX_ZZ(in) * MATRIX_WW(in)
795 - MATRIX_XX(in) * MATRIX_ZW(in) * MATRIX_WZ(in)
796 - MATRIX_ZX(in) * MATRIX_XZ(in) * MATRIX_WW(in)
797 + MATRIX_ZX(in) * MATRIX_XW(in) * MATRIX_WZ(in)
798 + MATRIX_WX(in) * MATRIX_XZ(in) * MATRIX_ZW(in)
799 - MATRIX_WX(in) * MATRIX_XW(in) * MATRIX_ZZ(in);
800
801 MATRIX_ZY(out) =
802 - MATRIX_XX(in) * MATRIX_ZY(in) * MATRIX_WW(in)
803 + MATRIX_XX(in) * MATRIX_ZW(in) * MATRIX_WY(in)
804 + MATRIX_ZX(in) * MATRIX_XY(in) * MATRIX_WW(in)
805 - MATRIX_ZX(in) * MATRIX_XW(in) * MATRIX_WY(in)
806 - MATRIX_WX(in) * MATRIX_XY(in) * MATRIX_ZW(in)
807 + MATRIX_WX(in) * MATRIX_XW(in) * MATRIX_ZY(in);
808
809 MATRIX_WY(out) =
810 MATRIX_XX(in) * MATRIX_ZY(in) * MATRIX_WZ(in)
811 - MATRIX_XX(in) * MATRIX_ZZ(in) * MATRIX_WY(in)
812 - MATRIX_ZX(in) * MATRIX_XY(in) * MATRIX_WZ(in)
813 + MATRIX_ZX(in) * MATRIX_XZ(in) * MATRIX_WY(in)
814 + MATRIX_WX(in) * MATRIX_XY(in) * MATRIX_ZZ(in)
815 - MATRIX_WX(in) * MATRIX_XZ(in) * MATRIX_ZY(in);
816
817 MATRIX_XZ(out) =
818 MATRIX_XY(in) * MATRIX_YZ(in) * MATRIX_WW(in)
819 - MATRIX_XY(in) * MATRIX_YW(in) * MATRIX_WZ(in)
820 - MATRIX_YY(in) * MATRIX_XZ(in) * MATRIX_WW(in)
821 + MATRIX_YY(in) * MATRIX_XW(in) * MATRIX_WZ(in)
822 + MATRIX_WY(in) * MATRIX_XZ(in) * MATRIX_YW(in)
823 - MATRIX_WY(in) * MATRIX_XW(in) * MATRIX_YZ(in);
824
825 MATRIX_YZ(out) =
826 - MATRIX_XX(in) * MATRIX_YZ(in) * MATRIX_WW(in)
827 + MATRIX_XX(in) * MATRIX_YW(in) * MATRIX_WZ(in)
828 + MATRIX_YX(in) * MATRIX_XZ(in) * MATRIX_WW(in)
829 - MATRIX_YX(in) * MATRIX_XW(in) * MATRIX_WZ(in)
830 - MATRIX_WX(in) * MATRIX_XZ(in) * MATRIX_YW(in)
831 + MATRIX_WX(in) * MATRIX_XW(in) * MATRIX_YZ(in);
832
833 MATRIX_ZZ(out) =
834 MATRIX_XX(in) * MATRIX_YY(in) * MATRIX_WW(in)
835 - MATRIX_XX(in) * MATRIX_YW(in) * MATRIX_WY(in)
836 - MATRIX_YX(in) * MATRIX_XY(in) * MATRIX_WW(in)
837 + MATRIX_YX(in) * MATRIX_XW(in) * MATRIX_WY(in)
838 + MATRIX_WX(in) * MATRIX_XY(in) * MATRIX_YW(in)
839 - MATRIX_WX(in) * MATRIX_XW(in) * MATRIX_YY(in);
840
841 MATRIX_WZ(out) =
842 - MATRIX_XX(in) * MATRIX_YY(in) * MATRIX_WZ(in)
843 + MATRIX_XX(in) * MATRIX_YZ(in) * MATRIX_WY(in)
844 + MATRIX_YX(in) * MATRIX_XY(in) * MATRIX_WZ(in)
845 - MATRIX_YX(in) * MATRIX_XZ(in) * MATRIX_WY(in)
846 - MATRIX_WX(in) * MATRIX_XY(in) * MATRIX_YZ(in)
847 + MATRIX_WX(in) * MATRIX_XZ(in) * MATRIX_YY(in);
848
849 MATRIX_XW(out) =
850 - MATRIX_XY(in) * MATRIX_YZ(in) * MATRIX_ZW(in)
851 + MATRIX_XY(in) * MATRIX_YW(in) * MATRIX_ZZ(in)
852 + MATRIX_YY(in) * MATRIX_XZ(in) * MATRIX_ZW(in)
853 - MATRIX_YY(in) * MATRIX_XW(in) * MATRIX_ZZ(in)
854 - MATRIX_ZY(in) * MATRIX_XZ(in) * MATRIX_YW(in)
855 + MATRIX_ZY(in) * MATRIX_XW(in) * MATRIX_YZ(in);
856
857 MATRIX_YW(out) =
858 MATRIX_XX(in) * MATRIX_YZ(in) * MATRIX_ZW(in)
859 - MATRIX_XX(in) * MATRIX_YW(in) * MATRIX_ZZ(in)
860 - MATRIX_YX(in) * MATRIX_XZ(in) * MATRIX_ZW(in)
861 + MATRIX_YX(in) * MATRIX_XW(in) * MATRIX_ZZ(in)
862 + MATRIX_ZX(in) * MATRIX_XZ(in) * MATRIX_YW(in)
863 - MATRIX_ZX(in) * MATRIX_XW(in) * MATRIX_YZ(in);
864
865 MATRIX_ZW(out) =
866 - MATRIX_XX(in) * MATRIX_YY(in) * MATRIX_ZW(in)
867 + MATRIX_XX(in) * MATRIX_YW(in) * MATRIX_ZY(in)
868 + MATRIX_YX(in) * MATRIX_XY(in) * MATRIX_ZW(in)
869 - MATRIX_YX(in) * MATRIX_XW(in) * MATRIX_ZY(in)
870 - MATRIX_ZX(in) * MATRIX_XY(in) * MATRIX_YW(in)
871 + MATRIX_ZX(in) * MATRIX_XW(in) * MATRIX_YY(in);
872
873 MATRIX_WW(out) =
874 MATRIX_XX(in) * MATRIX_YY(in) * MATRIX_ZZ(in)
875 - MATRIX_XX(in) * MATRIX_YZ(in) * MATRIX_ZY(in)
876 - MATRIX_YX(in) * MATRIX_XY(in) * MATRIX_ZZ(in)
877 + MATRIX_YX(in) * MATRIX_XZ(in) * MATRIX_ZY(in)
878 + MATRIX_ZX(in) * MATRIX_XY(in) * MATRIX_YZ(in)
879 - MATRIX_ZX(in) * MATRIX_XZ(in) * MATRIX_YY(in);
880
881 det =
882 MATRIX_XX(in) * MATRIX_XX(out)
883 + MATRIX_XY(in) * MATRIX_YX(out)
884 + MATRIX_XZ(in) * MATRIX_ZX(out)
885 + MATRIX_XW(in) * MATRIX_WX(out);
886
887 if (fabs(det) < DBL_EPSILON) return EINA_FALSE;
888
889 det = 1.0 / det;
890
891 MATRIX_XX(out) = MATRIX_XX(out) * det;
892 MATRIX_XY(out) = MATRIX_XY(out) * det;
893 MATRIX_XZ(out) = MATRIX_XZ(out) * det;
894 MATRIX_XW(out) = MATRIX_XW(out) * det;
895 MATRIX_YX(out) = MATRIX_YX(out) * det;
896 MATRIX_YY(out) = MATRIX_YY(out) * det;
897 MATRIX_YZ(out) = MATRIX_YZ(out) * det;
898 MATRIX_YW(out) = MATRIX_YW(out) * det;
899 MATRIX_ZX(out) = MATRIX_ZX(out) * det;
900 MATRIX_ZY(out) = MATRIX_ZY(out) * det;
901 MATRIX_ZZ(out) = MATRIX_ZZ(out) * det;
902 MATRIX_ZW(out) = MATRIX_ZW(out) * det;
903 MATRIX_WX(out) = MATRIX_WX(out) * det;
904 MATRIX_WY(out) = MATRIX_WY(out) * det;
905 MATRIX_WZ(out) = MATRIX_WZ(out) * det;
906 MATRIX_WW(out) = MATRIX_WW(out) * det;
907
908 return EINA_TRUE;
909 }
910
911 EAPI void
eina_matrix4_transpose(Eina_Matrix4 * out,const Eina_Matrix4 * in)912 eina_matrix4_transpose(Eina_Matrix4 *out, const Eina_Matrix4 *in)
913 {
914 MATRIX_XX(out) = MATRIX_XX(in);
915 MATRIX_XY(out) = MATRIX_YX(in);
916 MATRIX_XZ(out) = MATRIX_ZX(in);
917 MATRIX_XW(out) = MATRIX_WX(in);
918 MATRIX_YX(out) = MATRIX_XY(in);
919 MATRIX_YY(out) = MATRIX_YY(in);
920 MATRIX_YZ(out) = MATRIX_ZY(in);
921 MATRIX_YW(out) = MATRIX_WY(in);
922 MATRIX_ZX(out) = MATRIX_XZ(in);
923 MATRIX_ZY(out) = MATRIX_YZ(in);
924 MATRIX_ZZ(out) = MATRIX_ZZ(in);
925 MATRIX_ZW(out) = MATRIX_WZ(in);
926 MATRIX_WX(out) = MATRIX_XW(in);
927 MATRIX_WY(out) = MATRIX_YW(in);
928 MATRIX_WZ(out) = MATRIX_ZW(in);
929 MATRIX_WW(out) = MATRIX_WW(in);
930 }
931
932 EAPI void
eina_matrix4_multiply_copy(Eina_Matrix4 * out,const Eina_Matrix4 * mat_a,const Eina_Matrix4 * mat_b)933 eina_matrix4_multiply_copy(Eina_Matrix4 *out,
934 const Eina_Matrix4 *mat_a, const Eina_Matrix4 *mat_b)
935 {
936 if (out != mat_a && out != mat_b)
937 {
938 eina_matrix4_multiply(out, mat_a, mat_b);
939 }
940 else
941 {
942 Eina_Matrix4 result;
943
944 eina_matrix4_multiply(&result, mat_a, mat_b);
945 eina_matrix4_copy(out, &result);
946 }
947 }
948
949 EAPI void
eina_matrix4_identity(Eina_Matrix4 * out)950 eina_matrix4_identity(Eina_Matrix4 *out)
951 {
952 memset(out, 0, sizeof (Eina_Matrix4));
953
954 MATRIX_XX(out) = 1.0;
955 MATRIX_YY(out) = 1.0;
956 MATRIX_ZZ(out) = 1.0;
957 MATRIX_WW(out) = 1.0;
958 }
959
960 EAPI Eina_Matrix_Type
eina_matrix2_type_get(const Eina_Matrix2 * m)961 eina_matrix2_type_get(const Eina_Matrix2 *m)
962 {
963 if (EINA_DBL_EQ(MATRIX_XX(m), 1.0) &&
964 EINA_DBL_EQ(MATRIX_XY(m), 0.0) &&
965 EINA_DBL_EQ(MATRIX_YX(m), 0.0) &&
966 EINA_DBL_EQ(MATRIX_YY(m), 1.0))
967 return EINA_MATRIX_TYPE_IDENTITY;
968 return EINA_MATRIX_TYPE_AFFINE;
969 }
970
971 EAPI void
eina_matrix4_array_set(Eina_Matrix4 * m,const double * v)972 eina_matrix4_array_set(Eina_Matrix4 *m, const double *v)
973 {
974 memcpy(&MATRIX_XX(m), v, sizeof(double) * 16);
975 }
976
977 EAPI void
eina_matrix4_copy(Eina_Matrix4 * dst,const Eina_Matrix4 * src)978 eina_matrix4_copy(Eina_Matrix4 *dst, const Eina_Matrix4 *src)
979 {
980 memcpy(dst, src, sizeof(Eina_Matrix4));
981 }
982
983 EAPI void
eina_matrix4_multiply(Eina_Matrix4 * out,const Eina_Matrix4 * mat_a,const Eina_Matrix4 * mat_b)984 eina_matrix4_multiply(Eina_Matrix4 *out, const Eina_Matrix4 *mat_a,
985 const Eina_Matrix4 *mat_b)
986 {
987 if (eina_matrix4_type_get(mat_a) == EINA_MATRIX_TYPE_IDENTITY)
988 {
989 eina_matrix4_copy(out, mat_b);
990 return;
991 }
992
993 if (eina_matrix4_type_get(mat_b) == EINA_MATRIX_TYPE_IDENTITY)
994 {
995 eina_matrix4_copy(out, mat_a);
996 return;
997 }
998
999 eina_matrix4_compose(mat_a, mat_b, out);
1000 }
1001
1002 EAPI void
eina_matrix4_ortho_set(Eina_Matrix4 * m,double left,double right,double bottom,double top,double dnear,double dfar)1003 eina_matrix4_ortho_set(Eina_Matrix4 *m,
1004 double left, double right, double bottom, double top,
1005 double dnear, double dfar)
1006 {
1007 double w = right - left;
1008 double h = top - bottom;
1009 double depth = dnear - dfar;
1010
1011 MATRIX_XX(m) = 2.0f / w;
1012 MATRIX_XY(m) = 0.0f;
1013 MATRIX_XZ(m) = 0.0f;
1014 MATRIX_XW(m) = 0.0f;
1015
1016 MATRIX_YX(m) = 0.0f;
1017 MATRIX_YY(m) = 2.0f / h;
1018 MATRIX_YZ(m) = 0.0f;
1019 MATRIX_YW(m) = 0.0f;
1020
1021 MATRIX_ZX(m) = 0.0f;
1022 MATRIX_ZY(m) = 0.0f;
1023 MATRIX_ZZ(m) = 2.0f / depth;
1024 MATRIX_ZW(m) = 0.0f;
1025
1026 MATRIX_WX(m) = -(right + left) / w;
1027 MATRIX_WY(m) = -(top + bottom) / h;
1028 MATRIX_WZ(m) = (dfar + dnear) / depth;
1029 MATRIX_WW(m) = 1.0f;
1030 }
1031
1032 EAPI void
eina_matrix4_compose(const Eina_Matrix4 * mat_a,const Eina_Matrix4 * mat_b,Eina_Matrix4 * out)1033 eina_matrix4_compose(const Eina_Matrix4 *mat_a,
1034 const Eina_Matrix4 *mat_b,
1035 Eina_Matrix4 *out)
1036 {
1037 double xx, xy, xz, xw,
1038 yx, yy, yz, yw,
1039 zx, zy, zz, zw,
1040 wx, wy, wz, ww;
1041
1042 xx = MATRIX_XX(mat_a) * MATRIX_XX(mat_b) + MATRIX_XY(mat_a) * MATRIX_YX(mat_b) +
1043 MATRIX_XZ(mat_a) * MATRIX_ZX(mat_b) + MATRIX_XW(mat_a) * MATRIX_WX(mat_b);
1044 xy = MATRIX_XX(mat_a) * MATRIX_XY(mat_b) + MATRIX_XY(mat_a) * MATRIX_YY(mat_b) +
1045 MATRIX_XZ(mat_a) * MATRIX_ZY(mat_b) + MATRIX_XW(mat_a) * MATRIX_WY(mat_b);
1046 xz = MATRIX_XX(mat_a) * MATRIX_XZ(mat_b) + MATRIX_XY(mat_a) * MATRIX_YZ(mat_b) +
1047 MATRIX_XZ(mat_a) * MATRIX_ZZ(mat_b) + MATRIX_XW(mat_a) * MATRIX_WZ(mat_b);
1048 xw = MATRIX_XX(mat_a) * MATRIX_XW(mat_b) + MATRIX_XY(mat_a) * MATRIX_YW(mat_b) +
1049 MATRIX_XZ(mat_a) * MATRIX_ZW(mat_b) + MATRIX_XW(mat_a) * MATRIX_WW(mat_b);
1050
1051 yx = MATRIX_YX(mat_a) * MATRIX_XX(mat_b) + MATRIX_YY(mat_a) * MATRIX_YX(mat_b) +
1052 MATRIX_YZ(mat_a) * MATRIX_ZX(mat_b) + MATRIX_YW(mat_a) * MATRIX_WX(mat_b);
1053 yy = MATRIX_YX(mat_a) * MATRIX_XY(mat_b) + MATRIX_YY(mat_a) * MATRIX_YY(mat_b) +
1054 MATRIX_YZ(mat_a) * MATRIX_ZY(mat_b) + MATRIX_YW(mat_a) * MATRIX_WY(mat_b);
1055 yz = MATRIX_YX(mat_a) * MATRIX_XZ(mat_b) + MATRIX_YY(mat_a) * MATRIX_YZ(mat_b) +
1056 MATRIX_YZ(mat_a) * MATRIX_ZZ(mat_b) + MATRIX_YW(mat_a) * MATRIX_WZ(mat_b);
1057 yw = MATRIX_YX(mat_a) * MATRIX_XW(mat_b) + MATRIX_YY(mat_a) * MATRIX_YW(mat_b) +
1058 MATRIX_YZ(mat_a) * MATRIX_ZW(mat_b) + MATRIX_YW(mat_a) * MATRIX_WW(mat_b);
1059
1060 zx = MATRIX_ZX(mat_a) * MATRIX_XX(mat_b) + MATRIX_ZY(mat_a) * MATRIX_YX(mat_b) +
1061 MATRIX_ZZ(mat_a) * MATRIX_ZX(mat_b) + MATRIX_ZW(mat_a) * MATRIX_WX(mat_b);
1062 zy = MATRIX_ZX(mat_a) * MATRIX_XY(mat_b) + MATRIX_ZY(mat_a) * MATRIX_YY(mat_b) +
1063 MATRIX_ZZ(mat_a) * MATRIX_ZY(mat_b) + MATRIX_ZW(mat_a) * MATRIX_WY(mat_b);
1064 zz = MATRIX_ZX(mat_a) * MATRIX_XZ(mat_b) + MATRIX_ZY(mat_a) * MATRIX_YZ(mat_b) +
1065 MATRIX_ZZ(mat_a) * MATRIX_ZZ(mat_b) + MATRIX_ZW(mat_a) * MATRIX_WZ(mat_b);
1066 zw = MATRIX_ZX(mat_a) * MATRIX_XW(mat_b) + MATRIX_ZY(mat_a) * MATRIX_YW(mat_b) +
1067 MATRIX_ZZ(mat_a) * MATRIX_ZW(mat_b) + MATRIX_ZW(mat_a) * MATRIX_WW(mat_b);
1068
1069 wx = MATRIX_WX(mat_a) * MATRIX_XX(mat_b) + MATRIX_WY(mat_a) * MATRIX_YX(mat_b) +
1070 MATRIX_WZ(mat_a) * MATRIX_ZX(mat_b) + MATRIX_WW(mat_a) * MATRIX_WX(mat_b);
1071 wy = MATRIX_WX(mat_a) * MATRIX_XY(mat_b) + MATRIX_WY(mat_a) * MATRIX_YY(mat_b) +
1072 MATRIX_WZ(mat_a) * MATRIX_ZY(mat_b) + MATRIX_WW(mat_a) * MATRIX_WY(mat_b);
1073 wz = MATRIX_WX(mat_a) * MATRIX_XZ(mat_b) + MATRIX_WY(mat_a) * MATRIX_YZ(mat_b) +
1074 MATRIX_WZ(mat_a) * MATRIX_ZZ(mat_b) + MATRIX_WW(mat_a) * MATRIX_WZ(mat_b);
1075 ww = MATRIX_WX(mat_a) * MATRIX_XW(mat_b) + MATRIX_WY(mat_a) * MATRIX_YW(mat_b) +
1076 MATRIX_WZ(mat_a) * MATRIX_ZW(mat_b) + MATRIX_WW(mat_a) * MATRIX_WW(mat_b);
1077
1078 MATRIX_XX(out) = xx;
1079 MATRIX_XY(out) = xy;
1080 MATRIX_XZ(out) = xz;
1081 MATRIX_XW(out) = xw;
1082
1083 MATRIX_YX(out) = yx;
1084 MATRIX_YY(out) = yy;
1085 MATRIX_YZ(out) = yz;
1086 MATRIX_YW(out) = yw;
1087
1088 MATRIX_ZX(out) = zx;
1089 MATRIX_ZY(out) = zy;
1090 MATRIX_ZZ(out) = zz;
1091 MATRIX_ZW(out) = zw;
1092
1093 MATRIX_WX(out) = wx;
1094 MATRIX_WY(out) = wy;
1095 MATRIX_WZ(out) = wz;
1096 MATRIX_WW(out) = ww;
1097 }
1098
1099 EAPI void
eina_matrix4_translate(Eina_Matrix4 * t,double tx,double ty,double tz)1100 eina_matrix4_translate(Eina_Matrix4 *t, double tx, double ty, double tz)
1101 {
1102 Eina_Matrix4 tmp;
1103 MATRIX_XX(&tmp) = 1;
1104 MATRIX_XY(&tmp) = 0;
1105 MATRIX_XZ(&tmp) = 0;
1106 MATRIX_XW(&tmp) = tx;
1107
1108 MATRIX_YX(&tmp) = 0;
1109 MATRIX_YY(&tmp) = 1;
1110 MATRIX_YZ(&tmp) = 0;
1111 MATRIX_YW(&tmp) = ty;
1112
1113 MATRIX_ZX(&tmp) = 0;
1114 MATRIX_ZY(&tmp) = 0;
1115 MATRIX_ZZ(&tmp) = 1;
1116 MATRIX_ZW(&tmp) = tz;
1117
1118 MATRIX_WX(&tmp) = 0;
1119 MATRIX_WY(&tmp) = 0;
1120 MATRIX_WZ(&tmp) = 0;
1121 MATRIX_WW(&tmp) = 1;
1122
1123 eina_matrix4_compose(&tmp, t, t);
1124 }
1125
1126 EAPI void
eina_matrix4_scale(Eina_Matrix4 * t,double sx,double sy,double sz)1127 eina_matrix4_scale(Eina_Matrix4 *t, double sx, double sy, double sz)
1128 {
1129 Eina_Matrix4 tmp;
1130 MATRIX_XX(&tmp) = sx;
1131 MATRIX_XY(&tmp) = 0;
1132 MATRIX_XZ(&tmp) = 0;
1133 MATRIX_XW(&tmp) = 0;
1134
1135 MATRIX_YX(&tmp) = 0;
1136 MATRIX_YY(&tmp) = sy;
1137 MATRIX_YZ(&tmp) = 0;
1138 MATRIX_YW(&tmp) = 0;
1139
1140 MATRIX_ZX(&tmp) = 0;
1141 MATRIX_ZY(&tmp) = 0;
1142 MATRIX_ZZ(&tmp) = sz;
1143 MATRIX_ZW(&tmp) = 0;
1144
1145 MATRIX_WX(&tmp) = 0;
1146 MATRIX_WY(&tmp) = 0;
1147 MATRIX_WZ(&tmp) = 0;
1148 MATRIX_WW(&tmp) = 1;
1149
1150 eina_matrix4_compose(&tmp, t, t);
1151 }
1152
1153 EAPI void
eina_matrix4_rotate(Eina_Matrix4 * t,double rad,Eina_Matrix_Axis axis)1154 eina_matrix4_rotate(Eina_Matrix4 *t, double rad, Eina_Matrix_Axis axis)
1155 {
1156 double c, s;
1157
1158 /* Note: Local functions do not guarantee accuracy.
1159 * Errors occur in the calculation of very small or very large numbers.
1160 * Local cos and sin functions differ from the math header cosf and sinf functions
1161 * by result values. The 4th decimal place is different.
1162 * But local functions are certainly faster than functions in math library.
1163 * Later we would want someone to look at this and improve accuracy.
1164 */
1165 #if 1
1166 c = cos(rad);
1167 s = sin(rad);
1168 #else
1169 /* normalize the angle between -pi,pi */
1170 rad = fmod(rad + M_PI, 2 * M_PI) - M_PI;
1171 c = _cos(rad);
1172 s = _sin(rad);
1173 #endif
1174
1175 Eina_Matrix4 tmp;
1176 eina_matrix4_identity(&tmp);
1177
1178 switch (axis)
1179 {
1180 case EINA_MATRIX_AXIS_X:
1181 MATRIX_YY(&tmp) = c;
1182 MATRIX_YZ(&tmp) = -s;
1183 MATRIX_ZY(&tmp) = s;
1184 MATRIX_ZZ(&tmp) = c;
1185 break;
1186 case EINA_MATRIX_AXIS_Y:
1187 MATRIX_XX(&tmp) = c;
1188 MATRIX_XZ(&tmp) = s;
1189 MATRIX_ZX(&tmp) = -s;
1190 MATRIX_ZZ(&tmp) = c;
1191 break;
1192 case EINA_MATRIX_AXIS_Z:
1193 MATRIX_XX(&tmp) = c;
1194 MATRIX_XY(&tmp) = -s;
1195 MATRIX_YX(&tmp) = s;
1196 MATRIX_YY(&tmp) = c;
1197 break;
1198 }
1199 eina_matrix4_compose(&tmp, t, t);
1200 }
1201
1202 EAPI void
eina_matrix3_array_set(Eina_Matrix3 * m,const double * v)1203 eina_matrix3_array_set(Eina_Matrix3 *m, const double *v)
1204 {
1205 memcpy(&MATRIX_XX(m), v, sizeof(double) * 9);
1206 }
1207
1208 EAPI void
eina_matrix3_copy(Eina_Matrix3 * dst,const Eina_Matrix3 * src)1209 eina_matrix3_copy(Eina_Matrix3 *dst, const Eina_Matrix3 *src)
1210 {
1211 memcpy(dst, src, sizeof(Eina_Matrix3));
1212 }
1213
1214 EAPI void
eina_matrix3_multiply(Eina_Matrix3 * out,const Eina_Matrix3 * mat_a,const Eina_Matrix3 * mat_b)1215 eina_matrix3_multiply(Eina_Matrix3 *out, const Eina_Matrix3 *mat_a, const Eina_Matrix3 *mat_b)
1216 {
1217 if (eina_matrix3_type_get(mat_a) == EINA_MATRIX_TYPE_IDENTITY)
1218 {
1219 eina_matrix3_copy(out, mat_b);
1220 return;
1221 }
1222
1223 if (eina_matrix3_type_get(mat_b) == EINA_MATRIX_TYPE_IDENTITY)
1224 {
1225 eina_matrix3_copy(out, mat_a);
1226 return;
1227 }
1228
1229 eina_matrix3_compose(mat_a, mat_b, out);
1230 }
1231
1232 EAPI void
eina_matrix3_multiply_copy(Eina_Matrix3 * out,const Eina_Matrix3 * mat_a,const Eina_Matrix3 * mat_b)1233 eina_matrix3_multiply_copy(Eina_Matrix3 *out, const Eina_Matrix3 *mat_a, const Eina_Matrix3 *mat_b)
1234 {
1235 if (out != mat_a && out != mat_b)
1236 {
1237 eina_matrix3_multiply(out, mat_a, mat_b);
1238 }
1239 else
1240 {
1241 Eina_Matrix3 tmp;
1242
1243 eina_matrix3_multiply(&tmp, mat_a, mat_b);
1244 eina_matrix3_copy(out, &tmp);
1245 }
1246 }
1247
1248 EAPI void
eina_matrix3_position_transform_set(Eina_Matrix3 * out,const double p_x,const double p_y)1249 eina_matrix3_position_transform_set(Eina_Matrix3 *out, const double p_x,
1250 const double p_y)
1251 {
1252 eina_matrix3_identity(out);
1253 MATRIX_XZ(out) = p_x;
1254 MATRIX_YZ(out) = p_y;
1255 }
1256
1257 EAPI void
eina_matrix3_scale_transform_set(Eina_Matrix3 * out,double s_x,double s_y)1258 eina_matrix3_scale_transform_set(Eina_Matrix3 *out, double s_x, double s_y)
1259 {
1260 eina_matrix3_identity(out);
1261 MATRIX_XX(out) = s_x;
1262 MATRIX_YY(out) = s_y;
1263 }
1264
1265 EAPI void
eina_normal3_matrix_get(Eina_Matrix3 * out,const Eina_Matrix4 * m)1266 eina_normal3_matrix_get(Eina_Matrix3 *out, const Eina_Matrix4 *m)
1267 {
1268 /* Normal matrix is a transposed matrix of inversed modelview.
1269 * And we need only upper-left 3x3 terms to work with. */
1270
1271 double det;
1272
1273 double a = MATRIX_XX(m);
1274 double b = MATRIX_YX(m);
1275 double c = MATRIX_ZX(m);
1276
1277 double d = MATRIX_XY(m);
1278 double e = MATRIX_YY(m);
1279 double f = MATRIX_ZY(m);
1280
1281 double g = MATRIX_XZ(m);
1282 double h = MATRIX_YZ(m);
1283 double i = MATRIX_ZZ(m);
1284
1285 det = a * e * i + b * f * g + c * d * h - g * e * c - h * f * a - i * d * b;
1286
1287 if (fabs(det) >= DBL_EPSILON) det = 1.0 / det;
1288 else det = 0.0;
1289
1290 MATRIX_XX(out) = (e * i - f * h) * det;
1291 MATRIX_XY(out) = (h * c - i * b) * det;
1292 MATRIX_XZ(out) = (b * f - c * e) * det;
1293
1294 MATRIX_YX(out) = (g * f - d * i) * det;
1295 MATRIX_YY(out) = (a * i - g * c) * det;
1296 MATRIX_YZ(out) = (d * c - a * f) * det;
1297
1298 MATRIX_ZX(out) = (d * h - g * e) * det;
1299 MATRIX_ZY(out) = (g * b - a * h) * det;
1300 MATRIX_ZZ(out) = (a * e - d * b) * det;
1301 }
1302
1303 EAPI void
eina_matrix2_values_set(Eina_Matrix2 * m,double xx,double xy,double yx,double yy)1304 eina_matrix2_values_set(Eina_Matrix2 *m,
1305 double xx, double xy,
1306 double yx, double yy)
1307 {
1308 MATRIX_XX(m) = xx;
1309 MATRIX_XY(m) = xy;
1310 MATRIX_YX(m) = yx;
1311 MATRIX_YY(m) = yy;
1312 }
1313
1314 EAPI void
eina_matrix2_values_get(const Eina_Matrix2 * m,double * xx,double * xy,double * yx,double * yy)1315 eina_matrix2_values_get(const Eina_Matrix2 *m,
1316 double *xx, double *xy,
1317 double *yx, double *yy)
1318 {
1319 if (xx) *xx = MATRIX_XX(m);
1320 if (xy) *xy = MATRIX_XY(m);
1321 if (yx) *yx = MATRIX_YX(m);
1322 if (yy) *yy = MATRIX_YY(m);
1323 }
1324
1325 EAPI void
eina_matrix2_inverse(Eina_Matrix2 * out,const Eina_Matrix2 * mat)1326 eina_matrix2_inverse(Eina_Matrix2 *out, const Eina_Matrix2 *mat)
1327 {
1328 double det;
1329
1330 if (eina_matrix2_type_get(mat) == EINA_MATRIX_TYPE_IDENTITY)
1331 {
1332 eina_matrix2_copy(out, mat);
1333 return;
1334 }
1335
1336 det = MATRIX_XX(mat) * MATRIX_YY(mat) - MATRIX_YX(mat) * MATRIX_XY(mat);
1337
1338 if (EINA_DBL_EQ(det, 0.0))
1339 return;
1340
1341 det = 1.0 / det;
1342
1343 MATRIX_XX(out) = MATRIX_YY(mat) * det;
1344 MATRIX_XY(out) = -MATRIX_XY(mat) * det;
1345 MATRIX_YX(out) = -MATRIX_YX(mat) * det;
1346 MATRIX_YY(out) = MATRIX_XX(mat) * det;
1347 }
1348
1349 EAPI void
eina_matrix2_identity(Eina_Matrix2 * m)1350 eina_matrix2_identity(Eina_Matrix2 *m)
1351 {
1352 MATRIX_XX(m) = 1.0;
1353 MATRIX_XY(m) = 0.0;
1354
1355 MATRIX_YX(m) = 0.0;
1356 MATRIX_YY(m) = 1.0;
1357 }
1358
1359 EAPI void
eina_matrix2_array_set(Eina_Matrix2 * m,const double * v)1360 eina_matrix2_array_set(Eina_Matrix2 *m, const double *v)
1361 {
1362 memcpy(&MATRIX_XX(m), v, sizeof(double) * 4);
1363 }
1364
1365 EAPI void
eina_matrix2_copy(Eina_Matrix2 * dst,const Eina_Matrix2 * src)1366 eina_matrix2_copy(Eina_Matrix2 *dst, const Eina_Matrix2 *src)
1367 {
1368 memcpy(dst, src, sizeof(Eina_Matrix2));
1369 }
1370
1371 EAPI void
eina_matrix2_multiply(Eina_Matrix2 * out,const Eina_Matrix2 * mat_a,const Eina_Matrix2 * mat_b)1372 eina_matrix2_multiply(Eina_Matrix2 *out, const Eina_Matrix2 *mat_a, const Eina_Matrix2 *mat_b)
1373 {
1374 if (eina_matrix2_type_get(mat_a) == EINA_MATRIX_TYPE_IDENTITY)
1375 {
1376 eina_matrix2_copy(out, mat_b);
1377 return;
1378 }
1379
1380 if (eina_matrix2_type_get(mat_b) == EINA_MATRIX_TYPE_IDENTITY)
1381 {
1382 eina_matrix2_copy(out, mat_a);
1383 return;
1384 }
1385
1386 MATRIX_XX(out) = MATRIX_XX(mat_a) * MATRIX_XX(mat_b) + MATRIX_YX(mat_a) * MATRIX_XY(mat_b);
1387 MATRIX_YX(out) = MATRIX_XX(mat_a) * MATRIX_YX(mat_b) + MATRIX_YX(mat_a) * MATRIX_YY(mat_b);
1388
1389 MATRIX_XY(out) = MATRIX_XY(mat_a) * MATRIX_XX(mat_b) + MATRIX_YY(mat_a) * MATRIX_XY(mat_b);
1390 MATRIX_YY(out) = MATRIX_XY(mat_a) * MATRIX_YX(mat_b) + MATRIX_YY(mat_a) * MATRIX_YY(mat_b);
1391 }
1392
1393 EAPI void
eina_matrix2_multiply_copy(Eina_Matrix2 * out,const Eina_Matrix2 * mat_a,const Eina_Matrix2 * mat_b)1394 eina_matrix2_multiply_copy(Eina_Matrix2 *out, const Eina_Matrix2 *mat_a, const Eina_Matrix2 *mat_b)
1395 {
1396 if (out != mat_a && out != mat_b)
1397 {
1398 eina_matrix2_multiply(out, mat_a, mat_b);
1399 }
1400 else
1401 {
1402 Eina_Matrix2 tmp;
1403
1404 eina_matrix2_multiply(&tmp, mat_a, mat_b);
1405 eina_matrix2_copy(out, &tmp);
1406 }
1407 }
1408