Я использую SharpDX для выполнения Squad-интерполяции кватернионов, но вычисленные результаты не являются непрерывными. Вот код. В чем проблема и как ее исправить?
На следующем графике показано изменение компонента Y (Vector3.Y) после преобразования кватернионов в углы Эйлера, показывая вращение вокруг оси Y. На графике отображается разница .Y - [i-1].Y для каждого образца
график здесь
Я использую SharpDX для выполнения Squad-интерполяции кватернионов, но вычисленные результаты не являются непрерывными. Вот код. В чем проблема и как ее исправить? На следующем графике показано изменение компонента Y (Vector3.Y) после преобразования кватернионов в углы Эйлера, показывая вращение вокруг оси Y. На графике отображается разница [i].Y - [i-1].Y для каждого образца график здесь [code]using SharpDX; private void PerformSquadOperation() { Quaternion q0 = new Quaternion(0, 0, 0, 1); Quaternion q1 = new Quaternion(0.016118152f, -0.00038984258f, -0.007754744f, 0.9998398f); Quaternion q2 = new Quaternion(0.03223115f, -0.0007795604f, -0.015507007f, 0.9993598f); Quaternion q3 = new Quaternion(0.032017402f, 0.0037394506f, -0.1552901f, 0.9873428f); Quaternion q4 = new Quaternion(0.03117278f, 0.008184779f, -0.29201335f, 0.95587116f);
int samples = 1000; List q0q1 = new(); Quaternion[] q0q1Aux = Quaternion.SquadSetup(q0, q0, q1, q2); for (int i = 0; i < samples +1; i++) { float t = (float)i / samples; Quaternion current = Quaternion.Squad(q0, q0q1Aux[0], q0q1Aux[1], q0q1Aux[2], t); Vector3 currentEular = Quaternion2Eular(current); q0q1.Add((current, t, currentEular)); } List q1q2 = new(); Quaternion[] q1q2Aux = Quaternion.SquadSetup(q0, q1, q2, q3); for (int i = 0; i < samples + 1; i++) { float t = (float)i / samples; Quaternion current = Quaternion.Squad(q1, q1q2Aux[0], q1q2Aux[1], q1q2Aux[2], t); Vector3 currentEular = Quaternion2Eular(current); q1q2.Add((current, t, currentEular)); } List q2q3 = new(); Quaternion[] q2q3Aux = Quaternion.SquadSetup(q1, q2, q3, q4); for (int i = 0; i < samples + 1; i++) { float t = (float)i / samples; Quaternion current = Quaternion.Squad(q2, q2q3Aux[0], q2q3Aux[1], q2q3Aux[2], t); Vector3 currentEular = Quaternion2Eular(current); q2q3.Add((current, t, currentEular)); } List q3q4 = new(); Quaternion[] q3q4Aux = Quaternion.SquadSetup(q2, q3, q4, q4); for (int i = 0; i < samples + 1; i++) { float t = (float)i / samples; Quaternion current = Quaternion.Squad(q3, q3q4Aux[0], q3q4Aux[1], q3q4Aux[2], t); Vector3 currentEular = Quaternion2Eular(current); q3q4.Add((current, t, currentEular)); }
List AttPath = new(); AttPath.AddRange(q0q1); q1q2.RemoveAt(0); AttPath.AddRange(q1q2); List AttPath2 = new(); AttPath2.AddRange(q2q3); q3q4.RemoveAt(0); AttPath2.AddRange(q3q4);
List totalAttPath = new(); totalAttPath.AddRange(AttPath); AttPath2.RemoveAt(0); totalAttPath.AddRange(AttPath2); }
/// /// /// ///
/// X=A,Y=B,Z=C public static Vector3 Quaternion2Eular(Quaternion q) { Vector3 result = new(); q = Quaternion.Normalize(q); float w = q.W; float x = q.X; float y = q.Y; float z = q.Z; float ARad = MathF.Atan2(2 * (w * z + x * y), 1 - 2 * (y * y + z * z)); float BRad = MathF.Asin(2 * (w * y - z * x)); float CRad = MathF.Atan2(2 * (w * x + y * z), 1 - 2 * (x * x + y * y)); result.X = (float)Rad2Deg(ARad); result.Y = (float)Rad2Deg(BRad); result.Z = (float)Rad2Deg(CRad);
return result; }
public static double Rad2Deg(double rad) { double degree = rad * 180 / System.Math.PI; return degree; }