From f0e5754abcd90375a18ecbd2f6d7ef0c76a442b2 Mon Sep 17 00:00:00 2001 From: Unknown Date: Tue, 2 Jan 2018 17:47:33 +0100 Subject: [PATCH 1/7] Add unit tests which reveal converting problems with euler angles Partly covered methods which converts between euler angles and quaternions. Whats still missing here is applied rotation axis and rotation orientation (counter clockwise + right hand rule) --- .../OpenTK.Tests.Math.csproj | 1 + tests/OpenTK.Tests.Math/QuaternionTests.cs | 214 ++++++++++++++++++ 2 files changed, 215 insertions(+) create mode 100644 tests/OpenTK.Tests.Math/QuaternionTests.cs diff --git a/tests/OpenTK.Tests.Math/OpenTK.Tests.Math.csproj b/tests/OpenTK.Tests.Math/OpenTK.Tests.Math.csproj index 9b2ccec8..07882b1d 100644 --- a/tests/OpenTK.Tests.Math/OpenTK.Tests.Math.csproj +++ b/tests/OpenTK.Tests.Math/OpenTK.Tests.Math.csproj @@ -47,6 +47,7 @@ + diff --git a/tests/OpenTK.Tests.Math/QuaternionTests.cs b/tests/OpenTK.Tests.Math/QuaternionTests.cs new file mode 100644 index 00000000..27f0a28b --- /dev/null +++ b/tests/OpenTK.Tests.Math/QuaternionTests.cs @@ -0,0 +1,214 @@ +using Xunit; +using System; +using System.Collections.Generic; + +namespace OpenTK.Tests.Math +{ + /// + /// Generates Quaternion test data. + /// + public class QuaternionTestDataGenerator + { + /// + /// Returns the single axis test cases. + /// 1. param: rotation in euler angles + /// 2. param: expected result of xyz-component of quaternion + /// 3. param: test name (Don't found a working way how to pass this to xUnit runner). I let it here for test documentation + /// + /// The single axis test cases. + public static IEnumerable SingleAxisTestCases() + { + yield return new object[] { new Vector3(1, 0, 0), Vector3.UnitX, "Rotate around x axis" }; + yield return new object[] { new Vector3(0, 1, 0), Vector3.UnitY, "Rotate around y axis" }; + yield return new object[] { new Vector3(0, 0, 1), Vector3.UnitZ, "Rotate around z axis" }; + } + + /// + /// Returns the single ToAxisAngle test cases. + /// 1. param: Quaternion which a definied value of xyz-component. + /// 2. param: expected result of xyz-component of quaternion + /// 3. param: test name (Don't found a working way how to pass this to xUnit runner). I let it here for test documentation + /// + /// The single axis test cases. + public static IEnumerable ToAxisAngleTestCases() + { + yield return new object[] { new Quaternion(Vector3.UnitX, 0), Vector3.UnitX, "Rotate around x axis" }; + yield return new object[] { new Quaternion(Vector3.UnitY, 0), Vector3.UnitY, "Rotate around y axis" }; + yield return new object[] { new Quaternion(Vector3.UnitZ, 0), Vector3.UnitZ, "Rotate around z axis" }; + } + } + + /// + /// Provides some methods which helps to verify test results + /// + internal static class QuaternionTestHelper + { + /// + /// Verifies the direction of an given . + /// + /// false: When does contain xyz values, when it should be 0, + /// or does not contain 0 when it should be + /// To test + /// Expected directions. Values getting only 0 checked + public static bool VerifyEuqalSignleDirection(Vector3 toTest, Vector3 expected) + { + //To verify the direction of an vector, just respect the 0 values and check against these. + //The length of the vectors are ignored. + if (expected.X == 0) + { + if (toTest.X != 0) + return false; + } + else + { + if (toTest.X == 0) + return false; + } + + if (expected.Y == 0) + { + if (toTest.Y != 0) + return false; + } + else + { + if (toTest.Y == 0) + return false; + } + + if (expected.Z == 0) + { + if (toTest.Z != 0) + return false; + } + else + { + if (toTest.Z == 0) + return false; + } + + return true; + } + } + + public class Quaternion_Tests + { + /// + /// Checks if a single given value (either pitch, yaw or roll) get converted into correct x,y,z value of quaternion. + /// + /// euler angle values + /// expected xyz component of quaternion + /// Taken from nUnit test data. Don't know how to name data driven tests for xUnit which actually works. + [Theory] + [MemberData(nameof(QuaternionTestDataGenerator.SingleAxisTestCases), MemberType = typeof(QuaternionTestDataGenerator))] + public void CtorEulerAnglesFloat_SingleEulerAngleSet_RotateCorrectAxis(Vector3 eulerValues, Vector3 expectedResult, String testName) + { + //Arrange + Act: Create Quaternion with "pitch/yaw/roll" + var cut = new Quaternion(eulerValues.X, eulerValues.Y, eulerValues.Z); + + //Assert: Use helper, to check if part of the two correct axis is zero. I just want check the direction + Vector3 resultXYZ = cut.Xyz; + + Assert.True(QuaternionTestHelper.VerifyEuqalSignleDirection(resultXYZ, expectedResult)); + } + + /// + /// Checks if a single given value (either pitch, yaw or roll) get converted into correct x,y,z value of quaternion. + /// + /// euler angle values + /// expected xyz component of quaternion + /// Taken from nUnit test data. Don't know how to name data driven tests for xUnit which actually works. + [Theory] + [MemberData(nameof(QuaternionTestDataGenerator.SingleAxisTestCases), MemberType = typeof(QuaternionTestDataGenerator))] + public void CtorEulerAnglesVector3_SingleEulerAngleSet_RotateCorrectAxis(Vector3 eulerValues, Vector3 expectedResult, String testName) + { + //Arrange + Act: Create Quaternion with "pitch/yaw/roll" + var cut = new Quaternion(eulerValues.X, eulerValues.Y, eulerValues.Z); + + //Assert: Use helper, to check if part of the two correct axis is zero. I just want check the direction + Vector3 resultXYZ = cut.Xyz; + + Assert.True(QuaternionTestHelper.VerifyEuqalSignleDirection(resultXYZ, expectedResult)); + } + + /// + /// Checks if a single given value (either pitch, yaw or roll) get converted into correct x,y,z value of quaternion. + /// + /// euler angle values + /// expected xyz component of quaternion + /// Taken from nUnit test data. Don't know how to name data driven tests for xUnit which actually works. + [Theory] + [MemberData(nameof(QuaternionTestDataGenerator.SingleAxisTestCases), MemberType = typeof(QuaternionTestDataGenerator))] + public void FromEulerAnglesFloat_SingleEulerAngleSet_RotateCorrectAxis(Vector3 eulerValues, Vector3 expectedResult, String testName) + { + //Arrange + Act: Create Quaternion with "pitch/yaw/roll" + var cut = Quaternion.FromEulerAngles(eulerValues.X, eulerValues.Y, eulerValues.Z); + + //Assert: Use helper, to check if part of the two correct axis is zero. I just want check the direction + Vector3 resultXYZ = cut.Xyz; + + Assert.True(QuaternionTestHelper.VerifyEuqalSignleDirection(resultXYZ, expectedResult)); + } + + /// + /// Checks if a single given value (either pitch, yaw or roll) get converted into correct x,y,z value of quaternion. + /// + /// euler angle values + /// expected xyz component of quaternion + /// Taken from nUnit test data. Don't know how to name data driven tests for xUnit which actually works. + [Theory] + [MemberData(nameof(QuaternionTestDataGenerator.SingleAxisTestCases), MemberType = typeof(QuaternionTestDataGenerator))] + public void FromEulerAnglesVector3_SingleEulerAngleSet_RotateCorrectAxis(Vector3 eulerValues, Vector3 expectedResult, String testName) + { + //Arrange + Act: Create Quaternion with "pitch/yaw/roll" + var cut = Quaternion.FromEulerAngles(eulerValues); + + //Assert: Use helper, to check if part of the two correct axis is zero. I just want check the direction + Vector3 resultXYZ = cut.Xyz; + + Assert.True(QuaternionTestHelper.VerifyEuqalSignleDirection(resultXYZ, expectedResult)); + } + + /// + /// Checks if a single given value (either pitch, yaw or roll) get converted into correct x,y,z value of quaternion. + /// + /// euler angle values + /// expected xyz component of quaternion + /// Taken from nUnit test data. Don't know how to name data driven tests for xUnit which actually works. + [Theory] + [MemberData(nameof(QuaternionTestDataGenerator.SingleAxisTestCases), MemberType = typeof(QuaternionTestDataGenerator))] + public void FromEulerAnglesOut_SingleEulerAngleSet_RotateCorrectAxis(Vector3 eulerValues, Vector3 expectedResult, String testName) + { + //Arrange + Act: Create Quaternion with "pitch/yaw/roll" + var cut = Quaternion.Identity; + Quaternion.FromEulerAngles(ref eulerValues, out cut); + + //Assert: Use helper, to check if part of the two correct axis is zero. I just want check the direction + Vector3 resultXYZ = cut.Xyz; + + Assert.True(QuaternionTestHelper.VerifyEuqalSignleDirection(resultXYZ, expectedResult)); + } + + /// + /// Check if a quaternion returns a a rotation about the correct coordinate axis + /// + /// Prepared Quaternion + /// Expected result. + /// Taken from nUnit test data. Don't know how to name data driven tests for xUnit which actually works. + [Theory] + [MemberData(nameof(QuaternionTestDataGenerator.ToAxisAngleTestCases), MemberType = typeof(QuaternionTestDataGenerator))] + public void ToAxisAngle_SingleAxisSetAndAngleIgnored_RotateCorrectAxis(Quaternion cut, Vector3 expectedResult, String testName) + { + //Arrange + Act: Create Quaternion with rotation about X/Y/Z axis + Vector3 resultXYZ; + float dontCare; + cut.ToAxisAngle(out resultXYZ, out dontCare); + + //Assert: Use helper, to check if part of the two correct axis is zero. I just want check the direction + Assert.True(QuaternionTestHelper.VerifyEuqalSignleDirection(resultXYZ, expectedResult)); + } + + //TODO: Make also checks with rotation angle + } +} + From fca36b19b06c04e7ba283c2678d2148a37333cbc Mon Sep 17 00:00:00 2001 From: Unknown Date: Tue, 2 Jan 2018 17:53:04 +0100 Subject: [PATCH 2/7] Provide fix for converting euler angles to quaternion Fixed API documentation and changed convertion from euler angles to quaterion: Rotation will applied in following order: 1. xAxis, 2. yAxis, 3. zAxis. Right hand rule is used here. Rotation is interpreted counter clock wise, in viewing direction of positive axis. Still need to double check that with unit tests. --- src/OpenTK/Math/Quaternion.cs | 73 ++++++++++++++++++++--------------- 1 file changed, 41 insertions(+), 32 deletions(-) diff --git a/src/OpenTK/Math/Quaternion.cs b/src/OpenTK/Math/Quaternion.cs index bea308bc..ddd6cda6 100644 --- a/src/OpenTK/Math/Quaternion.cs +++ b/src/OpenTK/Math/Quaternion.cs @@ -66,34 +66,36 @@ namespace OpenTK { } /// - /// Construct a new Quaternion from given Euler angles + /// Construct a new Quaternion from given Euler angles. The rotations will get applied in following order: + /// 1. Around X, 2. Around Y, 3. Around Z /// - /// The pitch (attitude), rotation around X axis - /// The yaw (heading), rotation around Y axis - /// The roll (bank), rotation around Z axis - public Quaternion(float pitch, float yaw, float roll) + /// Counterclockwise rotation around X axis in radian + /// Counterclockwise rotation around Y axis in radian + /// Counterclockwise rotation around Z axis in radian + public Quaternion(float rotationX, float rotationY, float rotationZ) { - yaw *= 0.5f; - pitch *= 0.5f; - roll *= 0.5f; + rotationX *= 0.5f; + rotationY *= 0.5f; + rotationZ *= 0.5f; - float c1 = (float)Math.Cos(yaw); - float c2 = (float)Math.Cos(pitch); - float c3 = (float)Math.Cos(roll); - float s1 = (float)Math.Sin(yaw); - float s2 = (float)Math.Sin(pitch); - float s3 = (float)Math.Sin(roll); + float c1 = (float)Math.Cos(rotationX); + float c2 = (float)Math.Cos(rotationY); + float c3 = (float)Math.Cos(rotationZ); + float s1 = (float)Math.Sin(rotationX); + float s2 = (float)Math.Sin(rotationY); + float s3 = (float)Math.Sin(rotationZ); W = c1 * c2 * c3 - s1 * s2 * s3; - Xyz.X = s1 * s2 * c3 + c1 * c2 * s3; - Xyz.Y = s1 * c2 * c3 + c1 * s2 * s3; - Xyz.Z = c1 * s2 * c3 - s1 * c2 * s3; + Xyz.X = s1 * c2 * c3 + c1 * s2 * s3; + Xyz.Y = c1 * s2 * c3 - s1 * c2 * s3; + Xyz.Z = c1 * c2 * s3 + s1 * s2 * c3; } /// - /// Construct a new Quaternion from given Euler angles + /// Construct a new Quaternion from given Euler angles. The rotations will get applied in following order: + /// 1. Around X, 2. Around Y, 3. Around Z /// - /// The euler angles as a Vector3 + /// The counterclockwise euler angles as a Vector3 public Quaternion(Vector3 eulerAngles) : this(eulerAngles.X, eulerAngles.Y, eulerAngles.Z) { } @@ -431,10 +433,12 @@ namespace OpenTK /// /// Builds a Quaternion from the given euler angles + /// The rotations will get applied in following order: + /// 1. pitch, 2. yaw, 3. roll /// - /// The pitch (attitude), rotation around X axis - /// The yaw (heading), rotation around Y axis - /// The roll (bank), rotation around Z axis + /// The pitch (attitude), counterclockwise rotation around X axis + /// The yaw (heading), counterclockwise rotation around Y axis + /// The roll (bank), counterclockwise rotation around Z axis /// public static Quaternion FromEulerAngles(float pitch, float yaw, float roll) { @@ -443,8 +447,10 @@ namespace OpenTK /// /// Builds a Quaternion from the given euler angles + /// The rotations will get applied in following order: + /// 1. Around X, 2. Around Y, 3. Around Z /// - /// The euler angles as a vector + /// The counterclockwise euler angles as a vector /// The equivalent Quaternion public static Quaternion FromEulerAngles(Vector3 eulerAngles) { @@ -452,23 +458,26 @@ namespace OpenTK } /// - /// Builds a Quaternion from the given euler angles + /// Builds a Quaternion from the given euler angles in radians. + /// The rotations will get applied in following order: + /// 1. Around X, 2. Around Y, 3. Around Z /// - /// The euler angles a vector + /// The counterclockwise euler angles a vector /// The equivalent Quaternion public static void FromEulerAngles(ref Vector3 eulerAngles, out Quaternion result) { - float c1 = (float)Math.Cos(eulerAngles.Y * 0.5f); - float c2 = (float)Math.Cos(eulerAngles.X * 0.5f); + + float c1 = (float)Math.Cos(eulerAngles.X * 0.5f); + float c2 = (float)Math.Cos(eulerAngles.Y * 0.5f); float c3 = (float)Math.Cos(eulerAngles.Z * 0.5f); - float s1 = (float)Math.Sin(eulerAngles.Y * 0.5f); - float s2 = (float)Math.Sin(eulerAngles.X * 0.5f); + float s1 = (float)Math.Sin(eulerAngles.X * 0.5f); + float s2 = (float)Math.Sin(eulerAngles.Y * 0.5f); float s3 = (float)Math.Sin(eulerAngles.Z * 0.5f); result.W = c1 * c2 * c3 - s1 * s2 * s3; - result.Xyz.X = s1 * s2 * c3 + c1 * c2 * s3; - result.Xyz.Y = s1 * c2 * c3 + c1 * s2 * s3; - result.Xyz.Z = c1 * s2 * c3 - s1 * c2 * s3; + result.Xyz.X = s1 * c2 * c3 + c1 * s2 * s3; + result.Xyz.Y = c1 * s2 * c3 - s1 * c2 * s3; + result.Xyz.Z = c1 * c2 * s3 + s1 * s2 * c3; } /// From 079f5c5242b0d1b2024fc2be3432b0ba54549c4c Mon Sep 17 00:00:00 2001 From: Unknown Date: Tue, 2 Jan 2018 20:24:15 +0100 Subject: [PATCH 3/7] Fixed typos --- src/OpenTK/Math/Quaternion.cs | 15 ++++++++------- tests/OpenTK.Tests.Math/QuaternionTests.cs | 14 +++++++------- 2 files changed, 15 insertions(+), 14 deletions(-) diff --git a/src/OpenTK/Math/Quaternion.cs b/src/OpenTK/Math/Quaternion.cs index ddd6cda6..0d92d00a 100644 --- a/src/OpenTK/Math/Quaternion.cs +++ b/src/OpenTK/Math/Quaternion.cs @@ -66,8 +66,9 @@ namespace OpenTK { } /// - /// Construct a new Quaternion from given Euler angles. The rotations will get applied in following order: - /// 1. Around X, 2. Around Y, 3. Around Z + /// Construct a new Quaternion from given Euler angles in radians. + /// The rotations will get applied in following order: + /// 1. around X axis, 2. around Y axis, 3. around Z axis /// /// Counterclockwise rotation around X axis in radian /// Counterclockwise rotation around Y axis in radian @@ -409,7 +410,7 @@ namespace OpenTK } /// - /// Build a quaternion from the given axis and angle + /// Build a quaternion from the given axis and angle in radians /// /// The axis to rotate about /// The rotation angle in radians @@ -432,9 +433,9 @@ namespace OpenTK } /// - /// Builds a Quaternion from the given euler angles + /// Builds a Quaternion from the given euler angles in radians /// The rotations will get applied in following order: - /// 1. pitch, 2. yaw, 3. roll + /// 1. pitch (X axis), 2. yaw (Y axis), 3. roll (Z axis) /// /// The pitch (attitude), counterclockwise rotation around X axis /// The yaw (heading), counterclockwise rotation around Y axis @@ -446,9 +447,9 @@ namespace OpenTK } /// - /// Builds a Quaternion from the given euler angles + /// Builds a Quaternion from the given euler angles in radians. /// The rotations will get applied in following order: - /// 1. Around X, 2. Around Y, 3. Around Z + /// 1. X axis, 2. Y axis, 3. Z axis /// /// The counterclockwise euler angles as a vector /// The equivalent Quaternion diff --git a/tests/OpenTK.Tests.Math/QuaternionTests.cs b/tests/OpenTK.Tests.Math/QuaternionTests.cs index 27f0a28b..d07fa732 100644 --- a/tests/OpenTK.Tests.Math/QuaternionTests.cs +++ b/tests/OpenTK.Tests.Math/QuaternionTests.cs @@ -50,7 +50,7 @@ namespace OpenTK.Tests.Math /// or does not contain 0 when it should be /// To test /// Expected directions. Values getting only 0 checked - public static bool VerifyEuqalSignleDirection(Vector3 toTest, Vector3 expected) + public static bool VerifyEqualSingleDirection(Vector3 toTest, Vector3 expected) { //To verify the direction of an vector, just respect the 0 values and check against these. //The length of the vectors are ignored. @@ -109,7 +109,7 @@ namespace OpenTK.Tests.Math //Assert: Use helper, to check if part of the two correct axis is zero. I just want check the direction Vector3 resultXYZ = cut.Xyz; - Assert.True(QuaternionTestHelper.VerifyEuqalSignleDirection(resultXYZ, expectedResult)); + Assert.True(QuaternionTestHelper.VerifyEqualSingleDirection(resultXYZ, expectedResult)); } /// @@ -128,7 +128,7 @@ namespace OpenTK.Tests.Math //Assert: Use helper, to check if part of the two correct axis is zero. I just want check the direction Vector3 resultXYZ = cut.Xyz; - Assert.True(QuaternionTestHelper.VerifyEuqalSignleDirection(resultXYZ, expectedResult)); + Assert.True(QuaternionTestHelper.VerifyEqualSingleDirection(resultXYZ, expectedResult)); } /// @@ -147,7 +147,7 @@ namespace OpenTK.Tests.Math //Assert: Use helper, to check if part of the two correct axis is zero. I just want check the direction Vector3 resultXYZ = cut.Xyz; - Assert.True(QuaternionTestHelper.VerifyEuqalSignleDirection(resultXYZ, expectedResult)); + Assert.True(QuaternionTestHelper.VerifyEqualSingleDirection(resultXYZ, expectedResult)); } /// @@ -166,7 +166,7 @@ namespace OpenTK.Tests.Math //Assert: Use helper, to check if part of the two correct axis is zero. I just want check the direction Vector3 resultXYZ = cut.Xyz; - Assert.True(QuaternionTestHelper.VerifyEuqalSignleDirection(resultXYZ, expectedResult)); + Assert.True(QuaternionTestHelper.VerifyEqualSingleDirection(resultXYZ, expectedResult)); } /// @@ -186,7 +186,7 @@ namespace OpenTK.Tests.Math //Assert: Use helper, to check if part of the two correct axis is zero. I just want check the direction Vector3 resultXYZ = cut.Xyz; - Assert.True(QuaternionTestHelper.VerifyEuqalSignleDirection(resultXYZ, expectedResult)); + Assert.True(QuaternionTestHelper.VerifyEqualSingleDirection(resultXYZ, expectedResult)); } /// @@ -205,7 +205,7 @@ namespace OpenTK.Tests.Math cut.ToAxisAngle(out resultXYZ, out dontCare); //Assert: Use helper, to check if part of the two correct axis is zero. I just want check the direction - Assert.True(QuaternionTestHelper.VerifyEuqalSignleDirection(resultXYZ, expectedResult)); + Assert.True(QuaternionTestHelper.VerifyEqualSingleDirection(resultXYZ, expectedResult)); } //TODO: Make also checks with rotation angle From 5aed63e396daf6a1b83a3fbf4d3b2b8d40e07cca Mon Sep 17 00:00:00 2001 From: Unknown Date: Wed, 3 Jan 2018 19:40:11 +0100 Subject: [PATCH 4/7] Refactored helper unit test classes Extracted classes which provides data and verify test results into seperate files. Replaced String with string and removed the System namespace. --- .../QuaternionTestDataGenerator.cs | 39 +++++++ .../Helpers/QuaternionTestHelper.cs | 61 ++++++++++ .../OpenTK.Tests.Math.csproj | 6 + tests/OpenTK.Tests.Math/QuaternionTests.cs | 105 ++---------------- 4 files changed, 115 insertions(+), 96 deletions(-) create mode 100644 tests/OpenTK.Tests.Math/DataProviders/QuaternionTestDataGenerator.cs create mode 100644 tests/OpenTK.Tests.Math/Helpers/QuaternionTestHelper.cs diff --git a/tests/OpenTK.Tests.Math/DataProviders/QuaternionTestDataGenerator.cs b/tests/OpenTK.Tests.Math/DataProviders/QuaternionTestDataGenerator.cs new file mode 100644 index 00000000..19dd76ef --- /dev/null +++ b/tests/OpenTK.Tests.Math/DataProviders/QuaternionTestDataGenerator.cs @@ -0,0 +1,39 @@ +using System.Collections.Generic; + +namespace OpenTK.Tests.Math.DataProviders +{ + /// + /// Generates/Provides Quaternion test data. + /// + public class QuaternionTestDataGenerator + { + /// + /// Returns the single axis test cases. + /// 1. param: rotation in euler angles + /// 2. param: expected result of xyz-component of quaternion + /// 3. param: test name (Don't found a working way how to pass this to xUnit runner). I let it here for test documentation + /// + /// The single axis test cases. + public static IEnumerable SingleAxisTestCases() + { + yield return new object[] { new Vector3(1, 0, 0), Vector3.UnitX, "Rotate around x axis" }; + yield return new object[] { new Vector3(0, 1, 0), Vector3.UnitY, "Rotate around y axis" }; + yield return new object[] { new Vector3(0, 0, 1), Vector3.UnitZ, "Rotate around z axis" }; + } + + /// + /// Returns the single ToAxisAngle test cases. + /// 1. param: Quaternion which a definied value of xyz-component. + /// 2. param: expected result of xyz-component of quaternion + /// 3. param: test name (Don't found a working way how to pass this to xUnit runner). I let it here for test documentation + /// + /// The single axis test cases. + public static IEnumerable ToAxisAngleTestCases() + { + yield return new object[] { new Quaternion(Vector3.UnitX, 0), Vector3.UnitX, "Rotate around x axis" }; + yield return new object[] { new Quaternion(Vector3.UnitY, 0), Vector3.UnitY, "Rotate around y axis" }; + yield return new object[] { new Quaternion(Vector3.UnitZ, 0), Vector3.UnitZ, "Rotate around z axis" }; + } + } + +} diff --git a/tests/OpenTK.Tests.Math/Helpers/QuaternionTestHelper.cs b/tests/OpenTK.Tests.Math/Helpers/QuaternionTestHelper.cs new file mode 100644 index 00000000..d3d35dc8 --- /dev/null +++ b/tests/OpenTK.Tests.Math/Helpers/QuaternionTestHelper.cs @@ -0,0 +1,61 @@ +using Xunit; +using System; +using System.Collections.Generic; + +namespace OpenTK.Tests.Math.Helpers +{ + + /// + /// Provides some methods which helps to verify test results + /// + internal static class QuaternionTestHelper + { + /// + /// Verifies the direction of an given . + /// + /// false: When does contain xyz values, when it should be 0, + /// or does not contain 0 when it should be + /// To test + /// Expected directions. Values getting only 0 checked + public static bool VerifyEqualSingleDirection(Vector3 toTest, Vector3 expected) + { + //To verify the direction of an vector, just respect the 0 values and check against these. + //The length of the vectors are ignored. + if (expected.X == 0) + { + if (toTest.X != 0) + return false; + } + else + { + if (toTest.X == 0) + return false; + } + + if (expected.Y == 0) + { + if (toTest.Y != 0) + return false; + } + else + { + if (toTest.Y == 0) + return false; + } + + if (expected.Z == 0) + { + if (toTest.Z != 0) + return false; + } + else + { + if (toTest.Z == 0) + return false; + } + + return true; + } + } + +} diff --git a/tests/OpenTK.Tests.Math/OpenTK.Tests.Math.csproj b/tests/OpenTK.Tests.Math/OpenTK.Tests.Math.csproj index 07882b1d..71cd5cd6 100644 --- a/tests/OpenTK.Tests.Math/OpenTK.Tests.Math.csproj +++ b/tests/OpenTK.Tests.Math/OpenTK.Tests.Math.csproj @@ -48,10 +48,16 @@ + + + + + +