Tizen 2.1 base
[framework/osp/uifw.git] / src / ui / animations / FUiAnim_MatrixUtil.cpp
1 //
2 // Open Service Platform
3 // Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
4 //
5 // Licensed under the Flora License, Version 1.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://floralicense.org/license/
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        FUiAnim_MatrixUtil.cpp
20  * @brief       This file contains implementation of _MatrixUtil module
21  *
22  * This file contains implementation _MatrixUtil module.
23  */
24
25 #include <sys/time.h>
26 #include <FUiVariant.h>
27 #include <FGrpRectangle.h>
28 #include <FGrpFloatRectangle.h>
29 #include <FGrpPoint.h>
30 #include <FGrpFloatPoint.h>
31 #include <FGrpDimension.h>
32 #include <FGrpFloatDimension.h>
33 #include <FGrpColor.h>
34 #include <FGrpFloatMatrix4.h>
35 #include <FGrpFloatVector4.h>
36
37 #include "FUi_Math.h"
38 #include "FUiAnim_MatrixUtil.h"
39
40
41 using namespace Tizen;
42 using namespace Tizen::Base;
43 using namespace Tizen::Graphics;
44
45 namespace Tizen { namespace Ui { namespace Animations
46 {
47
48 static const float _IDENTITY_MATRIX[4][4] =
49 {
50         { 1.0f, 0.0f, 0.0f, 0.0f },
51         { 0.0f, 1.0f, 0.0f, 0.0f },
52         { 0.0f, 0.0f, 1.0f, 0.0f },
53         { 0.0f, 0.0f, 0.0f, 1.0f }
54 };
55
56
57 Matrix4Type
58 _GetMatrix4Type(const Tizen::Graphics::FloatMatrix4& floatMatrix)
59 {
60         if (floatMatrix.matrix[3][3] != 1.0f)
61         {
62                 return MATRIX4_Generic;
63         }
64
65         if (floatMatrix.matrix[1][0] != 0.0f || floatMatrix.matrix[2][0] != 0.0f || floatMatrix.matrix[2][1] != 0.0f)
66         {
67                 return MATRIX4_Generic;
68         }
69
70         if (floatMatrix.matrix[0][1] != 0.0f || floatMatrix.matrix[0][2] != 0.0f || floatMatrix.matrix[0][3] != 0.0f ||
71                 floatMatrix.matrix[1][2] != 0.0f || floatMatrix.matrix[1][3] != 0.0f || floatMatrix.matrix[2][3] != 0.0f)
72         {
73                 return MATRIX4_Generic;
74         }
75
76         bool isTranslate = (floatMatrix.matrix[3][0] != 0.0f || floatMatrix.matrix[3][1] != 0.0f || floatMatrix.matrix[3][2] != 0.0f);
77         bool isDiagonal = (floatMatrix.matrix[0][0] == 1.0f && floatMatrix.matrix[1][1] == 1.0f && floatMatrix.matrix[2][2] == 1.0f);
78
79         if (isTranslate && isDiagonal)
80         {
81                 return MATRIX4_Translation;
82         }
83
84         if (isTranslate)
85         {
86                 return MATRIX4_Generic;
87         }
88
89         if (isDiagonal)
90         {
91                 return MATRIX4_Identity;
92         }
93
94         return MATRIX4_Scale;
95 }
96
97 bool
98 _MatrixUtilIsEqual(const Tizen::Graphics::FloatMatrix4& m1, const Tizen::Graphics::FloatMatrix4& m2)
99 {
100         return (memcmp(m1.matrix, m2.matrix, sizeof(m1.matrix)) == 0);
101 }
102
103 void
104 _MatrixUtilSetIdentity(Tizen::Graphics::FloatMatrix4& m)
105 {
106         memcpy(m.matrix, _IDENTITY_MATRIX, sizeof(_IDENTITY_MATRIX));
107 }
108
109 void
110 _MatrixUtilSetTranslation(Tizen::Graphics::FloatMatrix4& m, float tx, float ty, float tz)
111 {
112         memcpy(m.matrix, _IDENTITY_MATRIX, sizeof(_IDENTITY_MATRIX));
113         m.matrix[3][0] = tx;
114         m.matrix[3][1] = ty;
115         m.matrix[3][2] = tz;
116         m.matrix[3][3] = 1.0f;
117 }
118
119 void
120 _MatrixUtilTransform(const Tizen::Graphics::FloatMatrix4& m, float* pX, float* pY, float* pZ)
121 {
122         FloatVector4 vec4(*pX, *pY, *pZ, 1.0f);
123         vec4 = m * vec4;
124         *pX = vec4.x;
125         *pY = vec4.y;
126         *pZ = vec4.z;
127
128         if (vec4.w != 1.0f && vec4.w != 0.0f)
129         {
130                 *pX /= vec4.w;
131                 *pY /= vec4.w;
132                 *pZ /= vec4.w;
133         }
134 }
135
136 void
137 _MatrixUtilTranslate(Tizen::Graphics::FloatMatrix4& m, float tx, float ty, float tz)
138 {
139         m.matrix[3][0] += (m.matrix[0][0] * tx + m.matrix[1][0] * ty + m.matrix[2][0] * tz);
140         m.matrix[3][1] += (m.matrix[0][1] * tx + m.matrix[1][1] * ty + m.matrix[2][1] * tz);
141         m.matrix[3][2] += (m.matrix[0][2] * tx + m.matrix[1][2] * ty + m.matrix[2][2] * tz);
142         m.matrix[3][3] += (m.matrix[0][3] * tx + m.matrix[1][3] * ty + m.matrix[2][3] * tz);
143 }
144
145 bool
146 _MatrixUtilIsTranslation(const Tizen::Graphics::FloatMatrix4& m)
147 {
148         bool isTranslate = (m.matrix[3][0] != 0.0f || m.matrix[3][1] != 0.0f || m.matrix[3][2] != 0.0f);
149         bool isDiagonal = (m.matrix[0][0] == 1.0f && m.matrix[1][1] == 1.0f && m.matrix[2][2] == 1.0f);
150
151         if (isTranslate && isDiagonal)
152         {
153                 return true;
154         }
155
156         return false;
157 }
158
159 void
160 _MatrixUtilScale(Tizen::Graphics::FloatMatrix4& m, float sx, float sy, float sz)
161 {
162         if (sx != 1.0f)
163         {
164                 m.matrix[0][0] *= sx;
165                 m.matrix[0][1] *= sx;
166                 m.matrix[0][2] *= sx;
167                 m.matrix[0][3] *= sx;
168         }
169
170         if (sy != 1.0f)
171         {
172                 m.matrix[1][0] *= sy;
173                 m.matrix[1][1] *= sy;
174                 m.matrix[1][2] *= sy;
175                 m.matrix[1][3] *= sy;
176         }
177
178         if (sz != 1.0f)
179         {
180                 m.matrix[2][0] *= sz;
181                 m.matrix[2][1] *= sz;
182                 m.matrix[2][2] *= sz;
183                 m.matrix[2][3] *= sz;
184         }
185 }
186
187 void
188 _MatrixUtilAtAnchor(Tizen::Graphics::FloatMatrix4& m, float x, float y, float z)
189 {
190         Tizen::Graphics::FloatMatrix4 tr;
191         Tizen::Graphics::FloatMatrix4 trInv;
192
193         tr.matrix[3][0] = x;
194         tr.matrix[3][1] = y;
195         tr.matrix[3][2] = z;
196
197         trInv.matrix[3][0] = -x;
198         trInv.matrix[3][1] = -y;
199         trInv.matrix[3][2] = -z;
200
201         m = tr * m * trInv;
202 }
203
204 void
205 _MatrixUtilRotate(Tizen::Graphics::FloatMatrix4& m, float angle, float x, float y, float z)
206 {
207         if (angle == 0.0f)
208         {
209                 return;
210         }
211
212         // Rotation using quaternion
213
214         angle = angle * M_PI / 180.0f;
215
216         angle /= 2.0f;
217         float sinA = sinf(angle);
218         float cosA = cosf(angle);
219         float sinA2 = sinA * sinA;
220
221         // normalize
222         float length = sqrtf(x * x + y * y + z * z);
223         if (length == 0.0f)
224         {
225                 // bad vector, just use something reasonable
226                 return;
227         }
228         else if (length != 1.0f)
229         {
230                 x /= length;
231                 y /= length;
232                 z /= length;
233         }
234
235
236         float mat[4][4] = { {0.0f, }, };
237
238         // optimize case where axis is along major axis
239         if (x == 1.0f && y == 0.0f && z == 0.0f)
240         {
241                 mat[0][0] = 1.0f;
242                 mat[0][1] = 0.0f;
243                 mat[0][2] = 0.0f;
244                 mat[1][0] = 0.0f;
245                 mat[1][1] = 1.0f - 2.0f * sinA2;
246                 mat[1][2] = 2.0f * sinA * cosA;
247                 mat[2][0] = 0.0f;
248                 mat[2][1] = -2.0f * sinA * cosA;
249                 mat[2][2] = 1.0f - 2.0f * sinA2;
250                 mat[0][3] = mat[1][3] = mat[2][3] = 0.0f;
251                 mat[3][0] = mat[3][1] = mat[3][2] = 0.0f;
252                 mat[3][3] = 1.0f;
253         }
254         else if (x == 0.0f && y == 1.0f && z == 0.0f)
255         {
256                 mat[0][0] = 1.0f - 2.0f * sinA2;
257                 mat[0][1] = 0.0f;
258                 mat[0][2] = -2.0f * sinA * cosA;
259                 mat[1][0] = 0.0f;
260                 mat[1][1] = 1.0f;
261                 mat[1][2] = 0.0f;
262                 mat[2][0] = 2.0f * sinA * cosA;
263                 mat[2][1] = 0.0f;
264                 mat[2][2] = 1.0f - 2.0f * sinA2;
265                 mat[0][3] = mat[1][3] = mat[2][3] = 0.0f;
266                 mat[3][0] = mat[3][1] = mat[3][2] = 0.0f;
267                 mat[3][3] = 1.0f;
268         }
269         else if (x == 0.0f && y == 0.0f && z == 1.0f)
270         {
271                 mat[0][0] = 1.0f - 2.0f * sinA2;
272                 mat[0][1] = 2.0f * sinA * cosA;
273                 mat[0][2] = 0.0f;
274                 mat[1][0] = -2.0f * sinA * cosA;
275                 mat[1][1] = 1.0f - 2.0f * sinA2;
276                 mat[1][2] = 0.0f;
277                 mat[2][0] = 0.0f;
278                 mat[2][1] = 0.0f;
279                 mat[2][2] = 1.0f;
280                 mat[0][3] = mat[1][3] = mat[2][3] = 0.0f;
281                 mat[3][0] = mat[3][1] = mat[3][2] = 0.0f;
282                 mat[3][3] = 1.0f;
283         }
284         else
285         {
286                 float x2 = x * x;
287                 float y2 = y * y;
288                 float z2 = z * z;
289
290                 mat[0][0] = 1.0f - 2.0f * (y2 + z2) * sinA2;
291                 mat[0][1] = 2.0f * (x * y * sinA2 + z * sinA * cosA);
292                 mat[0][2] = 2.0f * (x * z * sinA2 - y * sinA * cosA);
293                 mat[1][0] = 2.0f * (y * x * sinA2 - z * sinA * cosA);
294                 mat[1][1] = 1.0f - 2.0f * (z2 + x2) * sinA2;
295                 mat[1][2] = 2.0f * (y * z * sinA2 + x * sinA * cosA);
296                 mat[2][0] = 2.0f * (z * x * sinA2 + y * sinA * cosA);
297                 mat[2][1] = 2.0f * (z * y * sinA2 - x * sinA * cosA);
298                 mat[2][2] = 1.0f - 2.0f * (x2 + y2) * sinA2;
299                 mat[0][3] = mat[1][3] = mat[2][3] = 0.0f;
300                 mat[3][0] = mat[3][1] = mat[3][2] = 0.0f;
301                 mat[3][3] = 1.0f;
302         }
303
304         m *= Tizen::Graphics::FloatMatrix4(mat);
305 }
306
307 bool
308 _MatrixUtilInvert(Tizen::Graphics::FloatMatrix4& m)
309 {
310         // TODO:
311         //      WOW!!!  WOW!!!  WOW!!!  WOW!!!
312         //
313         float a0;
314         float a1;
315         float a2;
316         float a3;
317         float a4;
318         float a5;
319         float b0;
320         float b1;
321         float b2;
322         float b3;
323         float b4;
324         float b5;
325         float det;
326
327         if (m.IsIdentity())
328         {
329                 return true;
330         }
331
332         a0 = m.matrix[0][0] * m.matrix[1][1] - m.matrix[0][1] * m.matrix[1][0];
333         a1 = m.matrix[0][0] * m.matrix[1][2] - m.matrix[0][2] * m.matrix[1][0];
334         a2 = m.matrix[0][0] * m.matrix[1][3] - m.matrix[0][3] * m.matrix[1][0];
335         a3 = m.matrix[0][1] * m.matrix[1][2] - m.matrix[0][2] * m.matrix[1][1];
336         a4 = m.matrix[0][1] * m.matrix[1][3] - m.matrix[0][3] * m.matrix[1][1];
337         a5 = m.matrix[0][2] * m.matrix[1][3] - m.matrix[0][3] * m.matrix[1][2];
338
339         b0 = m.matrix[2][0] * m.matrix[3][1] - m.matrix[2][1] * m.matrix[3][0];
340         b1 = m.matrix[2][0] * m.matrix[3][2] - m.matrix[2][2] * m.matrix[3][0];
341         b2 = m.matrix[2][0] * m.matrix[3][3] - m.matrix[2][3] * m.matrix[3][0];
342         b3 = m.matrix[2][1] * m.matrix[3][2] - m.matrix[2][2] * m.matrix[3][1];
343         b4 = m.matrix[2][1] * m.matrix[3][3] - m.matrix[2][3] * m.matrix[3][1];
344         b5 = m.matrix[2][2] * m.matrix[3][3] - m.matrix[2][3] * m.matrix[3][2];
345
346         det = a0 * b5 - a1 * b4 + a2 * b3 + a3 * b2 - a4 * b1 + a5 * b0;
347 //      if (_FloatHardCompare(det, 0.0f))
348         if (det == 0.0f)
349         {
350                 return false;
351         }
352
353
354         float inverse_m[4][4];
355
356         inverse_m[0][0] = +m.matrix[1][1] * b5 - m.matrix[1][2] * b4 + m.matrix[1][3] * b3;
357         inverse_m[1][0] = -m.matrix[1][0] * b5 + m.matrix[1][2] * b2 + m.matrix[1][3] * b1;
358         inverse_m[2][0] = +m.matrix[1][0] * b4 - m.matrix[1][1] * b2 + m.matrix[1][3] * b0;
359         inverse_m[3][0] = -m.matrix[1][0] * b3 + m.matrix[1][1] * b1 - m.matrix[1][2] * b0;
360         inverse_m[0][1] = -m.matrix[0][1] * b5 + m.matrix[0][2] * b4 - m.matrix[0][3] * b3;
361         inverse_m[1][1] = +m.matrix[0][0] * b5 - m.matrix[0][2] * b2 + m.matrix[0][3] * b1;
362         inverse_m[2][1] = -m.matrix[0][0] * b4 + m.matrix[0][1] * b2 - m.matrix[0][3] * b0;
363         inverse_m[3][1] = +m.matrix[0][0] * b3 - m.matrix[0][1] * b1 + m.matrix[0][2] * b0;
364         inverse_m[0][2] = +m.matrix[3][1] * a5 - m.matrix[3][2] * a4 + m.matrix[3][3] * a3;
365         inverse_m[1][2] = -m.matrix[3][0] * a5 + m.matrix[3][2] * a2 - m.matrix[3][3] * a1;
366         inverse_m[2][2] = +m.matrix[3][0] * a4 - m.matrix[3][1] * a2 + m.matrix[3][3] * a0;
367         inverse_m[3][2] = -m.matrix[3][0] * a3 + m.matrix[3][1] * a1 - m.matrix[3][2] * a0;
368         inverse_m[0][3] = -m.matrix[2][1] * a5 + m.matrix[2][2] * a4 - m.matrix[2][3] * a3;
369         inverse_m[1][3] = +m.matrix[2][0] * a5 - m.matrix[2][2] * a2 + m.matrix[2][3] * a1;
370         inverse_m[2][3] = -m.matrix[2][0] * a4 + m.matrix[2][1] * a2 - m.matrix[2][3] * a0;
371         inverse_m[3][3] = +m.matrix[2][0] * a3 - m.matrix[2][1] * a1 + m.matrix[2][2] * a0;
372
373         for (int i = 0; i < 4; i++)
374         {
375                 for (int j = 0; j < 4; j++)
376                 {
377                         inverse_m[j][i] /= det;
378                 }
379         }
380
381         memcpy(m.matrix, inverse_m, sizeof(m.matrix));
382 //      __complexity = GenericMatrix;
383
384         return true;
385 }
386
387 void
388 _MatrixUtilMultiply(Tizen::Graphics::FloatMatrix4& d, const Tizen::Graphics::FloatMatrix4& m1, const Tizen::Graphics::FloatMatrix4& m2)
389 {
390         d = m1 * m2;
391 }
392
393 }}}
394
395
396 #if 0
397 void
398 __PrintMatrix(const Tizen::Graphics::FloatMatrix4& m)
399 {
400         printf("Matrix: %f %f %f %f\n", m.matrix[0][0], m.matrix[1][0], m.matrix[2][0], m.matrix[3][0]);
401         printf("        %f %f %f %f\n", m.matrix[0][1], m.matrix[1][1], m.matrix[2][1], m.matrix[3][1]);
402         printf("        %f %f %f %f\n", m.matrix[0][2], m.matrix[1][2], m.matrix[2][2], m.matrix[3][2]);
403         printf("        %f %f %f %f\n", m.matrix[0][3], m.matrix[1][3], m.matrix[2][2], m.matrix[3][3]);
404 }
405
406 void
407 __TestMatrix(void)
408 {
409         Tizen::Graphics::FloatMatrix4   ok;
410         Tizen::Graphics::FloatMatrix4   m;
411         Tizen::Graphics::FloatMatrix4   m1;
412         Tizen::Graphics::FloatMatrix4   m2;
413
414         Tizen::Ui::Animations::_MatrixUtilRotate(m1, 45, 0, 0, 1);
415         Tizen::Ui::Animations::_MatrixUtilRotate(m2, 45, 0, 1, 0);
416         ok = m1 * m2;
417         __PrintMatrix(ok);
418
419         Tizen::Ui::Animations::_MatrixUtilMultiply(m, m1, m2);
420         __PrintMatrix(m);
421
422
423         struct _VariantData
424         {
425                 union {
426                         int valueInt;
427                         unsigned int valueUInt;
428                         bool valueBool;
429                         float valueFloat;
430                         double valueDouble;
431                         long valueLong;
432                         unsigned long valueULong;
433                         long long valueLongLong;
434                         unsigned long long valueULongLong;
435                 } u;
436                 Tizen::Base::String* pString;
437                 Tizen::Base::DateTime* dateTime;
438                 Tizen::Graphics::Color* color;
439                 Tizen::Graphics::Point* point;
440                 Tizen::Graphics::FloatPoint* floatPoint;
441                 Tizen::Graphics::Rectangle* rect;
442                 Tizen::Graphics::FloatRectangle* rectf;
443                 Tizen::Graphics::Dimension* dimension;
444                 Tizen::Graphics::FloatDimension* floatDimension;
445                 Tizen::Graphics::FloatMatrix4* floatMatrix4;
446         };
447
448         struct timeval s;
449         struct timeval e;
450
451         gettimeofday(&s, null);
452         for (int i = 0; i < 10000; i++)
453         {
454                 Tizen::Ui::Variant v;
455                 v = 3;
456 //              memset(&v, 0, sizeof(v));
457 //              v.floatMatrix4 = new FloatMatrix4;
458 //              v.u.valueInt = 2;
459         }
460         gettimeofday(&e, null);
461         printf("--------- %d\n", static_cast< int >(e.tv_usec - s.tv_usec));
462 }
463 #endif
464