Как изменить «угол» кватерниона, но сохранить его направление. (Единство) - PullRequest
2 голосов
/ 11 июня 2019

Я провел много исследований, но действительно не могу понять, как я должен использовать кватернион для следующих действий:

У меня есть ориентация источника и ориентация цели, и я пытаюсь найти кватернион определенного угла (например, 10 градусов), который идет от одной ориентации к другой.

Я пытаюсь понять кватернионы, а также хочу избежать блокировки карданного подвеса, поэтому мне нужен ответ, который не нужно преобразовывать в углы Эйлера.

Я знаю, что есть функция Slerp, но она похожа на «процент» вместо угла. Также я не уверен, как найти разницу между источником и целью.

В основном я пытаюсь сделать следующее, но с кватернионами вместо векторов:

Vector3 source, target; //Lets pretend they are defined
Vector3 vect_dir = target - source;
float vect_length = Mathf.Min(10f * Time.deltaTime, vect_dir.magnitude);
Vector3 answer = vect_dir.normalized * vect_length;

Кто-нибудь знает, как сделать то же самое с кватернионами? Идея состоит в том, чтобы поставить значение скорости (10 в примере) на мой выбор. Это очень похоже на использование функции Slerp, за исключением того, что я хочу постоянное движение вместо движения, которое идет быстро и постепенно замедляется. Я также хотел бы избежать использования углов Эйлера из-за блокировки карданного подвеса.

1 Ответ

1 голос
/ 11 июня 2019

Рассмотрите возможность использования Quaternion.RotateTowards

Quaternion.RotateTowards принимает Quaternion от , Quaternion до иfloat maxDegreesDelta .Затем он возвращает значение, которое ближе к с :

  1. Quaternion между с и до то есть maxDegreesDelta градусов от от

  2. до

Таким образом, пример с Quaternion s, который соответствует вашему, может быть записан так:

Quaternion source, target; //Lets pretend they are defined
Quaternion reachedRotation = Quaternion.RotateTowards(source, target, 10f * Time.deltaTime);

Если вам нужна разница между достигнутой точкой и source, вы можете выполнить некоторую кватернионную математику:

Quaternion answer = Quaternion.Inverse(source) * midpoint;

В качестве альтернативы вы можете определить разницу между target и source и выразить ее в форме угла (величины) и оси (направления) с помощью Quaternion.ToAngleAxis:

Quaternion difference = Quaternion.Inverse(source) * target;
Vector3 differenceAxis;
float differenceAngle;
difference.ToAngleAxis(out differenceAngle, out differenceAxis);

А затем выведите answer, нажав differenceAngle:

Quaternion answer = Quaternion.AngleAxis(Mathf.Min(differenceAngle, 10f * Time.deltaTime), differenceAxis);

И если вы хотите найти поворот, который получается в результате «включения» answer наsource, просто умножьте их (порядок важен):

reachedRotation = source * answer;

Как пример, ваш пример с Vector3 s может быть записан как:

Vector3 source, target; //Lets pretend they are defined
Vector3 answer = Vector3.MoveTowards(source, target, 10f * Time.deltaTime) - source;
...