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