Revert "[Tizen] Appendix log for ttrace + Print keycode and timestamp"
[platform/core/uifw/dali-core.git] / automated-tests / src / dali / utc-Dali-Quaternion.cpp
1 /*
2  * Copyright ( c ) 2020 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 ( the "License" );
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17
18 #include <dali-test-suite-utils.h>
19 #include <dali/public-api/dali-core.h>
20 #include <stdlib.h>
21
22 #include <iostream>
23 #include <sstream>
24
25 using namespace Dali;
26
27 void utc_dali_quaternion_startup(void)
28 {
29   test_return_value = TET_UNDEF;
30 }
31
32 void utc_dali_quaternion_cleanup(void)
33 {
34   test_return_value = TET_PASS;
35 }
36
37 int UtcDaliQuaternionCtorDefaultP(void)
38 {
39   Quaternion q;
40   DALI_TEST_EQUALS(q.AsVector().w, 1.0f, TEST_LOCATION);
41   DALI_TEST_EQUALS(q.AsVector().x, 0.0f, TEST_LOCATION);
42   DALI_TEST_EQUALS(q.AsVector().y, 0.0f, TEST_LOCATION);
43   DALI_TEST_EQUALS(q.AsVector().z, 0.0f, TEST_LOCATION);
44   END_TEST;
45 }
46
47 int UtcDaliQuaternionCtorCosSinThetaP(void)
48 {
49   Quaternion q(1.0f, 0.1f, 0.2f, 0.3f);
50
51   DALI_TEST_EQUALS(q.AsVector().w, 1.0f, TEST_LOCATION);
52   DALI_TEST_EQUALS(q.AsVector().x, 0.1f, TEST_LOCATION);
53   DALI_TEST_EQUALS(q.AsVector().y, 0.2f, TEST_LOCATION);
54   DALI_TEST_EQUALS(q.AsVector().z, 0.3f, TEST_LOCATION);
55   END_TEST;
56 }
57
58 int UtcDaliQuaternionCtorVector4P(void)
59 {
60   Quaternion q(Vector4(1.0f, 0.1f, 0.2f, 0.3f));
61
62   DALI_TEST_EQUALS(q.AsVector().x, 1.0f, TEST_LOCATION);
63   DALI_TEST_EQUALS(q.AsVector().y, 0.1f, TEST_LOCATION);
64   DALI_TEST_EQUALS(q.AsVector().z, 0.2f, TEST_LOCATION);
65   DALI_TEST_EQUALS(q.AsVector().w, 0.3f, TEST_LOCATION);
66   END_TEST;
67 }
68
69 int UtcDaliQuaternionCtorAxisAngleVector3P(void)
70 {
71   Quaternion q(Dali::ANGLE_90, Vector3(1.0f, 2.0f, 3.0f));
72
73   // This will be normalised:
74   DALI_TEST_EQUALS(q.AsVector().w, 0.707f, 0.001, TEST_LOCATION);
75   DALI_TEST_EQUALS(q.AsVector().x, 0.189f, 0.001, TEST_LOCATION);
76   DALI_TEST_EQUALS(q.AsVector().y, 0.378f, 0.001, TEST_LOCATION);
77   DALI_TEST_EQUALS(q.AsVector().z, 0.567f, 0.001, TEST_LOCATION);
78   END_TEST;
79 }
80
81 int UtcDaliQuaternionCtorEulerAngleP(void)
82 {
83   Quaternion q1(0.924f, 0.383f, 0.0f, 0.0f);
84   Vector4    r1(Radian(Degree(45)), 0.0f, 0.0f, 0.0f);
85
86   Quaternion q2(0.793f, 0.0f, 0.609f, 0.0f);
87   Vector4    r2(0.0f, Radian(Degree(75)), 0.0f, 0.0f);
88
89   Quaternion q3(0.383f, 0.0f, 0.0f, 0.924f);
90   Vector4    r3(0.0f, 0.0f, Radian(Degree(135)), 0.0f);
91
92   Quaternion q4(0.795f, 0.478f, 0.374f, 0.006f);
93   Vector4    r4(Radian(Degree(71)), Radian(Degree(36)), Radian(Degree(27)), 0.0f);
94
95   Quaternion q5(-0.149f, -0.697f, 0.145f, -0.686f);
96   Vector4    r5(Radian(Degree(148.0)), Radian(Degree(-88.2)), Radian(Degree(8.0)), 0.0f);
97
98   DALI_TEST_EQUALS(q1.EulerAngles(), r1, 0.001, TEST_LOCATION);
99   DALI_TEST_EQUALS(q2.EulerAngles(), r2, 0.001, TEST_LOCATION);
100   DALI_TEST_EQUALS(q3.EulerAngles(), r3, 0.001, TEST_LOCATION);
101   DALI_TEST_EQUALS(q4.EulerAngles(), r4, 0.01, TEST_LOCATION);
102   DALI_TEST_EQUALS(q5.EulerAngles(), r5, 0.01, TEST_LOCATION);
103   END_TEST;
104 }
105
106 int UtcDaliQuaternionCtorMatrixP01(void)
107 {
108   // angle: 60 deg, axis: [1,2,3]
109   float  Mref_raw[16] = {0.535714f, 0.765794f, -0.355767f, 0.0f, -0.622936f, 0.642857f, 0.445741f, 0.0f, 0.570053f, -0.0171693f, 0.821429f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f};
110   Matrix Mref(Mref_raw);
111
112   Quaternion q1(Radian(M_PI / 3.0f), Vector3(1.0f, 2.0f, 3.0f));
113   Quaternion q2(Mref);
114
115   DALI_TEST_EQUALS(q1, q2, 0.001, TEST_LOCATION);
116   END_TEST;
117 }
118
119 int UtcDaliQuaternionCtorMatrixP02(void)
120 {
121   // IDENTITY rotation
122   Quaternion q;
123
124   Matrix m(q); // Convert to matrix
125
126   Quaternion q2(m); // and back to a quaternion
127
128   DALI_TEST_EQUALS(q, q2, 0.001, TEST_LOCATION);
129   DALI_TEST_EQUALS(m, Matrix::IDENTITY, 0.001f, TEST_LOCATION);
130   END_TEST;
131 }
132
133 int UtcDaliQuaternionCtorMatrixP03(void)
134 {
135   // Create an arbitrary forward vector
136   for(float x = -1.0f; x <= 1.0f; x += 0.1f)
137   {
138     for(float y = -1.0f; y < 1.0f; y += 0.1f)
139     {
140       for(float z = -1.0f; z < 1.0f; z += 0.1f)
141       {
142         Vector3 vForward(x, y, z);
143         vForward.Normalize();
144
145         // Construct an up vector from a sideways move
146         Vector3 vSide;
147         Vector3 vUp = vForward.Cross(Vector3(vForward.x + 1.0f, vForward.y, vForward.z));
148         if(vUp.Length() > 0.01)
149         {
150           vUp.Normalize();
151           vSide = vUp.Cross(vForward);
152           vSide.Normalize();
153         }
154         else
155         {
156           vSide = vForward.Cross(Vector3(vForward.x, vForward.y + 1.0f, vForward.z));
157           vSide.Normalize();
158           vUp = vForward.Cross(vSide);
159           vUp.Normalize();
160         }
161
162         // Generate a matrix, and then a quaternion from it
163         Matrix rotMatrix(Matrix::IDENTITY);
164         rotMatrix.SetXAxis(vSide);
165         rotMatrix.SetYAxis(vUp);
166         rotMatrix.SetZAxis(vForward);
167         Quaternion q(rotMatrix);
168
169         // Generate a matrix from the quaternion, check they are the same
170         Matrix resultMatrix(q);
171         DALI_TEST_EQUALS(resultMatrix, rotMatrix, 0.001f, TEST_LOCATION);
172
173         // Rotate an arbitrary vector by both quaternion and rotation matrix,
174         // check the result is the same
175
176         Vector4 aVector(-2.983f, -3.213f, 8.2239f, 1.0f);
177         Vector3 aVectorRotatedByQ = q.Rotate(Vector3(aVector));
178         Vector4 aVectorRotatedByR = rotMatrix * aVector;
179         DALI_TEST_EQUALS(aVectorRotatedByQ, Vector3(aVectorRotatedByR), 0.001f, TEST_LOCATION);
180       }
181     }
182   }
183   END_TEST;
184 }
185
186 int UtcDaliQuaternionCopyConstructor(void)
187 {
188   Quaternion q0(1.0f, 0.1f, 0.2f, 0.3f);
189   Quaternion q1(q0);
190   DALI_TEST_EQUALS(q1.AsVector().w, 1.0f, TEST_LOCATION);
191   DALI_TEST_EQUALS(q1.AsVector().x, 0.1f, TEST_LOCATION);
192   DALI_TEST_EQUALS(q1.AsVector().y, 0.2f, TEST_LOCATION);
193   DALI_TEST_EQUALS(q1.AsVector().z, 0.3f, TEST_LOCATION);
194
195   END_TEST;
196 }
197
198 int UtcDaliQuaternionMoveConstructor(void)
199 {
200   Quaternion q0(1.0f, 0.1f, 0.2f, 0.3f);
201   Quaternion q1 = std::move(q0);
202   DALI_TEST_EQUALS(q1.AsVector().w, 1.0f, TEST_LOCATION);
203   DALI_TEST_EQUALS(q1.AsVector().x, 0.1f, TEST_LOCATION);
204   DALI_TEST_EQUALS(q1.AsVector().y, 0.2f, TEST_LOCATION);
205   DALI_TEST_EQUALS(q1.AsVector().z, 0.3f, TEST_LOCATION);
206
207   END_TEST;
208 }
209
210 int UtcDaliQuaternionCopyAssignment(void)
211 {
212   Quaternion q0(1.0f, 0.1f, 0.2f, 0.3f);
213   Quaternion q1;
214   q1 = q0;
215   DALI_TEST_EQUALS(q1.AsVector().w, 1.0f, TEST_LOCATION);
216   DALI_TEST_EQUALS(q1.AsVector().x, 0.1f, TEST_LOCATION);
217   DALI_TEST_EQUALS(q1.AsVector().y, 0.2f, TEST_LOCATION);
218   DALI_TEST_EQUALS(q1.AsVector().z, 0.3f, TEST_LOCATION);
219
220   END_TEST;
221 }
222
223 int UtcDaliQuaternionMoveAssignment(void)
224 {
225   Quaternion q0(1.0f, 0.1f, 0.2f, 0.3f);
226   Quaternion q1;
227   q1 = std::move(q0);
228   DALI_TEST_EQUALS(q1.AsVector().w, 1.0f, TEST_LOCATION);
229   DALI_TEST_EQUALS(q1.AsVector().x, 0.1f, TEST_LOCATION);
230   DALI_TEST_EQUALS(q1.AsVector().y, 0.2f, TEST_LOCATION);
231   DALI_TEST_EQUALS(q1.AsVector().z, 0.3f, TEST_LOCATION);
232
233   END_TEST;
234 }
235
236 int UtcDaliQuaternionCtorAxesP01(void)
237 {
238   // angle: 60 deg, axis: [1,2,3]
239   float  Mref_raw[16] = {0.535714f, 0.765794f, -0.355767f, 0.0f, -0.622936f, 0.642857f, 0.445741f, 0.0f, 0.570053f, -0.0171693f, 0.821429f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f};
240   Matrix Mref(Mref_raw);
241
242   Quaternion q1(Radian(M_PI / 3.0f), Vector3(1.0f, 2.0f, 3.0f));
243   Quaternion q2(Mref.GetXAxis(), Mref.GetYAxis(), Mref.GetZAxis());
244
245   DALI_TEST_EQUALS(q1, q2, 0.001, TEST_LOCATION);
246   END_TEST;
247 }
248
249 int UtcDaliQuaternionCtorAxesP02(void)
250 {
251   Vector3 xAxis(Vector3::XAXIS);
252   Vector3 yAxis(Vector3::YAXIS);
253   Vector3 zAxis(Vector3::ZAXIS);
254
255   Quaternion q1(xAxis, yAxis, zAxis);
256
257   DALI_TEST_EQUALS(q1, Quaternion::IDENTITY, TEST_LOCATION);
258
259   xAxis = Vector3(1.0f, 1.0f, 0.0f);
260   xAxis.Normalize();
261   yAxis = Vector3(-1.0f, 1.0f, 0.0f); // 45 degrees anticlockwise ( +ve ) around z
262   yAxis.Normalize();
263   zAxis = xAxis.Cross(yAxis);
264   zAxis.Normalize();
265   Quaternion q2(xAxis, yAxis, zAxis);
266
267   DALI_TEST_EQUALS(q2, Quaternion(Radian(Degree(45)), Vector3::ZAXIS), 0.001f, TEST_LOCATION);
268   END_TEST;
269 }
270
271 int UtcDaliQuaternionCtorAxesP03(void)
272 {
273   // Create an arbitrary forward vector
274   for(float x = -1.0f; x <= 1.0f; x += 0.1f)
275   {
276     for(float y = -1.0f; y < 1.0f; y += 0.1f)
277     {
278       for(float z = -1.0f; z < 1.0f; z += 0.1f)
279       {
280         Vector3 vForward(x, y, z);
281         vForward.Normalize();
282
283         // Construct an up vector from a sideways move
284         Vector3 vSide;
285         Vector3 vUp = vForward.Cross(Vector3(vForward.x + 1.0f, vForward.y, vForward.z));
286         if(vUp.Length() > 0.01)
287         {
288           vUp.Normalize();
289           vSide = vUp.Cross(vForward);
290           vSide.Normalize();
291         }
292         else
293         {
294           vSide = vForward.Cross(Vector3(vForward.x, vForward.y + 1.0f, vForward.z));
295           vSide.Normalize();
296           vUp = vForward.Cross(vSide);
297           vUp.Normalize();
298         }
299
300         // Generate a quaternion
301         Quaternion q(vSide, vUp, vForward);
302
303         Matrix rotMatrix;
304         rotMatrix.SetXAxis(vSide);
305         rotMatrix.SetYAxis(vUp);
306         rotMatrix.SetZAxis(vForward);
307
308         // Generate a matrix from the quaternion, check they are the same
309         Matrix m(q);
310         DALI_TEST_EQUALS(m.GetXAxis(), vSide, 0.001f, TEST_LOCATION);
311         DALI_TEST_EQUALS(m.GetYAxis(), vUp, 0.001f, TEST_LOCATION);
312         DALI_TEST_EQUALS(m.GetZAxis(), vForward, 0.001f, TEST_LOCATION);
313
314         // Rotate an arbitrary vector by both quaternion and rotation matrix,
315         // check the result is the same
316
317         Vector4 aVector(2.043f, 12.8f, -3.872f, 1.0f);
318         Vector3 aVectorRotatedByQ = q.Rotate(Vector3(aVector));
319         Vector4 aVectorRotatedByR = rotMatrix * aVector;
320         DALI_TEST_EQUALS(aVectorRotatedByQ, Vector3(aVectorRotatedByR), 0.001f, TEST_LOCATION);
321       }
322     }
323   }
324   END_TEST;
325 }
326
327 int UtcDaliQuaternionCtorTwoVectorsP(void)
328 {
329   Vector3 v0(1.0f, 2.0f, 3.0f);
330   Vector3 v1(-2.0f, 10.0f, -1.0f);
331   v0.Normalize();
332   v1.Normalize();
333   Quaternion q(v0, v1);
334
335   DALI_TEST_EQUALS(q * v0, v1, 0.001, TEST_LOCATION);
336   END_TEST;
337 }
338
339 int UtcDaliQuaternionAsVectorP(void)
340 {
341   Vector4    v(1.0f, 0.1f, 0.2f, 0.3f);
342   Quaternion q(v);
343
344   DALI_TEST_EQUALS(v, q.AsVector(), TEST_LOCATION);
345   END_TEST;
346 }
347
348 int UtcDaliQuaternionToAxisAngleVector3P(void)
349 {
350   Quaternion q(0.932f, 1.1f, 3.4f, 2.7f);
351   Radian     angle;
352   Vector3    axis;
353   bool       converted = q.ToAxisAngle(axis, angle);
354   DALI_TEST_EQUALS(converted, true, TEST_LOCATION);
355   DALI_TEST_EQUALS(angle.radian, 0.74f, 0.01f, TEST_LOCATION);
356   DALI_TEST_EQUALS(axis.x, 3.03f, 0.01f, TEST_LOCATION);
357   DALI_TEST_EQUALS(axis.y, 9.38f, 0.01f, TEST_LOCATION);
358   DALI_TEST_EQUALS(axis.z, 7.45f, 0.01f, TEST_LOCATION);
359   END_TEST;
360 }
361
362 int UtcDaliQuaternionToAxisAngleVector3N(void)
363 {
364   Quaternion q(1, 2, 3, 4);
365   Radian     angle;
366   Vector3    axis;
367   bool       converted = q.ToAxisAngle(axis, angle);
368   DALI_TEST_EQUALS(converted, false, TEST_LOCATION);
369   DALI_TEST_EQUALS(angle.radian, 0.0f, 0.01f, TEST_LOCATION);
370   DALI_TEST_EQUALS(axis.x, 0.0f, 0.01f, TEST_LOCATION);
371   DALI_TEST_EQUALS(axis.y, 0.0f, 0.01f, TEST_LOCATION);
372   DALI_TEST_EQUALS(axis.z, 0.0f, 0.01f, TEST_LOCATION);
373   END_TEST;
374 }
375
376 int UtcDaliQuaternionSetEulerP(void)
377 {
378   // Test from euler angles
379   Quaternion e1;
380   e1.SetEuler(Dali::ANGLE_45, Dali::ANGLE_0, Dali::ANGLE_0);
381   Vector4 r1(0.383f, 0.0f, 0.0f, 0.924f);
382
383   Quaternion e2;
384   e2.SetEuler(Dali::ANGLE_0, Radian(Degree(75)), Dali::ANGLE_0);
385   Vector4 r2(0.0f, 0.609f, 0.0f, 0.793f);
386
387   Quaternion e3;
388   e3.SetEuler(Dali::ANGLE_0, Dali::ANGLE_0, Radian(Degree(135)));
389   Vector4 r3(0.0f, 0.0f, 0.924f, 0.383f);
390
391   Quaternion e4;
392   e4.SetEuler(Radian(Degree(71)), Radian(Degree(36)), Radian(Degree(27)));
393   Vector4 r4(0.478f, 0.374f, 0.006f, 0.795f);
394
395   Quaternion e5;
396   e5.SetEuler(Radian(Degree(-31)), Radian(Degree(-91)), Radian(Degree(-173)));
397   Vector4 r5(-0.697f, 0.145f, -0.686f, -0.149f);
398
399   DALI_TEST_EQUALS(e1.AsVector(), r1, 0.001, TEST_LOCATION);
400   DALI_TEST_EQUALS(e2.AsVector(), r2, 0.001, TEST_LOCATION);
401   DALI_TEST_EQUALS(e3.AsVector(), r3, 0.001, TEST_LOCATION);
402   DALI_TEST_EQUALS(e4.AsVector(), r4, 0.001, TEST_LOCATION);
403   DALI_TEST_EQUALS(e5.AsVector(), r5, 0.001, TEST_LOCATION);
404   END_TEST;
405 }
406
407 int UtcDaliQuaternionEulerAnglesP(void)
408 {
409   Quaternion q1(0.924f, 0.383f, 0.0f, 0.0f);
410   Vector4    r1(Radian(Degree(45)), 0.0f, 0.0f, 0.0f);
411
412   Quaternion q2(0.793f, 0.0f, 0.609f, 0.0f);
413   Vector4    r2(0.0f, Radian(Degree(75)), 0.0f, 0.0f);
414
415   Quaternion q3(0.383f, 0.0f, 0.0f, 0.924f);
416   Vector4    r3(0.0f, 0.0f, Radian(Degree(135)), 0.0f);
417
418   Quaternion q4(0.795f, 0.478f, 0.374f, 0.006f);
419   Vector4    r4(Radian(Degree(71)), Radian(Degree(36)), Radian(Degree(27)), 0.0f);
420
421   Quaternion q5(-0.149f, -0.697f, 0.145f, -0.686f);
422   Vector4    r5(Radian(Degree(148.0)), Radian(Degree(-88.2)), Radian(Degree(8.0)), 0.0f);
423
424   DALI_TEST_EQUALS(q1.EulerAngles(), r1, 0.001, TEST_LOCATION);
425   DALI_TEST_EQUALS(q2.EulerAngles(), r2, 0.001, TEST_LOCATION);
426   DALI_TEST_EQUALS(q3.EulerAngles(), r3, 0.001, TEST_LOCATION);
427   DALI_TEST_EQUALS(q4.EulerAngles(), r4, 0.01, TEST_LOCATION);
428   DALI_TEST_EQUALS(q5.EulerAngles(), r5, 0.01, TEST_LOCATION);
429   END_TEST;
430 }
431
432 int UtcDaliQuaternionToMatrixP01(void)
433 {
434   Quaternion q(Radian(0.69813), Vector3(1.0f, 0.0f, 0.0f)); // 40 degree rotation around X axis
435
436   // Result calculated using a different maths library ( with appropriate row/col ordering )
437
438   float  els[] = {1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.766f, 0.643f, 0.0f, 0.0f, -0.643f, 0.766f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f};
439   Matrix mRes(els);
440   Matrix m(q);
441
442   DALI_TEST_EQUALS(m, mRes, 0.01, TEST_LOCATION);
443   END_TEST;
444 }
445
446 int UtcDaliQuaternionToMatrixP02(void)
447 {
448   // rotation around arbitrary axis
449   Quaternion q2(Radian(-1.23918f), Vector3(7.0f, -13.0f, 11.0f));
450
451   float  els[] = {0.423f, -0.746f, -0.514f, 0.00f, 0.384f, 0.662f, -0.644f, 0.00f, 0.821f, 0.075f, 0.566f, 0.00f, 0.000f, 0.000f, 0.000f, 1.00f};
452   Matrix mRes2(els);
453
454   Matrix m2(q2);
455
456   DALI_TEST_EQUALS(m2, mRes2, 0.01, TEST_LOCATION);
457   END_TEST;
458 }
459
460 int UtcDaliQuaternionOperatorAdditionP(void)
461 {
462   Quaternion q1(0.383f, 0.0f, 0.0f, 0.924f);
463   Quaternion q2(0.0f, 0.609f, 0.0f, 0.793f);
464
465   Quaternion r1(0.383f, 0.609f, 0.0f, 1.717f);
466
467   DALI_TEST_EQUALS(q1 + q2, r1, 0.001f, TEST_LOCATION);
468   END_TEST;
469 }
470
471 int UtcDaliQuaternionOperatorSubtractionP(void)
472 {
473   Quaternion q1(0.383f, 0.450f, 0.123f, 0.924f);
474   Quaternion q2(0.383f, 0.690f, 0.234f, 1.917f);
475
476   Quaternion r1(0.0f, 0.240f, 0.111f, 0.993f);
477
478   DALI_TEST_EQUALS(q2 - q1, r1, 0.001f, TEST_LOCATION);
479   END_TEST;
480 }
481
482 int UtcDaliQuaternionConjugateP(void)
483 {
484   float   s1 = 0.784f;
485   Vector3 v1(0.045f, 0.443f, 0.432f);
486   float   s2 = 0.697f;
487   Vector3 v2(0.612, 0.344, -0.144);
488
489   Quaternion q1(s1, v1.x, v1.y, v1.z);
490   Quaternion q2(s2, v2.x, v2.y, v2.z);
491   q1.Conjugate();
492   q2.Conjugate();
493
494   Quaternion r1(s1, -v1.x, -v1.y, -v1.z);
495   Quaternion r2(s2, -v2.x, -v2.y, -v2.z);
496
497   DALI_TEST_EQUALS(q1, r1, 0.001f, TEST_LOCATION);
498   DALI_TEST_EQUALS(q2, r2, 0.001f, TEST_LOCATION);
499   END_TEST;
500 }
501
502 int UtcDaliQuaternionOperatorMultiplicationQuaternionP(void)
503 {
504   float   s1 = 0.784f;
505   Vector3 v1(0.045f, 0.443f, 0.432f);
506   float   s2 = 0.697f;
507   Vector3 v2(0.612, 0.344, -0.144);
508
509   Quaternion q1(s1, v1.x, v1.y, v1.z);
510   Quaternion q2(s2, v2.x, v2.y, v2.z);
511
512   Vector3    vp = v1.Cross(v2) + v2 * s1 + v1 * s2;
513   Quaternion r1(s1 * s2 - v1.Dot(v2), vp.x, vp.y, vp.z);
514
515   DALI_TEST_EQUALS(q1 * q2, r1, 0.001f, TEST_LOCATION);
516   END_TEST;
517 }
518
519 // Quaternion * vector == Vector rotation
520 int UtcDaliQuaternionOperatorMultiplicationVector3P(void)
521 {
522   // Rotation of vector p = ( x,y,z ) by Quaternion q == q [0,p] q^-1
523   Vector3    v(2, 3, 4);
524   Quaternion q(Radian(Degree(72)), Vector3::ZAXIS);
525   Quaternion qI = q;
526   qI.Invert();
527   Quaternion qv(0.0f, v.x, v.y, v.z);
528   Quaternion r1 = (q * qv) * qI;
529
530   Vector3 r2 = q * v;
531
532   DALI_TEST_EQUALS(r1.mVector.x, r2.x, 0.001, TEST_LOCATION);
533   DALI_TEST_EQUALS(r1.mVector.y, r2.y, 0.001, TEST_LOCATION);
534   DALI_TEST_EQUALS(r1.mVector.z, r2.z, 0.001, TEST_LOCATION);
535   END_TEST;
536 }
537
538 int UtcDaliQuaternionOperatorMultiplicationFloatP01(void)
539 {
540   // Rotation of vector p = ( x,y,z ) by Quaternion q == q [0,p] q^-1
541   Quaternion q(Vector4(0.1f, 0.2f, 0.3f, 1.0f));
542   Quaternion q2 = q * 2.f;
543   Vector4    v2(0.2f, 0.4f, 0.6f, 2.0f);
544
545   DALI_TEST_EQUALS(q2.AsVector(), v2, 0.001, TEST_LOCATION);
546   END_TEST;
547 }
548
549 int UtcDaliQuaternionOperatorMultiplicationFloatP02(void)
550 {
551   Quaternion q1(0.383f, 0.0f, 0.0f, 0.924f);
552   Quaternion r1(2.0f * 0.383f, 0.0f, 0.0f, 2.0f * 0.924f);
553
554   DALI_TEST_EQUALS(q1 * 2.0f, r1, 0.001f, TEST_LOCATION);
555   END_TEST;
556 }
557
558 int UtcDaliQuaternionOperatorMultiplicationFloatP03(void)
559 {
560   Quaternion q1(0.383f, 0.0f, 0.0f, 0.924f);
561   Quaternion r1(0.5f * 0.383f, 0.0f, 0.0f, 0.5f * 0.924f);
562
563   DALI_TEST_EQUALS(q1 / 2.0f, r1, 0.001f, TEST_LOCATION);
564   END_TEST;
565 }
566
567 int UtcDaliQuaternionOperatorDivisionQuaternionP(void)
568 {
569   Quaternion q1(0.383f, 0.0f, 0.0f, 0.924f);
570   Quaternion q2(0.0f, 0.609f, 0.0f, 0.793f);
571
572   // q1 / q2 = q1 * q2^-1
573   // q2^-1 = q2* / ||q2||^2
574   //       = Conjugate of q2 / Square of Norm of q2
575
576   Quaternion r1 = q2;
577   r1.Conjugate();
578   r1 *= 1.0f / q2.LengthSquared();
579   Quaternion r2 = q1 * r1;
580
581   DALI_TEST_EQUALS(q1 / q2, r2, 0.001f, TEST_LOCATION);
582   END_TEST;
583 }
584
585 int UtcDaliQuaternionOperatorDivisionFloatP(void)
586 {
587   Quaternion q1(0.383f, 0.0f, 0.0f, 0.924f);
588   Quaternion r1(2.0f * 0.383f, 0.0f, 0.0f, 2.0f * 0.924f);
589
590   DALI_TEST_EQUALS(q1, r1 / 2.0f, 0.001f, TEST_LOCATION);
591   END_TEST;
592 }
593
594 int UtcDaliQuaternionOperatorDivideAssignedFloatP(void)
595 {
596   Quaternion q1(0.383f, 0.0f, 0.0f, 0.924f);
597   Quaternion r1(2.0f * 0.383f, 0.0f, 0.0f, 2.0f * 0.924f);
598   r1 /= 2.0f;
599
600   DALI_TEST_EQUALS(q1, r1, 0.001f, TEST_LOCATION);
601   END_TEST;
602 }
603
604 int UtcDaliQuaternionOperatorNegationP(void)
605 {
606   Quaternion q1(0.383f, 0.0f, 0.0f, 0.924f);
607   Quaternion r1(-0.383f, -0.0f, -0.0f, -0.924f);
608
609   DALI_TEST_EQUALS(-q1, r1, 0.001f, TEST_LOCATION);
610   END_TEST;
611 }
612
613 int UtcDaliQuaternionOperatorAddAssignP(void)
614 {
615   Quaternion q1(0.383f, 0.0f, 0.0f, 0.924f);
616   Quaternion q2(0.0f, 0.609f, 0.0f, 0.793f);
617
618   Quaternion r1(0.383f, 0.609f, 0.0f, 1.717f);
619
620   q1 += q2;
621   DALI_TEST_EQUALS(q1, r1, 0.001f, TEST_LOCATION);
622   END_TEST;
623 }
624
625 int UtcDaliQuaternionOperatorSubtractAssignP(void)
626 {
627   Quaternion q1(0.383f, 0.450f, 0.123f, 0.924f);
628   Quaternion q2(0.383f, 0.690f, 0.234f, 1.917f);
629
630   Quaternion r1(0.0f, 0.240f, 0.111f, 0.993f);
631   q2 -= q1;
632   DALI_TEST_EQUALS(q2, r1, 0.001f, TEST_LOCATION);
633   END_TEST;
634 }
635
636 int UtcDaliQuaternionOperatorMultiplyAssignQuaternionP(void)
637 {
638   float   s1 = 0.784f;
639   Vector3 v1(0.045f, 0.443f, 0.432f);
640   float   s2 = 0.697f;
641   Vector3 v2(0.612, 0.344, -0.144);
642
643   Quaternion q1(s1, v1.x, v1.y, v1.z);
644   Quaternion q2(s2, v2.x, v2.y, v2.z);
645
646   Quaternion r3 = q2 * q1;
647   q2 *= q1;
648   DALI_TEST_EQUALS(q2, r3, 0.001f, TEST_LOCATION);
649   END_TEST;
650 }
651
652 int UtcDaliQuaternionOperatorMultiplyAssignFloatP01(void)
653 {
654   Quaternion q1(0.383f, 0.450f, 0.123f, 0.924f);
655   float      scale = 2.5f;
656   Quaternion r1(scale * 0.383f, scale * 0.450f, scale * 0.123f, scale * 0.924f);
657   q1 *= scale;
658   DALI_TEST_EQUALS(q1, r1, 0.001f, TEST_LOCATION);
659   END_TEST;
660 }
661
662 int UtcDaliQuaternionOperatorMultiplyAssignFloatP02(void)
663 {
664   Quaternion q1(0.383f, 0.450f, 0.123f, 0.924f);
665   float      scale = 2.5f;
666   Quaternion r1(0.383f / scale, 0.450f / scale, 0.123f / scale, 0.924f / scale);
667   q1 /= scale;
668   DALI_TEST_EQUALS(q1, r1, 0.001f, TEST_LOCATION);
669   END_TEST;
670 }
671
672 int UtcDaliQuaternionOperatorEqualityP(void)
673 {
674   Quaternion q1(0.383f, 0.450f, 0.123f, 0.924f);
675   Quaternion q2(0.383f, 0.450f, 0.123f, 0.924f);
676   Quaternion q3(0.383f, 0.450f, 0.123f, 0.800f);
677   Quaternion q4(0.383f, 0.450f, 0.100f, 0.800f);
678   Quaternion q5(0.383f, 0.100f, 0.100f, 0.800f);
679   Quaternion q6(0.100f, 0.100f, 0.100f, 0.800f);
680
681   Quaternion q7(-0.383f, -0.450f, -0.123f, -0.924f);
682   Quaternion q8(-0.383f, -0.450f, -0.123f, 0.924f);
683   Quaternion q9(-0.383f, -0.450f, 0.123f, 0.924f);
684   Quaternion q10(-0.383f, 0.450f, 0.123f, 0.924f);
685
686   DALI_TEST_CHECK(q1 == q2);
687   DALI_TEST_CHECK(!(q1 == q3));
688   DALI_TEST_CHECK(!(q1 == q4));
689   DALI_TEST_CHECK(!(q1 == q5));
690   DALI_TEST_CHECK(!(q1 == q6));
691   DALI_TEST_CHECK((q1 == q7));
692   DALI_TEST_CHECK(!(q1 == q8));
693   DALI_TEST_CHECK(!(q1 == q9));
694   DALI_TEST_CHECK(!(q1 == q10));
695   END_TEST;
696 }
697
698 int UtcDaliQuaternionOperatorInequalityP(void)
699 {
700   Quaternion q1(0.383f, 0.450f, 0.123f, 0.924f);
701   Quaternion q2(0.383f, 0.450f, 0.123f, 0.924f);
702   Quaternion q3(-0.383f, -0.0f, -0.0f, -0.924f);
703   DALI_TEST_CHECK(!(q1 != q2));
704   DALI_TEST_CHECK(q1 != q3);
705   END_TEST;
706 }
707
708 int UtcDaliQuaternionLengthP(void)
709 {
710   Quaternion q1(0.383f, 0.450f, 0.123f, 0.924f);
711   float      length = sqrtf(0.383f * 0.383f + 0.450f * 0.450f + 0.123f * 0.123f + 0.924f * 0.924f);
712   DALI_TEST_EQUALS(q1.Length(), length, 0.001f, TEST_LOCATION);
713   END_TEST;
714 }
715
716 int UtcDaliQuaternionLengthSquaredP(void)
717 {
718   Quaternion q1(0.383f, 0.450f, 0.123f, 0.924f);
719   float      lengthSquared = 0.383f * 0.383f + 0.450f * 0.450f + 0.123f * 0.123f + 0.924f * 0.924f;
720   DALI_TEST_EQUALS(q1.LengthSquared(), lengthSquared, 0.01f, TEST_LOCATION);
721   END_TEST;
722 }
723
724 int UtcDaliQuaternionNormalizeP(void)
725 {
726   Quaternion q1(0.118f, 0.692f, -0.127f, 0.701f);
727   Quaternion q2 = q1;
728   q2 *= 5.0f;
729   q2.Normalize();
730   DALI_TEST_EQUALS(q1, q2, 0.001f, TEST_LOCATION);
731   END_TEST;
732 }
733
734 int UtcDaliQuaternionNormalizedP(void)
735 {
736   Quaternion q1(0.118f, 0.692f, -0.127f, 0.701f);
737   Quaternion q2 = q1;
738   q2 *= 5.0f;
739   DALI_TEST_EQUALS(q1, q2.Normalized(), 0.001f, TEST_LOCATION);
740   END_TEST;
741 }
742
743 int UtcDaliQuaternionIsIdentityP(void)
744 {
745   Quaternion q(1.0f, 0.0f, 0.0f, 0.0f);
746   DALI_TEST_EQUALS(q.IsIdentity(), true, TEST_LOCATION);
747   END_TEST;
748 }
749
750 int UtcDaliQuaternionIsIdentityN(void)
751 {
752   Quaternion q(1.0f, 0.1f, 0.0f, 0.0f);
753   DALI_TEST_EQUALS(q.IsIdentity(), false, TEST_LOCATION);
754   END_TEST;
755 }
756
757 int UtcDaliQuaternionInvertP(void)
758 {
759   Quaternion q1(0.383f, 0.0f, 0.0f, 0.924f);
760
761   // q1^-1 = q1* / ||q1||^2
762   //       = Conjugate of q1 / Square of Norm of q1
763
764   Quaternion r1 = q1;
765   r1.Conjugate();
766   r1 *= 1.0f / q1.LengthSquared();
767
768   Quaternion q2 = q1;
769   q2.Invert();
770   DALI_TEST_EQUALS(q2, r1, 0.001f, TEST_LOCATION);
771   END_TEST;
772 }
773
774 int UtcDaliQuaternionDotP(void)
775 {
776   // q.q' = s*s' + v dot v'
777   float   s1 = 0.784f;
778   Vector3 v1(0.045f, 0.443f, 0.432f);
779   float   s2 = 0.697f;
780   Vector3 v2(0.612, 0.344, -0.144);
781
782   Quaternion q1(s1, v1.x, v1.y, v1.z);
783   Quaternion q2(s2, v2.x, v2.y, v2.z);
784
785   float r1 = s1 * s2 + v1.Dot(v2);
786
787   DALI_TEST_EQUALS(Quaternion::Dot(q1, q2), r1, TEST_LOCATION);
788   END_TEST;
789 }
790
791 int UtcDaliQuaternionRotateVector3P(void)
792 {
793   // Rotation of vector p = ( x,y,z ) by Quaternion q == q [0,p] q^-1
794   Vector3    v(2, 3, 4);
795   Quaternion q(Radian(Degree(72)), Vector3::ZAXIS);
796   Quaternion qI = q;
797   qI.Invert();
798   Quaternion qv(0.0f, v.x, v.y, v.z);
799   Quaternion r1 = q * qv * qI;
800
801   Vector3 r2 = q.Rotate(v);
802
803   DALI_TEST_EQUALS(r1.mVector.x, r2.x, 0.001f, TEST_LOCATION);
804   DALI_TEST_EQUALS(r1.mVector.y, r2.y, 0.001f, TEST_LOCATION);
805   DALI_TEST_EQUALS(r1.mVector.z, r2.z, 0.001f, TEST_LOCATION);
806
807   DALI_TEST_EQUALS(q.Rotate(v), q * v, 0.001f, TEST_LOCATION);
808   END_TEST;
809 }
810
811 int UtcDaliQuaternionRotateVector4P(void)
812 {
813   // Rotation of vector p = ( x,y,z ) by Quaternion q == q [0,p] q^-1
814   Vector4    v(2, 3, 4, 5);
815   Quaternion q(Radian(Degree(72)), Vector3::ZAXIS);
816   Quaternion qI = q;
817   qI.Invert();
818   Quaternion qv(0.0f, v.x, v.y, v.z);
819   Quaternion r1 = q * qv * qI;
820
821   Vector4 r2 = q.Rotate(v);
822
823   DALI_TEST_EQUALS(r1.mVector.x, r2.x, 0.001f, TEST_LOCATION);
824   DALI_TEST_EQUALS(r1.mVector.y, r2.y, 0.001f, TEST_LOCATION);
825   DALI_TEST_EQUALS(r1.mVector.z, r2.z, 0.001f, TEST_LOCATION);
826   DALI_TEST_EQUALS(r1.mVector.w, 0.0f, 0.001f, TEST_LOCATION);
827   END_TEST;
828 }
829
830 int UtcDaliQuaternionExpP01(void)
831 {
832   Quaternion q1(0.0f, 1.0f, 1.2f, 1.3f);
833   Quaternion q2 = q1.Exp();
834   Quaternion r2(-0.4452, 0.4406, 0.5287, 0.5728);
835
836   DALI_TEST_EQUALS(q2.Length(), 1.0f, 0.01f, TEST_LOCATION);
837
838   DALI_TEST_EQUALS(q2, r2, 0.001f, TEST_LOCATION);
839
840   // Note, this trick only works when |v| < pi, which it is!
841   Quaternion q3 = q2.Log();
842   DALI_TEST_EQUALS(q1, q3, 0.01f, TEST_LOCATION);
843   END_TEST;
844 }
845
846 int UtcDaliQuaternionExpP02(void)
847 {
848   Quaternion q1(0.0f, 0.0f, 0.0f, 0.0f);
849   Quaternion q2 = q1.Exp();
850   Quaternion r2(1.0f, 0.0f, 0.0f, 0.0f);
851
852   DALI_TEST_EQUALS(q2.Length(), 1.0f, 0.01f, TEST_LOCATION);
853
854   DALI_TEST_EQUALS(q2, r2, 0.001f, TEST_LOCATION);
855
856   // Note, this trick only works when |v| < pi, which it is!
857   Quaternion q3 = q2.Log();
858   DALI_TEST_EQUALS(q1, q3, 0.01f, TEST_LOCATION);
859   END_TEST;
860 }
861
862 int UtcDaliQuaternionExpN(void)
863 {
864   Quaternion q(Radian(0.0f), Vector3(5.0f, 6.0f, 7.0f));
865
866   // q.w is non-zero. Should assert.
867   try
868   {
869     q.Exp();
870     DALI_TEST_CHECK(false);
871   }
872   catch(DaliException& e)
873   {
874     DALI_TEST_CHECK(true);
875   }
876   END_TEST;
877 }
878
879 int UtcDaliQuaternionLogP01(void)
880 {
881   Quaternion q(Radian(Math::PI * 0.73f), Vector3(2, 3, 4));
882   Quaternion q2 = q;
883   q2.Normalize();
884
885   Quaternion r = q2.Log();
886   DALI_TEST_EQUALS(r.mVector.w, 0.0f, 0.01f, TEST_LOCATION);
887
888   Quaternion r2 = r.Exp();
889   DALI_TEST_EQUALS(r2, q2, 0.01f, TEST_LOCATION);
890   END_TEST;
891 }
892
893 int UtcDaliQuaternionLogP02(void)
894 {
895   Quaternion q1(1.0f, 0.0f, 0.0f, 0.0f);
896   Quaternion r1(0.0f, 0.0f, 0.0f, 0.0f);
897
898   Quaternion q2 = q1.Log();
899
900   DALI_TEST_EQUALS(q2, r1, 0.01f, TEST_LOCATION);
901
902   Quaternion q3 = q2.Exp();
903   DALI_TEST_EQUALS(q1, q3, 0.01f, TEST_LOCATION);
904   END_TEST;
905 }
906
907 int UtcDaliQuaternionLerpP(void)
908 {
909   Quaternion q1(Radian(Degree(-80)), Vector3(0.0f, 0.0f, 1.0f));
910   Quaternion q2(Radian(Degree(80)), Vector3(0.0f, 0.0f, 1.0f));
911
912   Quaternion p = Quaternion::Lerp(q1, q2, 0.0f);
913   DALI_TEST_EQUALS(p, q1, 0.001f, TEST_LOCATION);
914
915   p = Quaternion::Lerp(q1, q2, 1.0f);
916   DALI_TEST_EQUALS(p, q2, 0.001f, TEST_LOCATION);
917
918   p             = Quaternion::Lerp(q1, q2, 0.5f);
919   Quaternion r1 = (q1 + q2) * 0.5f;
920   r1.Normalize();
921   DALI_TEST_EQUALS(p, r1, 0.001f, TEST_LOCATION);
922   END_TEST;
923 }
924
925 int UtcDaliQuaternionSlerpP01(void)
926 {
927   Quaternion q1(Radian(M_PI / 4.0f), Vector3(0.0f, 0.0f, 1.0f));
928   Quaternion q2(Radian(-M_PI / 4.0f), Vector3(0.0f, 0.0f, 1.0f));
929
930   Quaternion q = Quaternion::Slerp(q1, q2, 0.0f);
931   DALI_TEST_EQUALS(q, q1, 0.001, TEST_LOCATION);
932
933   q = Quaternion::Slerp(q1, q2, 1.0f);
934   DALI_TEST_EQUALS(q, q2, 0.001, TEST_LOCATION);
935
936   // @ 25%, will be at M_PI/8
937   q = Quaternion::Slerp(q1, q2, 0.25f);
938   Vector3 axis;
939   Radian  angle;
940   bool    converted = q.ToAxisAngle(axis, angle);
941   DALI_TEST_EQUALS(converted, true, TEST_LOCATION);
942   DALI_TEST_EQUALS(angle.radian, Math::PI / 8.0f, 0.001, TEST_LOCATION);
943   DALI_TEST_EQUALS(axis.x, 0.0f, 0.001, TEST_LOCATION);
944   DALI_TEST_EQUALS(axis.y, 0.0f, 0.001, TEST_LOCATION);
945   DALI_TEST_EQUALS(axis.z, 1.0f, 0.001, TEST_LOCATION);
946   END_TEST;
947 }
948
949 int UtcDaliQuaternionSlerpP02(void)
950 {
951   Quaternion q1(Dali::ANGLE_30, Vector3(0.0f, 0.0f, 1.0f));
952   Quaternion q2(Dali::ANGLE_90, Vector3(0.0f, 0.0f, 1.0f));
953
954   Quaternion q = Quaternion::Slerp(q1, q2, 0.0f);
955
956   DALI_TEST_EQUALS(q, q1, 0.001, TEST_LOCATION);
957
958   q = Quaternion::Slerp(q1, q2, 1.0f);
959
960   DALI_TEST_EQUALS(q, q2, 0.001, TEST_LOCATION);
961
962   // @ 50%, will be at M_PI/3 around z
963   q = Quaternion::Slerp(q1, q2, 0.5f);
964
965   Quaternion r(Dali::ANGLE_60, Vector3(0.0f, 0.0f, 1.0f));
966   DALI_TEST_EQUALS(q, r, 0.001, TEST_LOCATION);
967   END_TEST;
968 }
969
970 int UtcDaliQuaternionSlerpP03(void)
971 {
972   Quaternion q1(Radian(Degree(125)), Vector3(0.0f, 0.0f, 1.0f));
973   Quaternion q2(Radian(Degree(-125)), Vector3(0.002f, 0.001f, 1.001f));
974
975   Quaternion q = Quaternion::Slerp(q1, q2, 0.0f);
976   DALI_TEST_EQUALS(q, q1, 0.001, TEST_LOCATION);
977
978   q = Quaternion::Slerp(q1, q2, 1.0f);
979   DALI_TEST_EQUALS(q, q2, 0.001, TEST_LOCATION);
980
981   q = Quaternion::Slerp(q1, q2, 0.05f);
982   Vector3 axis;
983   Radian  angle;
984   bool    converted = q.ToAxisAngle(axis, angle);
985   DALI_TEST_EQUALS(converted, true, TEST_LOCATION);
986
987   DALI_TEST_EQUALS(axis.x, 0.0f, 0.01, TEST_LOCATION);
988   DALI_TEST_EQUALS(axis.y, 0.0f, 0.01, TEST_LOCATION);
989   DALI_TEST_EQUALS(axis.z, 1.0f, 0.01, TEST_LOCATION);
990   END_TEST;
991 }
992
993 int UtcDaliQuaternionSlerpP04(void)
994 {
995   Quaternion q1(Radian(Degree(120)), Vector3(0.0f, 0.0f, 1.0f));
996   Quaternion q2(Radian(Degree(130)), Vector3(0.0f, 0.0f, 1.0f));
997
998   Quaternion q = Quaternion::Slerp(q1, q2, 0.0f);
999   DALI_TEST_EQUALS(q, q1, 0.001, TEST_LOCATION);
1000
1001   q = Quaternion::Slerp(q1, q2, 1.0f);
1002   DALI_TEST_EQUALS(q, q2, 0.001, TEST_LOCATION);
1003
1004   q = Quaternion::Slerp(q1, q2, 0.5f);
1005   Vector3 axis;
1006   Radian  angle;
1007   bool    converted = q.ToAxisAngle(axis, angle);
1008   DALI_TEST_EQUALS(converted, true, TEST_LOCATION);
1009   DALI_TEST_EQUALS(angle.radian, float(Radian(Degree(125))), 0.01f, TEST_LOCATION);
1010   DALI_TEST_EQUALS(axis.x, 0.0f, 0.01, TEST_LOCATION);
1011   DALI_TEST_EQUALS(axis.y, 0.0f, 0.01, TEST_LOCATION);
1012   DALI_TEST_EQUALS(axis.z, 1.0f, 0.01, TEST_LOCATION);
1013   END_TEST;
1014 }
1015
1016 int UtcDaliQuaternionSlerpNoInvertP01(void)
1017 {
1018   Quaternion q1(Dali::ANGLE_45, Vector3(0.0f, 0.0f, 1.0f));
1019   Quaternion q2(-Dali::ANGLE_45, Vector3(0.0f, 0.0f, 1.0f));
1020
1021   Quaternion q = Quaternion::SlerpNoInvert(q1, q2, 0.0f);
1022   DALI_TEST_EQUALS(q, q1, 0.001, TEST_LOCATION);
1023
1024   q = Quaternion::SlerpNoInvert(q1, q2, 1.0f);
1025   DALI_TEST_EQUALS(q, q2, 0.001, TEST_LOCATION);
1026
1027   // @ 25%, will be at M_PI/8
1028   q = Quaternion::SlerpNoInvert(q1, q2, 0.25f);
1029   Vector3 axis;
1030   Radian  angle;
1031   bool    converted = q.ToAxisAngle(axis, angle);
1032   DALI_TEST_EQUALS(converted, true, TEST_LOCATION);
1033   DALI_TEST_EQUALS(angle.radian, Math::PI / 8.0f, 0.001, TEST_LOCATION);
1034   DALI_TEST_EQUALS(axis.x, 0.0f, 0.001, TEST_LOCATION);
1035   DALI_TEST_EQUALS(axis.y, 0.0f, 0.001, TEST_LOCATION);
1036   DALI_TEST_EQUALS(axis.z, 1.0f, 0.001, TEST_LOCATION);
1037   END_TEST;
1038 }
1039
1040 int UtcDaliQuaternionSlerpNoInvertP02(void)
1041 {
1042   Quaternion q1(Radian(Degree(120)), Vector3(0.0f, 0.0f, 1.0f));
1043   Quaternion q2(Radian(Degree(130)), Vector3(0.0f, 0.0f, 1.0f));
1044
1045   Quaternion q = Quaternion::SlerpNoInvert(q1, q2, 0.0f);
1046   DALI_TEST_EQUALS(q, q1, 0.001, TEST_LOCATION);
1047
1048   q = Quaternion::SlerpNoInvert(q1, q2, 1.0f);
1049   DALI_TEST_EQUALS(q, q2, 0.001, TEST_LOCATION);
1050
1051   q = Quaternion::SlerpNoInvert(q1, q2, 0.5f);
1052   Vector3 axis;
1053   Radian  angle;
1054   bool    converted = q.ToAxisAngle(axis, angle);
1055   DALI_TEST_EQUALS(converted, true, TEST_LOCATION);
1056   DALI_TEST_EQUALS(angle.radian, float(Radian(Degree(125))), 0.01f, TEST_LOCATION);
1057   DALI_TEST_EQUALS(axis.x, 0.0f, 0.01, TEST_LOCATION);
1058   DALI_TEST_EQUALS(axis.y, 0.0f, 0.01, TEST_LOCATION);
1059   DALI_TEST_EQUALS(axis.z, 1.0f, 0.01, TEST_LOCATION);
1060   END_TEST;
1061 }
1062
1063 int UtcDaliQuaternionSquadP(void)
1064 {
1065   Quaternion q1(Radian(Degree(45)), Vector3(0.0f, 0.0f, 1.0f));
1066   Quaternion q1out(Radian(Degree(40)), Vector3(0.0f, 1.0f, 2.0f));
1067   Quaternion q2in(Radian(Degree(35)), Vector3(0.0f, 2.0f, 3.0f));
1068   Quaternion q2(Radian(Degree(30)), Vector3(0.0f, 1.0f, 3.0f));
1069
1070   Quaternion q = Quaternion::Squad(q1, q2, q1out, q2in, 0.0f);
1071   DALI_TEST_EQUALS(q, q1, 0.001f, TEST_LOCATION);
1072
1073   q = Quaternion::Squad(q1, q2, q1out, q2in, 1.0f);
1074   DALI_TEST_EQUALS(q, q2, 0.001f, TEST_LOCATION);
1075
1076   // Don't know what actual value should be, but can make some informed guesses.
1077   q = Quaternion::Squad(q1, q2, q1out, q2in, 0.5f);
1078   Radian  angle;
1079   Vector3 axis;
1080   q.Normalize();
1081   q.ToAxisAngle(axis, angle);
1082
1083   if(angle < 0.0f)
1084   {
1085     q = -q; // Might get negative quat
1086     q.ToAxisAngle(axis, angle);
1087   }
1088   float deg = Degree(angle).degree;
1089   DALI_TEST_CHECK(deg >= 0 && deg <= 90);
1090   DALI_TEST_CHECK(axis.y > 0);
1091   DALI_TEST_CHECK(axis.z > 0);
1092   END_TEST;
1093 }
1094
1095 int UtcDaliAngleBetweenP(void)
1096 {
1097   Quaternion q1(ANGLE_45, ANGLE_0, ANGLE_0);
1098   Quaternion q2(Radian(Degree(47)), ANGLE_0, ANGLE_0);
1099   DALI_TEST_EQUALS(Quaternion::AngleBetween(q1, q2), fabsf(Radian(Degree(45)) - Radian(Degree(47))), 0.001f, TEST_LOCATION);
1100
1101   Quaternion q3(Radian(Degree(80)), Vector3::YAXIS);
1102   Quaternion q4(Radian(Degree(90)), Vector3::YAXIS);
1103   DALI_TEST_EQUALS(Quaternion::AngleBetween(q3, q4), fabsf(Radian(Degree(80)) - Radian(Degree(90))), 0.001f, TEST_LOCATION);
1104
1105   Quaternion q5(Radian(Degree(0)), Vector3::YAXIS);
1106   Quaternion q6(Radian(Degree(90)), Vector3::XAXIS);
1107   DALI_TEST_EQUALS(Quaternion::AngleBetween(q5, q6), fabsf(Radian(Degree(0)) - Radian(Degree(90))), 0.001f, TEST_LOCATION);
1108
1109   Quaternion q7(Radian(Degree(0)), Vector3::YAXIS);
1110   Quaternion q8(Radian(Degree(0)), Vector3::XAXIS);
1111   DALI_TEST_EQUALS(Quaternion::AngleBetween(q7, q8), fabsf(Radian(Degree(0)) - Radian(Degree(0))), 0.001f, TEST_LOCATION);
1112
1113   Quaternion q9(Radian(Degree(0)), Vector3::XAXIS);
1114   Quaternion q10(Radian(Degree(180)), Vector3::XAXIS);
1115   DALI_TEST_EQUALS(Quaternion::AngleBetween(q9, q10), fabsf(Radian(Degree(0)) - Radian(Degree(180))), 0.001f, TEST_LOCATION);
1116
1117   Quaternion q11(Radian(Degree(1)), Vector3::YAXIS);
1118   Quaternion q12(Radian(Degree(240)), Vector3::YAXIS);
1119   DALI_TEST_EQUALS(Quaternion::AngleBetween(q11, q12), fabsf(Radian(Degree(1 - 240 + 360))), 0.001f, TEST_LOCATION);
1120
1121   Quaternion q13(Radian(Degree(240)), Vector3::YAXIS);
1122   Quaternion q14(Radian(Degree(1)), Vector3::YAXIS);
1123   DALI_TEST_EQUALS(Quaternion::AngleBetween(q13, q14), fabsf(Radian(Degree(240 - 1 - 360))), 0.001f, TEST_LOCATION);
1124
1125   Quaternion q15(Radian(Degree(240)), Vector3::YAXIS);
1126   Quaternion q16(Radian(Degree(1)), Vector3::ZAXIS);
1127   DALI_TEST_EQUALS(Quaternion::AngleBetween(q15, q16), Quaternion::AngleBetween(q16, q15), 0.001f, TEST_LOCATION);
1128   END_TEST;
1129 }
1130
1131 int UtcDaliQuaternionOStreamOperatorP(void)
1132 {
1133   std::ostringstream oss;
1134
1135   Quaternion quaternion(Dali::ANGLE_180, Vector3::YAXIS);
1136
1137   oss << quaternion;
1138
1139   std::string expectedOutput = "[ Axis: [0, 1, 0], Angle: 180 degrees ]";
1140
1141   DALI_TEST_EQUALS(oss.str(), expectedOutput, TEST_LOCATION);
1142   END_TEST;
1143 }