2 // Copyright (c) 2014 Samsung Electronics Co., Ltd.
4 // Licensed under the Flora License, Version 1.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
8 // http://floralicense.org/license/
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.
21 #include <dali/dali.h>
22 #include <dali-test-suite-utils.h>
27 void utc_dali_quaternion_startup(void)
29 test_return_value = TET_UNDEF;
32 void utc_dali_quaternion_cleanup(void)
34 test_return_value = TET_PASS;
38 int UtcDaliQuaternionCtor01(void)
40 TestApplication application; // Reset all test adapter return codes
42 DALI_TEST_EQUALS(r.AsVector().w, 1.0f, TEST_LOCATION);
43 DALI_TEST_EQUALS(r.AsVector().x, 0.0f, TEST_LOCATION);
44 DALI_TEST_EQUALS(r.AsVector().y, 0.0f, TEST_LOCATION);
45 DALI_TEST_EQUALS(r.AsVector().z, 0.0f, TEST_LOCATION);
49 int UtcDaliQuaternionCtor02(void)
51 TestApplication application; // Reset all test adapter return codes
53 Quaternion r(M_PI/2.0f, Vector4(1.0f, 2.0f, 3.0f, M_PI/3.0f));
55 // This will be normalised:
56 DALI_TEST_EQUALS(r.AsVector().w, 0.707f, 0.001, TEST_LOCATION);
57 DALI_TEST_EQUALS(r.AsVector().x, 0.189f, 0.001, TEST_LOCATION);
58 DALI_TEST_EQUALS(r.AsVector().y, 0.378f, 0.001, TEST_LOCATION);
59 DALI_TEST_EQUALS(r.AsVector().z, 0.567f, 0.001, TEST_LOCATION);
64 int UtcDaliQuaternionCtor03(void)
66 TestApplication application; // Reset all test adapter return codes
68 // Test from euler angles
69 Quaternion e1(Radian(Degree(45)), 0.0f, 0.0f);
70 Vector4 r1(0.383f, 0.0f, 0.0f, 0.924f);
72 Quaternion e2(0.0f, Radian(Degree(75)), 0.0f);
73 Vector4 r2(0.0f, 0.609f, 0.0f, 0.793f);
75 Quaternion e3(0.0f, 0.0f, Radian(Degree(135)));
76 Vector4 r3(0.0f, 0.0f, 0.924f, 0.383f);
78 Quaternion e4(Radian(Degree(71)), Radian(Degree(36)), Radian(Degree(27)));
79 Vector4 r4(0.478f, 0.374f, 0.006f, 0.795f);
81 Quaternion e5(Radian(Degree(-31)), Radian(Degree(-91)), Radian(Degree(-173)));
82 Vector4 r5(-0.697f, 0.145f, -0.686f, -0.149f);
84 DALI_TEST_EQUALS(e1.AsVector(), r1, 0.001, TEST_LOCATION);
85 DALI_TEST_EQUALS(e2.AsVector(), r2, 0.001, TEST_LOCATION);
86 DALI_TEST_EQUALS(e3.AsVector(), r3, 0.001, TEST_LOCATION);
87 DALI_TEST_EQUALS(e4.AsVector(), r4, 0.001, TEST_LOCATION);
88 DALI_TEST_EQUALS(e5.AsVector(), r5, 0.001, TEST_LOCATION);
93 int UtcDaliQuaternionFromAxisAngle(void)
95 TestApplication application; // Reset all test adapter return codes
97 Quaternion q = Quaternion::FromAxisAngle(Vector4(1.0f, 2.0f, 3.0f, M_PI/3.0f), M_PI/2.0f);
99 Quaternion r(0.707f, 0.189f, 0.378f, 0.567f);
101 DALI_TEST_EQUALS(q, r, 0.001, TEST_LOCATION);
105 int UtcDaliQuaternionToAxisAngle01(void)
107 TestApplication application; // Reset all test adapter return codes
108 Quaternion q(0.932f, 1.1f, 3.4f, 2.7f);
111 bool converted = q.ToAxisAngle(axis, angle);
112 DALI_TEST_EQUALS(converted, true, TEST_LOCATION);
113 DALI_TEST_EQUALS(angle, 0.74f, 0.01f, TEST_LOCATION);
114 DALI_TEST_EQUALS(axis.x, 3.03f, 0.01f, TEST_LOCATION);
115 DALI_TEST_EQUALS(axis.y, 9.38f, 0.01f, TEST_LOCATION);
116 DALI_TEST_EQUALS(axis.z, 7.45f, 0.01f, TEST_LOCATION);
120 int UtcDaliQuaternionToAxisAngle02(void)
122 TestApplication application; // Reset all test adapter return codes
123 Quaternion q(0.932f, 1.1f, 3.4f, 2.7f);
126 bool converted = q.ToAxisAngle(axis, angle);
127 DALI_TEST_EQUALS(converted, true, TEST_LOCATION);
128 DALI_TEST_EQUALS(angle, 0.74f, 0.01f, TEST_LOCATION);
129 DALI_TEST_EQUALS(axis.x, 3.03f, 0.01f, TEST_LOCATION);
130 DALI_TEST_EQUALS(axis.y, 9.38f, 0.01f, TEST_LOCATION);
131 DALI_TEST_EQUALS(axis.z, 7.45f, 0.01f, TEST_LOCATION);
132 DALI_TEST_EQUALS(axis.w, 0.0f, 0.01f, TEST_LOCATION);
137 int UtcDaliQuaternionToAxisAngle03(void)
139 TestApplication application; // Reset all test adapter return codes
140 Quaternion q(1, 2, 3, 4);
143 bool converted = q.ToAxisAngle(axis, angle);
144 DALI_TEST_EQUALS(converted, false, TEST_LOCATION);
145 DALI_TEST_EQUALS(angle, 0.0f, 0.01f, TEST_LOCATION);
146 DALI_TEST_EQUALS(axis.x, 0.0f, 0.01f, TEST_LOCATION);
147 DALI_TEST_EQUALS(axis.y, 0.0f, 0.01f, TEST_LOCATION);
148 DALI_TEST_EQUALS(axis.z, 0.0f, 0.01f, TEST_LOCATION);
152 int UtcDaliQuaternionToAxisAngle04(void)
154 TestApplication application; // Reset all test adapter return codes
155 Quaternion q(1, 2, 3, 4);
158 bool converted = q.ToAxisAngle(axis, angle);
159 DALI_TEST_EQUALS(converted, false, TEST_LOCATION);
160 DALI_TEST_EQUALS(angle, 0.0f, 0.01f, TEST_LOCATION);
161 DALI_TEST_EQUALS(axis.x, 0.0f, 0.01f, TEST_LOCATION);
162 DALI_TEST_EQUALS(axis.y, 0.0f, 0.01f, TEST_LOCATION);
163 DALI_TEST_EQUALS(axis.z, 0.0f, 0.01f, TEST_LOCATION);
164 DALI_TEST_EQUALS(axis.w, 0.0f, 0.01f, TEST_LOCATION);
170 int UtcDaliQuaternionEulerAngles(void)
172 TestApplication application; // Reset all test adapter return codes
174 Quaternion q1(0.924f, 0.383f, 0.0f, 0.0f);
175 Vector4 r1(Radian(Degree(45)), 0.0f, 0.0f, 0.0f);
177 Quaternion q2(0.793f, 0.0f, 0.609f, 0.0f);
178 Vector4 r2(0.0f, Radian(Degree(75)), 0.0f, 0.0f);
180 Quaternion q3(0.383f, 0.0f, 0.0f, 0.924f);
181 Vector4 r3(0.0f, 0.0f, Radian(Degree(135)), 0.0f);
183 Quaternion q4(0.795f, 0.478f, 0.374f, 0.006f);
184 Vector4 r4(Radian(Degree(71)), Radian(Degree(36)), Radian(Degree(27)), 0.0f);
186 Quaternion q5( -0.149f, -0.697f, 0.145f, -0.686f);
187 Vector4 r5(Radian(Degree(148.0)), Radian(Degree(-88.2)), Radian(Degree(8.0)), 0.0f);
189 DALI_TEST_EQUALS(q1.EulerAngles(), r1, 0.001, TEST_LOCATION);
190 DALI_TEST_EQUALS(q2.EulerAngles(), r2, 0.001, TEST_LOCATION);
191 DALI_TEST_EQUALS(q3.EulerAngles(), r3, 0.001, TEST_LOCATION);
192 DALI_TEST_EQUALS(q4.EulerAngles(), r4, 0.01, TEST_LOCATION);
193 DALI_TEST_EQUALS(q5.EulerAngles(), r5, 0.01, TEST_LOCATION);
198 int UtcDaliQuaternionToMatrix01(void)
200 TestApplication application; // Reset all test adapter return codes
202 Quaternion q(0.69813, Vector4(1.0f, 0.0f, 0.0f, 0.0f)); // 40 degree rotation around X axis
204 // Result calculated using a different maths library (with appropriate row/col ordering)
206 float els[] = { 1.0f, 0.0f, 0.0f, 0.0f,
207 0.0f, 0.766f, 0.643f, 0.0f,
208 0.0f, -0.643f, 0.766f, 0.0f,
209 0.0f, 0.0f, 0.0f, 1.0f };
213 DALI_TEST_EQUALS(m, mRes, 0.01, TEST_LOCATION);
217 int UtcDaliQuaternionToMatrix02(void)
219 TestApplication application; // Reset all test adapter return codes
221 // rotation around arbitrary axis
222 Quaternion q2(-1.23918f, Vector4(7.0f, -13.0f, 11.0f, 0.0f));
224 float els[] = { 0.423f, -0.746f, -0.514f, 0.00f,
225 0.384f, 0.662f, -0.644f, 0.00f,
226 0.821f, 0.075f, 0.566f, 0.00f,
227 0.000f, 0.000f, 0.000f, 1.00f };
232 DALI_TEST_EQUALS(m2, mRes2, 0.01, TEST_LOCATION);
237 int UtcDaliQuaternionFromMatrix01(void)
239 TestApplication application; // Reset all test adapter return codes
244 Matrix m(q); // Convert to matrix
246 Quaternion q2(m); // and back to a quaternion
248 DALI_TEST_EQUALS(q, q2, 0.001, TEST_LOCATION);
249 DALI_TEST_EQUALS(m, Matrix::IDENTITY, 0.001f, TEST_LOCATION);
253 int UtcDaliQuaternionFromMatrix02(void)
255 TestApplication application; // Reset all test adapter return codes
257 // Create an arbitrary forward vector
258 for( float x=-1.0f; x<=1.0f; x+=0.1f )
260 for( float y=-1.0f; y<1.0f; y+=0.1f )
262 for( float z=-1.0f; z<1.0f; z+=0.1f )
264 Vector3 vForward(x, y, z);
265 vForward.Normalize();
267 // Construct an up vector from a sideways move
269 Vector3 vUp = vForward.Cross(Vector3(vForward.x+1.0f, vForward.y, vForward.z));
270 if(vUp.Length() > 0.01 )
273 vSide = vUp.Cross(vForward);
278 vSide = vForward.Cross(Vector3(vForward.x, vForward.y+1.0f, vForward.z));
280 vUp = vForward.Cross(vSide);
284 // Generate a matrix, and then a quaternion from it
285 Matrix rotMatrix(Matrix::IDENTITY);
286 rotMatrix.SetXAxis(vSide);
287 rotMatrix.SetYAxis(vUp);
288 rotMatrix.SetZAxis(vForward);
289 Quaternion q( rotMatrix );
291 // Generate a matrix from the quaternion, check they are the same
292 Matrix resultMatrix(q);
293 DALI_TEST_EQUALS(resultMatrix, rotMatrix, 0.001f, TEST_LOCATION);
295 // Rotate an arbitrary vector by both quaternion and rotation matrix,
296 // check the result is the same
298 Vector4 aVector(-2.983f, -3.213f, 8.2239f, 1.0f);
299 Vector3 aVectorRotatedByQ = q.Rotate(Vector3(aVector));
300 Vector4 aVectorRotatedByR = rotMatrix*aVector;
301 DALI_TEST_EQUALS(aVectorRotatedByQ, Vector3(aVectorRotatedByR), 0.001f, TEST_LOCATION);
308 int UtcDaliQuaternionFromAxes01(void)
310 TestApplication application; // Reset all test adapter return codes
312 Vector3 xAxis( Vector3::XAXIS );
313 Vector3 yAxis( Vector3::YAXIS );
314 Vector3 zAxis( Vector3::ZAXIS );
316 Quaternion q1( xAxis, yAxis, zAxis);
318 DALI_TEST_EQUALS( q1, Quaternion::IDENTITY, TEST_LOCATION );
320 xAxis = Vector3( 1.0f, 1.0f, 0.0f );
322 yAxis = Vector3( -1.0f, 1.0f, 0.0f ); // 45 degrees anticlockwise (+ve) around z
324 zAxis = xAxis.Cross(yAxis);
326 Quaternion q2( xAxis, yAxis, zAxis );
328 DALI_TEST_EQUALS( q2, Quaternion(Radian(Degree(45)), Vector3::ZAXIS), 0.001f, TEST_LOCATION);
333 int UtcDaliQuaternionFromAxes02(void)
335 TestApplication application; // Reset all test adapter return codes
337 // Create an arbitrary forward vector
338 for( float x=-1.0f; x<=1.0f; x+=0.1f )
340 for( float y=-1.0f; y<1.0f; y+=0.1f )
342 for( float z=-1.0f; z<1.0f; z+=0.1f )
344 Vector3 vForward(x, y, z);
345 vForward.Normalize();
347 // Construct an up vector from a sideways move
349 Vector3 vUp = vForward.Cross(Vector3(vForward.x+1.0f, vForward.y, vForward.z));
350 if(vUp.Length() > 0.01 )
353 vSide = vUp.Cross(vForward);
358 vSide = vForward.Cross(Vector3(vForward.x, vForward.y+1.0f, vForward.z));
360 vUp = vForward.Cross(vSide);
364 // Generate a quaternion
365 Quaternion q( vSide, vUp, vForward );
368 rotMatrix.SetXAxis(vSide);
369 rotMatrix.SetYAxis(vUp);
370 rotMatrix.SetZAxis(vForward);
372 // Generate a matrix from the quaternion, check they are the same
374 DALI_TEST_EQUALS(m.GetXAxis(), vSide, 0.001f, TEST_LOCATION);
375 DALI_TEST_EQUALS(m.GetYAxis(), vUp, 0.001f, TEST_LOCATION);
376 DALI_TEST_EQUALS(m.GetZAxis(), vForward, 0.001f, TEST_LOCATION);
378 // Rotate an arbitrary vector by both quaternion and rotation matrix,
379 // check the result is the same
381 Vector4 aVector(2.043f, 12.8f, -3.872f, 1.0f);
382 Vector3 aVectorRotatedByQ = q.Rotate(Vector3(aVector));
383 Vector4 aVectorRotatedByR = rotMatrix*aVector;
384 DALI_TEST_EQUALS(aVectorRotatedByQ, Vector3(aVectorRotatedByR), 0.001f, TEST_LOCATION);
391 int UtcDaliQuaternionOperatorAddition(void)
393 TestApplication application; // Reset all test adapter return codes
394 Quaternion q1(0.383f, 0.0f, 0.0f, 0.924f);
395 Quaternion q2(0.0f, 0.609f, 0.0f, 0.793f);
397 Quaternion r1(0.383f, 0.609f, 0.0f, 1.717f);
399 DALI_TEST_EQUALS(q1+q2, r1, 0.001f, TEST_LOCATION);
403 int UtcDaliQuaternionOperatorSubtraction(void)
405 TestApplication application; // Reset all test adapter return codes
406 Quaternion q1(0.383f, 0.450f, 0.123f, 0.924f);
407 Quaternion q2(0.383f, 0.690f, 0.234f, 1.917f);
409 Quaternion r1(0.0f, 0.240f, 0.111f, 0.993f);
411 DALI_TEST_EQUALS(q2-q1, r1, 0.001f, TEST_LOCATION);
415 int UtcDaliQuaternionConjugate(void)
417 TestApplication application; // Reset all test adapter return codes
418 float s1=0.784f; Vector3 v1(0.045f, 0.443f, 0.432f);
419 float s2=0.697f; Vector3 v2(0.612, 0.344, -0.144);
421 Quaternion q1(s1, v1.x, v1.y, v1.z);
422 Quaternion q2(s2, v2.x, v2.y, v2.z);
426 Quaternion r1(s1, -v1.x, -v1.y, -v1.z);
427 Quaternion r2(s2, -v2.x, -v2.y, -v2.z);
429 DALI_TEST_EQUALS(q1, r1, 0.001f, TEST_LOCATION);
430 DALI_TEST_EQUALS(q2, r2, 0.001f, TEST_LOCATION);
434 int UtcDaliQuaternionOperatorMultiplication01(void)
436 TestApplication application; // Reset all test adapter return codes
437 float s1=0.784f; Vector3 v1(0.045f, 0.443f, 0.432f);
438 float s2=0.697f; Vector3 v2(0.612, 0.344, -0.144);
440 Quaternion q1(s1, v1.x, v1.y, v1.z);
441 Quaternion q2(s2, v2.x, v2.y, v2.z);
443 Vector3 vp = v1.Cross(v2) + v2*s1 + v1*s2;
444 Quaternion r1(s1*s2-v1.Dot(v2), vp.x, vp.y, vp.z);
446 DALI_TEST_EQUALS(q1*q2, r1, 0.001f, TEST_LOCATION);
450 int UtcDaliQuaternionOperatorDivision(void)
452 TestApplication application; // Reset all test adapter return codes
453 Quaternion q1(0.383f, 0.0f, 0.0f, 0.924f);
454 Quaternion q2(0.0f, 0.609f, 0.0f, 0.793f);
456 // q1 / q2 = q1 * q2^-1
457 // q2^-1 = q2* / ||q2||^2
458 // = Conjugate of q2 / Square of Norm of q2
462 r1 *= 1.0f/q2.LengthSquared();
463 Quaternion r2 = q1 * r1;
465 DALI_TEST_EQUALS(q1 / q2, r2, 0.001f, TEST_LOCATION);
469 int UtcDaliQuaternionOperatorScale01(void)
471 TestApplication application; // Reset all test adapter return codes
472 Quaternion q1(0.383f, 0.0f, 0.0f, 0.924f);
473 Quaternion r1(2.0f* 0.383f, 0.0f, 0.0f, 2.0f * 0.924f);
475 DALI_TEST_EQUALS(q1 * 2.0f, r1, 0.001f, TEST_LOCATION);
479 int UtcDaliQuaternionOperatorScale02(void)
481 TestApplication application; // Reset all test adapter return codes
482 Quaternion q1(0.383f, 0.0f, 0.0f, 0.924f);
483 Quaternion r1(0.5f* 0.383f, 0.0f, 0.0f, 0.5f * 0.924f);
485 DALI_TEST_EQUALS(q1 / 2.0f, r1, 0.001f, TEST_LOCATION);
489 int UtcDaliQuaternionOperatorNegation(void)
491 TestApplication application; // Reset all test adapter return codes
492 Quaternion q1(0.383f, 0.0f, 0.0f, 0.924f);
493 Quaternion r1(-0.383f, -0.0f, -0.0f, -0.924f);
495 DALI_TEST_EQUALS(-q1, r1, 0.001f, TEST_LOCATION);
499 int UtcDaliQuaternionOperatorAddAssign(void)
501 TestApplication application; // Reset all test adapter return codes
502 Quaternion q1(0.383f, 0.0f, 0.0f, 0.924f);
503 Quaternion q2(0.0f, 0.609f, 0.0f, 0.793f);
505 Quaternion r1(0.383f, 0.609f, 0.0f, 1.717f);
508 DALI_TEST_EQUALS(q1, r1, 0.001f, TEST_LOCATION);
512 int UtcDaliQuaternionOperatorSubtractAssign(void)
514 TestApplication application; // Reset all test adapter return codes
515 Quaternion q1(0.383f, 0.450f, 0.123f, 0.924f);
516 Quaternion q2(0.383f, 0.690f, 0.234f, 1.917f);
518 Quaternion r1(0.0f, 0.240f, 0.111f, 0.993f);
520 DALI_TEST_EQUALS(q2, r1, 0.001f, TEST_LOCATION);
524 int UtcDaliQuaternionOperatorMultiplyAssign(void)
526 TestApplication application; // Reset all test adapter return codes
527 float s1=0.784f; Vector3 v1(0.045f, 0.443f, 0.432f);
528 float s2=0.697f; Vector3 v2(0.612, 0.344, -0.144);
530 Quaternion q1(s1, v1.x, v1.y, v1.z);
531 Quaternion q2(s2, v2.x, v2.y, v2.z);
533 Quaternion r3 = q2 * q1;
535 DALI_TEST_EQUALS(q2, r3, 0.001f, TEST_LOCATION);
539 int UtcDaliQuaternionOperatorScaleAssign01(void)
541 TestApplication application; // Reset all test adapter return codes
542 Quaternion q1(0.383f, 0.450f, 0.123f, 0.924f);
544 Quaternion r1(scale*0.383f, scale*0.450f, scale*0.123f, scale*0.924f);
546 DALI_TEST_EQUALS(q1, r1, 0.001f, TEST_LOCATION);
550 int UtcDaliQuaternionOperatorScaleAssign02(void)
552 TestApplication application; // Reset all test adapter return codes
553 Quaternion q1(0.383f, 0.450f, 0.123f, 0.924f);
555 Quaternion r1(0.383f/scale, 0.450f/scale, 0.123f/scale, 0.924f/scale);
557 DALI_TEST_EQUALS(q1, r1, 0.001f, TEST_LOCATION);
561 int UtcDaliQuaternionOperatorEquality(void)
563 TestApplication application; // Reset all test adapter return codes
564 Quaternion q1(0.383f, 0.450f, 0.123f, 0.924f);
565 Quaternion q2(0.383f, 0.450f, 0.123f, 0.924f);
566 Quaternion q3(0.383f, 0.450f, 0.123f, 0.800f);
567 Quaternion q4(0.383f, 0.450f, 0.100f, 0.800f);
568 Quaternion q5(0.383f, 0.100f, 0.100f, 0.800f);
569 Quaternion q6(0.100f, 0.100f, 0.100f, 0.800f);
571 Quaternion q7(-0.383f, -0.450f, -0.123f, -0.924f);
572 Quaternion q8(-0.383f, -0.450f, -0.123f, 0.924f);
573 Quaternion q9(-0.383f, -0.450f, 0.123f, 0.924f);
574 Quaternion q10(-0.383f, 0.450f, 0.123f, 0.924f);
576 DALI_TEST_CHECK( q1 == q2 );
577 DALI_TEST_CHECK( !(q1 == q3) );
578 DALI_TEST_CHECK( !(q1 == q4) );
579 DALI_TEST_CHECK( !(q1 == q5) );
580 DALI_TEST_CHECK( !(q1 == q6) );
581 DALI_TEST_CHECK( (q1 == q7) );
582 DALI_TEST_CHECK( !(q1 == q8) );
583 DALI_TEST_CHECK( !(q1 == q9) );
584 DALI_TEST_CHECK( !(q1 == q10) );
588 int UtcDaliQuaternionOperatorInequality(void)
590 TestApplication application; // Reset all test adapter return codes
591 Quaternion q1(0.383f, 0.450f, 0.123f, 0.924f);
592 Quaternion q2(0.383f, 0.450f, 0.123f, 0.924f);
593 Quaternion q3(-0.383f, -0.0f, -0.0f, -0.924f);
594 DALI_TEST_CHECK( !(q1 != q2) );
595 DALI_TEST_CHECK( q1 != q3 );
599 int UtcDaliQuaternionLength(void)
601 TestApplication application; // Reset all test adapter return codes
602 Quaternion q1(0.383f, 0.450f, 0.123f, 0.924f);
603 float length = sqrtf(0.383f*0.383f + 0.450f*0.450f + 0.123f*0.123f + 0.924f*0.924f);
604 DALI_TEST_EQUALS(q1.Length(), length, 0.01f, TEST_LOCATION);
608 int UtcDaliQuaternionLengthSquared(void)
610 TestApplication application; // Reset all test adapter return codes
611 Quaternion q1(0.383f, 0.450f, 0.123f, 0.924f);
612 float lengthSquared = 0.383f*0.383f + 0.450f*0.450f + 0.123f*0.123f + 0.924f*0.924f;
613 DALI_TEST_EQUALS(q1.LengthSquared(), lengthSquared, 0.01f, TEST_LOCATION);
617 int UtcDaliQuaternionNormalize(void)
619 TestApplication application; // Reset all test adapter return codes
620 Quaternion q1(0.118f, 0.692f, -0.127f, 0.701f);
624 DALI_TEST_EQUALS(q1, q2, 0.001f, TEST_LOCATION);
628 int UtcDaliQuaternionNormalized(void)
630 TestApplication application; // Reset all test adapter return codes
631 Quaternion q1(0.118f, 0.692f, -0.127f, 0.701f);
634 DALI_TEST_EQUALS(q1, q2.Normalized(), 0.001f, TEST_LOCATION);
638 int UtcDaliQuaternionInvert(void)
640 TestApplication application; // Reset all test adapter return codes
641 Quaternion q1(0.383f, 0.0f, 0.0f, 0.924f);
643 // q1^-1 = q1* / ||q1||^2
644 // = Conjugate of q1 / Square of Norm of q1
648 r1 *= 1.0f/q1.LengthSquared();
652 DALI_TEST_EQUALS(q2, r1, 0.001f, TEST_LOCATION);
657 int UtcDaliQuaternionDot(void)
659 TestApplication application; // Reset all test adapter return codes
660 // q.q' = s*s' + v dot v'
661 float s1=0.784f; Vector3 v1(0.045f, 0.443f, 0.432f);
662 float s2=0.697f; Vector3 v2(0.612, 0.344, -0.144);
664 Quaternion q1(s1, v1.x, v1.y, v1.z);
665 Quaternion q2(s2, v2.x, v2.y, v2.z);
667 float r1 = s1*s2 + v1.Dot(v2);
669 DALI_TEST_EQUALS(Quaternion::Dot(q1, q2), r1, TEST_LOCATION);
674 // Quaternion * vector == Vector rotation
675 int UtcDaliQuaternionOperatorMultiplication02(void)
677 TestApplication application; // Reset all test adapter return codes
678 // Rotation of vector p = (x,y,z) by Quaternion q == q [0,p] q^-1
680 Quaternion q(Radian(Degree(72)), Vector3::ZAXIS);
683 Quaternion qv(0.0f, v.x, v.y, v.z);
684 Quaternion r1 = (q * qv) * qI;
688 DALI_TEST_EQUALS(r1.mVector.x, r2.x, 0.001, TEST_LOCATION);
689 DALI_TEST_EQUALS(r1.mVector.y, r2.y, 0.001, TEST_LOCATION);
690 DALI_TEST_EQUALS(r1.mVector.z, r2.z, 0.001, TEST_LOCATION);
694 int UtcDaliQuaternionRotate01(void)
696 TestApplication application; // Reset all test adapter return codes
697 // Rotation of vector p = (x,y,z) by Quaternion q == q [0,p] q^-1
699 Quaternion q(Radian(Degree(72)), Vector3::ZAXIS);
702 Quaternion qv(0.0f, v.x, v.y, v.z);
703 Quaternion r1 = q * qv * qI;
705 Vector3 r2 = q.Rotate(v);
707 DALI_TEST_EQUALS(r1.mVector.x, r2.x, 0.001f, TEST_LOCATION);
708 DALI_TEST_EQUALS(r1.mVector.y, r2.y, 0.001f, TEST_LOCATION);
709 DALI_TEST_EQUALS(r1.mVector.z, r2.z, 0.001f, TEST_LOCATION);
711 DALI_TEST_EQUALS(q.Rotate(v), q*v, 0.001f, TEST_LOCATION);
716 int UtcDaliQuaternionRotate02(void)
718 TestApplication application; // Reset all test adapter return codes
719 // Rotation of vector p = (x,y,z) by Quaternion q == q [0,p] q^-1
720 Vector4 v(2, 3, 4, 5);
721 Quaternion q(Radian(Degree(72)), Vector3::ZAXIS);
724 Quaternion qv(0.0f, v.x, v.y, v.z);
725 Quaternion r1 = q * qv * qI;
727 Vector4 r2 = q.Rotate(v);
729 DALI_TEST_EQUALS(r1.mVector.x, r2.x, 0.001f, TEST_LOCATION);
730 DALI_TEST_EQUALS(r1.mVector.y, r2.y, 0.001f, TEST_LOCATION);
731 DALI_TEST_EQUALS(r1.mVector.z, r2.z, 0.001f, TEST_LOCATION);
732 DALI_TEST_EQUALS(r1.mVector.w, 0.0f, 0.001f, TEST_LOCATION);
737 int UtcDaliQuaternionExp01(void)
739 TestApplication application; // Reset all test adapter return codes
740 Quaternion q1(0.0f, 1.0f, 1.2f, 1.3f);
741 Quaternion q2 = q1.Exp();
742 Quaternion r2(-0.4452, 0.4406, 0.5287, 0.5728);
744 DALI_TEST_EQUALS(q2.Length(), 1.0f, 0.01f, TEST_LOCATION);
746 DALI_TEST_EQUALS(q2, r2, 0.001f, TEST_LOCATION);
748 // Note, this trick only works when |v| < pi, which it is!
749 Quaternion q3 = q2.Log();
750 DALI_TEST_EQUALS(q1, q3, 0.01f, TEST_LOCATION);
755 int UtcDaliQuaternionExp02(void)
757 TestApplication application; // Reset all test adapter return codes
758 Quaternion q1(0.0f, 0.0f, 0.0f, 0.0f);
759 Quaternion q2 = q1.Exp();
760 Quaternion r2(1.0f, 0.0f, 0.0f, 0.0f);
762 DALI_TEST_EQUALS(q2.Length(), 1.0f, 0.01f, TEST_LOCATION);
764 DALI_TEST_EQUALS(q2, r2, 0.001f, TEST_LOCATION);
766 // Note, this trick only works when |v| < pi, which it is!
767 Quaternion q3 = q2.Log();
768 DALI_TEST_EQUALS(q1, q3, 0.01f, TEST_LOCATION);
773 int UtcDaliQuaternionExp03(void)
777 Quaternion q(0.0f, Vector3(5.0f, 6.0f, 7.0f));
779 // q.w is non-zero. Should assert.
783 DALI_TEST_CHECK(false);
785 catch(DaliException& e)
787 DALI_TEST_CHECK(true);
793 int UtcDaliQuaternionLog01(void)
795 TestApplication application; // Reset all test adapter return codes
796 Quaternion q(Math::PI*0.73f, Vector3(2,3,4));
800 Quaternion r = q2.Log();
801 DALI_TEST_EQUALS(r.mVector.w, 0.0f, 0.01f, TEST_LOCATION);
803 Quaternion r2 = r.Exp();
804 DALI_TEST_EQUALS(r2, q2, 0.01f, TEST_LOCATION);
808 int UtcDaliQuaternionLog02(void)
810 TestApplication application; // Reset all test adapter return codes
811 Quaternion q1(1.0f, 0.0f, 0.0f, 0.0f);
812 Quaternion r1(0.0f, 0.0f, 0.0f, 0.0f);
814 Quaternion q2 = q1.Log();
816 DALI_TEST_EQUALS(q2, r1, 0.01f, TEST_LOCATION);
818 Quaternion q3 = q2.Exp();
819 DALI_TEST_EQUALS(q1, q3, 0.01f, TEST_LOCATION);
825 int UtcDaliQuaternionLerp(void)
827 TestApplication application; // Reset all test adapter return codes
828 Quaternion q1(Radian(Degree(-80)), Vector3(0.0f, 0.0f, 1.0f));
829 Quaternion q2(Radian(Degree( 80)), Vector3(0.0f, 0.0f, 1.0f));
831 Quaternion p = Quaternion::Lerp(q1, q2, 0.0f);
832 DALI_TEST_EQUALS(p, q1, 0.001f, TEST_LOCATION);
834 p = Quaternion::Lerp(q1, q2, 1.0f);
835 DALI_TEST_EQUALS(p, q2, 0.001f, TEST_LOCATION);
837 p = Quaternion::Lerp(q1, q2, 0.5f);
838 Quaternion r1 = (q1 + q2) * 0.5f;
840 DALI_TEST_EQUALS(p, r1, 0.001f, TEST_LOCATION);
846 int UtcDaliQuaternionSlerp01(void)
848 TestApplication application;
850 Quaternion q1(M_PI/4.0f, Vector4(0.0f, 0.0f, 1.0f, 0.0f));
851 Quaternion q2(-M_PI/4.0f, Vector4(0.0f, 0.0f, 1.0f, 0.0f));
853 Quaternion q = Quaternion::Slerp(q1, q2, 0.0f);
854 DALI_TEST_EQUALS(q, q1, 0.001, TEST_LOCATION);
856 q = Quaternion::Slerp(q1, q2, 1.0f);
857 DALI_TEST_EQUALS(q, q2, 0.001, TEST_LOCATION);
859 // @ 25%, will be at M_PI/8
860 q = Quaternion::Slerp(q1, q2, 0.25f);
863 bool converted = q.ToAxisAngle(axis, angle);
864 DALI_TEST_EQUALS(converted, true, TEST_LOCATION);
865 DALI_TEST_EQUALS(angle, Math::PI/8.0f, 0.001, TEST_LOCATION);
866 DALI_TEST_EQUALS(axis.x, 0.0f, 0.001, TEST_LOCATION);
867 DALI_TEST_EQUALS(axis.y, 0.0f, 0.001, TEST_LOCATION);
868 DALI_TEST_EQUALS(axis.z, 1.0f, 0.001, TEST_LOCATION);
874 int UtcDaliQuaternionSlerp02(void)
876 TestApplication application;
878 Quaternion q1(M_PI/6, Vector3(0.0f, 0.0f, 1.0f));
879 Quaternion q2(M_PI/2, Vector3(0.0f, 0.0f, 1.0f));
881 Quaternion q = Quaternion::Slerp(q1, q2, 0.0f);
883 DALI_TEST_EQUALS(q, q1, 0.001, TEST_LOCATION);
885 q = Quaternion::Slerp(q1, q2, 1.0f);
887 DALI_TEST_EQUALS(q, q2, 0.001, TEST_LOCATION);
889 // @ 50%, will be at M_PI/3 around z
890 q = Quaternion::Slerp(q1, q2, 0.5f);
892 Quaternion r( M_PI/3, Vector3( 0.0f, 0.0f, 1.0f));
893 DALI_TEST_EQUALS( q, r, 0.001, TEST_LOCATION );
898 int UtcDaliQuaternionSlerp03(void)
900 TestApplication application;
902 Quaternion q1(Radian(Degree(125)), Vector3(0.0f, 0.0f, 1.0f));
903 Quaternion q2(Radian(Degree(-125)), Vector3(0.002f, 0.001f, 1.001f));
905 Quaternion q = Quaternion::Slerp(q1, q2, 0.0f);
906 DALI_TEST_EQUALS(q, q1, 0.001, TEST_LOCATION);
908 q = Quaternion::Slerp(q1, q2, 1.0f);
909 DALI_TEST_EQUALS(q, q2, 0.001, TEST_LOCATION);
911 q = Quaternion::Slerp(q1, q2, 0.05f);
914 bool converted = q.ToAxisAngle(axis, angle);
915 DALI_TEST_EQUALS(converted, true, TEST_LOCATION);
917 DALI_TEST_EQUALS(axis.x, 0.0f, 0.01, TEST_LOCATION);
918 DALI_TEST_EQUALS(axis.y, 0.0f, 0.01, TEST_LOCATION);
919 DALI_TEST_EQUALS(axis.z, 1.0f, 0.01, TEST_LOCATION);
925 int UtcDaliQuaternionSlerp04(void)
927 TestApplication application;
929 Quaternion q1(Radian(Degree(120)), Vector3(0.0f, 0.0f, 1.0f));
930 Quaternion q2(Radian(Degree(130)), Vector3(0.0f, 0.0f, 1.0f));
932 Quaternion q = Quaternion::Slerp(q1, q2, 0.0f);
933 DALI_TEST_EQUALS(q, q1, 0.001, TEST_LOCATION);
935 q = Quaternion::Slerp(q1, q2, 1.0f);
936 DALI_TEST_EQUALS(q, q2, 0.001, TEST_LOCATION);
938 q = Quaternion::Slerp(q1, q2, 0.5f);
941 bool converted = q.ToAxisAngle(axis, angle);
942 DALI_TEST_EQUALS(converted, true, TEST_LOCATION);
943 DALI_TEST_EQUALS(angle, float(Radian(Degree(125))), 0.01f, TEST_LOCATION);
944 DALI_TEST_EQUALS(axis.x, 0.0f, 0.01, TEST_LOCATION);
945 DALI_TEST_EQUALS(axis.y, 0.0f, 0.01, TEST_LOCATION);
946 DALI_TEST_EQUALS(axis.z, 1.0f, 0.01, TEST_LOCATION);
952 int UtcDaliQuaternionSlerpNoInvert01(void)
954 TestApplication application;
956 Quaternion q1(M_PI/4.0f, Vector4(0.0f, 0.0f, 1.0f, 0.0f));
957 Quaternion q2(-M_PI/4.0f, Vector4(0.0f, 0.0f, 1.0f, 0.0f));
959 Quaternion q = Quaternion::SlerpNoInvert(q1, q2, 0.0f);
960 DALI_TEST_EQUALS(q, q1, 0.001, TEST_LOCATION);
962 q = Quaternion::SlerpNoInvert(q1, q2, 1.0f);
963 DALI_TEST_EQUALS(q, q2, 0.001, TEST_LOCATION);
965 // @ 25%, will be at M_PI/8
966 q = Quaternion::SlerpNoInvert(q1, q2, 0.25f);
969 bool converted = q.ToAxisAngle(axis, angle);
970 DALI_TEST_EQUALS(converted, true, TEST_LOCATION);
971 DALI_TEST_EQUALS(angle, Math::PI/8.0f, 0.001, TEST_LOCATION);
972 DALI_TEST_EQUALS(axis.x, 0.0f, 0.001, TEST_LOCATION);
973 DALI_TEST_EQUALS(axis.y, 0.0f, 0.001, TEST_LOCATION);
974 DALI_TEST_EQUALS(axis.z, 1.0f, 0.001, TEST_LOCATION);
979 int UtcDaliQuaternionSlerpNoInvert02(void)
981 TestApplication application;
983 Quaternion q1(Radian(Degree(120)), Vector3(0.0f, 0.0f, 1.0f));
984 Quaternion q2(Radian(Degree(130)), Vector3(0.0f, 0.0f, 1.0f));
986 Quaternion q = Quaternion::SlerpNoInvert(q1, q2, 0.0f);
987 DALI_TEST_EQUALS(q, q1, 0.001, TEST_LOCATION);
989 q = Quaternion::SlerpNoInvert(q1, q2, 1.0f);
990 DALI_TEST_EQUALS(q, q2, 0.001, TEST_LOCATION);
992 q = Quaternion::SlerpNoInvert(q1, q2, 0.5f);
995 bool converted = q.ToAxisAngle(axis, angle);
996 DALI_TEST_EQUALS(converted, true, TEST_LOCATION);
997 DALI_TEST_EQUALS(angle, float(Radian(Degree(125))), 0.01f, TEST_LOCATION);
998 DALI_TEST_EQUALS(axis.x, 0.0f, 0.01, TEST_LOCATION);
999 DALI_TEST_EQUALS(axis.y, 0.0f, 0.01, TEST_LOCATION);
1000 DALI_TEST_EQUALS(axis.z, 1.0f, 0.01, TEST_LOCATION);
1005 int UtcDaliQuaternionSquad(void)
1007 TestApplication application; // Reset all test adapter return codes
1008 Quaternion q1(Radian(Degree(45)), Vector3(0.0f, 0.0f, 1.0f));
1009 Quaternion q1out(Radian(Degree(40)), Vector3(0.0f, 1.0f, 2.0f));
1010 Quaternion q2in(Radian(Degree(35)), Vector3(0.0f, 2.0f, 3.0f));
1011 Quaternion q2(Radian(Degree(30)), Vector3(0.0f, 1.0f, 3.0f));
1013 Quaternion q = Quaternion::Squad(q1, q2, q1out, q2in, 0.0f);
1014 DALI_TEST_EQUALS(q, q1, 0.001f, TEST_LOCATION);
1016 q = Quaternion::Squad(q1, q2, q1out, q2in, 1.0f);
1017 DALI_TEST_EQUALS(q, q2, 0.001f, TEST_LOCATION);
1019 // Don't know what actual value should be, but can make some informed guesses.
1020 q = Quaternion::Squad(q1, q2, q1out, q2in, 0.5f);
1024 q.ToAxisAngle(axis, angle);
1028 q = -q; // Might get negative quat
1029 q.ToAxisAngle(axis, angle);
1031 float deg = Degree(Radian(angle));
1032 DALI_TEST_CHECK(deg >= 0 && deg <= 90);
1033 DALI_TEST_CHECK(axis.y > 0);
1034 DALI_TEST_CHECK(axis.z > 0);
1038 int UtcDaliAngleBetween(void)
1040 TestApplication application; // Reset all test adapter return codes
1042 Quaternion q1(Radian(Degree(45)), 0.0f, 0.0f);
1043 Quaternion q2(Radian(Degree(47)), 0.0f, 0.0f);
1044 DALI_TEST_EQUALS(Quaternion::AngleBetween(q1, q2), fabsf(Radian(Degree(45)) - Radian(Degree(47))), 0.001f, TEST_LOCATION);
1046 Quaternion q3(Radian(Degree(80)), Vector3::YAXIS);
1047 Quaternion q4(Radian(Degree(90)), Vector3::YAXIS);
1048 DALI_TEST_EQUALS(Quaternion::AngleBetween(q3, q4), fabsf(Radian(Degree(80)) - Radian(Degree(90))), 0.001f, TEST_LOCATION);
1050 Quaternion q5(Radian(Degree(0)), Vector3::YAXIS);
1051 Quaternion q6(Radian(Degree(90)), Vector3::XAXIS);
1052 DALI_TEST_EQUALS(Quaternion::AngleBetween(q5, q6), fabsf(Radian(Degree(0)) - Radian(Degree(90))), 0.001f, TEST_LOCATION);
1054 Quaternion q7(Radian(Degree(0)), Vector3::YAXIS);
1055 Quaternion q8(Radian(Degree(0)), Vector3::XAXIS);
1056 DALI_TEST_EQUALS(Quaternion::AngleBetween(q7, q8), fabsf(Radian(Degree(0)) - Radian(Degree(0))), 0.001f, TEST_LOCATION);
1058 Quaternion q9(Radian(Degree(0)), Vector3::XAXIS);
1059 Quaternion q10(Radian(Degree(180)), Vector3::XAXIS);
1060 DALI_TEST_EQUALS(Quaternion::AngleBetween(q9, q10), fabsf(Radian(Degree(0)) - Radian(Degree(180))), 0.001f, TEST_LOCATION);
1062 Quaternion q11(Radian(Degree(1)), Vector3::YAXIS);
1063 Quaternion q12(Radian(Degree(240)), Vector3::YAXIS);
1064 DALI_TEST_EQUALS(Quaternion::AngleBetween(q11, q12), fabsf(Radian( Degree(1 - 240 + 360) )), 0.001f, TEST_LOCATION);
1066 Quaternion q13(Radian(Degree(240)), Vector3::YAXIS);
1067 Quaternion q14(Radian(Degree(1)), Vector3::YAXIS);
1068 DALI_TEST_EQUALS(Quaternion::AngleBetween(q13, q14), fabsf(Radian( Degree(240 - 1 - 360) )), 0.001f, TEST_LOCATION);
1070 Quaternion q15(Radian(Degree(240)), Vector3::YAXIS);
1071 Quaternion q16(Radian(Degree(1)), Vector3::ZAXIS);
1072 DALI_TEST_EQUALS(Quaternion::AngleBetween(q15, q16), Quaternion::AngleBetween(q16, q15), 0.001f, TEST_LOCATION);
1076 int UtcDaliQuaternionOStreamOperator(void)
1078 TestApplication application; // Reset all test adapter return codes
1080 std::ostringstream oss;
1082 Quaternion quaternion(M_PI, Vector3::YAXIS);
1086 std::string expectedOutput = "[ Axis: [0, 1, 0], Angle: 180 degrees ]";
1088 DALI_TEST_EQUALS( oss.str(), expectedOutput, TEST_LOCATION);