【发布时间】:2018-08-25 15:30:09
【问题描述】:
我在引擎中旋转游戏对象时遇到问题。我正在尝试以两种方式旋转。 我正在使用MathGeoLib 来计算引擎中的数学。
第一种方式:绕轴正确旋转,但如果我想向后旋转,如果我不按照相反的顺序进行旋转,则旋转无法正常工作。
例如:
X 轴旋转 50 度,Y 轴旋转 30 度 -> Y 轴旋转 -50 度,X 轴旋转 -30 度。有效。
X 轴旋转 50 度,Y 轴旋转 30 度 -> X 轴旋转 -50 度,Y 轴旋转 -30 度。没有。
代码:
void ComponentTransform::SetRotation(float3 euler_rotation)
{
float3 diff = euler_rotation - editor_rotation;
editor_rotation = euler_rotation;
math::Quat mod = math::Quat::FromEulerXYZ(diff.x * DEGTORAD, diff.y * DEGTORAD, diff.z * DEGTORAD);
quat_rotation = quat_rotation * mod;
UpdateMatrix();
}
第二种方式:开始围绕轴旋转良好,但在旋转了几次后,它会停止围绕轴正确旋转,但是如果我不管旋转顺序如何都将它旋转回来,它会起作用,不像第一种方式。
代码:
void ComponentTransform::SetRotation(float3 euler_rotation)
{
editor_rotation = euler_rotation;
quat_rotation = math::Quat::FromEulerXYZ(euler_rotation.x * DEGTORAD, euler_rotation.y * DEGTORAD, euler_rotation.z * DEGTORAD);
UpdateMatrix();
}
其余代码:
#define DEGTORAD 0.0174532925199432957f
void ComponentTransform::UpdateMatrix()
{
if (!this->GetGameObject()->IsParent())
{
//Get parent transform component
ComponentTransform* parent_transform = (ComponentTransform*)this->GetGameObject()->GetParent()->GetComponent(Component::CompTransform);
//Create matrix from position, rotation(quaternion) and scale
transform_matrix = math::float4x4::FromTRS(position, quat_rotation, scale);
//Multiply the object transform by parent transform
transform_matrix = parent_transform->transform_matrix * transform_matrix;
//If object have childs, call this function in childs objects
for (std::list<GameObject*>::iterator it = this->GetGameObject()->childs.begin(); it != this->GetGameObject()->childs.end(); it++)
{
ComponentTransform* child_transform = (ComponentTransform*)(*it)->GetComponent(Component::CompTransform);
child_transform->UpdateMatrix();
}
}
else
{
//Create matrix from position, rotation(quaternion) and scale
transform_matrix = math::float4x4::FromTRS(position, quat_rotation, scale);
//If object have childs, call this function in childs objects
for (std::list<GameObject*>::iterator it = this->GetGameObject()->childs.begin(); it != this->GetGameObject()->childs.end(); it++)
{
ComponentTransform* child_transform = (ComponentTransform*)(*it)->GetComponent(Component::CompTransform);
child_transform->UpdateMatrix();
}
}
}
MathGeoLib:
Quat MUST_USE_RESULT Quat::FromEulerXYZ(float x, float y, float z) { return (Quat::RotateX(x) * Quat::RotateY(y) * Quat::RotateZ(z)).Normalized(); }
Quat MUST_USE_RESULT Quat::RotateX(float angle)
{
return Quat(float3(1,0,0), angle);
}
Quat MUST_USE_RESULT Quat::RotateY(float angle)
{
return Quat(float3(0,1,0), angle);
}
Quat MUST_USE_RESULT Quat::RotateZ(float angle)
{
return Quat(float3(0,0,1), angle);
}
Quat(const float3 &rotationAxis, float rotationAngleRadians) { SetFromAxisAngle(rotationAxis, rotationAngleRadians); }
void Quat::SetFromAxisAngle(const float3 &axis, float angle)
{
assume1(axis.IsNormalized(), axis);
assume1(MATH_NS::IsFinite(angle), angle);
float sinz, cosz;
SinCos(angle*0.5f, sinz, cosz);
x = axis.x * sinz;
y = axis.y * sinz;
z = axis.z * sinz;
w = cosz;
}
有什么帮助吗?
谢谢。
【问题讨论】:
-
这就是轮换的工作方式。你有什么问题?
-
那么这两种方法中哪一种是正确的?因为你可以看到结果不相等
-
在什么意义上正确?
-
我的意思是。第一个在一些旋转后没有正确地围绕轴旋转,但我可以不管顺序旋转,第二个总是围绕轴旋转,但如果我想旋转回来,需要遵循一个顺序。似乎两者都是正确的,但都有问题。我应该使用哪一个?
标签: c++ math rotation quaternions euler-angles