我不知道问题的第一部分(它的不同之处足以成为它自己的问题),但我可以回答你的第二部分。
所以,你有这些输入:
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
}
希望对您有所帮助。