AxaAngleRotation3D到Quaternion会产生意外结果

时间:2016-08-02 14:43:23

标签: c# wpf 3d rotation quaternions

我正在使用WPF 3D(使用C#)开发控制器,以便能够使用ProjectionCamera - 和Move() - 函数轻松移动和旋转Pitch()。我的控制器将成为可以附加到Behavior<ProjectionCamera>的{​​{1}}。为了初始化控制器,我想通过查看其当前的ProjectionCameraUp矢量来计算相机的当前旋转,并将它们与默认的相机方向进行比较(ForwardUp = [0 1 0])。换句话说,我想计算一个旋转,它会将相机默认的方向转换为当前的方向。

最终,我想将旋转表示为单个Forward = [0 0 -1],但作为中间步骤,我首先计算 zNZ 正确的欧拉角旋转 >表示为Quaternion - 值,遵循默认定义Wikipedia

AxisAngleRotation3D

var alphaRotation = CalculateRotation(z, x, N);
var betaRotation = CalculateRotation(N, z, Z);
var gammaRotation = CalculateRotation(Z, N, X);

根据一些单元测试,似乎可以正确计算欧拉角旋转。但是,当我将这些旋转转换为单个CalculateRotation(Vector3D axisOfRotation, Vector3D from, Vector3D to) : AxisAngleRotation3D 时,生成的Quaternion表示与欧拉角度旋转不同的旋转,我不知道为什么

这就是我将欧拉角转换为单个四元数的方法:

Quaternion

例如,当我使用var rotation = new Quaternion(alphaRotation.Axis, alphaRotation.Angle) * new Quaternion(betaRotation.Axis, betaRotation.Angle) * new Quaternion(gammaRotation.Axis, gammaRotation.Angle); ProjectionCamera初始化UpDirection时,意味着它已围绕其[1 0 0]轴旋转了90度({{ 1}}),计算出的欧拉角旋转如下:

LookDirection

我的测试验证,按顺序应用时,这些旋转会将默认[0 0 -1] - 向量(alphaRotation --> 90 deg. around [0 1 0] betaRotation --> 90 deg. around [0 0 -1] gammaRotation --> -90 deg. around [1 0 0] )转换为当前Up - 向量([0 1 0]) ,有效地旋转90度。围绕Up轴。 (手动验证这一点也很合理。)

但是,当我将计算出的[1 0 0]应用于默认的[0 0 -1] - 向量时,它会转换为向量QuaternionRotation,这显然是错误的。我在单元测试中对这些结果进行了硬编码,得到了相同的结果:

Up

当您运行上述测试时,您会看到[-1 0 0]为您提供了预期的向量( [TestMethod] public void ConversionTest() { var vector = new Vector3D(0, 1, 0); var alphaRotation = new AxisAngleRotation3D(new Vector3D(0, 1, 0), 90); var betaRotation = new AxisAngleRotation3D(new Vector3D(0, 0, -1), 90); var gammaRotation = new AxisAngleRotation3D(new Vector3D(1, 0, 0), -90); var a = new Quaternion(alphaRotation.Axis, alphaRotation.Angle); var b = new Quaternion(betaRotation.Axis, betaRotation.Angle); var c = new Quaternion(gammaRotation.Axis, gammaRotation.Angle); var combinedRotation = a * b * c; var x = Apply(vector, alphaRotation, betaRotation, gammaRotation); var y = Apply(vector, combinedRotation); } ),但x将是不同的,它应该是完全相同的旋转。

我错过了什么?

1 个答案:

答案 0 :(得分:0)

我解决了这个问题。显然,应该颠倒个体Quaternions的乘法顺序。因此,要将Euler Angles(或任何一组旋转)转换为.NET中的单个Quaternion ,您应该执行以下操作:

var rotation = gammaRotation * betaRotation * alphaRotation;

其中rotation表示首先应用alphaRotation,然后是betaRotation,最后是gammaRotation。我只是希望他们记录下来,因为订单的含义取决于您正在使用的特定库....