2 * Copyright (c) 2014 Samsung Electronics Co., Ltd.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
22 #include <dali/public-api/dali-core.h>
23 #include <dali-test-suite-utils.h>
28 void utc_dali_quaternion_startup(void)
30 test_return_value = TET_UNDEF;
33 void utc_dali_quaternion_cleanup(void)
35 test_return_value = TET_PASS;
39 int UtcDaliQuaternionCtor01(void)
41 TestApplication application; // Reset all test adapter return codes
43 DALI_TEST_EQUALS(r.AsVector().w, 1.0f, TEST_LOCATION);
44 DALI_TEST_EQUALS(r.AsVector().x, 0.0f, TEST_LOCATION);
45 DALI_TEST_EQUALS(r.AsVector().y, 0.0f, TEST_LOCATION);
46 DALI_TEST_EQUALS(r.AsVector().z, 0.0f, TEST_LOCATION);
50 int UtcDaliQuaternionCtor02(void)
52 TestApplication application; // Reset all test adapter return codes
54 Quaternion r( Radian(Math::PI_2), Vector3( 1.0f, 2.0f, 3.0f ));
56 // This will be normalised:
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)), Radian(0.0f), Radian(0.0f) );
70 Vector4 r1(0.383f, 0.0f, 0.0f, 0.924f);
72 Quaternion e2( Radian(0.0f), Radian(Degree(75)), Radian(0.0f) );
73 Vector4 r2(0.0f, 0.609f, 0.0f, 0.793f);
75 Quaternion e3( Radian(0.0f), Radian(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 UtcDaliQuaternionToAxisAngle01(void)
95 TestApplication application; // Reset all test adapter return codes
96 Quaternion q(0.932f, 1.1f, 3.4f, 2.7f);
99 bool converted = q.ToAxisAngle(axis, angle);
100 DALI_TEST_EQUALS(converted, true, TEST_LOCATION);
101 DALI_TEST_EQUALS(angle.radian, 0.74f, 0.01f, TEST_LOCATION);
102 DALI_TEST_EQUALS(axis.x, 3.03f, 0.01f, TEST_LOCATION);
103 DALI_TEST_EQUALS(axis.y, 9.38f, 0.01f, TEST_LOCATION);
104 DALI_TEST_EQUALS(axis.z, 7.45f, 0.01f, TEST_LOCATION);
108 int UtcDaliQuaternionToAxisAngle02(void)
110 TestApplication application; // Reset all test adapter return codes
111 Quaternion q(0.932f, 1.1f, 3.4f, 2.7f);
114 bool converted = q.ToAxisAngle(axis, angle);
115 DALI_TEST_EQUALS(converted, true, TEST_LOCATION);
116 DALI_TEST_EQUALS(angle.radian, 0.74f, 0.01f, TEST_LOCATION);
117 DALI_TEST_EQUALS(axis.x, 3.03f, 0.01f, TEST_LOCATION);
118 DALI_TEST_EQUALS(axis.y, 9.38f, 0.01f, TEST_LOCATION);
119 DALI_TEST_EQUALS(axis.z, 7.45f, 0.01f, TEST_LOCATION);
124 int UtcDaliQuaternionToAxisAngle03(void)
126 TestApplication application; // Reset all test adapter return codes
127 Quaternion q(1, 2, 3, 4);
130 bool converted = q.ToAxisAngle(axis, angle);
131 DALI_TEST_EQUALS(converted, false, TEST_LOCATION);
132 DALI_TEST_EQUALS(angle.radian, 0.0f, 0.01f, TEST_LOCATION);
133 DALI_TEST_EQUALS(axis.x, 0.0f, 0.01f, TEST_LOCATION);
134 DALI_TEST_EQUALS(axis.y, 0.0f, 0.01f, TEST_LOCATION);
135 DALI_TEST_EQUALS(axis.z, 0.0f, 0.01f, TEST_LOCATION);
139 int UtcDaliQuaternionToAxisAngle04(void)
141 TestApplication application; // Reset all test adapter return codes
142 Quaternion q(1, 2, 3, 4);
145 bool converted = q.ToAxisAngle(axis, angle);
146 DALI_TEST_EQUALS(converted, false, TEST_LOCATION);
147 DALI_TEST_EQUALS(angle.radian, 0.0f, 0.01f, TEST_LOCATION);
148 DALI_TEST_EQUALS(axis.x, 0.0f, 0.01f, TEST_LOCATION);
149 DALI_TEST_EQUALS(axis.y, 0.0f, 0.01f, TEST_LOCATION);
150 DALI_TEST_EQUALS(axis.z, 0.0f, 0.01f, TEST_LOCATION);
156 int UtcDaliQuaternionEulerAngles(void)
158 TestApplication application; // Reset all test adapter return codes
160 Quaternion q1(0.924f, 0.383f, 0.0f, 0.0f);
161 Vector4 r1(Radian(Degree(45)), 0.0f, 0.0f, 0.0f);
163 Quaternion q2(0.793f, 0.0f, 0.609f, 0.0f);
164 Vector4 r2(0.0f, Radian(Degree(75)), 0.0f, 0.0f);
166 Quaternion q3(0.383f, 0.0f, 0.0f, 0.924f);
167 Vector4 r3(0.0f, 0.0f, Radian(Degree(135)), 0.0f);
169 Quaternion q4(0.795f, 0.478f, 0.374f, 0.006f);
170 Vector4 r4(Radian(Degree(71)), Radian(Degree(36)), Radian(Degree(27)), 0.0f);
172 Quaternion q5( -0.149f, -0.697f, 0.145f, -0.686f);
173 Vector4 r5(Radian(Degree(148.0)), Radian(Degree(-88.2)), Radian(Degree(8.0)), 0.0f);
175 DALI_TEST_EQUALS(q1.EulerAngles(), r1, 0.001, TEST_LOCATION);
176 DALI_TEST_EQUALS(q2.EulerAngles(), r2, 0.001, TEST_LOCATION);
177 DALI_TEST_EQUALS(q3.EulerAngles(), r3, 0.001, TEST_LOCATION);
178 DALI_TEST_EQUALS(q4.EulerAngles(), r4, 0.01, TEST_LOCATION);
179 DALI_TEST_EQUALS(q5.EulerAngles(), r5, 0.01, TEST_LOCATION);
184 int UtcDaliQuaternionToMatrix01(void)
186 TestApplication application; // Reset all test adapter return codes
188 Quaternion q( Radian(0.69813), Vector3(1.0f, 0.0f, 0.0f) ); // 40 degree rotation around X axis
190 // Result calculated using a different maths library (with appropriate row/col ordering)
192 float els[] = { 1.0f, 0.0f, 0.0f, 0.0f,
193 0.0f, 0.766f, 0.643f, 0.0f,
194 0.0f, -0.643f, 0.766f, 0.0f,
195 0.0f, 0.0f, 0.0f, 1.0f };
199 DALI_TEST_EQUALS(m, mRes, 0.01, TEST_LOCATION);
203 int UtcDaliQuaternionToMatrix02(void)
205 TestApplication application; // Reset all test adapter return codes
207 // rotation around arbitrary axis
208 Quaternion q2( Radian(-1.23918f), Vector3(7.0f, -13.0f, 11.0f) );
210 float els[] = { 0.423f, -0.746f, -0.514f, 0.00f,
211 0.384f, 0.662f, -0.644f, 0.00f,
212 0.821f, 0.075f, 0.566f, 0.00f,
213 0.000f, 0.000f, 0.000f, 1.00f };
218 DALI_TEST_EQUALS(m2, mRes2, 0.01, TEST_LOCATION);
223 int UtcDaliQuaternionFromMatrix01(void)
225 TestApplication application; // Reset all test adapter return codes
230 Matrix m(q); // Convert to matrix
232 Quaternion q2(m); // and back to a quaternion
234 DALI_TEST_EQUALS(q, q2, 0.001, TEST_LOCATION);
235 DALI_TEST_EQUALS(m, Matrix::IDENTITY, 0.001f, TEST_LOCATION);
239 int UtcDaliQuaternionFromMatrix02(void)
241 TestApplication application; // Reset all test adapter return codes
243 // Create an arbitrary forward vector
244 for( float x=-1.0f; x<=1.0f; x+=0.1f )
246 for( float y=-1.0f; y<1.0f; y+=0.1f )
248 for( float z=-1.0f; z<1.0f; z+=0.1f )
250 Vector3 vForward(x, y, z);
251 vForward.Normalize();
253 // Construct an up vector from a sideways move
255 Vector3 vUp = vForward.Cross(Vector3(vForward.x+1.0f, vForward.y, vForward.z));
256 if(vUp.Length() > 0.01 )
259 vSide = vUp.Cross(vForward);
264 vSide = vForward.Cross(Vector3(vForward.x, vForward.y+1.0f, vForward.z));
266 vUp = vForward.Cross(vSide);
270 // Generate a matrix, and then a quaternion from it
271 Matrix rotMatrix(Matrix::IDENTITY);
272 rotMatrix.SetXAxis(vSide);
273 rotMatrix.SetYAxis(vUp);
274 rotMatrix.SetZAxis(vForward);
275 Quaternion q( rotMatrix );
277 // Generate a matrix from the quaternion, check they are the same
278 Matrix resultMatrix(q);
279 DALI_TEST_EQUALS(resultMatrix, rotMatrix, 0.001f, TEST_LOCATION);
281 // Rotate an arbitrary vector by both quaternion and rotation matrix,
282 // check the result is the same
284 Vector4 aVector(-2.983f, -3.213f, 8.2239f, 1.0f);
285 Vector3 aVectorRotatedByQ = q.Rotate(Vector3(aVector));
286 Vector4 aVectorRotatedByR = rotMatrix*aVector;
287 DALI_TEST_EQUALS(aVectorRotatedByQ, Vector3(aVectorRotatedByR), 0.001f, TEST_LOCATION);
294 int UtcDaliQuaternionFromAxes01(void)
296 TestApplication application; // Reset all test adapter return codes
298 Vector3 xAxis( Vector3::XAXIS );
299 Vector3 yAxis( Vector3::YAXIS );
300 Vector3 zAxis( Vector3::ZAXIS );
302 Quaternion q1( xAxis, yAxis, zAxis);
304 DALI_TEST_EQUALS( q1, Quaternion::IDENTITY, TEST_LOCATION );
306 xAxis = Vector3( 1.0f, 1.0f, 0.0f );
308 yAxis = Vector3( -1.0f, 1.0f, 0.0f ); // 45 degrees anticlockwise (+ve) around z
310 zAxis = xAxis.Cross(yAxis);
312 Quaternion q2( xAxis, yAxis, zAxis );
314 DALI_TEST_EQUALS( q2, Quaternion(Radian(Degree(45)), Vector3::ZAXIS), 0.001f, TEST_LOCATION);
319 int UtcDaliQuaternionFromAxes02(void)
321 TestApplication application; // Reset all test adapter return codes
323 // Create an arbitrary forward vector
324 for( float x=-1.0f; x<=1.0f; x+=0.1f )
326 for( float y=-1.0f; y<1.0f; y+=0.1f )
328 for( float z=-1.0f; z<1.0f; z+=0.1f )
330 Vector3 vForward(x, y, z);
331 vForward.Normalize();
333 // Construct an up vector from a sideways move
335 Vector3 vUp = vForward.Cross(Vector3(vForward.x+1.0f, vForward.y, vForward.z));
336 if(vUp.Length() > 0.01 )
339 vSide = vUp.Cross(vForward);
344 vSide = vForward.Cross(Vector3(vForward.x, vForward.y+1.0f, vForward.z));
346 vUp = vForward.Cross(vSide);
350 // Generate a quaternion
351 Quaternion q( vSide, vUp, vForward );
354 rotMatrix.SetXAxis(vSide);
355 rotMatrix.SetYAxis(vUp);
356 rotMatrix.SetZAxis(vForward);
358 // Generate a matrix from the quaternion, check they are the same
360 DALI_TEST_EQUALS(m.GetXAxis(), vSide, 0.001f, TEST_LOCATION);
361 DALI_TEST_EQUALS(m.GetYAxis(), vUp, 0.001f, TEST_LOCATION);
362 DALI_TEST_EQUALS(m.GetZAxis(), vForward, 0.001f, TEST_LOCATION);
364 // Rotate an arbitrary vector by both quaternion and rotation matrix,
365 // check the result is the same
367 Vector4 aVector(2.043f, 12.8f, -3.872f, 1.0f);
368 Vector3 aVectorRotatedByQ = q.Rotate(Vector3(aVector));
369 Vector4 aVectorRotatedByR = rotMatrix*aVector;
370 DALI_TEST_EQUALS(aVectorRotatedByQ, Vector3(aVectorRotatedByR), 0.001f, TEST_LOCATION);
377 int UtcDaliQuaternionOperatorAddition(void)
379 TestApplication application; // Reset all test adapter return codes
380 Quaternion q1(0.383f, 0.0f, 0.0f, 0.924f);
381 Quaternion q2(0.0f, 0.609f, 0.0f, 0.793f);
383 Quaternion r1(0.383f, 0.609f, 0.0f, 1.717f);
385 DALI_TEST_EQUALS(q1+q2, r1, 0.001f, TEST_LOCATION);
389 int UtcDaliQuaternionOperatorSubtraction(void)
391 TestApplication application; // Reset all test adapter return codes
392 Quaternion q1(0.383f, 0.450f, 0.123f, 0.924f);
393 Quaternion q2(0.383f, 0.690f, 0.234f, 1.917f);
395 Quaternion r1(0.0f, 0.240f, 0.111f, 0.993f);
397 DALI_TEST_EQUALS(q2-q1, r1, 0.001f, TEST_LOCATION);
401 int UtcDaliQuaternionConjugate(void)
403 TestApplication application; // Reset all test adapter return codes
404 float s1=0.784f; Vector3 v1(0.045f, 0.443f, 0.432f);
405 float s2=0.697f; Vector3 v2(0.612, 0.344, -0.144);
407 Quaternion q1(s1, v1.x, v1.y, v1.z);
408 Quaternion q2(s2, v2.x, v2.y, v2.z);
412 Quaternion r1(s1, -v1.x, -v1.y, -v1.z);
413 Quaternion r2(s2, -v2.x, -v2.y, -v2.z);
415 DALI_TEST_EQUALS(q1, r1, 0.001f, TEST_LOCATION);
416 DALI_TEST_EQUALS(q2, r2, 0.001f, TEST_LOCATION);
420 int UtcDaliQuaternionOperatorMultiplication01(void)
422 TestApplication application; // Reset all test adapter return codes
423 float s1=0.784f; Vector3 v1(0.045f, 0.443f, 0.432f);
424 float s2=0.697f; Vector3 v2(0.612, 0.344, -0.144);
426 Quaternion q1(s1, v1.x, v1.y, v1.z);
427 Quaternion q2(s2, v2.x, v2.y, v2.z);
429 Vector3 vp = v1.Cross(v2) + v2*s1 + v1*s2;
430 Quaternion r1(s1*s2-v1.Dot(v2), vp.x, vp.y, vp.z);
432 DALI_TEST_EQUALS(q1*q2, r1, 0.001f, TEST_LOCATION);
436 int UtcDaliQuaternionOperatorDivision(void)
438 TestApplication application; // Reset all test adapter return codes
439 Quaternion q1(0.383f, 0.0f, 0.0f, 0.924f);
440 Quaternion q2(0.0f, 0.609f, 0.0f, 0.793f);
442 // q1 / q2 = q1 * q2^-1
443 // q2^-1 = q2* / ||q2||^2
444 // = Conjugate of q2 / Square of Norm of q2
448 r1 *= 1.0f/q2.LengthSquared();
449 Quaternion r2 = q1 * r1;
451 DALI_TEST_EQUALS(q1 / q2, r2, 0.001f, TEST_LOCATION);
455 int UtcDaliQuaternionOperatorScale01(void)
457 TestApplication application; // Reset all test adapter return codes
458 Quaternion q1(0.383f, 0.0f, 0.0f, 0.924f);
459 Quaternion r1(2.0f* 0.383f, 0.0f, 0.0f, 2.0f * 0.924f);
461 DALI_TEST_EQUALS(q1 * 2.0f, r1, 0.001f, TEST_LOCATION);
465 int UtcDaliQuaternionOperatorScale02(void)
467 TestApplication application; // Reset all test adapter return codes
468 Quaternion q1(0.383f, 0.0f, 0.0f, 0.924f);
469 Quaternion r1(0.5f* 0.383f, 0.0f, 0.0f, 0.5f * 0.924f);
471 DALI_TEST_EQUALS(q1 / 2.0f, r1, 0.001f, TEST_LOCATION);
475 int UtcDaliQuaternionOperatorNegation(void)
477 TestApplication application; // Reset all test adapter return codes
478 Quaternion q1(0.383f, 0.0f, 0.0f, 0.924f);
479 Quaternion r1(-0.383f, -0.0f, -0.0f, -0.924f);
481 DALI_TEST_EQUALS(-q1, r1, 0.001f, TEST_LOCATION);
485 int UtcDaliQuaternionOperatorAddAssign(void)
487 TestApplication application; // Reset all test adapter return codes
488 Quaternion q1(0.383f, 0.0f, 0.0f, 0.924f);
489 Quaternion q2(0.0f, 0.609f, 0.0f, 0.793f);
491 Quaternion r1(0.383f, 0.609f, 0.0f, 1.717f);
494 DALI_TEST_EQUALS(q1, r1, 0.001f, TEST_LOCATION);
498 int UtcDaliQuaternionOperatorSubtractAssign(void)
500 TestApplication application; // Reset all test adapter return codes
501 Quaternion q1(0.383f, 0.450f, 0.123f, 0.924f);
502 Quaternion q2(0.383f, 0.690f, 0.234f, 1.917f);
504 Quaternion r1(0.0f, 0.240f, 0.111f, 0.993f);
506 DALI_TEST_EQUALS(q2, r1, 0.001f, TEST_LOCATION);
510 int UtcDaliQuaternionOperatorMultiplyAssign(void)
512 TestApplication application; // Reset all test adapter return codes
513 float s1=0.784f; Vector3 v1(0.045f, 0.443f, 0.432f);
514 float s2=0.697f; Vector3 v2(0.612, 0.344, -0.144);
516 Quaternion q1(s1, v1.x, v1.y, v1.z);
517 Quaternion q2(s2, v2.x, v2.y, v2.z);
519 Quaternion r3 = q2 * q1;
521 DALI_TEST_EQUALS(q2, r3, 0.001f, TEST_LOCATION);
525 int UtcDaliQuaternionOperatorScaleAssign01(void)
527 TestApplication application; // Reset all test adapter return codes
528 Quaternion q1(0.383f, 0.450f, 0.123f, 0.924f);
530 Quaternion r1(scale*0.383f, scale*0.450f, scale*0.123f, scale*0.924f);
532 DALI_TEST_EQUALS(q1, r1, 0.001f, TEST_LOCATION);
536 int UtcDaliQuaternionOperatorScaleAssign02(void)
538 TestApplication application; // Reset all test adapter return codes
539 Quaternion q1(0.383f, 0.450f, 0.123f, 0.924f);
541 Quaternion r1(0.383f/scale, 0.450f/scale, 0.123f/scale, 0.924f/scale);
543 DALI_TEST_EQUALS(q1, r1, 0.001f, TEST_LOCATION);
547 int UtcDaliQuaternionOperatorEquality(void)
549 TestApplication application; // Reset all test adapter return codes
550 Quaternion q1(0.383f, 0.450f, 0.123f, 0.924f);
551 Quaternion q2(0.383f, 0.450f, 0.123f, 0.924f);
552 Quaternion q3(0.383f, 0.450f, 0.123f, 0.800f);
553 Quaternion q4(0.383f, 0.450f, 0.100f, 0.800f);
554 Quaternion q5(0.383f, 0.100f, 0.100f, 0.800f);
555 Quaternion q6(0.100f, 0.100f, 0.100f, 0.800f);
557 Quaternion q7(-0.383f, -0.450f, -0.123f, -0.924f);
558 Quaternion q8(-0.383f, -0.450f, -0.123f, 0.924f);
559 Quaternion q9(-0.383f, -0.450f, 0.123f, 0.924f);
560 Quaternion q10(-0.383f, 0.450f, 0.123f, 0.924f);
562 DALI_TEST_CHECK( q1 == q2 );
563 DALI_TEST_CHECK( !(q1 == q3) );
564 DALI_TEST_CHECK( !(q1 == q4) );
565 DALI_TEST_CHECK( !(q1 == q5) );
566 DALI_TEST_CHECK( !(q1 == q6) );
567 DALI_TEST_CHECK( (q1 == q7) );
568 DALI_TEST_CHECK( !(q1 == q8) );
569 DALI_TEST_CHECK( !(q1 == q9) );
570 DALI_TEST_CHECK( !(q1 == q10) );
574 int UtcDaliQuaternionOperatorInequality(void)
576 TestApplication application; // Reset all test adapter return codes
577 Quaternion q1(0.383f, 0.450f, 0.123f, 0.924f);
578 Quaternion q2(0.383f, 0.450f, 0.123f, 0.924f);
579 Quaternion q3(-0.383f, -0.0f, -0.0f, -0.924f);
580 DALI_TEST_CHECK( !(q1 != q2) );
581 DALI_TEST_CHECK( q1 != q3 );
585 int UtcDaliQuaternionLength(void)
587 TestApplication application; // Reset all test adapter return codes
588 Quaternion q1(0.383f, 0.450f, 0.123f, 0.924f);
589 float length = sqrtf(0.383f*0.383f + 0.450f*0.450f + 0.123f*0.123f + 0.924f*0.924f);
590 DALI_TEST_EQUALS(q1.Length(), length, 0.01f, TEST_LOCATION);
594 int UtcDaliQuaternionLengthSquared(void)
596 TestApplication application; // Reset all test adapter return codes
597 Quaternion q1(0.383f, 0.450f, 0.123f, 0.924f);
598 float lengthSquared = 0.383f*0.383f + 0.450f*0.450f + 0.123f*0.123f + 0.924f*0.924f;
599 DALI_TEST_EQUALS(q1.LengthSquared(), lengthSquared, 0.01f, TEST_LOCATION);
603 int UtcDaliQuaternionNormalize(void)
605 TestApplication application; // Reset all test adapter return codes
606 Quaternion q1(0.118f, 0.692f, -0.127f, 0.701f);
610 DALI_TEST_EQUALS(q1, q2, 0.001f, TEST_LOCATION);
614 int UtcDaliQuaternionNormalized(void)
616 TestApplication application; // Reset all test adapter return codes
617 Quaternion q1(0.118f, 0.692f, -0.127f, 0.701f);
620 DALI_TEST_EQUALS(q1, q2.Normalized(), 0.001f, TEST_LOCATION);
624 int UtcDaliQuaternionInvert(void)
626 TestApplication application; // Reset all test adapter return codes
627 Quaternion q1(0.383f, 0.0f, 0.0f, 0.924f);
629 // q1^-1 = q1* / ||q1||^2
630 // = Conjugate of q1 / Square of Norm of q1
634 r1 *= 1.0f/q1.LengthSquared();
638 DALI_TEST_EQUALS(q2, r1, 0.001f, TEST_LOCATION);
643 int UtcDaliQuaternionDot(void)
645 TestApplication application; // Reset all test adapter return codes
646 // q.q' = s*s' + v dot v'
647 float s1=0.784f; Vector3 v1(0.045f, 0.443f, 0.432f);
648 float s2=0.697f; Vector3 v2(0.612, 0.344, -0.144);
650 Quaternion q1(s1, v1.x, v1.y, v1.z);
651 Quaternion q2(s2, v2.x, v2.y, v2.z);
653 float r1 = s1*s2 + v1.Dot(v2);
655 DALI_TEST_EQUALS(Quaternion::Dot(q1, q2), r1, TEST_LOCATION);
660 // Quaternion * vector == Vector rotation
661 int UtcDaliQuaternionOperatorMultiplication02(void)
663 TestApplication application; // Reset all test adapter return codes
664 // Rotation of vector p = (x,y,z) by Quaternion q == q [0,p] q^-1
666 Quaternion q(Radian(Degree(72)), Vector3::ZAXIS);
669 Quaternion qv(0.0f, v.x, v.y, v.z);
670 Quaternion r1 = (q * qv) * qI;
674 DALI_TEST_EQUALS(r1.mVector.x, r2.x, 0.001, TEST_LOCATION);
675 DALI_TEST_EQUALS(r1.mVector.y, r2.y, 0.001, TEST_LOCATION);
676 DALI_TEST_EQUALS(r1.mVector.z, r2.z, 0.001, TEST_LOCATION);
680 int UtcDaliQuaternionRotate01(void)
682 TestApplication application; // Reset all test adapter return codes
683 // Rotation of vector p = (x,y,z) by Quaternion q == q [0,p] q^-1
685 Quaternion q(Radian(Degree(72)), Vector3::ZAXIS);
688 Quaternion qv(0.0f, v.x, v.y, v.z);
689 Quaternion r1 = q * qv * qI;
691 Vector3 r2 = q.Rotate(v);
693 DALI_TEST_EQUALS(r1.mVector.x, r2.x, 0.001f, TEST_LOCATION);
694 DALI_TEST_EQUALS(r1.mVector.y, r2.y, 0.001f, TEST_LOCATION);
695 DALI_TEST_EQUALS(r1.mVector.z, r2.z, 0.001f, TEST_LOCATION);
697 DALI_TEST_EQUALS(q.Rotate(v), q*v, 0.001f, TEST_LOCATION);
702 int UtcDaliQuaternionRotate02(void)
704 TestApplication application; // Reset all test adapter return codes
705 // Rotation of vector p = (x,y,z) by Quaternion q == q [0,p] q^-1
706 Vector4 v(2, 3, 4, 5);
707 Quaternion q(Radian(Degree(72)), Vector3::ZAXIS);
710 Quaternion qv(0.0f, v.x, v.y, v.z);
711 Quaternion r1 = q * qv * qI;
713 Vector4 r2 = q.Rotate(v);
715 DALI_TEST_EQUALS(r1.mVector.x, r2.x, 0.001f, TEST_LOCATION);
716 DALI_TEST_EQUALS(r1.mVector.y, r2.y, 0.001f, TEST_LOCATION);
717 DALI_TEST_EQUALS(r1.mVector.z, r2.z, 0.001f, TEST_LOCATION);
718 DALI_TEST_EQUALS(r1.mVector.w, 0.0f, 0.001f, TEST_LOCATION);
723 int UtcDaliQuaternionExp01(void)
725 TestApplication application; // Reset all test adapter return codes
726 Quaternion q1(0.0f, 1.0f, 1.2f, 1.3f);
727 Quaternion q2 = q1.Exp();
728 Quaternion r2(-0.4452, 0.4406, 0.5287, 0.5728);
730 DALI_TEST_EQUALS(q2.Length(), 1.0f, 0.01f, TEST_LOCATION);
732 DALI_TEST_EQUALS(q2, r2, 0.001f, TEST_LOCATION);
734 // Note, this trick only works when |v| < pi, which it is!
735 Quaternion q3 = q2.Log();
736 DALI_TEST_EQUALS(q1, q3, 0.01f, TEST_LOCATION);
741 int UtcDaliQuaternionExp02(void)
743 TestApplication application; // Reset all test adapter return codes
744 Quaternion q1(0.0f, 0.0f, 0.0f, 0.0f);
745 Quaternion q2 = q1.Exp();
746 Quaternion r2(1.0f, 0.0f, 0.0f, 0.0f);
748 DALI_TEST_EQUALS(q2.Length(), 1.0f, 0.01f, TEST_LOCATION);
750 DALI_TEST_EQUALS(q2, r2, 0.001f, TEST_LOCATION);
752 // Note, this trick only works when |v| < pi, which it is!
753 Quaternion q3 = q2.Log();
754 DALI_TEST_EQUALS(q1, q3, 0.01f, TEST_LOCATION);
759 int UtcDaliQuaternionExp03(void)
763 Quaternion q( Radian( 0.0f ), Vector3(5.0f, 6.0f, 7.0f) );
765 // q.w is non-zero. Should assert.
769 DALI_TEST_CHECK(false);
771 catch(DaliException& e)
773 DALI_TEST_CHECK(true);
779 int UtcDaliQuaternionLog01(void)
781 TestApplication application; // Reset all test adapter return codes
782 Quaternion q( Radian( Math::PI*0.73f ), Vector3(2,3,4) );
786 Quaternion r = q2.Log();
787 DALI_TEST_EQUALS(r.mVector.w, 0.0f, 0.01f, TEST_LOCATION);
789 Quaternion r2 = r.Exp();
790 DALI_TEST_EQUALS(r2, q2, 0.01f, TEST_LOCATION);
794 int UtcDaliQuaternionLog02(void)
796 TestApplication application; // Reset all test adapter return codes
797 Quaternion q1(1.0f, 0.0f, 0.0f, 0.0f);
798 Quaternion r1(0.0f, 0.0f, 0.0f, 0.0f);
800 Quaternion q2 = q1.Log();
802 DALI_TEST_EQUALS(q2, r1, 0.01f, TEST_LOCATION);
804 Quaternion q3 = q2.Exp();
805 DALI_TEST_EQUALS(q1, q3, 0.01f, TEST_LOCATION);
811 int UtcDaliQuaternionLerp(void)
813 TestApplication application; // Reset all test adapter return codes
814 Quaternion q1(Radian(Degree(-80)), Vector3(0.0f, 0.0f, 1.0f));
815 Quaternion q2(Radian(Degree( 80)), Vector3(0.0f, 0.0f, 1.0f));
817 Quaternion p = Quaternion::Lerp(q1, q2, 0.0f);
818 DALI_TEST_EQUALS(p, q1, 0.001f, TEST_LOCATION);
820 p = Quaternion::Lerp(q1, q2, 1.0f);
821 DALI_TEST_EQUALS(p, q2, 0.001f, TEST_LOCATION);
823 p = Quaternion::Lerp(q1, q2, 0.5f);
824 Quaternion r1 = (q1 + q2) * 0.5f;
826 DALI_TEST_EQUALS(p, r1, 0.001f, TEST_LOCATION);
832 int UtcDaliQuaternionSlerp01(void)
834 TestApplication application;
836 Quaternion q1(Radian(M_PI/4.0f), Vector3(0.0f, 0.0f, 1.0f));
837 Quaternion q2(Radian(-M_PI/4.0f), Vector3(0.0f, 0.0f, 1.0f));
839 Quaternion q = Quaternion::Slerp(q1, q2, 0.0f);
840 DALI_TEST_EQUALS(q, q1, 0.001, TEST_LOCATION);
842 q = Quaternion::Slerp(q1, q2, 1.0f);
843 DALI_TEST_EQUALS(q, q2, 0.001, TEST_LOCATION);
845 // @ 25%, will be at M_PI/8
846 q = Quaternion::Slerp(q1, q2, 0.25f);
849 bool converted = q.ToAxisAngle(axis, angle);
850 DALI_TEST_EQUALS(converted, true, TEST_LOCATION);
851 DALI_TEST_EQUALS(angle.radian, Math::PI/8.0f, 0.001, TEST_LOCATION);
852 DALI_TEST_EQUALS(axis.x, 0.0f, 0.001, TEST_LOCATION);
853 DALI_TEST_EQUALS(axis.y, 0.0f, 0.001, TEST_LOCATION);
854 DALI_TEST_EQUALS(axis.z, 1.0f, 0.001, TEST_LOCATION);
860 int UtcDaliQuaternionSlerp02(void)
862 TestApplication application;
864 Quaternion q1( Dali::ANGLE_30, Vector3(0.0f, 0.0f, 1.0f));
865 Quaternion q2( Dali::ANGLE_90, Vector3(0.0f, 0.0f, 1.0f));
867 Quaternion q = Quaternion::Slerp(q1, q2, 0.0f);
869 DALI_TEST_EQUALS(q, q1, 0.001, TEST_LOCATION);
871 q = Quaternion::Slerp(q1, q2, 1.0f);
873 DALI_TEST_EQUALS(q, q2, 0.001, TEST_LOCATION);
875 // @ 50%, will be at M_PI/3 around z
876 q = Quaternion::Slerp(q1, q2, 0.5f);
878 Quaternion r( Dali::ANGLE_120, Vector3( 0.0f, 0.0f, 1.0f));
879 DALI_TEST_EQUALS( q, r, 0.001, TEST_LOCATION );
884 int UtcDaliQuaternionSlerp03(void)
886 TestApplication application;
888 Quaternion q1(Radian(Degree(125)), Vector3(0.0f, 0.0f, 1.0f));
889 Quaternion q2(Radian(Degree(-125)), Vector3(0.002f, 0.001f, 1.001f));
891 Quaternion q = Quaternion::Slerp(q1, q2, 0.0f);
892 DALI_TEST_EQUALS(q, q1, 0.001, TEST_LOCATION);
894 q = Quaternion::Slerp(q1, q2, 1.0f);
895 DALI_TEST_EQUALS(q, q2, 0.001, TEST_LOCATION);
897 q = Quaternion::Slerp(q1, q2, 0.05f);
900 bool converted = q.ToAxisAngle(axis, angle);
901 DALI_TEST_EQUALS(converted, true, TEST_LOCATION);
903 DALI_TEST_EQUALS(axis.x, 0.0f, 0.01, TEST_LOCATION);
904 DALI_TEST_EQUALS(axis.y, 0.0f, 0.01, TEST_LOCATION);
905 DALI_TEST_EQUALS(axis.z, 1.0f, 0.01, TEST_LOCATION);
911 int UtcDaliQuaternionSlerp04(void)
913 TestApplication application;
915 Quaternion q1(Radian(Degree(120)), Vector3(0.0f, 0.0f, 1.0f));
916 Quaternion q2(Radian(Degree(130)), Vector3(0.0f, 0.0f, 1.0f));
918 Quaternion q = Quaternion::Slerp(q1, q2, 0.0f);
919 DALI_TEST_EQUALS(q, q1, 0.001, TEST_LOCATION);
921 q = Quaternion::Slerp(q1, q2, 1.0f);
922 DALI_TEST_EQUALS(q, q2, 0.001, TEST_LOCATION);
924 q = Quaternion::Slerp(q1, q2, 0.5f);
927 bool converted = q.ToAxisAngle(axis, angle);
928 DALI_TEST_EQUALS(converted, true, TEST_LOCATION);
929 DALI_TEST_EQUALS(angle.radian, float(Radian(Degree(125))), 0.01f, TEST_LOCATION);
930 DALI_TEST_EQUALS(axis.x, 0.0f, 0.01, TEST_LOCATION);
931 DALI_TEST_EQUALS(axis.y, 0.0f, 0.01, TEST_LOCATION);
932 DALI_TEST_EQUALS(axis.z, 1.0f, 0.01, TEST_LOCATION);
938 int UtcDaliQuaternionSlerpNoInvert01(void)
940 TestApplication application;
942 Quaternion q1( Dali::ANGLE_45, Vector3(0.0f, 0.0f, 1.0f));
943 Quaternion q2(-Dali::ANGLE_45, Vector3(0.0f, 0.0f, 1.0f));
945 Quaternion q = Quaternion::SlerpNoInvert(q1, q2, 0.0f);
946 DALI_TEST_EQUALS(q, q1, 0.001, TEST_LOCATION);
948 q = Quaternion::SlerpNoInvert(q1, q2, 1.0f);
949 DALI_TEST_EQUALS(q, q2, 0.001, TEST_LOCATION);
951 // @ 25%, will be at M_PI/8
952 q = Quaternion::SlerpNoInvert(q1, q2, 0.25f);
955 bool converted = q.ToAxisAngle(axis, angle);
956 DALI_TEST_EQUALS(converted, true, TEST_LOCATION);
957 DALI_TEST_EQUALS(angle.radian, Math::PI/8.0f, 0.001, TEST_LOCATION);
958 DALI_TEST_EQUALS(axis.x, 0.0f, 0.001, TEST_LOCATION);
959 DALI_TEST_EQUALS(axis.y, 0.0f, 0.001, TEST_LOCATION);
960 DALI_TEST_EQUALS(axis.z, 1.0f, 0.001, TEST_LOCATION);
965 int UtcDaliQuaternionSlerpNoInvert02(void)
967 TestApplication application;
969 Quaternion q1(Radian(Degree(120)), Vector3(0.0f, 0.0f, 1.0f));
970 Quaternion q2(Radian(Degree(130)), Vector3(0.0f, 0.0f, 1.0f));
972 Quaternion q = Quaternion::SlerpNoInvert(q1, q2, 0.0f);
973 DALI_TEST_EQUALS(q, q1, 0.001, TEST_LOCATION);
975 q = Quaternion::SlerpNoInvert(q1, q2, 1.0f);
976 DALI_TEST_EQUALS(q, q2, 0.001, TEST_LOCATION);
978 q = Quaternion::SlerpNoInvert(q1, q2, 0.5f);
981 bool converted = q.ToAxisAngle(axis, angle);
982 DALI_TEST_EQUALS(converted, true, TEST_LOCATION);
983 DALI_TEST_EQUALS(angle.radian, float(Radian(Degree(125))), 0.01f, TEST_LOCATION);
984 DALI_TEST_EQUALS(axis.x, 0.0f, 0.01, TEST_LOCATION);
985 DALI_TEST_EQUALS(axis.y, 0.0f, 0.01, TEST_LOCATION);
986 DALI_TEST_EQUALS(axis.z, 1.0f, 0.01, TEST_LOCATION);
991 int UtcDaliQuaternionSquad(void)
993 TestApplication application; // Reset all test adapter return codes
994 Quaternion q1(Radian(Degree(45)), Vector3(0.0f, 0.0f, 1.0f));
995 Quaternion q1out(Radian(Degree(40)), Vector3(0.0f, 1.0f, 2.0f));
996 Quaternion q2in(Radian(Degree(35)), Vector3(0.0f, 2.0f, 3.0f));
997 Quaternion q2(Radian(Degree(30)), Vector3(0.0f, 1.0f, 3.0f));
999 Quaternion q = Quaternion::Squad(q1, q2, q1out, q2in, 0.0f);
1000 DALI_TEST_EQUALS(q, q1, 0.001f, TEST_LOCATION);
1002 q = Quaternion::Squad(q1, q2, q1out, q2in, 1.0f);
1003 DALI_TEST_EQUALS(q, q2, 0.001f, TEST_LOCATION);
1005 // Don't know what actual value should be, but can make some informed guesses.
1006 q = Quaternion::Squad(q1, q2, q1out, q2in, 0.5f);
1010 q.ToAxisAngle(axis, angle);
1014 q = -q; // Might get negative quat
1015 q.ToAxisAngle(axis, angle);
1017 float deg = Degree(angle).degree;
1018 DALI_TEST_CHECK(deg >= 0 && deg <= 90);
1019 DALI_TEST_CHECK(axis.y > 0);
1020 DALI_TEST_CHECK(axis.z > 0);
1024 int UtcDaliAngleBetween(void)
1026 TestApplication application; // Reset all test adapter return codes
1028 Quaternion q1( ANGLE_45, ANGLE_0, ANGLE_0 );
1029 Quaternion q2(Radian(Degree(47)), ANGLE_0, ANGLE_0 );
1030 DALI_TEST_EQUALS(Quaternion::AngleBetween(q1, q2), fabsf(Radian(Degree(45)) - Radian(Degree(47))), 0.001f, TEST_LOCATION);
1032 Quaternion q3(Radian(Degree(80)), Vector3::YAXIS);
1033 Quaternion q4(Radian(Degree(90)), Vector3::YAXIS);
1034 DALI_TEST_EQUALS(Quaternion::AngleBetween(q3, q4), fabsf(Radian(Degree(80)) - Radian(Degree(90))), 0.001f, TEST_LOCATION);
1036 Quaternion q5(Radian(Degree(0)), Vector3::YAXIS);
1037 Quaternion q6(Radian(Degree(90)), Vector3::XAXIS);
1038 DALI_TEST_EQUALS(Quaternion::AngleBetween(q5, q6), fabsf(Radian(Degree(0)) - Radian(Degree(90))), 0.001f, TEST_LOCATION);
1040 Quaternion q7(Radian(Degree(0)), Vector3::YAXIS);
1041 Quaternion q8(Radian(Degree(0)), Vector3::XAXIS);
1042 DALI_TEST_EQUALS(Quaternion::AngleBetween(q7, q8), fabsf(Radian(Degree(0)) - Radian(Degree(0))), 0.001f, TEST_LOCATION);
1044 Quaternion q9(Radian(Degree(0)), Vector3::XAXIS);
1045 Quaternion q10(Radian(Degree(180)), Vector3::XAXIS);
1046 DALI_TEST_EQUALS(Quaternion::AngleBetween(q9, q10), fabsf(Radian(Degree(0)) - Radian(Degree(180))), 0.001f, TEST_LOCATION);
1048 Quaternion q11(Radian(Degree(1)), Vector3::YAXIS);
1049 Quaternion q12(Radian(Degree(240)), Vector3::YAXIS);
1050 DALI_TEST_EQUALS(Quaternion::AngleBetween(q11, q12), fabsf(Radian( Degree(1 - 240 + 360) )), 0.001f, TEST_LOCATION);
1052 Quaternion q13(Radian(Degree(240)), Vector3::YAXIS);
1053 Quaternion q14(Radian(Degree(1)), Vector3::YAXIS);
1054 DALI_TEST_EQUALS(Quaternion::AngleBetween(q13, q14), fabsf(Radian( Degree(240 - 1 - 360) )), 0.001f, TEST_LOCATION);
1056 Quaternion q15(Radian(Degree(240)), Vector3::YAXIS);
1057 Quaternion q16(Radian(Degree(1)), Vector3::ZAXIS);
1058 DALI_TEST_EQUALS(Quaternion::AngleBetween(q15, q16), Quaternion::AngleBetween(q16, q15), 0.001f, TEST_LOCATION);
1062 int UtcDaliQuaternionOStreamOperator(void)
1064 TestApplication application; // Reset all test adapter return codes
1066 std::ostringstream oss;
1068 Quaternion quaternion( Dali::ANGLE_180, Vector3::YAXIS );
1072 std::string expectedOutput = "[ Axis: [0, 1, 0], Angle: 180 degrees ]";
1074 DALI_TEST_EQUALS( oss.str(), expectedOutput, TEST_LOCATION);