Revert " modify license, permission and remove ^M char"
[framework/osp/uifw.git] / src / ui / animations / FUiAnim_TransformMatrix3Df.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_TransformMatrix3Df.cpp
20  * @brief       This file contains implementation of _TransformMatrix3Df class
21  *
22  * This file contains implementation _TransformMatrix3Df class.
23  */
24
25 #include <math.h>
26 #include <FGrpFloatMatrix4.h>
27
28 #include "FUiAnim_MatrixUtil.h"
29 #include "FUiAnim_TransformMatrix3Df.h"
30
31 using namespace Tizen::Graphics;
32 using namespace Tizen::Ui;
33 using namespace Tizen::Ui::Animations;
34
35 #define DEGTORAD(d)     ((d) * M_PI / 180.0f)
36 #define RADTODEG(r)     ((r) * 180.0f / M_PI)
37
38 #if 0
39 void
40 DumpQuaternion(const _TransformMatrix3Df& tm)
41 {
42         float x, y, z, w;
43         float halfth;
44
45         tm.GetQuaternion(x, y, z, w);
46         halfth = acosf(w);
47         if (halfth > 1e-5f)
48         {
49                 float sinh = sin(halfth);
50                 float rx = x / sinh;
51                 float ry = y / sinh;
52                 float rz = z / sinh;
53                 printf("QuatR: x= %f,  y= %f,  z= %f,      w= %f\n", x, y, z, w);
54                 printf("Quat: rx= %f, ry= %f, rz= %f, theta= %f\n", rx, ry, rz, 2.0f * halfth * 180.0f / M_PI);
55         }
56
57         tm.GetEulerAngles(x, y, z);
58         printf("Euler Rotation: %f, %f, %f\n", x, y, z);
59 }
60
61 void
62 DumpMatrix(const FloatMatrix4& m)
63 {
64         printf("Matrix: %f %f %f %f\n", m.matrix[0][0], m.matrix[1][0], m.matrix[2][0], m.matrix[3][0]);
65         printf("        %f %f %f %f\n", m.matrix[0][1], m.matrix[1][1], m.matrix[2][1], m.matrix[3][1]);
66         printf("        %f %f %f %f\n", m.matrix[0][2], m.matrix[1][2], m.matrix[2][2], m.matrix[3][2]);
67         printf("        %f %f %f %f\n", m.matrix[0][3], m.matrix[1][3], m.matrix[2][2], m.matrix[3][3]);
68 }
69 #endif
70
71 namespace {
72
73 FloatMatrix4
74 GetTranslationMatrix(float tx, float ty, float tz)
75 {
76         FloatMatrix4 tm;
77         tm.matrix[0][3] = tx;
78         tm.matrix[1][3] = ty;
79         tm.matrix[2][3] = tz;
80         return tm;
81 }
82
83 }
84
85 namespace Tizen { namespace Ui { namespace Animations {
86
87 _TransformMatrix3Df::_TransformMatrix3Df(void)
88         : __transformType(MATRIX4_Identity)
89         , __usePerspective(false)
90         , __useScale(false)
91         , __useShear(false)
92         , __useRotation(false)
93         , __useTranslation(false)
94         , __scaleX(1.0f)
95         , __scaleY(1.0f)
96         , __scaleZ(1.0f)
97         , __shearXY(0.0f)
98         , __shearXZ(0.0f)
99         , __shearYZ(0.0f)
100         , __quatX(0.0f)
101         , __quatY(0.0f)
102         , __quatZ(0.0f)
103         , __quatW(1.0f)
104         , __translationX(0.0f)
105         , __translationY(0.0f)
106         , __translationZ(0.0f)
107         , __perspectiveX(0.0f)
108         , __perspectiveY(0.0f)
109         , __perspectiveZ(0.0f)
110         , __perspectiveW(1.0f)
111         , __rotAnchorX(0.0f)
112         , __rotAnchorY(0.0f)
113         , __rotAnchorZ(0.0f)
114         , __scaleAnchorX(0.0f)
115         , __scaleAnchorY(0.0f)
116         , __scaleAnchorZ(0.0f)
117         , __rotX(0.0f)
118         , __rotY(0.0f)
119         , __rotZ(0.0f)
120 {
121 }
122
123 _TransformMatrix3Df::~_TransformMatrix3Df(void)
124 {
125 }
126
127 void
128 _TransformMatrix3Df::Clear(void)
129 {
130         __rotX = __rotY = __rotZ = 0.0f;
131         __scaleX = __scaleY = __scaleZ = 1.0f;
132         __shearXY = __shearXZ = __shearYZ = 0.0f;
133         __quatX = __quatY = __quatZ = 0.0f; __quatW = 1.0f;
134         __translationX = __translationY = __translationZ = 0.0f;
135         __perspectiveX = __perspectiveY = __perspectiveZ = 0.0f; __perspectiveW = 1.0f;
136
137         __usePerspective = false;
138         __useScale = false;
139         __useRotation = false;
140         __useTranslation = false;
141         __transformType = MATRIX4_Identity;
142 }
143
144 bool
145 _TransformMatrix3Df::SetTransformMatrix(const FloatMatrix4& transformMatrix)
146 {
147         // Check if fast-path is available
148 //      if (transformMatrix.IsIdentity())
149 #if 0
150         if (transformMatrix == FloatMatrix4::IDENTITY_MATRIX)
151         {
152                 Clear();
153                 return true;
154         }
155 #endif
156
157         // Normalize the matrix.
158 //      float mw = transformMatrix.Get(3, 3);
159         float mw = transformMatrix.matrix[3][3];
160 //      if (_FloatHardCompare(mw, 0.0f))
161         if (unlikely(mw == 0.0f))
162         {
163                 return false;
164         }
165
166         FloatMatrix4 locmat;
167         for (int i = 0; i < 4; i++)
168         {
169                 for (int j = 0; j < 4; j++)
170                         //locmat.Set(i, j, transformMatrix.Get(j, i) / mw);
171                         locmat.matrix[j][i] = transformMatrix.matrix[i][j] / mw;
172         }
173
174         // pmat is used to solve for perspective, but it also provides
175         // an easy way to test for singularity of the upper 3x3 component.
176         //
177         FloatMatrix4 pmat(locmat);
178         for (int i = 0; i < 3; i++)
179 //              pmat.Set(i, 3, 0.0f);
180                 pmat.matrix[3][i] = 0.0f;
181
182 //      pmat.Set(3, 3, 1.0f);
183         pmat.matrix[3][3] = 1.0f;
184
185         FloatMatrix4 pmatInverseTranspose(pmat);
186 //      if (!pmatInverseTranspose.Invert())
187 //              return false;
188 #if 0
189         if (!pmatInverseTranspose.IsInvertible())
190         {
191                 return false;
192         }
193 #endif
194         if (pmatInverseTranspose.Invert() != E_SUCCESS)
195         {
196                 return false;
197         }
198
199
200         // First, isolate perspective.  This is the messiest.
201 //      if (!_FloatHardCompare(locmat.Get(0, 3), 0.0f) || !_FloatHardCompare(locmat.Get(1, 3), 0.0f) || !_FloatHardCompare(locmat.Get(2, 3), 0.0f))
202         if (unlikely(locmat.matrix[3][0] != 0.0f) || unlikely(locmat.matrix[3][1] != 0.0f) || unlikely(locmat.matrix[3][2] != 0.0f))
203         {
204                 // prhs is the right hand side of the equation.
205                 Vector4Df prhs, psol;
206
207 //              prhs.x = locmat.Get(0, 3);
208 //              prhs.y = locmat.Get(1, 3);
209 //              prhs.z = locmat.Get(2, 3);
210 //              prhs.w = locmat.Get(3, 3);
211                 prhs.x = locmat.matrix[3][0];
212                 prhs.y = locmat.matrix[3][1];
213                 prhs.z = locmat.matrix[3][2];
214                 prhs.w = locmat.matrix[3][3];
215
216
217                 pmatInverseTranspose.Transpose();
218
219                 // Solve the equation by inverting pmat and multiplying
220                 // prhs by the inverse.  (This is the easiest way, not necessarily the best.)
221                 // inverse function (and det4x4, above) from the Matrix Inversion gem in the first volume.
222                 //
223                 //V4MulPointByMatrix(prhs, pmatInverseTranspose, psol);
224                 psol = prhs.Transform(pmatInverseTranspose);
225
226
227                 // Stuff the answer away.
228                 __perspectiveX = psol.x;
229                 __perspectiveY = psol.y;
230                 __perspectiveZ = psol.z;
231                 __perspectiveW = psol.w;
232
233                 // Clear the perspective partition.
234 //              locmat.Set(0, 3, 0.0f);
235 //              locmat.Set(1, 3, 0.0f);
236 //              locmat.Set(2, 3, 0.0f);
237 //              locmat.Set(3, 3, 1.0f);
238                 locmat.matrix[3][0] = (0.0f);
239                 locmat.matrix[3][1] = (0.0f);
240                 locmat.matrix[3][2] = (0.0f);
241                 locmat.matrix[3][3] = (1.0f);
242         }
243         else
244         {
245                 // No perspective.
246                 __perspectiveX = 0.0f;
247                 __perspectiveY = 0.0f;
248                 __perspectiveZ = 0.0f;
249                 __perspectiveW = 1.0f;  // CHECKME: W of perspective is 1, right ? (or 0 ?)
250         }
251
252         // Next take care of translation (easy).
253 //      __translationX = locmat.Get(3, 0);
254 //      __translationY = locmat.Get(3, 1);
255 //      __translationZ = locmat.Get(3, 2);
256         __translationX = locmat.matrix[0][3];
257         __translationY = locmat.matrix[1][3];
258         __translationZ = locmat.matrix[2][3];
259
260         for (int i = 0; i < 3; i++)
261         {
262 //              locmat.Set(3, i, 0.0f);
263                 locmat.matrix[i][3] = 0.0f;
264         }
265
266
267         // Now get scale and shear.
268         Vector3Df row[3];
269         for (int i = 0; i < 3; i++)
270         {
271 //              row[i].x = locmat.Get(i, 0);
272 //              row[i].y = locmat.Get(i, 1);
273 //              row[i].z = locmat.Get(i, 2);
274                 row[i].x = locmat.matrix[0][i];
275                 row[i].y = locmat.matrix[1][i];
276                 row[i].z = locmat.matrix[2][i];
277         }
278
279         // Compute X scale factor and normalize first row.
280         __scaleX = row[0].GetLength();
281         row[0].Scale(1.0f);
282
283         // Compute XY shear factor and make 2nd row orthogonal to 1st.
284         __shearXY = row[0].Dot(row[1]);
285         Vector3Df::Combine(row[1], row[1], row[0], 1.0f, -__shearXY);
286
287         // Now, compute Y scale and normalize 2nd row.
288         __scaleY = row[1].GetLength();
289         row[1].Scale(1.0f);
290         __shearXY /= __scaleY;
291
292         // Compute XZ and YZ shears, orthogonalize 3rd row.
293         __shearXZ = row[0].Dot(row[2]);
294         Vector3Df::Combine(row[2], row[2], row[0], 1.0f, -__shearXZ);
295         __shearYZ = row[1].Dot(row[2]);
296         Vector3Df::Combine(row[2], row[2], row[1], 1.0f, -__shearYZ);
297
298         // Next, get Z scale and normalize 3rd row.
299         __scaleZ = row[2].GetLength();
300         row[2].Scale(1.0f);
301         __shearXZ /= __scaleZ;
302         __shearYZ /= __scaleZ;
303
304         // At this point, the matrix (in rows[]) is orthonormal.
305         // Check for a coordinate system flip.  If the determinant
306         // is -1, then negate the matrix and the scaling factors.
307         //
308         Vector3Df pdum3 = row[1].Cross(row[2]);
309         if (row[0].Dot(pdum3) < 0.0f)
310         {
311                 for (int i = 0; i < 3; i++)
312                 {
313                         row[i].x *= -1.0f;
314                         row[i].y *= -1.0f;
315                         row[i].z *= -1.0f;
316                 }
317
318                 __scaleX *= -1.0f;
319                 __scaleY *= -1.0f;
320                 __scaleZ *= -1.0f;
321         }
322
323         // Now, get the rotations out
324         // For correctness, we use quaternions
325         float s, t, x, y, z, w;
326
327         t = row[0].x + row[1].y + row[2].z + 1.0f;
328
329         if (t > 1e-4f)
330         {
331                 s = 0.5f / sqrtf(t);
332                 w = 0.25f / s;
333                 x = (row[2].y - row[1].z) * s;
334                 y = (row[0].z - row[2].x) * s;
335                 z = (row[1].x - row[0].y) * s;
336         }
337         else if (row[0].x > row[1].y && row[0].x > row[2].z)
338         {
339                 s = sqrtf(1.0f + row[0].x - row[1].y - row[2].z) * 2.0f; // S = 4 * qx
340                 x = 0.25f * s;
341                 y = (row[0].y + row[1].x) / s;
342                 z = (row[0].z + row[2].x) / s;
343                 w = (row[2].y - row[1].z) / s;
344         }
345         else if (row[1].y > row[2].z)
346         {
347                 s = sqrtf(1.0f + row[1].y - row[0].x - row[2].z) * 2.0f; // S = 4 * qy
348                 x = (row[0].y + row[1].x) / s;
349                 y = 0.25f * s;
350                 z = (row[1].z + row[2].y) / s;
351                 w = (row[0].z - row[2].x) / s;
352         }
353         else
354         {
355                 s = sqrtf(1.0f + row[2].z - row[0].x - row[1].y) * 2.0f; // S = 4 * qz
356                 x = (row[0].z + row[2].x) / s;
357                 y = (row[1].z + row[2].y) / s;
358                 z = 0.25f * s;
359                 w = (row[1].x - row[0].y) / s;
360         }
361
362         __quatX = -x;
363         __quatY = -y;
364         __quatZ = -z;
365         __quatW = w;
366
367
368         __rotY = asinf(-row[0].z);
369         if (cosf(__rotY) != 0.0f)
370         {
371                 __rotX = RADTODEG(atan2f(row[1].z, row[2].z));
372                 __rotZ = RADTODEG(atan2f(row[0].y, row[0].x));
373         }
374         else
375         {
376                 __rotX = RADTODEG(atan2f(-row[2].x, row[1].y));
377                 __rotZ = 0.0f;
378         }
379
380         __rotY = RADTODEG(__rotY);
381
382
383
384         // Clear anchor information
385         __rotAnchorX = 0.0f;
386         __rotAnchorY = 0.0f;
387         __rotAnchorZ = 0.0f;
388         __scaleAnchorX = 0.0f;
389         __scaleAnchorY = 0.0f;
390         __scaleAnchorZ = 0.0f;
391
392 #if 0
393         //printf("--------- Rotate: %f, %f, %f, %f\n", __quatX, __quatY, __quatZ, __quatW);
394         DumpQuaternion(*this);
395         DumpMatrix(transformMatrix);
396 //      printf("--------- Scale: %f, %f, %f\n", __scaleX, __scaleY, __scaleZ);
397 //      printf("--------- Translate: %f, %f, %f\n", __translationX, __translationY, __translationZ);
398         printf("\n\n");
399 #endif
400
401         UpdateMatrixType(true);
402
403         return true;
404 }
405
406 FloatMatrix4
407 _TransformMatrix3Df::Interpolate(const _TransformMatrix3Df& transformMatrixFrom, float progress) const
408 {
409 #define FLOAT_INTP(v, c, f, t, p)       do { if (likely((f.v) != (t.v))) c.v = (f.v) + ((t.v) - (f.v)) * (p); else c.v = f.v; } while (0)
410
411         const _TransformMatrix3Df& fromTransform = transformMatrixFrom;
412         const _TransformMatrix3Df& toTransform = *this;
413         _TransformMatrix3Df currentTransform;
414
415         FLOAT_INTP(__scaleX, currentTransform, fromTransform, toTransform, progress);
416         FLOAT_INTP(__scaleY, currentTransform, fromTransform, toTransform, progress);
417         FLOAT_INTP(__scaleZ, currentTransform, fromTransform, toTransform, progress);
418         FLOAT_INTP(__shearXY, currentTransform, fromTransform, toTransform, progress);
419         FLOAT_INTP(__shearXZ, currentTransform, fromTransform, toTransform, progress);
420         FLOAT_INTP(__shearYZ, currentTransform, fromTransform, toTransform, progress);
421         FLOAT_INTP(__translationX, currentTransform, fromTransform, toTransform, progress);
422         FLOAT_INTP(__translationY, currentTransform, fromTransform, toTransform, progress);
423         FLOAT_INTP(__translationZ, currentTransform, fromTransform, toTransform, progress);
424         FLOAT_INTP(__perspectiveX, currentTransform, fromTransform, toTransform, progress);
425         FLOAT_INTP(__perspectiveY, currentTransform, fromTransform, toTransform, progress);
426         FLOAT_INTP(__perspectiveZ, currentTransform, fromTransform, toTransform, progress);
427         FLOAT_INTP(__perspectiveW, currentTransform, fromTransform, toTransform, progress);
428
429         // Interpolate anchor points
430         FLOAT_INTP(__rotAnchorX, currentTransform, fromTransform, toTransform, progress);
431         FLOAT_INTP(__rotAnchorY, currentTransform, fromTransform, toTransform, progress);
432         FLOAT_INTP(__rotAnchorZ, currentTransform, fromTransform, toTransform, progress);
433         FLOAT_INTP(__scaleAnchorX, currentTransform, fromTransform, toTransform, progress);
434         FLOAT_INTP(__scaleAnchorY, currentTransform, fromTransform, toTransform, progress);
435         FLOAT_INTP(__scaleAnchorZ, currentTransform, fromTransform, toTransform, progress);
436
437         // rotation component
438         // WARNING:
439         //      It is not needed to update __rotX/Y/Z because the calculating interpolated matrix would not use those values
440 #if 0
441         FLOAT_INTP(__rotX, currentTransform, fromTransform, toTransform, progress);
442         FLOAT_INTP(__rotY, currentTransform, fromTransform, toTransform, progress);
443         FLOAT_INTP(__rotZ, currentTransform, fromTransform, toTransform, progress);
444         currentTransform.UpdateRotationFromEulerAngles(currentTransform.__rotX, currentTransform.__rotY, currentTransform.__rotZ);
445 #else
446         DoSlerp(&currentTransform.__quatX, &fromTransform.__quatX, &toTransform.__quatX, progress);
447 #endif
448
449         // WARNING:
450         //      'GetTransformMatrix' will use matrix type
451         currentTransform.UpdateMatrixType(true);
452
453
454 #if 0
455         printf("----------p: %f\n", progress);
456         printf("--------- qf: %f, %f, %f, %f\n", fromTransform.__quatX, fromTransform.__quatY, fromTransform.__quatZ, fromTransform.__quatW);
457         printf("--------- qt: %f, %f, %f, %f\n", toTransform.__quatX, toTransform.__quatY, toTransform.__quatZ, toTransform.__quatW);
458         printf("--------- q: %f, %f, %f, %f\n", currentTransform.__quatX, currentTransform.__quatY, currentTransform.__quatZ, currentTransform.__quatW);
459
460         float rx, ry, rz;
461         float halfth = acosf(currentTransform.__quatW);
462         if (halfth > 1e-5)
463         {
464                 rx = currentTransform.__quatX / sinf(halfth);
465                 ry = currentTransform.__quatY / sinf(halfth);
466                 rz = currentTransform.__quatZ / sinf(halfth);
467                 printf(" ==> q: %f, %f, %f, %f\n", rx, ry, rz, 2.0f * halfth * 180 / M_PI);
468                 printf(" ==> q: %f, %f, %f, %f\n", -rx, -ry, -rz, 2.0f * halfth * 180 / M_PI);
469         }
470 #endif
471
472 #if 1
473         return currentTransform.GetTransformMatrix();
474 #else
475         printf("--------- q: %f, %f, %f, %f\n", currentTransform.__quatX, currentTransform.__quatY, currentTransform.__quatZ, currentTransform.__quatW);
476         FloatMatrix4 cm = currentTransform.GetTransformMatrix();
477         DumpMatrix(cm);
478         return cm;
479 #endif
480
481 #undef  FLOAT_INTP
482 }
483
484 void
485 _TransformMatrix3Df::UpdateMatrixType(bool needFullCheck)
486 {
487         if (unlikely(needFullCheck))
488         {
489                 __useRotation = (unlikely(!_FloatCompare(__quatX, 0.0f)) || unlikely(!_FloatCompare(__quatY, 0.0f)) || unlikely(!_FloatCompare(__quatZ, 0.0f)) || unlikely(!_FloatCompare(__quatW, 1.0f)));
490                 __useShear = (unlikely(!_FloatCompare(__shearXY, 0.0f)) || unlikely(!_FloatCompare(__shearXZ, 0.0f)) || unlikely(!_FloatCompare(__shearYZ, 0.0f)));
491                 __useScale = (unlikely(!_FloatCompare(__scaleX, 1.0f)) || unlikely(!_FloatCompare(__scaleY, 1.0f)) || unlikely(!_FloatCompare(__scaleZ, 1.0f)));
492                 __useTranslation = (unlikely(!_FloatCompare(__translationX, 0.0f)) || unlikely(!_FloatCompare(__translationY, 0.0f)) || unlikely(!_FloatCompare(__translationZ, 0.0f)));
493                 __usePerspective = (unlikely(!_FloatCompare(__perspectiveX, 0.0f)) || unlikely(!_FloatCompare(__perspectiveY, 0.0f)) || unlikely(!_FloatCompare(__perspectiveZ, 0.0f)) || unlikely(!_FloatCompare(__perspectiveW, 1.0f)));
494         }
495
496
497         if (unlikely(__usePerspective) || unlikely(__useRotation) || unlikely(__useShear))
498         {
499                 __transformType = MATRIX4_Generic;
500         }
501         else if (unlikely(__useScale))
502         {
503                 __transformType = MATRIX4_Scale;
504         }
505         else if (likely(__useTranslation))
506         {
507                 __transformType = MATRIX4_Translation;
508         }
509         else
510         {
511                 __transformType = MATRIX4_Identity;
512         }
513 }
514
515 FloatMatrix4
516 _TransformMatrix3Df::GetTransformMatrix(void) const
517 {
518         FloatMatrix4 m;
519
520         if (likely(__transformType == MATRIX4_Translation))
521         {
522                 m.matrix[3][0] = __translationX;
523                 m.matrix[3][1] = __translationY;
524                 m.matrix[3][2] = __translationZ;
525                 m.matrix[3][3] = 1.0f;
526                 return m;
527         }
528         else if (unlikely(__transformType == MATRIX4_Identity))
529         {
530                 _MatrixUtilSetIdentity(m);
531                 return m;
532         }
533
534
535
536         // apply perspective;
537 //      m.Set(0, 3, __perspectiveX);
538 //      m.Set(1, 3, __perspectiveY);
539 //      m.Set(2, 3, __perspectiveZ);
540 //      m.Set(3, 3, __perspectiveW);
541         m.matrix[3][0] = __perspectiveX;
542         m.matrix[3][1] = __perspectiveY;
543         m.matrix[3][2] = __perspectiveZ;
544         m.matrix[3][3] = __perspectiveW;
545
546
547         // apply translation
548 //      m.Set(3, 0, __translationX);
549 //      m.Set(3, 1, __translationY);
550 //      m.Set(3, 2, __translationZ);
551 //      m.Set(3, 3, __perspectiveW + (__perspectiveX * __translationX) + (__perspectiveY * __translationY) + (__perspectiveZ * __translationZ));
552         m.matrix[0][3] = __translationX;
553         m.matrix[1][3] = __translationY;
554         m.matrix[2][3] = __translationZ;
555         m.matrix[3][3] = __perspectiveW + (__perspectiveX * __translationX) + (__perspectiveY * __translationY) + (__perspectiveZ * __translationZ);
556
557
558         // apply rotation
559         if (unlikely(__quatX != 0.0f) || unlikely(__quatY != 0.0f) || unlikely(__quatZ != 0.0f))
560         {
561             float xx = __quatX * __quatX;
562             float xy = __quatX * __quatY;
563             float xz = __quatX * __quatZ;
564             float xw = __quatX * __quatW;
565             float yy = __quatY * __quatY;
566             float yz = __quatY * __quatZ;
567             float yw = __quatY * __quatW;
568             float zz = __quatZ * __quatZ;
569             float zw = __quatZ * __quatW;
570
571                 // Construct a composite rotation matrix from the quaternion values
572 #if 0
573                 const float rotM[4][4] = { // WARNING: C++ array is row-major order !
574                         { 1 - 2 * (yy + zz),     2 * (xy + zw),     2 * (xz - yw), 0 },
575                         {     2 * (xy - zw), 1 - 2 * (xx + zz),     2 * (yz + xw), 0 },
576                         {     2 * (xz + yw),     2 * (yz - xw), 1 - 2 * (xx + yy), 0 },
577                         {                 0,                 0,                 0, 1 }
578                 };
579 #else
580                 const float rotM[4][4] = { // WARNING: C++ array is row-major order !
581                         { 1 - 2 * (yy + zz),     2 * (xy - zw),     2 * (xz + yw), 0 },
582                         {     2 * (xy + zw), 1 - 2 * (xx + zz),     2 * (yz - xw), 0 },
583                         {     2 * (xz - yw),     2 * (yz + xw), 1 - 2 * (xx + yy), 0 },
584                         {                 0,                 0,                 0, 1 }
585                 };
586 #endif
587 #if 0
588                 m = FloatMatrix4(rotM) * m;
589 #else
590 #if 0
591                 if (__rotAnchorX != 0.0f || __rotAnchorY != 0.0f || __rotAnchorZ != 0.0f)
592                         m = GetTranslationMatrix(-__rotAnchorX, -__rotAnchorY, -__rotAnchorZ) * FloatMatrix4(rotM) * GetTranslationMatrix(__rotAnchorX, __rotAnchorY, __rotAnchorZ) * m;
593                 else
594                         m = FloatMatrix4(rotM) * m;
595 #else
596                 if (__rotAnchorX != 0.0f || __rotAnchorY != 0.0f || __rotAnchorZ != 0.0f)
597                 {
598                         const FloatMatrix4& back = GetTranslationMatrix(-__rotAnchorX, -__rotAnchorY, -__rotAnchorZ);
599                         const FloatMatrix4& move = GetTranslationMatrix(__rotAnchorX, __rotAnchorY, __rotAnchorZ);
600                         FloatMatrix4 intm;
601                         _MatrixUtilMultiply(intm, back, FloatMatrix4(rotM));
602                         _MatrixUtilMultiply(intm, intm, move);
603                         _MatrixUtilMultiply(m, intm, m);
604                 }
605                 else
606                 {
607                         _MatrixUtilMultiply(m, FloatMatrix4(rotM), m);
608                 }
609 #endif
610 #endif
611         }
612
613
614         // apply shear
615
616         if (__shearYZ)
617         {
618                 FloatMatrix4 sh;
619                 //sh.Set(2, 1, __shearYZ);
620                 sh.matrix[1][2] = __shearYZ;
621 //              m = sh * m;
622                 _MatrixUtilMultiply(m, sh, m);
623         }
624
625         if (__shearXZ)
626         {
627                 FloatMatrix4 sh;
628                 //sh.Set(2, 0, __shearXZ);
629                 sh.matrix[0][2] = __shearXZ;
630 //              m = sh * m;
631                 _MatrixUtilMultiply(m, sh, m);
632         }
633
634         if (__shearXY)
635         {
636                 FloatMatrix4 sh;
637                 //sh.Set(1, 0, __shearXY);
638                 sh.matrix[0][1] = __shearXY;
639 //              m = sh * m;
640                 _MatrixUtilMultiply(m, sh, m);
641         }
642
643         // apply scale
644 #if 0
645         if (__scaleX != 1.0f)
646         {
647 //              m.Set(0, 0, m.Get(0, 0) * __scaleX);
648 //              m.Set(0, 1, m.Get(0, 1) * __scaleX);
649 //              m.Set(0, 2, m.Get(0, 2) * __scaleX);
650 //              m.Set(0, 3, m.Get(0, 3) * __scaleX);
651                 m.matrix[0][0] = m.matrix[0][0] * __scaleX;
652                 m.matrix[1][0] = m.matrix[1][0] * __scaleX;
653                 m.matrix[2][0] = m.matrix[2][0] * __scaleX;
654                 m.matrix[3][0] = m.matrix[3][0] * __scaleX;
655         }
656
657         if (__scaleY != 1.0f)
658         {
659 //              m.Set(1, 0, m.Get(1, 0) * __scaleY);
660 //              m.Set(1, 1, m.Get(1, 1) * __scaleY);
661 //              m.Set(1, 2, m.Get(1, 2) * __scaleY);
662 //              m.Set(1, 3, m.Get(1, 3) * __scaleY);
663                 m.matrix[0][1] = m.matrix[0][1] * __scaleX;
664                 m.matrix[1][1] = m.matrix[1][1] * __scaleX;
665                 m.matrix[2][1] = m.matrix[2][1] * __scaleX;
666                 m.matrix[3][1] = m.matrix[3][1] * __scaleX;
667         }
668
669         if (__scaleZ != 1.0f)
670         {
671 //              m.Set(2, 0, m.Get(2, 0) * __scaleZ);
672 //              m.Set(2, 1, m.Get(2, 1) * __scaleZ);
673 //              m.Set(2, 2, m.Get(2, 2) * __scaleZ);
674 //              m.Set(2, 3, m.Get(2, 3) * __scaleZ);
675                 m.matrix[0][2] = m.matrix[0][2] * __scaleX;
676                 m.matrix[1][2] = m.matrix[1][2] * __scaleX;
677                 m.matrix[2][2] = m.matrix[2][2] * __scaleX;
678                 m.matrix[3][2] = m.matrix[3][2] * __scaleX;
679         }
680 #else
681         if (__scaleAnchorX != 0.0f || __scaleAnchorY != 0.0f || __scaleAnchorZ != 0.0f)
682         {
683                 FloatMatrix4 sc;
684                 _MatrixUtilScale(sc, __scaleX, __scaleY, __scaleZ);
685 //              m = GetTranslationMatrix(-__scaleAnchorX, -__scaleAnchorY, -__scaleAnchorZ) * sc * GetTranslationMatrix(__scaleAnchorX, __scaleAnchorY, __scaleAnchorZ) * m;
686
687                 const FloatMatrix4& back = GetTranslationMatrix(-__scaleAnchorX, -__scaleAnchorY, -__scaleAnchorZ);
688                 const FloatMatrix4& move = GetTranslationMatrix(__scaleAnchorX, __scaleAnchorY, __scaleAnchorZ);
689                 FloatMatrix4 intm;
690                 _MatrixUtilMultiply(intm, back, sc);
691                 _MatrixUtilMultiply(intm, intm, move);
692                 _MatrixUtilMultiply(m, intm, m);
693         }
694         else
695         {
696                 if (__scaleX != 1.0f)
697                 {
698                         m.matrix[0][0] = m.matrix[0][0] * __scaleX;
699                         m.matrix[1][0] = m.matrix[1][0] * __scaleX;
700                         m.matrix[2][0] = m.matrix[2][0] * __scaleX;
701                         m.matrix[3][0] = m.matrix[3][0] * __scaleX;
702                 }
703
704                 if (__scaleY != 1.0f)
705                 {
706                         m.matrix[0][1] = m.matrix[0][1] * __scaleY;
707                         m.matrix[1][1] = m.matrix[1][1] * __scaleY;
708                         m.matrix[2][1] = m.matrix[2][1] * __scaleY;
709                         m.matrix[3][1] = m.matrix[3][1] * __scaleY;
710                 }
711
712                 if (__scaleZ != 1.0f)
713                 {
714                         m.matrix[0][2] = m.matrix[0][2] * __scaleZ;
715                         m.matrix[1][2] = m.matrix[1][2] * __scaleZ;
716                         m.matrix[2][2] = m.matrix[2][2] * __scaleZ;
717                         m.matrix[3][2] = m.matrix[3][2] * __scaleZ;
718                 }
719         }
720 #endif
721
722         m.Transpose();
723
724         return m;
725 }
726
727 void
728 _TransformMatrix3Df::UpdateRotationFromEulerAngles(float x, float y, float z)
729 {
730         // WARNING:
731         //      Internal quaternion complies with left-hand system.
732         //
733         float hx = 0.5f * DEGTORAD(x);
734         float hy = 0.5f * DEGTORAD(y);
735         float hz = 0.5f * DEGTORAD(z);
736         float xcosh = cosf(hx);
737         float ycosh = cosf(hy);
738         float zcosh = cosf(hz);
739         float xsinh = sinf(hx);
740         float ysinh = sinf(hy);
741         float zsinh = sinf(hz);
742
743         __quatW = zcosh * ycosh * xcosh + zsinh * ysinh * xsinh;
744         __quatX = zcosh * ycosh * xsinh - zsinh * ysinh * xcosh;
745         __quatY = zcosh * ysinh * xcosh + zsinh * ycosh * xsinh;
746         __quatZ = zsinh * ycosh * xcosh - zcosh * ysinh * xsinh;
747
748 #if 0
749         printf("--euler:%f,%f,%f(%f, %f, %f)\n",
750                 x, y, z,
751                 atan2f(2.0f * (__quatW * __quatX + __quatY * __quatZ), 1.0f - 2.0f * (__quatX * __quatX + __quatY * __quatY)) * 180.0f / M_PI,
752                 asinf(2.0f * (__quatW * __quatY - __quatZ * __quatX)) * 180.0f / M_PI,
753                 atan2f(2.0f * (__quatW * __quatZ + __quatX * __quatY), 1.0f - 2.0f * (__quatY * __quatY + __quatZ * __quatZ)) * 180.0f / M_PI
754         );
755 #endif
756
757         __rotX = x;
758         __rotY = y;
759         __rotZ = z;
760
761
762         __useRotation = (unlikely(!_FloatCompare(__quatX, 0.0f)) || unlikely(!_FloatCompare(__quatY, 0.0f)) || unlikely(!_FloatCompare(__quatZ, 0.0f)) || unlikely(!_FloatCompare(__quatW, 1.0f)));
763         UpdateMatrixType(false);
764
765         //DumpQuaternion(*this);
766 }
767
768 #if 0
769 void
770 _TransformMatrix3Df::CalcEulerAngles(void)
771 {
772         exit(1);
773
774         float sx = __quatX * __quatX;
775         float sy = __quatY * __quatY;
776         float sz = __quatZ * __quatZ;
777
778 #if 0
779         float sw = __quatW * __quatW;
780
781         __rotX = atan2f(2.0f * (__quatY * __quatZ + __quatX * __quatW), (sw - sx - sy + sz));
782         __rotY = asinf(-2.0f * (__quatX * __quatZ - __quatY * __quatW));
783         __rotZ = atan2f(2.0f * (__quatX * __quatY + __quatZ * __quatW), (sw + sx - sy - sz));
784 #else
785         __rotX = atan2f(2.0f * (__quatX * __quatW + __quatY * __quatZ), 1.0f - 2.0f * (sx + sy));
786         __rotY = asinf(-2.0f * (__quatX * __quatZ - __quatY * __quatW));
787         __rotZ = atan2f(2.0f * (__quatX * __quatY + __quatZ * __quatW), 1.0f - 2.0f * (sy + sz));
788 #endif
789
790         __rotX *= 180.0f / M_PI;
791         __rotY *= 180.0f / M_PI;
792         __rotZ *= 180.0f / M_PI;
793 }
794 #endif
795
796 void
797 _TransformMatrix3Df::GetEulerAngles(float& x, float& y, float& z) const
798 {
799         x = __rotX;
800         y = __rotY;
801         z = __rotZ;
802 }
803
804 void
805 _TransformMatrix3Df::GetQuaternion(float& x, float& y, float& z, float& w) const
806 {
807         x = __quatX;
808         y = __quatY;
809         z = __quatZ;
810         w = __quatW;
811 }
812
813 void
814 _TransformMatrix3Df::GetRotationAnchor(float& x, float& y, float& z) const
815 {
816         x = __rotAnchorX;
817         y = __rotAnchorY;
818         z = __rotAnchorZ;
819 }
820
821 void
822 _TransformMatrix3Df::SetRotationAnchor(float x, float y, float z)
823 {
824         __rotAnchorX = x;
825         __rotAnchorY = y;
826         __rotAnchorZ = z;
827 }
828
829 void
830 _TransformMatrix3Df::GetScaleFactors(float& x, float& y, float& z) const
831 {
832         x = __scaleX;
833         y = __scaleY;
834         z = __scaleZ;
835 }
836
837 void
838 _TransformMatrix3Df::SetScaleFactors(float x, float y, float z)
839 {
840         __scaleX = x;
841         __scaleY = y;
842         __scaleZ = z;
843
844         __useScale = (unlikely(!_FloatCompare(x, 1.0f)) || unlikely(!_FloatCompare(y, 1.0f)) || unlikely(!_FloatCompare(z, 1.0f)));
845         UpdateMatrixType(false);
846 }
847
848 void
849 _TransformMatrix3Df::GetScaleAnchor(float& x, float& y, float& z) const
850 {
851         x = __scaleAnchorX;
852         y = __scaleAnchorY;
853         z = __scaleAnchorZ;
854 }
855
856 void
857 _TransformMatrix3Df::SetScaleAnchor(float x, float y, float z)
858 {
859         __scaleAnchorX = x;
860         __scaleAnchorY = y;
861         __scaleAnchorZ = z;
862 }
863
864 void
865 _TransformMatrix3Df::GetShearFactors(float& xy, float& xz, float& yz) const
866 {
867         xy = __shearXY;
868         xz = __shearXZ;
869         yz = __shearYZ;
870 }
871
872 void
873 _TransformMatrix3Df::SetShearFactors(float xy, float xz, float yz)
874 {
875         __shearXY = xy;
876         __shearXZ = xz;
877         __shearYZ = yz;
878
879         __useShear = (unlikely(!_FloatCompare(xy, 0.0f)) || unlikely(!_FloatCompare(xz, 0.0f)) || unlikely(!_FloatCompare(yz, 0.0f)));
880         UpdateMatrixType(false);
881 }
882
883 void
884 _TransformMatrix3Df::GetTranslationFactors(float& x, float& y, float& z) const
885 {
886         x = __translationX;
887         y = __translationY;
888         z = __translationZ;
889 }
890
891 void
892 _TransformMatrix3Df::SetTranslationFactors(float x, float y, float z)
893 {
894         __translationX = x;
895         __translationY = y;
896         __translationZ = z;
897
898         __useTranslation = (unlikely(!_FloatCompare(x, 0.0f)) || unlikely(!_FloatCompare(y, 0.0f)) || unlikely(!_FloatCompare(z, 0.0f)));
899         UpdateMatrixType(false);
900 }
901
902 void
903 _TransformMatrix3Df::GetPerspectiveFactors(float& x, float& y, float& z, float& w) const
904 {
905         x = __perspectiveX;
906         y = __perspectiveY;
907         z = __perspectiveZ;
908         w = __perspectiveW;
909 }
910
911 void
912 _TransformMatrix3Df::SetPerspectiveFactors(float x, float y, float z, float w)
913 {
914         __perspectiveX = x;
915         __perspectiveY = y;
916         __perspectiveZ = z;
917         __perspectiveW = w;
918
919         __usePerspective = (unlikely(!_FloatCompare(x, 0.0f)) || !unlikely(_FloatCompare(y, 0.0f)) || !unlikely(_FloatCompare(z, 0.0f)) || unlikely(!_FloatCompare(w, 1.0f)));
920         UpdateMatrixType(false);
921 }
922
923 // Perform a spherical linear interpolation between the two
924 // passed quaternions with 0 <= t <= 1
925 void
926 _TransformMatrix3Df::DoSlerp(float* result, const float* src1, const float* src2, float t) const
927 {
928         float ax, ay, az, aw;
929         float bx, by, bz, bw;
930         float cx, cy, cz, cw;
931         float angle;
932         float th, invth, scale, invscale;
933
934         if (unlikely(t == 0.0f))
935         {
936                 result[0] = src1[0];
937                 result[1] = src1[1];
938                 result[2] = src1[2];
939                 result[3] = src1[3];
940                 return;
941         }
942
943         if (unlikely(t == 1.0f))
944         {
945                 result[0] = src2[0];
946                 result[1] = src2[1];
947                 result[2] = src2[2];
948                 result[3] = src2[3];
949                 return;
950         }
951
952
953         ax = src1[0]; ay = src1[1]; az = src1[2]; aw = src1[3];
954         bx = src2[0]; by = src2[1]; bz = src2[2]; bw = src2[3];
955
956         angle = ax * bx + ay * by + az * bz + aw * bw;
957
958 #if 1
959         if (angle < 0.0f)
960         {
961                 ax = -ax; ay = -ay;
962                 az = -az; aw = -aw;
963                 angle = -angle;
964         }
965
966         if (angle + 1.0f > 0.05f)
967         {
968                 if (1.0f - angle >= 0.05f)
969                 {
970                         th = acosf(angle);
971                         invth = 1.0f / sinf(th);
972                         scale = sinf(th * (1.0f - t)) * invth;
973                         invscale = sinf(th * t) * invth;
974                 }
975                 else
976                 {
977                         scale = 1.0f - t;
978                         invscale = t;
979                 }
980         }
981         else
982         {
983                 bx = -ay;
984                 by = ax;
985                 bz = -aw;
986                 bw = az;
987                 scale = sinf(M_PI * (0.5f - t));
988                 invscale = sinf(M_PI * t);
989         }
990
991         cx = ax * scale + bx * invscale;
992         cy = ay * scale + by * invscale;
993         cz = az * scale + bz * invscale;
994         cw = aw * scale + bw * invscale;
995         //cz = -cz;
996 #if 0
997         float the, a, rx, ry, rz;
998         the = acosf(cw);
999         a = the * 2.0f * 180.0f / M_PI;
1000         rx = cx / sinf(the);
1001         ry = cy / sinf(the);
1002         rz = cz / sinf(the);
1003 //printf("--- angle= %f(f= %f,%f,%f)(%f, %f, %f, %f)\n", a, rx, ry, rz, cx, cy, cz, cw);
1004 #endif
1005 #endif
1006
1007 #if 0
1008         if (angle < 0)
1009         {
1010                 bx = -bx;
1011                 by = -by;
1012                 bz = -bz;
1013                 bw = -bw;
1014                 angle = -angle;
1015         }
1016
1017         if (angle <= -1.0f || angle >= 1.0f)
1018         {
1019                 cx = ax;
1020                 cy = ay;
1021                 cz = az;
1022                 cw = aw;
1023         }
1024         else
1025         {
1026                 th = acos(angle);
1027                 float sinHalfTheta = sqrt(1.0 - angle * angle);
1028                 if (abs(sinHalfTheta) < 0.001)
1029                 {
1030                         cx = ax * 0.5 + bx * 0.5;
1031                         cy = ay * 0.5 + by * 0.5;
1032                         cz = az * 0.5 + bz * 0.5;
1033                         cw = aw * 0.5 + bw * 0.5;
1034                 }
1035                 else
1036                 {
1037                         float ra = sin((1.0 - t) * th) / sinHalfTheta;
1038                         float rb = sin(t * th) / sinHalfTheta;
1039                         cx = ax * ra + bx * rb;
1040                         cy = ay * ra + by * rb;
1041                         cz = az * ra + bz * rb;
1042                         cw = aw * ra + bw * rb;
1043                 }
1044         }
1045 #endif
1046
1047
1048         result[0] = cx;
1049         result[1] = cy;
1050         result[2] = cz;
1051         result[3] = cw;
1052 }
1053
1054 #if 0
1055 void
1056 _TransformMatrix3Df::V4MulPointByMatrix(const _Vector4Df& pin, const FloatMatrix4& m, _Vector4Df& pout) const
1057 {
1058 /*
1059         pout.x = (pin.x * m.Get(0, 0))
1060                    + (pin.y * m.Get(1, 0))
1061                    + (pin.z * m.Get(2, 0))
1062                    + (pin.w * m.Get(3, 0));
1063
1064         pout.y = (pin.x * m.Get(0, 1))
1065                    + (pin.y * m.Get(1, 1))
1066                    + (pin.z * m.Get(2, 1))
1067                    + (pin.w * m.Get(3, 1));
1068
1069         pout.z = (pin.x * m.Get(0, 2))
1070                    + (pin.y * m.Get(1, 2))
1071                    + (pin.z * m.Get(2, 2))
1072                    + (pin.w * m.Get(3, 2));
1073
1074         pout.w = (pin.x * m.Get(0, 3))
1075                    + (pin.y * m.Get(1, 3))
1076                    + (pin.z * m.Get(2, 3))
1077                    + (pin.w * m.Get(3, 3));
1078 */
1079
1080         pout.x = (pin.x * m.matrix[0][0])
1081                    + (pin.y * m.matrix[0][1])
1082                    + (pin.z * m.matrix[0][2])
1083                    + (pin.w * m.matrix[0][3]);
1084
1085         pout.y = (pin.x * m.matrix[1][0])
1086                    + (pin.y * m.matrix[1][1])
1087                    + (pin.z * m.matrix[1][2])
1088                    + (pin.w * m.matrix[1][3]);
1089
1090         pout.z = (pin.x * m.matrix[2][0])
1091                    + (pin.y * m.matrix[2][1])
1092                    + (pin.z * m.matrix[2][2])
1093                    + (pin.w * m.matrix[2][3]);
1094
1095         pout.w = (pin.x * m.matrix[3][0])
1096                    + (pin.y * m.matrix[3][1])
1097                    + (pin.z * m.matrix[3][2])
1098                    + (pin.w * m.matrix[3][3]);
1099
1100 }
1101
1102 float
1103 _TransformMatrix3Df::V3SquaredLength(const _Vector3Df& v) const
1104 {
1105         return ((v.x * v.x) + (v.y * v.y) + (v.z * v.z));
1106 }
1107
1108 float
1109 _TransformMatrix3Df::V3Length(const _Vector3Df& v) const
1110 {
1111         return (sqrtf(V3SquaredLength(v)));
1112 }
1113
1114 void
1115 _TransformMatrix3Df::V3Scale(_Vector3Df& v, float newlen) const
1116 {
1117         float len = V3Length(v);
1118
1119         if (len != 0.0f)
1120         {
1121         v.x *= newlen / len;
1122                 v.y *= newlen / len;
1123                 v.z *= newlen / len;
1124         }
1125 }
1126
1127 float
1128 _TransformMatrix3Df::V3Dot(const _Vector3Df& a, const _Vector3Df& b) const
1129 {
1130     return ((a.x * b.x) + (a.y * b.y) + (a.z * b.z));
1131 }
1132
1133 void
1134 _TransformMatrix3Df::V3Combine(const _Vector3Df& a, const _Vector3Df& b, _Vector3Df& result, float ascl, float bscl) const
1135 {
1136         result.x = (ascl * a.x) + (bscl * b.x);
1137         result.y = (ascl * a.y) + (bscl * b.y);
1138         result.z = (ascl * a.z) + (bscl * b.z);
1139 }
1140
1141 void
1142 _TransformMatrix3Df::V3Cross(const _Vector3Df& a, const _Vector3Df& b, _Vector3Df& c) const
1143 {
1144         c.x = (a.y * b.z) - (a.z * b.y);
1145         c.y = (a.z * b.x) - (a.x * b.z);
1146         c.z = (a.x * b.y) - (a.y * b.x);
1147 }
1148 #endif
1149
1150 }}}             // Tizen::Ui::Animations
1151
1152