diff --git a/src/OpenTK/Math/Quaternion.cs b/src/OpenTK/Math/Quaternion.cs index bea308bc..0d92d00a 100644 --- a/src/OpenTK/Math/Quaternion.cs +++ b/src/OpenTK/Math/Quaternion.cs @@ -66,34 +66,37 @@ namespace OpenTK { } /// - /// Construct a new Quaternion from given Euler angles + /// 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 /// - /// 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) { } @@ -407,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 @@ -430,11 +433,13 @@ 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 (X axis), 2. yaw (Y axis), 3. roll (Z axis) /// - /// 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) { @@ -442,9 +447,11 @@ 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. X axis, 2. Y axis, 3. Z axis /// - /// The euler angles as a vector + /// The counterclockwise euler angles as a vector /// The equivalent Quaternion public static Quaternion FromEulerAngles(Vector3 eulerAngles) { @@ -452,23 +459,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; } /// diff --git a/tests/OpenTK.Tests.Math/DataProviders/QuaternionTestDataGenerator.cs b/tests/OpenTK.Tests.Math/DataProviders/QuaternionTestDataGenerator.cs new file mode 100644 index 00000000..c01bb252 --- /dev/null +++ b/tests/OpenTK.Tests.Math/DataProviders/QuaternionTestDataGenerator.cs @@ -0,0 +1,37 @@ +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 + /// + /// 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 + /// + /// 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 9b2ccec8..71cd5cd6 100644 --- a/tests/OpenTK.Tests.Math/OpenTK.Tests.Math.csproj +++ b/tests/OpenTK.Tests.Math/OpenTK.Tests.Math.csproj @@ -47,10 +47,17 @@ + + + + + + +