四元数 – 通过反复试验得出的结果,你能解释一下原因吗?

首先,我不确定这个问题是否值得欢迎,我检查了
FAQ并发现“我希望别人解释”问题.

主要问题是我需要在我的应用程序中存储两次所有对象的旋转.这是因为一方面我使用Bullet Physics的物理模拟存储其表示.另一方面,我自己存储旋转,所有对象都有共同点,无论它们是否在物理模拟中,如灯光,任务目标等等.除了物理库,我还使用了GLM数学库.

我必须同步两个表示.顺便说一句,位置和规模不会产生任何问题.困难在于物理模拟任何我自己的表示都是不同的,所以我不能只复制值.我没有发现所有这些差异,但它可能与左手坐标系统和右手坐标系统有关,度数与弧度相关,Y坐标与Z向上相关.

我自己的表示只是将欧拉角存储在glm :: vec3向量中.由于我使用OpenGL绘图,我猜这个空间是右手.对于欧拉角,订单很重要.我计算旋转矩阵的方法是首先创建每个组件的矩阵,然后将它们乘以X * Y * Z顺序.此外,在我自己的表示中,正Y坐标指向上方.

物理模拟使用四元数来存储旋转.经过一些研究后,我读到了这个库中左手空间的假设.我没有关于哪个坐标是向上的信息,也没有关于返回欧拉角的顺序的信息.

这里是将旋转从物理模拟转换为我自己的表示的代码,反之亦然.

#include <GLM/glm.hpp>
#include <GLM/gtc/quaternion.hpp>
#include <BULLET/btBulletDynamicsCommon.h>

/*******************************************************************
 * euler angles "glm::vec3 input" from my own representation
 * to quaternion "btQuaternion output" of physics simulation
 *******************************************************************/
glm::quat quaternion(glm::vec3(input.x, input.z, input.y) * 3.14159f / 180.f);
btQuaternion output(quaternion.x, quaternion.y, quaternion.z, quaternion.w);

/*******************************************************************
 * quaternion "btQuaternion input" from physics simulation
 * to euler angles "glm::vec3 output" of my own representation
 *******************************************************************/
glm::quat quaternion(input.getW(), -input.getX(), -input.getY(), -input.getZ());
glm::vec3 angles = glm::eulerAngles(quaternion);
glm::vec3 output(-angles.x, -angles.y, -angles.z);

我通过反复试验找到了这个脏代码并且它有效.但正如您可以看到通过不同的四元数类型的否定,组件调配和类型转换.我想其中许多是不必要的,任务可以更简单地执行.

您能否解释为什么我的转换有效以及如何简化它们?顺便说一下,我想看看如果转换不起作用它看起来如何,这里是screenshot

最佳答案 显然,
Euler angles有很多不同的定义,你的两个库使用不同的约定.

GLM’s source开始他们使用Pitch,Yaw,Roll:

template <typename T> 
GLM_FUNC_QUALIFIER detail::tvec3<T> eulerAngles
(
    detail::tquat<T> const & x
)
{
    return detail::tvec3<T>(pitch(x), yaw(x), roll(x));
}

…而在Bullet’s documentation他们使用Yaw,Pitch,Roll.

我没有检查过,但是组合旋转绝对不是可交换的,这可以解释一些坐标的负值 – 与采用反向旋转相同.

点赞