Я провел другой день, пытаясь найти то же самое для редактора анимации;вот как я это сделал:
- Возьмите ось, вокруг которой хотите найти вращение, и найдите для нее ортогональный вектор.
- Поверните этот новый вектор, используя свой кватернион.
- Проецируйте этот повернутый вектор на плоскость, нормалью которой является ваша ось
Акос точечного произведения этого спроецированного вектора и исходного ортогонального угла - ваш угол.
public static float FindQuaternionTwist(Quaternion q, Vector3 axis)
{
axis.Normalize();
// Get the plane the axis is a normal of
Vector3 orthonormal1, orthonormal2;
ExMath.FindOrthonormals(axis, out orthonormal1, out orthonormal2);
Vector3 transformed = Vector3.Transform(orthonormal1, q);
// Project transformed vector onto plane
Vector3 flattened = transformed - (Vector3.Dot(transformed, axis) * axis);
flattened.Normalize();
// Get angle between original vector and projected transform to get angle around normal
float a = (float)Math.Acos((double)Vector3.Dot(orthonormal1, flattened));
return a;
}
Вот код для поиска ортонормированных значений, однако вы, вероятно, сможете добиться большего успеха, если вам нужен только один для вышеуказанного метода:
private static Matrix OrthoX = Matrix.CreateRotationX(MathHelper.ToRadians(90));
private static Matrix OrthoY = Matrix.CreateRotationY(MathHelper.ToRadians(90));
public static void FindOrthonormals(Vector3 normal, out Vector3 orthonormal1, out Vector3 orthonormal2)
{
Vector3 w = Vector3.Transform(normal, OrthoX);
float dot = Vector3.Dot(normal, w);
if (Math.Abs(dot) > 0.6)
{
w = Vector3.Transform(normal, OrthoY);
}
w.Normalize();
orthonormal1 = Vector3.Cross(normal, w);
orthonormal1.Normalize();
orthonormal2 = Vector3.Cross(normal, orthonormal1);
orthonormal2.Normalize();
}
Хотя приведенное выше работаетВы можете обнаружить, что он не ведет себя так, как вы ожидаете.Например, если ваш кватернион поворачивает вектор на 90 градусов.вокруг X и 90 град.вокруг Y вы найдете, если вы разложите вращение вокруг Z, это будет 90 градусов.также.Если вы представляете вектор, совершающий эти вращения, то это имеет смысл, но в зависимости от вашего приложения это может быть нежелательным поведением.Для моего приложения - ограничения скелетных суставов - я получил гибридную систему.Матрицы / кваты использовались повсеместно, но когда дело дошло до метода ограничения соединений, я использовал внутренние углы Эйлера, разлагая кват вращения на повороты вокруг X, Y, Z каждый раз.
Удачи, надеюсь, это помогло.