我需要以某个对象的特定轴的欧拉角显示旋转。 我知道,检索对象以欧拉角旋转会产生不一致的结果,其中一些结果可以通过对结果简单地使用模数360来解决。但是,当分配一个值为“ transform.localRotation.eulerAngles”的向量时,单位有时会执行的置换不是检索Vector3“ V”,而是检索“(180,180,180)-V”。 据我了解,“(180,180,180)-V”不会产生与V相同的真实世界旋转,与“(180,180,180)+ V”的确不会影响实际旋转。 对此现象的解释是什么?假设我知道其欧拉角旋转轴的理想值和可行值,对欧拉角旋转矢量进行标准化的最佳方法是什么? (例如,要对其进行归一化处理,使其所有值均为mod 360,并且假设Z的表示形式为Z = 0,则Z轴等于0)
答案 0 :(得分:0)
我不太确定我是否正确理解了您的问题,但是欧拉角仅代表以特定顺序绕3轴应用3圈旋转的角度,对吗?那么,为什么要在各处加180以使其标准化呢?您应该通过对每个角度进行模运算来将每个角度分别设置在0-360范围内。
您的问题似乎暗示您仅通过绕两个轴而不是三个轴旋转即可获得任何方向...这是您要实现的目标吗? 使用四元数可能会为您提供帮助,实际上,可以仅使用4个标量值(一个轴和一个角度)来定义方向
答案 1 :(得分:0)
我不知道问题的第一部分(它本身是一个与众不同的问题,imo),但我可以回答你的第二部分。
因此,您有以下输入:
Quaternion desiredRotation;
float knownZ;
您正在尝试找到Vector3 eulers
的位置,其中eulers.z
大约是knownZ
和Quaternion.Euler(eulers) == desiredRotation
。
这是我要使用的过程:
首先,确定由desiredRotation
旋转的向上方向和由knownZ
旋转的向上和向右方向:
Vector3 upDirEnd = desiredRotation * Vector3.up;
Quaternion rollRotation = Quaternion.Euler(0,0,knownZ);
Vector3 upDirAfterRoll = rollRotation * Vector3.up;
Vector3 rightDirAfterRoll = rollRotation * Vector3.right;
我们知道在应用desiredRotation
之后的局部向上方向,并且在应用滚动knownZ
之后唯一可以调整向上方向的是由欧拉螺距分量完成的旋转。因此,如果我们可以计算出upDirAfterRoll
到upDirEnd
围绕rightDirAfterRoll
轴的角度...
float determinedX = Vector3.SignedAngle(upDirAfterRoll, upDirEnd, rightDirAfterRoll);
// Normalizing determinedX
determinedX = (determinedX + 360f) % 360f;
...我们可以确定eulers
的x分量!
然后,对eulers
的偏航分量执行相同的操作,以使新的前进方向与最终前进方向对齐:
Vector3 forwardDirEnd = desiredRotation * Vector3.forward;
Quaternion rollAndPitchRotation = Quaternion.Euler(determinedX, 0, knownZ);
Vector3 forwardDirAfterRollAndPitch = rollAndPitchRotation * Vector3.forward;
Vector3 upDirAfterRollAndPitch = upDirEnd; // unnecessary but here for clarity
float determinedY = Vector3.SignedAngle(forwardDirAfterRollAndPitch, forwardDirEnd, upDirAfterRollAndPitch );
// Normalizing determinedY
determinedY = (determinedY + 360f) % 360f;
Vector3 eulers = new Vector3(determinedX, determinedY, knownZ);
为确保可以使用给定的分量生成给定的四元数,您可以检查给定SignedAngle
的轴是否实际上可以将输入向量旋转到目标向量,或者可以只比较计算出的欧拉给定的四元数:
Quaternion fromEuler = Quaternion.Euler(eulerAngles);
if (fromEuler==desiredRotation)
{
// use eulerAngles here
}
else
{
// component and quaternion incompatible
}
希望有帮助。