Changed indicator bg color.
[platform/framework/native/uifw.git] / src / ui / FUi_Matrix3Df.cpp
1 //
2 // Open Service Platform
3 // Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
4 //
5 // Licensed under the Apache License, Version 2.0 (the License);
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 //     http://www.apache.org/licenses/LICENSE-2.0/
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 //
17
18 /**
19  * @file                FUi_Matrix3Df.h
20  * @brief               Header file of _Matrix3Df class
21  *
22  * This file contains declarations _Matrix3Df class.
23  */
24
25 #include <math.h>
26 #include "FUi_Math.h"
27 #include "FUi_Matrix3Df.h"
28
29 #define PI              3.141592653f
30
31 namespace
32 {
33
34 float identityTransform[4][4] =
35 {
36         { 1.0f, 0.0f, 0.0f, 0.0f },
37         { 0.0f, 1.0f, 0.0f, 0.0f },
38         { 0.0f, 0.0f, 1.0f, 0.0f },
39         { 0.0f, 0.0f, 0.0f, 1.0f }
40 };
41
42 };
43
44 namespace Tizen { namespace Ui { namespace Animations
45 {
46
47 _Matrix3Df::_Matrix3Df(void)
48 {
49         LoadIdentity();
50 }
51
52 _Matrix3Df::_Matrix3Df(const float* pValues)
53 {
54         memcpy(__m, pValues, sizeof(__m));
55         __complexity = GenericMatrix;
56 }
57
58 _Matrix3Df&
59 _Matrix3Df::Assign(const _Matrix3Df& rhs)
60 {
61         memcpy(__m, rhs.__m, sizeof(__m));
62         __complexity = rhs.__complexity;
63
64         return *this;
65 }
66
67 _Matrix3Df&
68 _Matrix3Df::operator =(const _Matrix3Df& rhs)
69 {
70         if (&rhs != this)
71                 return Assign(rhs);
72
73         return *this;
74 }
75
76 bool
77 _Matrix3Df::operator ==(const _Matrix3Df& rhs) const
78 {
79         return (__m[0][0] == rhs.__m[0][0] &&
80                         __m[0][1] == rhs.__m[0][1] &&
81                         __m[0][2] == rhs.__m[0][2] &&
82                         __m[0][3] == rhs.__m[0][3] &&
83                         __m[1][0] == rhs.__m[1][0] &&
84                         __m[1][1] == rhs.__m[1][1] &&
85                         __m[1][2] == rhs.__m[1][2] &&
86                         __m[1][3] == rhs.__m[1][3] &&
87                         __m[2][0] == rhs.__m[2][0] &&
88                         __m[2][1] == rhs.__m[2][1] &&
89                         __m[2][2] == rhs.__m[2][2] &&
90                         __m[2][3] == rhs.__m[2][3] &&
91                         __m[3][0] == rhs.__m[3][0] &&
92                         __m[3][1] == rhs.__m[3][1] &&
93                         __m[3][2] == rhs.__m[3][2] &&
94                         __m[3][3] == rhs.__m[3][3]);
95 }
96
97 bool
98 _Matrix3Df::operator !=(const _Matrix3Df& rhs) const
99 {
100         return (__m[0][0] != rhs.__m[0][0] ||
101                         __m[0][1] != rhs.__m[0][1] ||
102                         __m[0][2] != rhs.__m[0][2] ||
103                         __m[0][3] != rhs.__m[0][3] ||
104                         __m[1][0] != rhs.__m[1][0] ||
105                         __m[1][1] != rhs.__m[1][1] ||
106                         __m[1][2] != rhs.__m[1][2] ||
107                         __m[1][3] != rhs.__m[1][3] ||
108                         __m[2][0] != rhs.__m[2][0] ||
109                         __m[2][1] != rhs.__m[2][1] ||
110                         __m[2][2] != rhs.__m[2][2] ||
111                         __m[2][3] != rhs.__m[2][3] ||
112                         __m[3][0] != rhs.__m[3][0] ||
113                         __m[3][1] != rhs.__m[3][1] ||
114                         __m[3][2] != rhs.__m[3][2] ||
115                         __m[3][3] != rhs.__m[3][3]);
116 }
117
118 void
119 _Matrix3Df::Optimize(void)
120 {
121         if (__m[3][3] != 1.0f)
122         {
123                 __complexity = GenericMatrix;
124                 return;
125         }
126
127         if (__m[1][0] != 0.0f || __m[2][0] != 0.0f || __m[2][1] != 0.0f)
128         {
129                 __complexity = GenericMatrix;
130                 return;
131         }
132
133         if (__m[0][1] != 0.0f || __m[0][2] != 0.0f || __m[0][3] != 0.0f ||
134                 __m[1][2] != 0.0f || __m[1][3] != 0.0f || __m[2][3] != 0.0f)
135         {
136                 __complexity = GenericMatrix;
137                 return;
138         }
139
140         bool isTranslate = (__m[3][0] != 0.0f || __m[3][1] != 0.0f || __m[3][2] != 0.0f);
141         bool isDiagonal = (__m[0][0] == 1.0f && __m[1][1] == 1.0f && __m[2][2] == 1.0f);
142
143         if (isTranslate && isDiagonal)
144                 __complexity = TranslationMatrix;
145         else if (isTranslate)
146                 __complexity = GenericMatrix;
147         else if (isDiagonal)
148                 __complexity = IdentityMatrix;
149         else
150                 __complexity = ScaleMatrix;
151 }
152
153 _Matrix3Df&
154 _Matrix3Df::operator *=(const _Matrix3Df& rhs)
155 {
156         if (__complexity == IdentityMatrix)
157         {
158                 *this = rhs;
159         }
160         else if (rhs.__complexity == IdentityMatrix)
161         {
162                 // nothing...
163         }
164         else
165         {
166                 *this = *this * rhs;
167         }
168
169         return *this;
170 }
171
172 _Matrix3Df&
173 _Matrix3Df::MultiplyMatrix(const _Matrix3Df& matrix)
174 {
175         *this = *this * matrix;
176
177         return *this;
178 }
179
180 _Matrix3Df&
181 _Matrix3Df::Concatenate(const _Matrix3Df* matrix)
182 {
183         return Concatenate(*matrix);
184 }
185
186 _Matrix3Df&
187 _Matrix3Df::Concatenate(const _Matrix3Df& matrix)
188 {
189         *this = matrix * *this;
190
191         return *this;
192 }
193
194 float
195 _Matrix3Df::GetDeterminant(void) const
196 {
197         float a0, a1, a2, a3, a4, a5;
198         float b0, b1, b2, b3, b4, b5;
199         float det;
200
201         a0 = __m[0][0] * __m[1][1] - __m[0][1] * __m[1][0];
202         a1 = __m[0][0] * __m[1][2] - __m[0][2] * __m[1][0];
203         a2 = __m[0][0] * __m[1][3] - __m[0][3] * __m[1][0];
204         a3 = __m[0][1] * __m[1][2] - __m[0][2] * __m[1][1];
205         a4 = __m[0][1] * __m[1][3] - __m[0][3] * __m[1][1];
206         a5 = __m[0][2] * __m[1][3] - __m[0][3] * __m[1][2];
207
208         b0 = __m[2][0] * __m[3][1] - __m[2][1] * __m[3][0];
209         b1 = __m[2][0] * __m[3][2] - __m[2][2] * __m[3][0];
210         b2 = __m[2][0] * __m[3][3] - __m[2][3] * __m[3][0];
211         b3 = __m[2][1] * __m[3][2] - __m[2][2] * __m[3][1];
212         b4 = __m[2][1] * __m[3][3] - __m[2][3] * __m[3][1];
213         b5 = __m[2][2] * __m[3][3] - __m[2][3] * __m[3][2];
214
215         det = a0 * b5 - a1 * b4 + a2 * b3 + a3 * b2 - a4 * b1 + a5 * b0;
216
217         return det;
218 }
219
220 bool
221 _Matrix3Df::IsInvertible(void) const
222 {
223         if (__complexity == IdentityMatrix)
224                 return true;
225
226         if (__complexity == TranslationMatrix)
227                 return true;
228
229         return !_FloatHardCompare(GetDeterminant(), 0.0f);
230 }
231
232 bool
233 _Matrix3Df::Invert(void)
234 {
235         // TODO:
236         //      Optimize using NEON
237         float a0, a1, a2, a3, a4, a5;
238         float b0, b1, b2, b3, b4, b5;
239         float det;
240
241         if (__complexity == IdentityMatrix)
242                 return true;
243
244         if (__complexity == TranslationMatrix)
245         {
246                 __m[3][0] = -__m[3][0];
247                 __m[3][1] = -__m[3][1];
248                 __m[3][2] = -__m[3][2];
249                 return true;
250         }
251
252
253         a0 = __m[0][0] * __m[1][1] - __m[0][1] * __m[1][0];
254         a1 = __m[0][0] * __m[1][2] - __m[0][2] * __m[1][0];
255         a2 = __m[0][0] * __m[1][3] - __m[0][3] * __m[1][0];
256         a3 = __m[0][1] * __m[1][2] - __m[0][2] * __m[1][1];
257         a4 = __m[0][1] * __m[1][3] - __m[0][3] * __m[1][1];
258         a5 = __m[0][2] * __m[1][3] - __m[0][3] * __m[1][2];
259
260         b0 = __m[2][0] * __m[3][1] - __m[2][1] * __m[3][0];
261         b1 = __m[2][0] * __m[3][2] - __m[2][2] * __m[3][0];
262         b2 = __m[2][0] * __m[3][3] - __m[2][3] * __m[3][0];
263         b3 = __m[2][1] * __m[3][2] - __m[2][2] * __m[3][1];
264         b4 = __m[2][1] * __m[3][3] - __m[2][3] * __m[3][1];
265         b5 = __m[2][2] * __m[3][3] - __m[2][3] * __m[3][2];
266
267         det = a0 * b5 - a1 * b4 + a2 * b3 + a3 * b2 - a4 * b1 + a5 * b0;
268         if (_FloatHardCompare(det, 0.0f))
269                 return false;
270
271
272         float inverse_m[4][4];
273
274         inverse_m[0][0] = +__m[1][1] * b5 - __m[1][2] * b4 + __m[1][3] * b3;
275         inverse_m[1][0] = -__m[1][0] * b5 + __m[1][2] * b2 + __m[1][3] * b1;
276         inverse_m[2][0] = +__m[1][0] * b4 - __m[1][1] * b2 + __m[1][3] * b0;
277         inverse_m[3][0] = -__m[1][0] * b3 + __m[1][1] * b1 - __m[1][2] * b0;
278         inverse_m[0][1] = -__m[0][1] * b5 + __m[0][2] * b4 - __m[0][3] * b3;
279         inverse_m[1][1] = +__m[0][0] * b5 - __m[0][2] * b2 + __m[0][3] * b1;
280         inverse_m[2][1] = -__m[0][0] * b4 + __m[0][1] * b2 - __m[0][3] * b0;
281         inverse_m[3][1] = +__m[0][0] * b3 - __m[0][1] * b1 + __m[0][2] * b0;
282         inverse_m[0][2] = +__m[3][1] * a5 - __m[3][2] * a4 + __m[3][3] * a3;
283         inverse_m[1][2] = -__m[3][0] * a5 + __m[3][2] * a2 - __m[3][3] * a1;
284         inverse_m[2][2] = +__m[3][0] * a4 - __m[3][1] * a2 + __m[3][3] * a0;
285         inverse_m[3][2] = -__m[3][0] * a3 + __m[3][1] * a1 - __m[3][2] * a0;
286         inverse_m[0][3] = -__m[2][1] * a5 + __m[2][2] * a4 - __m[2][3] * a3;
287         inverse_m[1][3] = +__m[2][0] * a5 - __m[2][2] * a2 + __m[2][3] * a1;
288         inverse_m[2][3] = -__m[2][0] * a4 + __m[2][1] * a2 - __m[2][3] * a0;
289         inverse_m[3][3] = +__m[2][0] * a3 - __m[2][1] * a1 + __m[2][2] * a0;
290
291         for (int i = 0; i < 4; i++)
292         {
293                 for (int j = 0; j < 4; j++)
294                         inverse_m[j][i] /= det;
295         }
296
297         memcpy(__m, inverse_m, sizeof(__m));
298         __complexity = GenericMatrix;
299
300         return true;
301 }
302
303 void
304 _Matrix3Df::LoadIdentity(void)
305 {
306         memcpy(__m, identityTransform, sizeof(__m));
307         __complexity = IdentityMatrix;
308 }
309
310 void
311 _Matrix3Df::Transpose(void)
312 {
313         int i, j;
314         float tmp;
315
316         for (i = 0; i < 4; i++)
317         {
318                 for (j = i + 1; j < 4; j++)
319                 {
320                         tmp = __m[i][j];
321                         __m[i][j] = __m[j][i];
322                         __m[j][i] = tmp;
323                 }
324         }
325
326         __complexity = GenericMatrix;
327 }
328
329 void
330 _Matrix3Df::Translate(float tx, float ty, float tz)
331 {
332         if (__complexity == IdentityMatrix)
333         {
334                 __m[3][0] = tx;
335                 __m[3][1] = ty;
336                 __m[3][2] = tz;
337                 __complexity = TranslationMatrix;
338         }
339         else if (__complexity == TranslationMatrix)
340         {
341                 __m[3][0] += tx;
342                 __m[3][1] += ty;
343                 __m[3][2] += tz;
344         }
345         else if (__complexity == ScaleMatrix)
346         {
347                 __m[3][0] = __m[0][0] * tx;
348                 __m[3][1] = __m[1][1] * ty;
349                 __m[3][2] = __m[1][2] * tz;
350                 __complexity = GenericMatrix;
351         }
352         else
353         {
354 #ifndef GEM_SIMD
355                 __m[3][0] += (__m[0][0] * tx + __m[1][0] * ty + __m[2][0] * tz);
356                 __m[3][1] += (__m[0][1] * tx + __m[1][1] * ty + __m[2][1] * tz);
357                 __m[3][2] += (__m[0][2] * tx + __m[1][2] * ty + __m[2][2] * tz);
358                 __m[3][3] += (__m[0][3] * tx + __m[1][3] * ty + __m[2][3] * tz);
359                 __complexity = GenericMatrix;
360 #else
361                 float32x4_t f4Dest;
362
363                 f4Dest = vld1q_f32(m_mtx.m[3]);
364                 f4Dest = vmlaq_n_f32(f4Dest, vld1q_f32(m_mtx.m[0]), tx);
365                 f4Dest = vmlaq_n_f32(f4Dest, vld1q_f32(m_mtx.m[1]), ty);
366                 f4Dest = vmlaq_n_f32(f4Dest, vld1q_f32(m_mtx.m[2]), tz);
367
368                 vst1q_f32(m_mtx.m[3], f4Dest);
369 #endif
370         }
371 }
372
373 void
374 _Matrix3Df::Scale(float sx, float sy, float sz)
375 {
376 #ifndef GEM_SIMD
377         if (sx != 1.0f)
378         {
379                 __m[0][0] *= sx;
380                 __m[0][1] *= sx;
381                 __m[0][2] *= sx;
382                 __m[0][3] *= sx;
383         }
384
385         if (sy != 1.0f)
386         {
387                 __m[1][0] *= sy;
388                 __m[1][1] *= sy;
389                 __m[1][2] *= sy;
390                 __m[1][3] *= sy;
391         }
392
393         if (sz != 1.0f)
394         {
395                 __m[2][0] *= sz;
396                 __m[2][1] *= sz;
397                 __m[2][2] *= sz;
398                 __m[2][3] *= sz;
399         }
400
401         if (__complexity == IdentityMatrix)
402                 __complexity = ScaleMatrix;
403         else
404                 __complexity = GenericMatrix;
405
406 #else
407         vst1q_f32(m_mtx.m[0], vmulq_n_f32(vld1q_f32(m_mtx.m[0]), sx));
408         vst1q_f32(m_mtx.m[1], vmulq_n_f32(vld1q_f32(m_mtx.m[1]), sy));
409         vst1q_f32(m_mtx.m[2], vmulq_n_f32(vld1q_f32(m_mtx.m[2]), sz));
410 #endif
411 }
412
413 void
414 _Matrix3Df::Shear(float xy, float yz, float zx, float yx, float zy, float xz)
415 {
416         _Matrix3Df ShearMatrix;
417
418         // refer: http://www.j3d.org/matrix_faq/matrfaq_latest.html#Q43
419
420         if (xy == 0.0f && yz == 0.0f && zx == 0.0f &&
421                 yx == 0.0f && zy == 0.0f && xz == 0.0f)
422                 return;
423
424
425         memcpy(ShearMatrix.__m, identityTransform, sizeof(ShearMatrix.__m));
426
427         ShearMatrix.__m[0][1] = xy;
428         ShearMatrix.__m[0][2] = xz;
429
430         ShearMatrix.__m[1][0] = yx;
431         ShearMatrix.__m[1][2] = yz;
432
433         ShearMatrix.__m[2][0] = zx;
434         ShearMatrix.__m[2][1] = zy;
435
436         ShearMatrix.__complexity = GenericMatrix;
437
438         *this = *this * ShearMatrix;
439 }
440
441 void
442 _Matrix3Df::Rotate(float angle, float x, float y, float z)
443 {
444 #if 1
445         if (angle == 0.0f)
446                 return;
447
448         // Rotation using quaternion
449
450         angle = angle * M_PI / 180.0f;
451
452         angle /= 2.0f;
453         float sinA = sinf(angle);
454         float cosA = cosf(angle);
455         float sinA2 = sinA * sinA;
456
457         // normalize
458         float length = sqrtf(x * x + y * y + z * z);
459         if (length == 0.0f)
460         {
461                 // bad vector, just use something reasonable
462 #if 0
463                 x = 0.0f;
464                 y = 0.0f;
465                 z = 1.0f;
466 #else
467                 return;
468 #endif
469         }
470         else if (length != 1.0f)
471         {
472                 x /= length;
473                 y /= length;
474                 z /= length;
475         }
476
477
478         float mat[4][4] = { {0.0f, }, };
479
480         // optimize case where axis is along major axis
481         if (x == 1.0f && y == 0.0f && z == 0.0f)
482         {
483                 mat[0][0] = 1.0f;
484                 mat[0][1] = 0.0f;
485                 mat[0][2] = 0.0f;
486                 mat[1][0] = 0.0f;
487                 mat[1][1] = 1.0f - 2.0f * sinA2;
488                 mat[1][2] = 2.0f * sinA * cosA;
489                 mat[2][0] = 0.0f;
490                 mat[2][1] = -2.0f * sinA * cosA;
491                 mat[2][2] = 1.0f - 2.0f * sinA2;
492                 mat[0][3] = mat[1][3] = mat[2][3] = 0.0f;
493                 mat[3][0] = mat[3][1] = mat[3][2] = 0.0f;
494                 mat[3][3] = 1.0f;
495         }
496         else if (x == 0.0f && y == 1.0f && z == 0.0f)
497         {
498                 mat[0][0] = 1.0f - 2.0f * sinA2;
499                 mat[0][1] = 0.0f;
500                 mat[0][2] = -2.0f * sinA * cosA;
501                 mat[1][0] = 0.0f;
502                 mat[1][1] = 1.0f;
503                 mat[1][2] = 0.0f;
504                 mat[2][0] = 2.0f * sinA * cosA;
505                 mat[2][1] = 0.0f;
506                 mat[2][2] = 1.0f - 2.0f * sinA2;
507                 mat[0][3] = mat[1][3] = mat[2][3] = 0.0f;
508                 mat[3][0] = mat[3][1] = mat[3][2] = 0.0f;
509                 mat[3][3] = 1.0f;
510         }
511         else if (x == 0.0f && y == 0.0f && z == 1.0f)
512         {
513                 mat[0][0] = 1.0f - 2.0f * sinA2;
514                 mat[0][1] = 2.0f * sinA * cosA;
515                 mat[0][2] = 0.0f;
516                 mat[1][0] = -2.0f * sinA * cosA;
517                 mat[1][1] = 1.0f - 2.0f * sinA2;
518                 mat[1][2] = 0.0f;
519                 mat[2][0] = 0.0f;
520                 mat[2][1] = 0.0f;
521                 mat[2][2] = 1.0f;
522                 mat[0][3] = mat[1][3] = mat[2][3] = 0.0f;
523                 mat[3][0] = mat[3][1] = mat[3][2] = 0.0f;
524                 mat[3][3] = 1.0f;
525         }
526         else
527         {
528                 float x2 = x * x;
529                 float y2 = y * y;
530                 float z2 = z * z;
531
532                 mat[0][0] = 1.0f - 2.0f * (y2 + z2) * sinA2;
533                 mat[0][1] = 2.0f * (x * y * sinA2 + z * sinA * cosA);
534                 mat[0][2] = 2.0f * (x * z * sinA2 - y * sinA * cosA);
535                 mat[1][0] = 2.0f * (y * x * sinA2 - z * sinA * cosA);
536                 mat[1][1] = 1.0f - 2.0f * (z2 + x2) * sinA2;
537                 mat[1][2] = 2.0f * (y * z * sinA2 + x * sinA * cosA);
538                 mat[2][0] = 2.0f * (z * x * sinA2 + y * sinA * cosA);
539                 mat[2][1] = 2.0f * (z * y * sinA2 - x * sinA * cosA);
540                 mat[2][2] = 1.0f - 2.0f * (x2 + y2) * sinA2;
541                 mat[0][3] = mat[1][3] = mat[2][3] = 0.0f;
542                 mat[3][0] = mat[3][1] = mat[3][2] = 0.0f;
543                 mat[3][3] = 1.0f;
544         }
545
546         *this *= _Matrix3Df((const float*)mat);
547 #else
548         _Matrix3Df rotMat;
549         float sinAngle, cosAngle;
550         float mag;
551
552         if (angle == 0.0f)
553                 return;
554
555         mag = sqrtf(x * x + y * y + z * z);
556         sinAngle = sinf(angle * PI / 180.0f);
557         cosAngle = cosf(angle * PI / 180.0f);
558
559         if (mag > 0.0f)
560         {
561                 float xx, yy, zz, xy, yz, zx, xs, ys, zs;
562                 float oneMinusCos;
563
564                 x /= mag;
565                 y /= mag;
566                 z /= mag;
567
568                 xx = x * x;
569                 yy = y * y;
570                 zz = z * z;
571                 xy = x * y;
572                 yz = y * z;
573                 zx = z * x;
574                 xs = x * sinAngle;
575                 ys = y * sinAngle;
576                 zs = z * sinAngle;
577                 oneMinusCos = 1.0f - cosAngle;
578
579                 rotMat.__m[0][0] = (oneMinusCos * xx) + cosAngle;
580                 rotMat.__m[1][0] = (oneMinusCos * xy) - zs;
581                 rotMat.__m[2][0] = (oneMinusCos * zx) + ys;
582                 rotMat.__m[3][0] = 0.0f;
583
584                 rotMat.__m[0][1] = (oneMinusCos * xy) + zs;
585                 rotMat.__m[1][1] = (oneMinusCos * yy) + cosAngle;
586                 rotMat.__m[2][1] = (oneMinusCos * yz) - xs;
587                 rotMat.__m[3][1] = 0.0f;
588
589                 rotMat.__m[0][2] = (oneMinusCos * zx) - ys;
590                 rotMat.__m[1][2] = (oneMinusCos * yz) + xs;
591                 rotMat.__m[2][2] = (oneMinusCos * zz) + cosAngle;
592                 rotMat.__m[3][2] = 0.0f;
593
594                 rotMat.__m[0][3] = 0.0f;
595                 rotMat.__m[1][3] = 0.0f;
596                 rotMat.__m[2][3] = 0.0f;
597                 rotMat.__m[3][3] = 1.0f;
598
599                 rotMat.__complexity = GenericMatrix;
600
601                 *this = *this * rotMat;
602         }
603 #endif
604 }
605
606 void
607 _Matrix3Df::MakeOrthogonal(float left, float right, float bottom, float top, float n, float f)
608 {
609         _Matrix3Df mat;
610         float w, h, d;
611
612         memcpy(mat.__m, identityTransform, sizeof(mat.__m));
613
614         w = right - left;
615         h = top - bottom;
616         d = f - n;
617
618         // CHECKME:
619         if (w == 0.0f)
620                 w = ALMOST_ZERO_FLOAT;
621         if (h == 0.0f)
622                 h = ALMOST_ZERO_FLOAT;
623         if (d == 0.0f)
624                 d = ALMOST_ZERO_FLOAT;
625
626         mat.__m[0][0] = 2.0f / w;
627         mat.__m[1][1] = 2.0f / h;
628         mat.__m[2][2] = -2.0f / d;
629
630         mat.__m[3][0] = -(right + left) / w;
631         mat.__m[3][1] = -(bottom + top) / h;
632         mat.__m[3][2] = -(n + f) / d;
633         mat.__m[3][3] = 1.0f;
634
635         mat.__complexity = GenericMatrix;
636
637         *this *= mat;
638 }
639
640 void
641 _Matrix3Df::MakeFrustum(float left, float right, float bottom, float top, float nearZ, float farZ)
642 {
643         _Matrix3Df mat;
644         float w, h, d;
645
646         memcpy(mat.__m, identityTransform, sizeof(mat.__m));
647
648         w = right - left;
649         h = top - bottom;
650         d = farZ - nearZ;
651
652         // CHECKME:
653         if (w == 0.0f)
654                 w = ALMOST_ZERO_FLOAT;
655         if (h == 0.0f)
656                 h = ALMOST_ZERO_FLOAT;
657         if (d == 0.0f)
658                 d = ALMOST_ZERO_FLOAT;
659
660         mat.__m[0][0] = 2.0f * nearZ / w;
661         mat.__m[1][1] = 2.0f * nearZ / h;
662         mat.__m[2][0] = (right + left) / w;
663         mat.__m[2][1] = (top + bottom) / h;
664         mat.__m[2][2] = -(farZ + nearZ) / d;
665         mat.__m[2][3] = -1.0f;
666         mat.__m[3][2] = -2.0f * farZ * nearZ / d;
667         mat.__m[3][3] = 0.0f;
668
669         mat.__complexity = GenericMatrix;
670
671         *this *= mat;
672 }
673
674 void
675 _Matrix3Df::MakePerspective(float fovy, float aspect, float nearZ, float farZ)
676 {
677         float frustumW, frustumH;
678
679         frustumH = tanf(fovy / 360.0f * PI) * nearZ;
680         frustumW = frustumH * aspect;
681
682         MakeFrustum(-frustumW, frustumW, -frustumH, frustumH, nearZ, farZ);
683 }
684
685 void
686 _Matrix3Df::MakeLookAt(float eyeX, float eyeY, float eyeZ, float centerX, float centerY, float centerZ, float upX, float upY, float upZ)
687 {
688         _Matrix3Df mat;
689         float x[3], y[3], z[3];
690         float mag;
691
692         // Make rotation matrix
693         // Z vector
694         z[0] = eyeX - centerX;
695         z[1] = eyeY - centerY;
696         z[2] = eyeZ - centerZ;
697
698         mag = sqrtf(z[0] * z[0] + z[1] * z[1] + z[2] * z[2]);
699         if (mag)
700         {
701                 // mpichler, 19950515
702                 z[0] /= mag;
703                 z[1] /= mag;
704                 z[2] /= mag;
705         }
706
707         // Y vector
708         y[0] = upX;
709         y[1] = upY;
710         y[2] = upZ;
711
712         // X vector = Y cross Z
713         x[0] = y[1] * z[2] - y[2] * z[1];
714         x[1] = -y[0] * z[2] + y[2] * z[0];
715         x[2] = y[0] * z[1] - y[1] * z[0];
716
717         // Recompute Y = Z cross X
718         y[0] = z[1] * x[2] - z[2] * x[1];
719         y[1] = -z[0] * x[2] + z[2] * x[0];
720         y[2] = z[0] * x[1] - z[1] * x[0];
721
722         // mpichler, 19950515
723         // cross product gives area of parallelogram, which is < 1.0 for
724         // non-perpendicular unit-length vectors; so normalize x, y here
725         mag = sqrtf(x[0] * x[0] + x[1] * x[1] + x[2] * x[2]);
726         if (mag)
727         {
728                 x[0] /= mag;
729                 x[1] /= mag;
730                 x[2] /= mag;
731         }
732
733         mag = sqrtf(y[0] * y[0] + y[1] * y[1] + y[2] * y[2]);
734         if (mag)
735         {
736                 y[0] /= mag;
737                 y[1] /= mag;
738                 y[2] /= mag;
739         }
740
741         mat.__m[0][0] = x[0];
742         mat.__m[1][0] = x[1];
743         mat.__m[2][0] = x[2];
744         mat.__m[3][0] = 0.0f;
745         mat.__m[0][1] = y[0];
746         mat.__m[1][1] = y[1];
747         mat.__m[2][1] = y[2];
748         mat.__m[3][1] = 0.0f;
749         mat.__m[0][2] = z[0];
750         mat.__m[1][2] = z[1];
751         mat.__m[2][2] = z[2];
752         mat.__m[3][2] = 0.0f;
753
754         mat.__complexity = GenericMatrix;
755
756         *this *= mat;
757
758         // Translate Eye to Origin
759         Translate(-eyeX, -eyeY, -eyeZ);
760 }
761
762 _Matrix3Df&
763 _Matrix3Df::MakeTransformAtAnchor(float x, float y, float z)
764 {
765         *this = _Matrix3DfTr(x, y, z) * (*this) * _Matrix3DfTr(-x, -y, -z);
766
767         return *this;
768 }
769
770 float
771 _Matrix3Df::Normalize(void)
772 {
773         float w;
774
775         w = __m[3][3];
776         if (w == 1.0f || w == 0.0f)
777                 return w;
778
779         for (int i = 0; i < 4; i++)
780         {
781                 for (int j = 0; j < 4; j++)
782                         __m[i][j] /= w;
783         }
784
785         __complexity = GenericMatrix;
786
787         return w;
788 }
789
790 void
791 _Matrix3Df::Transform(float* pX, float* pY, float* pZ) const
792 {
793 #ifndef GEM_SIMD
794         float x, y, z, w;
795
796         x = *pX;
797         y = *pY;
798         z = *pZ;
799
800         if (__complexity == IdentityMatrix)
801         {
802                 return;
803         }
804         else if (__complexity == TranslationMatrix)
805         {
806                 *pX += __m[3][0];
807                 *pY += __m[3][1];
808                 *pZ += __m[3][2];
809         }
810         else if (__complexity == ScaleMatrix)
811         {
812                 *pX = __m[0][0] * x;
813                 *pY = __m[1][1] * y;
814                 *pZ = __m[2][2] * z;
815         }
816         else
817         {
818                 *pX = (__m[0][0] * x) + (__m[1][0] * y) + (__m[2][0] * z) + (__m[3][0]);
819                 *pY = (__m[0][1] * x) + (__m[1][1] * y) + (__m[2][1] * z) + (__m[3][1]);
820                 *pZ = (__m[0][2] * x) + (__m[1][2] * y) + (__m[2][2] * z) + (__m[3][2]);
821                 w = (__m[0][3] * x) + (__m[1][3] * y) + (__m[2][3] * z) + (__m[3][3]);
822
823                 // TODO: what if w == 0 ????
824
825                 if (w != 1.0f)
826                 {
827                         *pX /= w;
828                         *pY /= w;
829                         *pZ /= w;
830                 }
831         }
832 #else
833         float pVector[4];
834         float32x4_t f4Dest;
835
836         f4Dest = vmulq_n_f32(vld1q_f32(m_mtx.m[0]), *pX);
837         f4Dest = vmlaq_n_f32(f4Dest, vld1q_f32(m_mtx.m[1]), *pY);
838         f4Dest = vmlaq_n_f32(f4Dest, vld1q_f32(m_mtx.m[2]), *pZ);
839         f4Dest = vmlaq_n_f32(f4Dest, vld1q_f32(m_mtx.m[3]), 1.0f);
840
841         vst1q_f32(pVector, f4Dest);
842
843         *pX = pVector[0] / pVector[3];
844         *pY = pVector[1] / pVector[3];
845         *pZ = pVector[2] / pVector[3];
846 #endif
847
848
849         // CHECKME:
850         //      Needless to check 4th row ??
851 }
852
853 }}}             // Tizen::Ui::Animations
854