##### Примечание:
В данном тексте GPT4 употребляет слово «вращение» и как глагол, и как существительное.
- <u>Как существительное</u> - обозначение ориентации (куда смотрит) объекта в 3D-пространстве.
- <u>Как глагол</u> - это процесс изменения ориентации объекта.
Умножение кватернионов друг на друга обычно используется для композиции (комбинирования) вращений.
"Композиция" означает применение одного вращения после другого. Композиция часто описывается как "цепочка" преобразований, где результат каждого шага используется как вход для следующего.
Если у вас есть два кватерниона Q и R, то их композиция (Q \* R) будет новым вращением, которое сначала применяет R, а затем Q. Порядок важен: сначала будет применено вращение R, а затем вращение Q при умножении QR.
Стоит заметить, что умножение кватернионов не коммутативно, то есть Q \* R обычно не равно R \* Q.
<br>
Давайте рассмотрим пример.
Предположим, что у нас есть объект, который мы хотим повернуть. Пусть Q представляет вращение на 90 градусов вокруг оси X, а R представляет вращение на 90 градусов вокруг оси Y.
Если мы сначала применим вращение R, объект повернется на 90 градусов вокруг оси Y. Затем, если мы применим вращение Q, объект повернется на 90 градусов вокруг оси X.
В итоге мы получим объект, который был сначала повернут на 90 градусов вокруг оси Y, а затем на 90 градусов вокруг оси X. Это именно то вращение, которое представляет собой кватернион QR.
Нужно уточнить, что в данном примере мы крутим объект для наглядности, но по факту после умножения кватернионов мы получаем новый кватернион. И этот новый кватернион мы уже применяем к объекту, которому хотим изменить ориентацию. (Мое примечание)
Таким образом, кватернионы позволяют нам комбинировать вращения, умножая их. Это очень мощный инструмент для работы с 3D вращениями.
### Как получить глобальную ориентацию, имея локальную
```csharp
_rotation = Parent._rotation * _localRotation;
```
Давайте разберём это выражение подробнее:
* \_rotation - глобальная ориентация объекта
* Parent.\_rotation - это глобальная ориентация родительского объекта относительно мировых координат.
* \_localRotation - это локальная ориентация объекта относительно его родительского объекта.
Чтобы получить глобальную ориентацию (\_rotation)
Нам нужно взять локальную ориентацию (рисунок ниже)

И повернуть (умножить) на глобальную ориентацию (рисунок ниже)

Глобальное ориентация нашего объекта (\_rotation) получается путем вращения его локально (\_localRotation), а затем вращения полученного результата в соответствии с глобальной ориентацией его родителя (Parent.\_rotation)".
В других словах, мы применяем локальную ориентацию к нашему объекту (то есть вращаем его относительно его собственной системы координат), а затем применяем глобальную ориентацию его родителя (то есть вращаем полученный результат в мировой системе координат).
### Как получить локальную ориентацию, имея глобальную
```csharp
_localRotation = Quaternion.Inverse(Parent._rotation) * _rotation;
```
##### Разбор от GPT
Эта строка кода вычисляет локальное вращение (`_localRotation`) дочернего объекта относительно его родительского объекта.
Посмотрим подробнее на каждую часть этой строки:
1. `_rotation` - это глобальное вращение дочернего объекта.
2. `Parent._rotation` - это глобальное вращение родительского объекта.
3. `Quaternion.Inverse(Parent._rotation)` - эта функция возвращает обратное вращение родительского объекта. Если вы повернете объект с использованием определенного вращения, а затем повернете его обратно с использованием обратного вращения, он вернется в свое исходное положение. В этом случае, мы вычисляем обратное вращение, чтобы "отменить" вращение родительского объекта.
4. `Quaternion.Inverse(Parent._rotation) * _rotation` - здесь мы умножаем обратное вращение родителя на глобальное вращение дочернего объекта. Это "отменяет" вращение родителя в глобальном вращении дочернего объекта, оставляя только вращение дочернего объекта относительно родителя.
Таким образом, `_localRotation` становится вращением дочернего объекта относительно его родительского объекта в локальной системе координат. Это позволяет нам видеть, каким образом дочерний объект повернут относительно своего родителя, независимо от вращения самого родительского объекта в глобальном пространстве.
##### Разбор от меня
У нас есть родитель, внутри родителя ребенок.
Нам нужно получить локальную ориентацию ребенка относительно родителя (\_localRotaion)
нам доступно:
- Глобальная ориентация **родителя** относительно мира (Parent.\_rotation)
- Глобальная ориентация **ребенка** относительно мира (\_rotation).
Функция Quaternion.Inverse переворачивает кватернион родителя, тем самым он становится противоположным. Например, был 60 градусов по оси X, стал -60 градусов по оси X.
Для общего понимания привожу еще один пример: если мы умножим Parent.\_rotation на Inverse, то мы вернем родителя на исходную (первоначальную/нулевую/дефолтную) ориентацию
Дальше идет умножение inverse родителя на \_rotation ребенка.
В данном случае, inverse(Parent.\_rotation) дает нам величину смещения, которую нужно применить к \_rotation, чтобы получить его локальную ориентацию.
Объясню на простых числах.
Например, у нас есть число 5 и число 7. Относительно цифры 5, число 7 является 2. То есть, если в качестве родителя взять число 5, а в качестве ребенка число 7, то получается, что это их глобальные значения, а число 2 - локальное (относительно 5).
Допустим, нам нужно получить локальную позицию ребенка. Входные данные: Это глобальная позиция родителя (5) и глобальная позиция ребенка (7)
Как нам вычислить локальную позицию ребенка?
Нам нужно из 7 вычесть 5, тогда мы получим 2.
С кватернионами почти тоже самое!
Мы взяли 5 и перевернули. Получилось «-5». Это число нам показывает на сколько нужно сместить кватернион ребенка, чтобы получить локальное значение. 7 смещаем на «-5» и получаем 2.