Unity初心者でも！数学苦手でも！角度のQuaternion表現を理解したい！！

## はじめに
最近Unityをはじめました。前からCADさわったりはしていたので，3次元の概念については余裕だろ〜と思っていました。
**なんですかQuaternionって。**
パラメータが4つってどういうことですか。
リファレンスを読んでも
>クォータ二オンは複素数に基づいており、直感的に理解するのは容易ではありません。個々のクォータニオンの成分 (x,y,z,w) にアクセスしたり変更したりすることはほとんどありません。たいてい、既存の回転 (例えば、Transform から取得) を使用して新しい回転を構築するために使用します (例えば、2 つのローテーションの間を円滑に補間するなど)。使用する Quaternion 関数の 99% は、Quaternion.LookRotation、Quaternion.Angle、Quaternion.Euler、Quaternion.Slerp、Quaternion.FromToRotation、Quaternion.identity です (他の関数が使用されることはほとんどありません)。 

とあり，「サジ投げとるやないかい！」と思ったのでめっちゃ頑張って勉強しました。
間違っていたらあたたかく指摘していただけると嬉しいです:innocent:
(ちなみに私は一応理系なので語彙があれな時はまあそういうことです)

## 参考
本記事はを書くにあたって以下の記事で勉強しました。
ありがとうございます:pray:

- [Unity道場スペシャル博多](https://www.dropbox.com/s/em7iqkax0771qb0/Unity%E9%81%93%E5%A0%B4%E3%82%B9%E3%83%9A%E3%82%B7%E3%83%A3%E3%83%AB%E5%8D%9A%E5%A4%9A-yasuhara.pdf?dl=0)
- [クォータニオン（回転）についてメモ](http://edom18.hateblo.jp/entry/2018/06/25/084023)
- [クォータニオンで回転を表現する定義にθ/2が使用される理由](https://qiita.com/yuji_yasuhara/items/a5b7c489e1d521adbd72)

## 超ざっくり複素数平面
詳しい人に怒られそうな感じでやっていきたいと思います！(高校数学だしいけると思うので)
わかる方はこの項目飛ばして大丈夫です。
平面上の任意の点を表現するとき，以下のような座標の表現をします。

```math
P(x座標, y座標)
```
<img width="459" alt="スクリーンショット 2019-06-07 19.12.32.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/230703/87680b00-c273-8661-9b46-190c3f41b663.png">
複素数平面では，この時のx軸を**実軸**，y軸を**虚軸**として以下のような表現をします。

```math
P(実軸の座標, 虚軸の座標 i)\\
(iは虚数単位)
```
<img width="437" alt="スクリーンショット 2019-06-07 19.19.39.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/230703/765c895c-2930-15dc-1640-6349e176b2e0.png">
この虚数平面上に，半径1の円があると考えます(**単位円**)。
この円周上にある点は以下の複素数で表現することができます。

```math
\cos\theta+i\sin\theta\\
(iは虚数単位)
```
<img width="451" alt="スクリーンショット 2019-06-07 19.26.13.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/230703/62c229ee-3241-8afd-19f4-b02087126b02.png">
ここで，実部が0の複素数`i`が表現する点を考えます。`i`は`θ=90°`の位置の点を表現しています。
この`i`にさらに`i`をかけると

```math
i\times i = -1
```
となります。このとき，`-1`が表現する点を考えると単位円上の`θ=180°`の点になります。
さらに`i`をかけると`-i`となり，この点が表現する点は単位円上の`θ=270°`の点です。
図に示すとこんな感じ。
<img width="448" alt="スクリーンショット 2019-06-07 19.56.12.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/230703/55e9ca60-5885-c7dd-d912-f446e3ed2a5a.png">
つまり，**単位円上の点を掛け合わせること＝回転角を足すこと**になります。


## 平面から立体へ

アイルランドの数学者ウィリアム・ローワン・ハミルトンは(たぶん)考えました。**これを三次元空間の力学に応用できないか。**
これによって生まれたのがQuaternionです。
虚数で3次元空間を表現するために，ハミルトンは虚数単位を3つ作って解決しました。(本記事では`i`，`j`，`k`とします)
この虚数単位は以下のようなものであると定義されました。

```math
i^2=-1, j^2=-1, k^2=-1\\
ij=k, ji=-k\\
jk=i, kj=-i\\
ki=j, ik= -j\\
ijk=-1
```
虚数単位が3つにふえた複素数は以下のような数として表現できます。

```math
ix+jy+kz+w\\
(x,y,z,wは実数)
```
そしてこれは`(x,y,z)`の向きに`w`進んだ位置(ベクトルの大きさ)の点を示します。
<img width="589" alt="スクリーンショット 2019-06-07 20.35.38.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/230703/4fcb95a8-1cb0-547a-1da1-668c837061b5.png">
これらの係数をまとめたものをQuaternionとしました。
(つまりQuaternionは本来回転を示すものではないです)

```math
Quaternion=(x, y, z, w)
```
これに以下の条件を付与することで回転に限定して考えられるようになります。

```math
x^2+y^2+z^2+w^2=1
```

## 回転したい！
先ほど，**単位円上の点を掛け合わせること＝回転角を足すこと**という話をしました。
つまりQuaternionをいい感じにかけたら回転ができるのではないか…
では以下の`点P`を`V`分だけ回転させた`点P'`を考えていきます。実部はベクトルの大きさを示すパラメータなので，`V`の実部は0です。
ここで，実部の係数が0のQuaternionをpure quaternionと呼びます。

```math
P=p_1i+p_2j+p_3k+p_4\\
V=v_1i+v_2j+v_3k+0
```
ではいざかけてみましょう！
となりましたが純粋に`P`と`V`をかけても回転後のPの角度は求められません…
なぜなら実部が残ってしまうから。これを消すために，以下のように計算すると，`w`が0になって，計算結果がpure quaternionになります。

```math
P'=PVP
```
こうするとうまく回転します。

## おわりません
虚数単位が3つある複素数は以下のように表現できるという話でした。

```math
ix+jy+kz+w\\
(ｘ, y, z, wは実数)
```
しかし，虚数単位が1つだった時`cosθ+isinθ`と表現したように，θを使おうとしたときに問題が発生します。
`P`を2回かけているので最初の位置が`θ`ではなく`2θ`になっています…
ということでθを2分の1して，以下のような表現になります。

```math
\cos\frac{\theta}{2}+(ix+jy+kz)\sin\frac{\theta}{2}
```
完全に理解した…:innocent:

## 結論
**`Quaternion.Angle`，`Quaternion.Euler`を使おう。**
UnityのrotationをQuaternionで直接いじりたくて勉強しましたが，私には無理だということがわかりました…
大人しく`Quaternion.Angle`でオイラー角に直してから`Quaternion.Euler`でQuaternionに戻します…
ありがとうございました:wave: