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