首先,我不确定这个问题是否值得欢迎,我检查了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 ......
答案 0 :(得分:2)
显然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 。
我没有检查过,但是组合旋转肯定是不是可交换的,这可以解释一些坐标的负值 - 与采用反向旋转相同。