summaryrefslogtreecommitdiff
path: root/src/lib/evas/include/evas_3d_utils.h
diff options
context:
space:
mode:
authorTaekyun Kim <tkq.kim@samsung.com>2013-12-27 16:56:30 +0900
committerChunEon Park <hermet@hermet.pe.kr>2014-04-25 16:15:41 +0900
commit8fda63173063e03e1d48c8b026ecf8b94298162c (patch)
treec5988ae26377679bf58bf777148a6b1a6c5a3912 /src/lib/evas/include/evas_3d_utils.h
parent96f9353f4c951dd5dd41a687e272ffe1c28bb9ba (diff)
Evas: 3D: Introducing 3D scene rendering features
Enable 3D features using --enable-evas-3d=yes when configuring. APIs are exposed through Evas_3D.h. Currently, evas-3d is being supported only on gl_x11 engine. Conflicts: src/lib/evas/Evas_Eo.h
Diffstat (limited to 'src/lib/evas/include/evas_3d_utils.h')
-rw-r--r--src/lib/evas/include/evas_3d_utils.h1526
1 files changed, 1526 insertions, 0 deletions
diff --git a/src/lib/evas/include/evas_3d_utils.h b/src/lib/evas/include/evas_3d_utils.h
new file mode 100644
index 0000000000..196d3df5f5
--- /dev/null
+++ b/src/lib/evas/include/evas_3d_utils.h
@@ -0,0 +1,1526 @@
1#ifndef EVAS_PRIVATE_H
2# error You shall not include this header directly
3#endif
4
5#include <math.h>
6
7#define DEGREE_TO_RADIAN(x) (((x) * M_PI) / 180.0)
8#define EVAS_MATRIX_IS_IDENTITY 0x00000001
9
10typedef struct _Evas_Color
11{
12 Evas_Real r;
13 Evas_Real g;
14 Evas_Real b;
15 Evas_Real a;
16} Evas_Color;
17
18typedef struct _Evas_Vec2
19{
20 Evas_Real x;
21 Evas_Real y;
22} Evas_Vec2;
23
24typedef struct _Evas_Vec3
25{
26 Evas_Real x;
27 Evas_Real y;
28 Evas_Real z;
29} Evas_Vec3;
30
31typedef struct _Evas_Vec4
32{
33 Evas_Real x;
34 Evas_Real y;
35 Evas_Real z;
36 Evas_Real w;
37} Evas_Vec4;
38
39typedef struct _Evas_Mat2
40{
41 Evas_Real m[4];
42 int flags;
43} Evas_Mat2;
44
45typedef struct _Evas_Mat3
46{
47 Evas_Real m[9];
48 int flags;
49} Evas_Mat3;
50
51typedef struct _Evas_Mat4
52{
53 Evas_Real m[16];
54 int flags;
55} Evas_Mat4;
56
57typedef struct _Evas_Box2
58{
59 Evas_Vec2 p0;
60 Evas_Vec2 p1;
61} Evas_Box2;
62
63typedef struct _Evas_Box3
64{
65 Evas_Vec3 p0;
66 Evas_Vec3 p1;
67} Evas_Box3;
68
69typedef struct _Evas_Triangle3
70{
71 Evas_Vec3 p0;
72 Evas_Vec3 p1;
73 Evas_Vec3 p2;
74} Evas_Triangle3;
75
76typedef struct _Evas_Ray3
77{
78 Evas_Vec3 org;
79 Evas_Vec3 dir;
80} Evas_Ray3;
81
82/* 2D vector */
83static inline void
84evas_vec2_set(Evas_Vec2 *dst, Evas_Real x, Evas_Real y)
85{
86 dst->x = x;
87 dst->y = y;
88}
89
90static inline void
91evas_vec2_array_set(Evas_Vec2 *dst, const Evas_Real *v)
92{
93 dst->x = v[0];
94 dst->y = v[1];
95}
96
97static inline void
98evas_vec2_copy(Evas_Vec2 *dst, const Evas_Vec2 *src)
99{
100 dst->x = src->x;
101 dst->y = src->y;
102}
103
104static inline void
105evas_vec2_negate(Evas_Vec2 *out, const Evas_Vec2 *v)
106{
107 out->x = -v->x;
108 out->y = -v->y;
109}
110
111static inline void
112evas_vec2_add(Evas_Vec2 *out, const Evas_Vec2 *a, const Evas_Vec2 *b)
113{
114 out->x = a->x + b->x;
115 out->y = a->y + b->y;
116}
117
118static inline void
119evas_vec2_subtract(Evas_Vec2 *out, const Evas_Vec2 *a, const Evas_Vec2 *b)
120{
121 out->x = a->x - b->x;
122 out->y = a->y - b->y;
123}
124
125static inline void
126evas_vec2_scale(Evas_Vec2 *out, const Evas_Vec2 *v, Evas_Real scale)
127{
128 out->x = scale * v->x;
129 out->y = scale * v->y;
130}
131
132static inline Evas_Real
133evas_vec2_dot_product(const Evas_Vec2 *a, const Evas_Vec2 *b)
134{
135 return (a->x * b->x) + (a->y * b->y);
136}
137
138static inline Evas_Real
139evas_vec2_length_get(const Evas_Vec2 *v)
140{
141 return (Evas_Real)sqrt((double)((v->x * v->x) + (v->y * v->y)));
142}
143
144static inline Evas_Real
145evas_vec2_length_square_get(const Evas_Vec2 *v)
146{
147 return (v->x * v->x) + (v->y * v->y);
148}
149
150static inline Evas_Real
151evas_vec2_distance_get(const Evas_Vec2 *a, const Evas_Vec2 *b)
152{
153 Evas_Vec2 v;
154
155 evas_vec2_subtract(&v, a, b);
156 return evas_vec2_length_get(&v);
157}
158
159static inline Evas_Real
160evas_vec2_distance_square_get(const Evas_Vec2 *a, const Evas_Vec2 *b)
161{
162 Evas_Vec2 v;
163
164 evas_vec2_subtract(&v, a, b);
165 return evas_vec2_length_square_get(&v);
166}
167
168static inline void
169evas_vec2_normalize(Evas_Vec2 *out, const Evas_Vec2 *v)
170{
171 /* Assume "v" is not a zero vector */
172 evas_vec2_scale(out, v, 1.0 / evas_vec2_length_get(v));
173}
174
175static inline void
176evas_vec2_transform(Evas_Vec2 *out, const Evas_Mat2 *m, const Evas_Vec2 *v)
177{
178 Evas_Vec2 tmp;
179
180 tmp.x = (m->m[0] * v->x) + (m->m[2] * v->y);
181 tmp.y = (m->m[1] * v->x) + (m->m[3] * v->y);
182
183 evas_vec2_copy(out, &tmp);
184}
185
186static inline void
187evas_vec2_homogeneous_position_transform(Evas_Vec2 *out, const Evas_Mat3 *m, const Evas_Vec2 *v)
188{
189 Evas_Vec2 tmp;
190
191 tmp.x = (m->m[0] * v->x) + (m->m[3] * v->y) + m->m[6];
192 tmp.y = (m->m[1] * v->x) + (m->m[4] * v->y) + m->m[7];
193
194 evas_vec2_scale(out, &tmp, 1.0 / ((m->m[2] * v->x) + (m->m[5] * v->y) + m->m[8]));
195}
196
197static inline void
198evas_vec2_homogeneous_direction_transform(Evas_Vec2 *out, const Evas_Mat3 *m, const Evas_Vec2 *v)
199{
200 Evas_Vec2 tmp;
201
202 tmp.x = (m->m[0] * v->x) + (m->m[3] * v->y);
203 tmp.y = (m->m[1] * v->x) + (m->m[4] * v->y);
204
205 evas_vec2_copy(out, &tmp);
206}
207
208/* 3D vector */
209static inline void
210evas_vec3_set(Evas_Vec3 *dst, Evas_Real x, Evas_Real y, Evas_Real z)
211{
212 dst->x = x;
213 dst->y = y;
214 dst->z = z;
215}
216
217static inline void
218evas_vec3_array_set(Evas_Vec3 *dst, const Evas_Real *v)
219{
220 dst->x = v[0];
221 dst->y = v[1];
222 dst->z = v[2];
223}
224
225static inline void
226evas_vec3_copy(Evas_Vec3 *dst, const Evas_Vec3 *src)
227{
228 dst->x = src->x;
229 dst->y = src->y;
230 dst->z = src->z;
231}
232
233static inline void
234evas_vec3_negate(Evas_Vec3 *out, const Evas_Vec3 *v)
235{
236 out->x = -v->x;
237 out->y = -v->y;
238 out->z = -v->z;
239}
240
241static inline void
242evas_vec3_add(Evas_Vec3 *out, const Evas_Vec3 *a, const Evas_Vec3 *b)
243{
244 out->x = a->x + b->x;
245 out->y = a->y + b->y;
246 out->z = a->z + b->z;
247}
248
249static inline void
250evas_vec3_subtract(Evas_Vec3 *out, const Evas_Vec3 *a, const Evas_Vec3 *b)
251{
252 out->x = a->x - b->x;
253 out->y = a->y - b->y;
254 out->z = a->z - b->z;
255}
256
257static inline void
258evas_vec3_scale(Evas_Vec3 *out, const Evas_Vec3 *v, Evas_Real scale)
259{
260 out->x = scale * v->x;
261 out->y = scale * v->y;
262 out->z = scale * v->z;
263}
264
265static inline void
266evas_vec3_multiply(Evas_Vec3 *out, const Evas_Vec3 *a, const Evas_Vec3 *b)
267{
268 out->x = a->x * b->x;
269 out->y = a->y * b->y;
270 out->z = a->z * b->z;
271}
272
273static inline Evas_Real
274evas_vec3_dot_product(const Evas_Vec3 *a, const Evas_Vec3 *b)
275{
276 return (a->x * b->x) + (a->y * b->y) + (a->z * b->z);
277}
278
279static inline void
280evas_vec3_cross_product(Evas_Vec3 *out, const Evas_Vec3 *a, const Evas_Vec3 *b)
281{
282 Evas_Vec3 tmp;
283
284 tmp.x = a->y * b->z - a->z * b->y;
285 tmp.y = a->z * b->x - a->x * b->z;
286 tmp.z = a->x * b->y - a->y * b->x;
287
288 evas_vec3_copy(out, &tmp);
289}
290
291static inline Evas_Real
292evas_vec3_length_get(const Evas_Vec3 *v)
293{
294 return (Evas_Real)sqrt((double)((v->x * v->x) + (v->y * v->y) + (v->z * v->z)));
295}
296
297static inline Evas_Real
298evas_vec3_length_square_get(const Evas_Vec3 *v)
299{
300 return (v->x * v->x) + (v->y * v->y) + (v->z * v->z);
301}
302
303static inline Evas_Real
304evas_vec3_distance_get(const Evas_Vec3 *a, const Evas_Vec3 *b)
305{
306 Evas_Vec3 v;
307
308 evas_vec3_subtract(&v, a, b);
309 return evas_vec3_length_get(&v);
310}
311
312static inline Evas_Real
313evas_vec3_distance_square_get(const Evas_Vec3 *a, const Evas_Vec3 *b)
314{
315 Evas_Vec3 v;
316
317 evas_vec3_subtract(&v, a, b);
318 return evas_vec3_length_square_get(&v);
319}
320
321static inline void
322evas_vec3_normalize(Evas_Vec3 *out, const Evas_Vec3 *v)
323{
324 /* Assume "v" is not a zero vector */
325 evas_vec3_scale(out, v, 1.0 / evas_vec3_length_get(v));
326}
327
328static inline void
329evas_vec3_transform(Evas_Vec3 *out, const Evas_Vec3 *v, const Evas_Mat3 *m)
330{
331 Evas_Vec3 tmp;
332
333 if (m->flags & EVAS_MATRIX_IS_IDENTITY)
334 {
335 evas_vec3_copy(out, v);
336 return;
337 }
338
339 tmp.x = (m->m[0] * v->x) + (m->m[3] * v->y) + (m->m[6] * v->z);
340 tmp.y = (m->m[1] * v->x) + (m->m[4] * v->y) + (m->m[7] * v->z);
341 tmp.z = (m->m[2] * v->x) + (m->m[5] * v->y) + (m->m[8] * v->z);
342
343 evas_vec3_copy(out, &tmp);
344}
345
346static inline void
347evas_vec3_homogeneous_position_transform(Evas_Vec3 *out, const Evas_Vec3 *v, const Evas_Mat4 *m)
348{
349 Evas_Vec3 tmp;
350
351 if (m->flags & EVAS_MATRIX_IS_IDENTITY)
352 {
353 evas_vec3_copy(out, v);
354 return;
355 }
356
357 tmp.x = (m->m[0] * v->x) + (m->m[4] * v->y) + (m->m[8] * v->z) + m->m[12];
358 tmp.y = (m->m[1] * v->x) + (m->m[5] * v->y) + (m->m[9] * v->z) + m->m[13];
359 tmp.z = (m->m[2] * v->x) + (m->m[6] * v->y) + (m->m[10] * v->z) + m->m[14];
360
361 evas_vec3_scale(out, &tmp,
362 1.0 / ((m->m[3] * v->x) + (m->m[7] * v->y) + (m->m[11] * v->z) + m->m[15]));
363}
364
365static inline void
366evas_vec3_homogeneous_direction_transform(Evas_Vec3 *out, const Evas_Vec3 *v, const Evas_Mat4 *m)
367{
368 Evas_Vec3 tmp;
369
370 if (m->flags & EVAS_MATRIX_IS_IDENTITY)
371 {
372 evas_vec3_copy(out, v);
373 return;
374 }
375
376 tmp.x = (m->m[0] * v->x) + (m->m[4] * v->y) + (m->m[8] * v->z);
377 tmp.y = (m->m[1] * v->x) + (m->m[5] * v->y) + (m->m[9] * v->z);
378 tmp.z = (m->m[2] * v->x) + (m->m[6] * v->y) + (m->m[10] * v->z);
379
380 evas_vec3_copy(out, &tmp);
381}
382
383static inline void
384evas_vec3_quaternion_rotate(Evas_Vec3 *out, const Evas_Vec3 *v, const Evas_Vec4 *q)
385{
386 Evas_Vec3 uv, uuv;
387 Evas_Vec3 axis;
388
389 evas_vec3_set(&axis, q->x, q->y, q->z);
390
391 evas_vec3_cross_product(&uv, &axis, v);
392 evas_vec3_cross_product(&uuv, &axis, &uv);
393
394 evas_vec3_scale(&uv, &uv, 2.0 * q->w);
395 evas_vec3_scale(&uuv, &uuv, 2.0);
396
397 out->x = v->x + uv.x + uuv.x;
398 out->y = v->y + uv.y + uuv.y;
399 out->z = v->z + uv.z + uuv.z;
400}
401
402/* 4D vector */
403static inline void
404evas_vec4_set(Evas_Vec4 *dst, Evas_Real x, Evas_Real y, Evas_Real z, Evas_Real w)
405{
406 dst->x = x;
407 dst->y = y;
408 dst->z = z;
409 dst->w = w;
410}
411
412static inline void
413evas_vec4_array_set(Evas_Vec4 *dst, const Evas_Real *v)
414{
415 dst->x = v[0];
416 dst->y = v[1];
417 dst->z = v[2];
418 dst->w = v[3];
419}
420
421static inline void
422evas_vec4_copy(Evas_Vec4 *dst, const Evas_Vec4 *src)
423{
424 dst->x = src->x;
425 dst->y = src->y;
426 dst->z = src->z;
427 dst->w = src->w;
428}
429
430static inline void
431evas_vec4_homogeneous_regulate(Evas_Vec4 *out, const Evas_Vec4 *v)
432{
433 if (v->w != 0.0)
434 {
435 Evas_Real scale = 1.0 / v->w;
436
437 out->x = v->x * scale;
438 out->y = v->y * scale;
439 out->z = v->z * scale;
440 out->w = 1.0;
441 }
442}
443
444static inline void
445evas_vec4_negate(Evas_Vec4 *out, const Evas_Vec4 *v)
446{
447 out->x = -v->x;
448 out->y = -v->y;
449 out->z = -v->z;
450 out->w = -v->w;
451}
452
453static inline void
454evas_vec4_add(Evas_Vec4 *out, const Evas_Vec4 *a, const Evas_Vec4 *b)
455{
456 out->x = a->x + b->x;
457 out->y = a->y + b->y;
458 out->z = a->z + b->z;
459 out->w = a->w + b->w;
460}
461
462static inline void
463evas_vec4_subtract(Evas_Vec4 *out, const Evas_Vec4 *a, const Evas_Vec4 *b)
464{
465 out->x = a->x - b->x;
466 out->y = a->y - b->y;
467 out->z = a->z - b->z;
468 out->w = a->w - b->w;
469}
470
471static inline void
472evas_vec4_scale(Evas_Vec4 *out, const Evas_Vec4 *v, Evas_Real scale)
473{
474 out->x = scale * v->x;
475 out->y = scale * v->y;
476 out->z = scale * v->z;
477 out->w = scale * v->w;
478}
479
480static inline void
481evas_vec4_multiply(Evas_Vec4 *out, const Evas_Vec4 *a, const Evas_Vec4 *b)
482{
483 out->x = a->x * b->x;
484 out->y = a->y * b->y;
485 out->z = a->z * b->z;
486 out->w = a->w * b->w;
487}
488
489static inline Evas_Real
490evas_vec4_length_get(const Evas_Vec4 *v)
491{
492 return (Evas_Real)sqrt((double)((v->x * v->x) + (v->y * v->y) +
493 (v->z * v->z) + (v->w + v->w)));
494}
495
496static inline Evas_Real
497evas_vec4_length_square_get(const Evas_Vec4 *v)
498{
499 return (v->x * v->x) + (v->y * v->y) + (v->z * v->z) + (v->w * v->w);
500}
501
502static inline Evas_Real
503evas_vec4_distance_get(const Evas_Vec4 *a, const Evas_Vec4 *b)
504{
505 Evas_Vec4 v;
506
507 evas_vec4_subtract(&v, a, b);
508 return evas_vec4_length_get(&v);
509}
510
511static inline Evas_Real
512evas_vec4_distance_square_get(const Evas_Vec4 *a, const Evas_Vec4 *b)
513{
514 Evas_Vec4 v;
515
516 evas_vec4_subtract(&v, a, b);
517 return evas_vec4_length_square_get(&v);
518}
519
520static inline void
521evas_vec4_normalize(Evas_Vec4 *out, const Evas_Vec4 *v)
522{
523 /* Assume "v" is not a zero vector */
524 evas_vec4_scale(out, v, 1.0 / evas_vec4_length_get(v));
525}
526
527static inline void
528evas_vec4_transform(Evas_Vec4 *out, const Evas_Vec4 *v, const Evas_Mat4 *m)
529{
530 Evas_Vec4 tmp;
531
532 if (m->flags & EVAS_MATRIX_IS_IDENTITY)
533 {
534 evas_vec4_copy(out, v);
535 return;
536 }
537
538 tmp.x = (m->m[0] * v->x) + (m->m[4] * v->y) + (m->m[ 8] * v->z) + (m->m[12] * v->w);
539 tmp.y = (m->m[1] * v->x) + (m->m[5] * v->y) + (m->m[ 9] * v->z) + (m->m[13] * v->w);
540 tmp.z = (m->m[2] * v->x) + (m->m[6] * v->y) + (m->m[10] * v->z) + (m->m[14] * v->w);
541 tmp.w = (m->m[3] * v->x) + (m->m[7] * v->y) + (m->m[11] * v->z) + (m->m[15] * v->w);
542
543 evas_vec4_copy(out, &tmp);
544}
545
546static inline void
547evas_vec3_homogeneous_position_set(Evas_Vec3 *out, const Evas_Vec4 *v)
548{
549 /* Assume "v" is a positional vector. (v->w != 0.0) */
550 Evas_Real h = 1.0 / v->w;
551
552 out->x = v->x * h;
553 out->y = v->y * h;
554 out->z = v->z * h;
555}
556
557static inline void
558evas_vec3_homogeneous_direction_set(Evas_Vec3 *out, const Evas_Vec4 *v)
559{
560 /* Assume "v" is a directional vector. (v->w == 0.0) */
561 out->x = v->x;
562 out->y = v->y;
563 out->z = v->z;
564}
565
566static inline void
567evas_vec4_homogeneous_position_set(Evas_Vec4 *out, const Evas_Vec3 *v)
568{
569 out->x = v->x;
570 out->y = v->y;
571 out->z = v->z;
572 out->w = 1.0;
573}
574
575static inline void
576evas_vec4_homogeneous_direction_set(Evas_Vec4 *out, const Evas_Vec3 *v)
577{
578 out->x = v->x;
579 out->y = v->y;
580 out->z = v->z;
581 out->w = 0.0;
582}
583
584/* 4x4 matrix */
585static inline void
586evas_mat4_identity_set(Evas_Mat4 *m)
587{
588 m->m[0] = 1.0;
589 m->m[1] = 0.0;
590 m->m[2] = 0.0;
591 m->m[3] = 0.0;
592
593 m->m[4] = 0.0;
594 m->m[5] = 1.0;
595 m->m[6] = 0.0;
596 m->m[7] = 0.0;
597
598 m->m[8] = 0.0;
599 m->m[9] = 0.0;
600 m->m[10] = 1.0;
601 m->m[11] = 0.0;
602
603 m->m[12] = 0.0;
604 m->m[13] = 0.0;
605 m->m[14] = 0.0;
606 m->m[15] = 1.0;
607
608 m->flags = EVAS_MATRIX_IS_IDENTITY;
609}
610
611static inline void
612evas_mat4_array_set(Evas_Mat4 *m, const Evas_Real *v)
613{
614 memcpy(&m->m[0], v, sizeof(Evas_Real) * 16);
615 m->flags = 0;
616}
617
618static inline void
619evas_mat4_copy(Evas_Mat4 *dst, const Evas_Mat4 *src)
620{
621 memcpy(dst, src, sizeof(Evas_Mat4));
622}
623
624static inline void
625evas_mat4_nocheck_multiply(Evas_Mat4 *out, const Evas_Mat4 *mat_a, const Evas_Mat4 *mat_b)
626{
627 Evas_Real *d = &out->m[0];
628 const Evas_Real *a = &mat_a->m[0];
629 const Evas_Real *b = &mat_b->m[0];
630
631 if (mat_a->flags & EVAS_MATRIX_IS_IDENTITY)
632 {
633 evas_mat4_copy(out, mat_b);
634 return;
635 }
636
637 if (mat_b->flags & EVAS_MATRIX_IS_IDENTITY)
638 {
639 evas_mat4_copy(out, mat_a);
640 return;
641 }
642
643 d[ 0] = a[ 0] * b[ 0] + a[ 4] * b[ 1] + a[ 8] * b[ 2] + a[12] * b [3];
644 d[ 4] = a[ 0] * b[ 4] + a[ 4] * b[ 5] + a[ 8] * b[ 6] + a[12] * b [7];
645 d[ 8] = a[ 0] * b[ 8] + a[ 4] * b[ 9] + a[ 8] * b[10] + a[12] * b[11];
646 d[12] = a[ 0] * b[12] + a[ 4] * b[13] + a[ 8] * b[14] + a[12] * b[15];
647
648 d[ 1] = a[ 1] * b[ 0] + a[ 5] * b[ 1] + a[ 9] * b[ 2] + a[13] * b [3];
649 d[ 5] = a[ 1] * b[ 4] + a[ 5] * b[ 5] + a[ 9] * b[ 6] + a[13] * b [7];
650 d[ 9] = a[ 1] * b[ 8] + a[ 5] * b[ 9] + a[ 9] * b[10] + a[13] * b[11];
651 d[13] = a[ 1] * b[12] + a[ 5] * b[13] + a[ 9] * b[14] + a[13] * b[15];
652
653 d[ 2] = a[ 2] * b[ 0] + a[ 6] * b[ 1] + a[10] * b[ 2] + a[14] * b [3];
654 d[ 6] = a[ 2] * b[ 4] + a[ 6] * b[ 5] + a[10] * b[ 6] + a[14] * b [7];
655 d[10] = a[ 2] * b[ 8] + a[ 6] * b[ 9] + a[10] * b[10] + a[14] * b[11];
656 d[14] = a[ 2] * b[12] + a[ 6] * b[13] + a[10] * b[14] + a[14] * b[15];
657
658 d[ 3] = a[ 3] * b[ 0] + a[ 7] * b[ 1] + a[11] * b[ 2] + a[15] * b [3];
659 d[ 7] = a[ 3] * b[ 4] + a[ 7] * b[ 5] + a[11] * b[ 6] + a[15] * b [7];
660 d[11] = a[ 3] * b[ 8] + a[ 7] * b[ 9] + a[11] * b[10] + a[15] * b[11];
661 d[15] = a[ 3] * b[12] + a[ 7] * b[13] + a[11] * b[14] + a[15] * b[15];
662
663 out->flags = 0;
664}
665
666static inline void
667evas_mat4_multiply(Evas_Mat4 *out, const Evas_Mat4 *mat_a, const Evas_Mat4 *mat_b)
668{
669 if (out != mat_a && out != mat_b)
670 {
671 evas_mat4_nocheck_multiply(out, mat_a, mat_b);
672 }
673 else
674 {
675 Evas_Mat4 result;
676
677 evas_mat4_nocheck_multiply(&result, mat_a, mat_b);
678 evas_mat4_copy(out, &result);
679 }
680}
681
682static inline void
683evas_mat4_look_at_set(Evas_Mat4 *m,
684 const Evas_Vec3 *pos, const Evas_Vec3 *center, const Evas_Vec3 *up)
685{
686 Evas_Vec3 x, y, z;
687
688 evas_vec3_subtract(&z, pos, center);
689 evas_vec3_normalize(&z, &z);
690
691 evas_vec3_cross_product(&x, up, &z);
692 evas_vec3_normalize(&x, &x);
693
694 evas_vec3_cross_product(&y, &z, &x);
695 evas_vec3_normalize(&y, &y);
696
697 m->m[ 0] = x.x;
698 m->m[ 1] = y.x;
699 m->m[ 2] = z.x;
700 m->m[ 3] = 0.0;
701
702 m->m[ 4] = x.y;
703 m->m[ 5] = y.y;
704 m->m[ 6] = z.y;
705 m->m[ 7] = 0.0;
706
707 m->m[ 8] = x.z;
708 m->m[ 9] = y.z;
709 m->m[10] = z.z;
710 m->m[11] = 0.0;
711
712 m->m[12] = -evas_vec3_dot_product(&x, pos);
713 m->m[13] = -evas_vec3_dot_product(&y, pos);
714 m->m[14] = -evas_vec3_dot_product(&z, pos);
715 m->m[15] = 1.0;
716
717 m->flags = 0;
718}
719
720static inline void
721evas_mat4_frustum_set(Evas_Mat4 *m,
722 Evas_Real left, Evas_Real right, Evas_Real bottom, Evas_Real top,
723 Evas_Real near, Evas_Real far)
724{
725 Evas_Real w = right - left;
726 Evas_Real h = top - bottom;
727 Evas_Real depth = near - far;
728 Evas_Real near_2 = 2.0f * near;
729
730 m->m[ 0] = near_2 / w;
731 m->m[ 1] = 0.0f;
732 m->m[ 2] = 0.0f;
733 m->m[ 3] = 0.0f;
734
735 m->m[ 4] = 0.0f;
736 m->m[ 5] = near_2 / h;
737 m->m[ 6] = 0.0f;
738 m->m[ 7] = 0.0f;
739
740 m->m[ 8] = (right + left) / w;
741 m->m[ 9] = (top + bottom) / h;
742 m->m[10] = (far + near) / depth;
743 m->m[11] = -1.0f;
744
745 m->m[12] = 0.0f;
746 m->m[13] = 0.0f;
747 m->m[14] = near_2 * far / depth;
748 m->m[15] = 0.0f;
749
750 m->flags = 0;
751}
752
753static inline void
754evas_mat4_ortho_set(Evas_Mat4 *m,
755 Evas_Real left, Evas_Real right, Evas_Real bottom, Evas_Real top,
756 Evas_Real near, Evas_Real far)
757{
758 Evas_Real w = right - left;
759 Evas_Real h = top - bottom;
760 Evas_Real depth = near - far;
761
762 m->m[ 0] = 2.0f / w;
763 m->m[ 1] = 0.0f;
764 m->m[ 2] = 0.0f;
765 m->m[ 3] = 0.0f;
766
767 m->m[ 4] = 0.0f;
768 m->m[ 5] = 2.0f / h;
769 m->m[ 6] = 0.0f;
770 m->m[ 7] = 0.0f;
771
772 m->m[ 8] = 0.0f;
773 m->m[ 9] = 0.0f;
774 m->m[10] = 2.0f / depth;
775 m->m[11] = 0.0f;
776
777 m->m[12] = -(right + left) / w;
778 m->m[13] = -(top + bottom) / h;
779 m->m[14] = (far + near) / depth;
780 m->m[15] = 1.0f;
781
782 m->flags = 0;
783}
784
785static inline void
786evas_mat4_nocheck_inverse(Evas_Mat4 *out, const Evas_Mat4 *mat)
787{
788 Evas_Real *d = &out->m[0];
789 const Evas_Real *m = &mat->m[0];
790 Evas_Real det;
791
792 if (mat->flags & EVAS_MATRIX_IS_IDENTITY)
793 {
794 evas_mat4_copy(out, mat);
795 return;
796 }
797
798 d[ 0] = m[ 5] * m[10] * m[15] -
799 m[ 5] * m[11] * m[14] -
800 m[ 9] * m[ 6] * m[15] +
801 m[ 9] * m[ 7] * m[14] +
802 m[13] * m[ 6] * m[11] -
803 m[13] * m[ 7] * m[10];
804
805 d[ 4] = -m[ 4] * m[10] * m[15] +
806 m[ 4] * m[11] * m[14] +
807 m[ 8] * m[ 6] * m[15] -
808 m[ 8] * m[ 7] * m[14] -
809 m[12] * m[ 6] * m[11] +
810 m[12] * m[ 7] * m[10];
811
812 d[ 8] = m[ 4] * m[ 9] * m[15] -
813 m[ 4] * m[11] * m[13] -
814 m[ 8] * m[ 5] * m[15] +
815 m[ 8] * m[ 7] * m[13] +
816 m[12] * m[ 5] * m[11] -
817 m[12] * m[ 7] * m[ 9];
818
819 d[12] = -m[ 4] * m[ 9] * m[14] +
820 m[ 4] * m[10] * m[13] +
821 m[ 8] * m[ 5] * m[14] -
822 m[ 8] * m[ 6] * m[13] -
823 m[12] * m[ 5] * m[10] +
824 m[12] * m[ 6] * m[ 9];
825
826 d[ 1] = -m[ 1] * m[10] * m[15] +
827 m[ 1] * m[11] * m[14] +
828 m[ 9] * m[ 2] * m[15] -
829 m[ 9] * m[ 3] * m[14] -
830 m[13] * m[ 2] * m[11] +
831 m[13] * m[ 3] * m[10];
832
833 d[ 5] = m[ 0] * m[10] * m[15] -
834 m[ 0] * m[11] * m[14] -
835 m[ 8] * m[ 2] * m[15] +
836 m[ 8] * m[ 3] * m[14] +
837 m[12] * m[ 2] * m[11] -
838 m[12] * m[ 3] * m[10];
839
840 d[ 9] = -m[ 0] * m[ 9] * m[15] +
841 m[ 0] * m[11] * m[13] +
842 m[ 8] * m[ 1] * m[15] -
843 m[ 8] * m[ 3] * m[13] -
844 m[12] * m[ 1] * m[11] +
845 m[12] * m[ 3] * m[ 9];
846
847 d[13] = m[ 0] * m[ 9] * m[14] -
848 m[ 0] * m[10] * m[13] -
849 m[ 8] * m[ 1] * m[14] +
850 m[ 8] * m[ 2] * m[13] +
851 m[12] * m[ 1] * m[10] -
852 m[12] * m[ 2] * m[ 9];
853
854 d[ 2] = m[ 1] * m[ 6] * m[15] -
855 m[ 1] * m[ 7] * m[14] -
856 m[ 5] * m[ 2] * m[15] +
857 m[ 5] * m[ 3] * m[14] +
858 m[13] * m[ 2] * m[ 7] -
859 m[13] * m[ 3] * m[ 6];
860
861 d[ 6] = -m[ 0] * m[ 6] * m[15] +
862 m[ 0] * m[ 7] * m[14] +
863 m[ 4] * m[ 2] * m[15] -
864 m[ 4] * m[ 3] * m[14] -
865 m[12] * m[ 2] * m[ 7] +
866 m[12] * m[ 3] * m[ 6];
867
868 d[10] = m[ 0] * m[ 5] * m[15] -
869 m[ 0] * m[ 7] * m[13] -
870 m[ 4] * m[ 1] * m[15] +
871 m[ 4] * m[ 3] * m[13] +
872 m[12] * m[ 1] * m[ 7] -
873 m[12] * m[ 3] * m[ 5];
874
875 d[14] = -m[ 0] * m[ 5] * m[14] +
876 m[ 0] * m[ 6] * m[13] +
877 m[ 4] * m[ 1] * m[14] -
878 m[ 4] * m[ 2] * m[13] -
879 m[12] * m[ 1] * m[ 6] +
880 m[12] * m[ 2] * m[ 5];
881
882 d[ 3] = -m[ 1] * m[ 6] * m[11] +
883 m[ 1] * m[ 7] * m[10] +
884 m[ 5] * m[ 2] * m[11] -
885 m[ 5] * m[ 3] * m[10] -
886 m[ 9] * m[ 2] * m[ 7] +
887 m[ 9] * m[ 3] * m[ 6];
888
889 d[ 7] = m[ 0] * m[ 6] * m[11] -
890 m[ 0] * m[ 7] * m[10] -
891 m[ 4] * m[ 2] * m[11] +
892 m[ 4] * m[ 3] * m[10] +
893 m[ 8] * m[ 2] * m[ 7] -
894 m[ 8] * m[ 3] * m[ 6];
895
896 d[11] = -m[ 0] * m[ 5] * m[11] +
897 m[ 0] * m[ 7] * m[ 9] +
898 m[ 4] * m[ 1] * m[11] -
899 m[ 4] * m[ 3] * m[ 9] -
900 m[ 8] * m[ 1] * m[ 7] +
901 m[ 8] * m[ 3] * m[ 5];
902
903 d[15] = m[ 0] * m[ 5] * m[10] -
904 m[ 0] * m[ 6] * m[ 9] -
905 m[ 4] * m[ 1] * m[10] +
906 m[ 4] * m[ 2] * m[ 9] +
907 m[ 8] * m[ 1] * m[ 6] -
908 m[ 8] * m[ 2] * m[ 5];
909
910 det = m[0] * d[0] + m[1] * d[4] + m[2] * d[8] + m[3] * d[12];
911
912 if (det == 0.0)
913 return;
914
915 det = 1.0 / det;
916
917 d[ 0] *= det;
918 d[ 1] *= det;
919 d[ 2] *= det;
920 d[ 3] *= det;
921 d[ 4] *= det;
922 d[ 5] *= det;
923 d[ 6] *= det;
924 d[ 7] *= det;
925 d[ 8] *= det;
926 d[ 9] *= det;
927 d[10] *= det;
928 d[11] *= det;
929 d[12] *= det;
930 d[13] *= det;
931 d[14] *= det;
932 d[15] *= det;
933
934 out->flags = 0;
935}
936
937static inline void
938evas_mat4_inverse(Evas_Mat4 *out, const Evas_Mat4 *mat)
939{
940 if (out != mat)
941 {
942 evas_mat4_nocheck_inverse(out, mat);
943 }
944 else
945 {
946 Evas_Mat4 tmp;
947
948 evas_mat4_nocheck_inverse(&tmp, mat);
949 evas_mat4_copy(out, &tmp);
950 }
951}
952
953static inline void
954evas_normal_matrix_get(Evas_Mat3 *out, const Evas_Mat4 *m)
955{
956 /* Normal matrix is a transposed matirx of inversed modelview.
957 * And we need only upper-left 3x3 terms to work with. */
958
959 Evas_Real det;
960 Evas_Real a = m->m[0];
961 Evas_Real b = m->m[4];
962 Evas_Real c = m->m[8];
963 Evas_Real d = m->m[1];
964 Evas_Real e = m->m[5];
965 Evas_Real f = m->m[9];
966 Evas_Real g = m->m[2];
967 Evas_Real h = m->m[6];
968 Evas_Real i = m->m[10];
969
970 det = a * e * i + b * f * g + c * d * h - g * e * c - h * f * a - i * d * b;
971 det = 1.0 / det;
972
973 out->m[0] = (e * i - f * h) * det;
974 out->m[1] = (h * c - i * b) * det;
975 out->m[2] = (b * f - c * e) * det;
976 out->m[3] = (g * f - d * i) * det;
977 out->m[4] = (a * i - g * c) * det;
978 out->m[5] = (d * c - a * f) * det;
979 out->m[6] = (d * h - g * e) * det;
980 out->m[7] = (g * b - a * h) * det;
981 out->m[8] = (a * e - d * b) * det;
982
983 out->flags = 0;
984}
985
986/* 3x3 matrix */
987static inline void
988evas_mat3_identity_set(Evas_Mat3 *m)
989{
990 m->m[0] = 1.0;
991 m->m[1] = 0.0;
992 m->m[2] = 0.0;
993 m->m[3] = 0.0;
994 m->m[4] = 1.0;
995 m->m[5] = 0.0;
996 m->m[6] = 0.0;
997 m->m[7] = 0.0;
998 m->m[8] = 1.0;
999
1000 m->flags = EVAS_MATRIX_IS_IDENTITY;
1001}
1002
1003static inline void
1004evas_mat3_array_set(Evas_Mat3 *m, const Evas_Real *v)
1005{
1006 memcpy(&m->m[0], v, sizeof(Evas_Real) * 9);
1007 m->flags = 0;
1008}
1009
1010static inline void
1011evas_mat3_copy(Evas_Mat3 *dst, const Evas_Mat3 *src)
1012{
1013 memcpy(dst, src, sizeof(Evas_Mat3));
1014}
1015
1016static inline void
1017evas_mat3_nocheck_multiply(Evas_Mat3 *out, const Evas_Mat3 *mat_a, const Evas_Mat3 *mat_b)
1018{
1019 Evas_Real *d = &out->m[0];
1020 const Evas_Real *a = &mat_a->m[0];
1021 const Evas_Real *b = &mat_b->m[0];
1022
1023 if (mat_a->flags & EVAS_MATRIX_IS_IDENTITY)
1024 {
1025 evas_mat3_copy(out, mat_b);
1026 return;
1027 }
1028
1029 if (mat_b->flags & EVAS_MATRIX_IS_IDENTITY)
1030 {
1031 evas_mat3_copy(out, mat_a);
1032 return;
1033 }
1034
1035 d[0] = a[0] * b[0] + a[3] * b[1] + a[6] * b[2];
1036 d[3] = a[0] * b[3] + a[3] * b[4] + a[6] * b[5];
1037 d[6] = a[0] * b[6] + a[3] * b[7] + a[6] * b[8];
1038
1039 d[1] = a[1] * b[0] + a[4] * b[1] + a[7] * b[2];
1040 d[4] = a[1] * b[3] + a[4] * b[4] + a[7] * b[5];
1041 d[7] = a[1] * b[6] + a[4] * b[7] + a[7] * b[8];
1042
1043 d[2] = a[2] * b[0] + a[5] * b[1] + a[8] * b[2];
1044 d[5] = a[2] * b[3] + a[5] * b[4] + a[8] * b[5];
1045 d[8] = a[2] * b[6] + a[5] * b[7] + a[8] * b[8];
1046
1047 out->flags = 0;
1048}
1049
1050static inline void
1051evas_mat3_multiply(Evas_Mat3 *out, const Evas_Mat3 *mat_a, const Evas_Mat3 *mat_b)
1052{
1053 if (out != mat_a && out != mat_b)
1054 {
1055 evas_mat3_nocheck_multiply(out, mat_a, mat_b);
1056 }
1057 else
1058 {
1059 Evas_Mat3 tmp;
1060
1061 evas_mat3_nocheck_multiply(&tmp, mat_a, mat_b);
1062 evas_mat3_copy(out, &tmp);
1063 }
1064}
1065
1066static inline void
1067evas_mat3_nocheck_inverse(Evas_Mat3 *out, const Evas_Mat3 *mat)
1068{
1069 Evas_Real *d = &out->m[0];
1070 const Evas_Real *m = &mat->m[0];
1071 Evas_Real det;
1072
1073 if (mat->flags & EVAS_MATRIX_IS_IDENTITY)
1074 {
1075 evas_mat3_copy(out, mat);
1076 return;
1077 }
1078
1079 d[0] = m[4] * m[8] - m[7] * m[5];
1080 d[1] = m[7] * m[2] - m[1] * m[8];
1081 d[2] = m[1] * m[5] - m[4] * m[2];
1082 d[3] = m[6] * m[5] - m[3] * m[8];
1083 d[4] = m[0] * m[8] - m[6] * m[2];
1084 d[5] = m[3] * m[2] - m[0] * m[5];
1085 d[6] = m[3] * m[7] - m[6] * m[4];
1086 d[7] = m[6] * m[1] - m[0] * m[7];
1087 d[8] = m[0] * m[4] - m[3] * m[1];
1088
1089 det = m[0] * d[0] + m[1] * d[3] + m[2] * d[6];
1090
1091 if (det == 0.0)
1092 return;
1093
1094 det = 1.0 / det;
1095
1096 d[0] *= det;
1097 d[1] *= det;
1098 d[2] *= det;
1099 d[3] *= det;
1100 d[4] *= det;
1101 d[5] *= det;
1102 d[6] *= det;
1103 d[7] *= det;
1104 d[8] *= det;
1105
1106 out->flags = 0;
1107}
1108
1109static inline void
1110evas_mat3_invserse(Evas_Mat3 *out, const Evas_Mat3 *mat)
1111{
1112 if (out != mat)
1113 {
1114 evas_mat3_nocheck_inverse(out, mat);
1115 }
1116 else
1117 {
1118 Evas_Mat3 tmp;
1119
1120 evas_mat3_nocheck_inverse(&tmp, mat);
1121 evas_mat3_copy(out, &tmp);
1122 }
1123}
1124
1125/* 2x2 matrix */
1126static inline void
1127evas_mat2_identity_set(Evas_Mat2 *m)
1128{
1129 m->m[0] = 1.0;
1130 m->m[1] = 0.0;
1131 m->m[2] = 0.0;
1132 m->m[3] = 1.0;
1133
1134 m->flags = EVAS_MATRIX_IS_IDENTITY;
1135}
1136
1137static inline void
1138evas_mat2_array_set(Evas_Mat2 *m, const Evas_Real *v)
1139{
1140 memcpy(&m->m[0], v, sizeof(Evas_Real) * 4);
1141 m->flags = 0;
1142}
1143
1144static inline void
1145evas_mat2_copy(Evas_Mat2 *dst, const Evas_Mat2 *src)
1146{
1147 memcpy(dst, src, sizeof(Evas_Mat2));
1148}
1149
1150static inline void
1151evas_mat2_nocheck_multiply(Evas_Mat2 *out, const Evas_Mat2 *mat_a, const Evas_Mat2 *mat_b)
1152{
1153 Evas_Real *d = &out->m[0];
1154 const Evas_Real *a = &mat_a->m[0];
1155 const Evas_Real *b = &mat_b->m[0];
1156
1157 if (mat_a->flags & EVAS_MATRIX_IS_IDENTITY)
1158 {
1159 evas_mat2_copy(out, mat_b);
1160 return;
1161 }
1162
1163 if (mat_b->flags & EVAS_MATRIX_IS_IDENTITY)
1164 {
1165 evas_mat2_copy(out, mat_a);
1166 return;
1167 }
1168
1169 d[0] = a[0] * b[0] + a[2] * b[1];
1170 d[2] = a[0] * b[2] + a[2] * b[3];
1171
1172 d[1] = a[1] * b[0] + a[3] * b[1];
1173 d[3] = a[1] * b[2] + a[3] * b[3];
1174
1175 out->flags = 0;
1176}
1177
1178static inline void
1179evas_mat2_multiply(Evas_Mat2 *out, const Evas_Mat2 *mat_a, const Evas_Mat2 *mat_b)
1180{
1181 if (out != mat_a && out != mat_b)
1182 {
1183 evas_mat2_nocheck_multiply(out, mat_a, mat_b);
1184 }
1185 else
1186 {
1187 Evas_Mat2 tmp;
1188
1189 evas_mat2_nocheck_multiply(&tmp, mat_a, mat_b);
1190 evas_mat2_copy(out, &tmp);
1191 }
1192}
1193
1194static inline void
1195evas_mat2_nocheck_inverse(Evas_Mat2 *out, const Evas_Mat2 *mat)
1196{
1197 Evas_Real *d = &out->m[0];
1198 const Evas_Real *m = &mat->m[0];
1199 Evas_Real det;
1200
1201 if (mat->flags & EVAS_MATRIX_IS_IDENTITY)
1202 {
1203 evas_mat2_copy(out, mat);
1204 return;
1205 }
1206
1207 det = m[0] * m[3] - m[2] * m[1];
1208
1209 if (det == 0.0)
1210 return;
1211
1212 det = 1.0 / det;
1213
1214 d[0] = m[3] * det;
1215 d[1] = -m[1] * det;
1216 d[2] = -m[2] * det;
1217 d[3] = m[0] * det;
1218
1219 out->flags = 0;
1220}
1221
1222static inline void
1223evas_mat2_invserse(Evas_Mat2 *out, const Evas_Mat2 *mat)
1224{
1225 if (out != mat)
1226 {
1227 evas_mat2_nocheck_inverse(out, mat);
1228 }
1229 else
1230 {
1231 Evas_Mat2 tmp;
1232
1233 evas_mat2_nocheck_inverse(&tmp, mat);
1234 evas_mat2_copy(out, &tmp);
1235 }
1236}
1237
1238static inline void
1239evas_box2_set(Evas_Box2 *box, Evas_Real x0, Evas_Real y0, Evas_Real x1, Evas_Real y1)
1240{
1241 box->p0.x = x0;
1242 box->p0.y = y0;
1243 box->p1.x = x1;
1244 box->p1.y = y1;
1245}
1246
1247static inline void
1248evas_box3_set(Evas_Box3 *box, Evas_Real x0, Evas_Real y0, Evas_Real z0, Evas_Real x1, Evas_Real y1, Evas_Real z1)
1249{
1250 box->p0.x = x0;
1251 box->p0.y = y0;
1252 box->p0.z = z0;
1253 box->p1.x = x1;
1254 box->p1.y = y1;
1255 box->p1.z = z1;
1256}
1257
1258static inline void
1259evas_box3_empty_set(Evas_Box3 *box)
1260{
1261 evas_vec3_set(&box->p0, 0.0, 0.0, 0.0);
1262 evas_vec3_set(&box->p1, 0.0, 0.0, 0.0);
1263}
1264
1265static inline void
1266evas_box3_copy(Evas_Box3 *dst, const Evas_Box3 *src)
1267{
1268 evas_vec3_copy(&dst->p0, &src->p0);
1269 evas_vec3_copy(&dst->p1, &src->p1);
1270}
1271
1272static inline void
1273evas_box3_union(Evas_Box3 *out, const Evas_Box3 *a, const Evas_Box3 *b)
1274{
1275 evas_vec3_set(&out->p0, MIN(a->p0.x, b->p0.x), MIN(a->p0.y, b->p0.y), MIN(a->p0.z, b->p0.z));
1276 evas_vec3_set(&out->p1, MAX(a->p1.x, b->p1.x), MAX(a->p1.y, b->p1.y), MAX(a->p1.z, b->p1.z));
1277}
1278
1279static inline void
1280evas_box3_transform(Evas_Box3 *out EINA_UNUSED, const Evas_Box3 *box EINA_UNUSED, const Evas_Mat4 *mat EINA_UNUSED)
1281{
1282 /* TODO: */
1283}
1284
1285static inline void
1286evas_mat4_position_get(const Evas_Mat4 *matrix, Evas_Vec4 *position)
1287{
1288 Evas_Vec4 pos;
1289
1290 pos.x = 0.0;
1291 pos.y = 0.0;
1292 pos.z = 0.0;
1293 pos.w = 1.0;
1294
1295 evas_vec4_transform(position, &pos, matrix);
1296}
1297
1298static inline void
1299evas_mat4_direction_get(const Evas_Mat4 *matrix, Evas_Vec3 *direction)
1300{
1301 /* TODO: Check correctness. */
1302
1303 Evas_Vec4 dir;
1304
1305 dir.x = 0.0;
1306 dir.y = 0.0;
1307 dir.z = 1.0;
1308 dir.w = 1.0;
1309
1310 evas_vec4_transform(&dir, &dir, matrix);
1311
1312 direction->x = dir.x;
1313 direction->y = dir.y;
1314 direction->z = dir.z;
1315}
1316
1317static inline void
1318evas_vec4_quaternion_multiply(Evas_Vec4 *out, const Evas_Vec4 *a, const Evas_Vec4 *b)
1319{
1320 Evas_Vec4 r;
1321
1322 r.x = (a->w * b->x) + (a->x * b->w) + (a->y * b->z) - (a->z * b->y);
1323 r.y = (a->w * b->y) - (a->x * b->z) + (a->y * b->w) + (a->z * b->x);
1324 r.z = (a->w * b->z) + (a->x * b->y) - (a->y * b->x) + (a->z * b->w);
1325 r.w = (a->w * b->w) - (a->x * b->x) - (a->y * b->y) - (a->z * b->z);
1326
1327 *out = r;
1328}
1329
1330static inline void
1331evas_vec4_quaternion_inverse(Evas_Vec4 *out, const Evas_Vec4 *q)
1332{
1333 Evas_Real norm = (q->x * q->x) + (q->y * q->y) + (q->z * q->z) + (q->w * q->w);
1334
1335 if (norm > 0.0)
1336 {
1337 Evas_Real inv_norm = 1.0 / norm;
1338 out->x = -q->x * inv_norm;
1339 out->y = -q->y * inv_norm;
1340 out->z = -q->z * inv_norm;
1341 out->w = q->w * inv_norm;
1342 }
1343 else
1344 {
1345 out->x = 0.0;
1346 out->y = 0.0;
1347 out->z = 0.0;
1348 out->w = 0.0;
1349 }
1350}
1351
1352static inline void
1353evas_vec4_quaternion_rotation_matrix_get(const Evas_Vec4 *q, Evas_Mat3 *mat)
1354{
1355 Evas_Real x, y, z;
1356 Evas_Real xx, xy, xz;
1357 Evas_Real yy, yz;
1358 Evas_Real zz;
1359 Evas_Real wx, wy, wz;
1360
1361 x = 2.0 * q->x;
1362 y = 2.0 * q->y;
1363 z = 2.0 * q->z;
1364
1365 xx = q->x * x;
1366 xy = q->x * y;
1367 xz = q->x * z;
1368
1369 yy = q->y * y;
1370 yz = q->y * z;
1371
1372 zz = q->z * z;
1373
1374 wx = q->w * x;
1375 wy = q->w * y;
1376 wz = q->w * z;
1377
1378 mat->m[0] = 1.0 - yy - zz;
1379 mat->m[1] = xy + wz;
1380 mat->m[2] = xz - wy;
1381 mat->m[3] = xy - wz;
1382 mat->m[4] = 1.0 - xx - zz;
1383 mat->m[5] = yz + wx;
1384 mat->m[6] = xz + wy;
1385 mat->m[7] = yz - wx;
1386 mat->m[8] = 1.0 - xx - yy;
1387}
1388
1389static inline void
1390evas_mat4_build(Evas_Mat4 *out,
1391 const Evas_Vec3 *position, const Evas_Vec4 *orientation, const Evas_Vec3 *scale)
1392{
1393 Evas_Mat3 rot;
1394
1395 evas_vec4_quaternion_rotation_matrix_get(orientation, &rot);
1396
1397 out->m[ 0] = scale->x * rot.m[0];
1398 out->m[ 1] = scale->x * rot.m[1];
1399 out->m[ 2] = scale->x * rot.m[2];
1400 out->m[ 3] = 0.0;
1401
1402 out->m[ 4] = scale->y * rot.m[3];
1403 out->m[ 5] = scale->y * rot.m[4];
1404 out->m[ 6] = scale->y * rot.m[5];
1405 out->m[ 7] = 0.0;
1406
1407 out->m[ 8] = scale->z * rot.m[6];
1408 out->m[ 9] = scale->z * rot.m[7];
1409 out->m[10] = scale->z * rot.m[8];
1410 out->m[11] = 0.0;
1411
1412 out->m[12] = position->x;
1413 out->m[13] = position->y;
1414 out->m[14] = position->z;
1415 out->m[15] = 1.0;
1416}
1417
1418static inline void
1419evas_mat4_inverse_build(Evas_Mat4 *out, const Evas_Vec3 *position,
1420 const Evas_Vec4 *orientation, const Evas_Vec3 *scale)
1421{
1422 Evas_Vec4 inv_rotation;
1423 Evas_Vec3 inv_scale;
1424 Evas_Vec3 inv_translate;
1425
1426 Evas_Mat3 rot;
1427
1428 /* Inverse scale. */
1429 evas_vec3_set(&inv_scale, 1.0 / scale->x, 1.0 / scale->y, 1.0 / scale->z);
1430
1431 /* Inverse rotation. */
1432 evas_vec4_quaternion_inverse(&inv_rotation, orientation);
1433
1434 /* Inverse translation. */
1435 evas_vec3_negate(&inv_translate, position);
1436 evas_vec3_quaternion_rotate(&inv_translate, &inv_translate, &inv_rotation);
1437 evas_vec3_multiply(&inv_translate, &inv_translate, &inv_scale);
1438
1439 /* Get 3x3 rotation matrix. */
1440 evas_vec4_quaternion_rotation_matrix_get(&inv_rotation, &rot);
1441
1442 out->m[ 0] = inv_scale.x * rot.m[0];
1443 out->m[ 1] = inv_scale.y * rot.m[1];
1444 out->m[ 2] = inv_scale.z * rot.m[2];
1445 out->m[ 3] = 0.0;
1446
1447 out->m[ 4] = inv_scale.x * rot.m[3];
1448 out->m[ 5] = inv_scale.y * rot.m[4];
1449 out->m[ 6] = inv_scale.z * rot.m[5];
1450 out->m[ 7] = 0.0;
1451
1452 out->m[ 8] = inv_scale.x * rot.m[6];
1453 out->m[ 9] = inv_scale.y * rot.m[7];
1454 out->m[10] = inv_scale.z * rot.m[8];
1455 out->m[11] = 0.0;
1456
1457 out->m[12] = inv_translate.x;
1458 out->m[13] = inv_translate.y;
1459 out->m[14] = inv_translate.z;
1460 out->m[15] = 1.0;
1461}
1462
1463static inline void
1464evas_color_set(Evas_Color *color, Evas_Real r, Evas_Real g, Evas_Real b, Evas_Real a)
1465{
1466 color->r = r;
1467 color->g = g;
1468 color->b = b;
1469 color->a = a;
1470}
1471
1472static inline void
1473evas_color_blend(Evas_Color *dst, const Evas_Color *c0, const Evas_Color *c1, Evas_Real w)
1474{
1475 dst->r = c0->r * w + c1->r * (1.0 - w);
1476 dst->g = c0->g * w + c1->g * (1.0 - w);
1477 dst->b = c0->b * w + c1->b * (1.0 - w);
1478 dst->a = c0->a * w + c1->a * (1.0 - w);
1479}
1480
1481static inline void
1482evas_ray3_init(Evas_Ray3 *ray, Evas_Real x, Evas_Real y, const Evas_Mat4 *mvp)
1483{
1484 Evas_Mat4 mat;
1485 Evas_Vec4 near, far;
1486
1487 /* Get the matrix which transforms from normalized device coordinate to modeling coodrinate. */
1488 evas_mat4_inverse(&mat, mvp);
1489
1490 /* Transform near point. */
1491 near.x = x;
1492 near.y = y;
1493 near.z = -1.0;
1494 near.w = 1.0;
1495
1496 evas_vec4_transform(&near, &near, &mat);
1497
1498 near.w = 1.0 / near.w;
1499 near.x *= near.w;
1500 near.y *= near.w;
1501 near.z *= near.w;
1502
1503 evas_vec3_set(&ray->org, near.x, near.y, near.z);
1504
1505 /* Transform far point. */
1506 far.x = x;
1507 far.y = y;
1508 far.z = 1.0;
1509 far.w = 1.0;
1510
1511 evas_vec4_transform(&far, &far, &mat);
1512
1513 far.w = 1.0 / far.w;
1514 far.x *= far.w;
1515 far.y *= far.w;
1516 far.z *= far.w;
1517
1518 evas_vec3_set(&ray->dir, far.x - near.x, far.y - near.y, far.z - near.z);
1519}
1520
1521static inline Eina_Bool
1522evas_box3_ray3_intersect(const Evas_Box3 *box EINA_UNUSED, const Evas_Ray3 *ray EINA_UNUSED)
1523{
1524 /* TODO: */
1525 return EINA_TRUE;
1526}