目指せ回転マスター！Quaternion系VEX関数まとめ

**Houdini Apprentice Advent Calender** の18日目の記事になります。

この記事を作成するにあたって、細かい内容を示したHipファイルが[こちら](https://drive.google.com/file/d/1CdXL4Rai0vp9N9UcBroQLE827ja6D_Wa/view?usp=share_link)になります。ぜひこのファイルを一緒に見ながらお読みください。
<font color="DarkGray">リンク先が切れていた場合、お手数ですが筆者プロフィールからDMにてご連絡ください</font>

また、こちらの記事は@ijiVFXさんのこの記事に影響を受けています。
[君はお隣さん？一番近い点？それとも座標？](https://qiita.com/ijiVFX/items/0e36f17ddb690ab615eb)

# Quaternion系vex関数
Houdini初心者の方々にとって、回転ってけっこうつまずきがち(だと思っている)ので、こちらの記事で**Quaternion**系**vex**の紹介をしてみようと思います。
**Quaternion**を理解すると回転がめちゃくちゃ操作しやすくなるので！

ということで、**Quaternion**を扱う**vex**は以下の通り10個あります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1041568/118aace3-b4d4-277c-4203-e2ded883eea5.png)
この関数一つずつ、使い方と挙動をまとめていきたいと思います。


## quaternion
まずは**Quaternion**を作成するところから。
ノードとかで作ったり勝手に作られてたりしますが、もちろん**vex**で作成できます。
**quaternion**関数は**Quatenion**を作成するときによく用いられる関数です。

関数|挙動
---|---
**quaternion(rotations**<sup><font color="Green">matrix3</font></sup>**)**  |3×3回転行列**rotations**を**Quaternion**に変換する
**quaternion(angle**<sup><font color="blue">float</font></sup>**, axis**<sup><font color="BlueViolet">vector</font></sup>**)**  |ベクトル**axis**を回転軸として、角度**angle**回転する**Quaternion**を作成する
**quaternion(angleaxis**<sup><font color="BlueViolet">vector</font></sup>**)**  |正規化した回転軸と回転角度の乗算値**angleaxis**から**Quaternion**を作成

- **作例**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1041568/e1c1d1a5-b6af-f4b7-0586-ae8242d57265.png)
**quaternion**関数を使ってオブジェクトを回転する作例です。
**orient**アトリビュートを**Quaternion**で作成しています。

## qrotate
**qrotate**関数によって、**Quaternion**でベクトルを回転できます。**quaternion**を作る関数をいくつかあるんですが、最終的な回転はこの関数によって行われるので、**Quaternion**系関数の中で最も使われる関数ではないのでしょうか！？

関数|挙動
---|---
**qrotate(quaternion**<sup><font color="BlueViolet">vector4</font></sup>**, v**<sup><font color="BlueViolet">vector</font></sup>**)** | ベクトル**v**を**quaternion**によって回転する

- **作例**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1041568/31ca5325-a770-f4bc-7bef-2ce46e674e75.png)

**noise**をもとに回転**Quaternion**を作成し、**qrotate**関数を使って**v**を回転して移動するという作例です。
ちょっと作例が難しくなってしまいましたが、**Solver**は分かると楽しいのでぜひ触ってみてください！



## eulertoquaternion
**eulertoquaternion**関数によって、オイラー回転を**Quaternion**回転に変換できます。
また**quaterniontoeuler**関数によって、**Quaternion**回転をオイラー回転に変換できます。

関数|挙動
---|---
**eulertoquaternion(rotations**<sup><font color="BlueViolet">vector</font></sup>**, order**<sup><font color="OliveDrab">int</font></sup>**)** | オイラー角を**Quaternion**に変換
**quaterniontoeuler(orient**<sup><font color="BlueViolet">vector4</font></sup>**, order**<sup><font color="OliveDrab">int</font></sup>**)** | **Quaternion**をオイラー角に変換

- **作例**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1041568/9b30d0ed-14fd-452f-dda5-5db4b4d82888.png)

**eulertoquaternion**関数を使って**transform**を作成し、**intrinsics**に登録するという作例です。
一つだったら**transformSOP**で一発なんですが、まとめて処理したいときに知ってると便利ですね！

## dihedral
**dihedral**関数によって、ベクトルをもう一つのベクトルに回転する**Quaternion**を計算できます。
個人的に好きな関数です！

関数|挙動
---|---
**dihedral(a**<sup><font color="BlueViolet">vector</font></sup>**, b**<sup><font color="BlueViolet">vector</font></sup>**)** | オイラー角を**Quaternion**に変換

- **作例**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1041568/bbbcb899-9eb4-2d31-9176-4b89f8d88010.png)


**dihedral**関数を使って**rotate**を作成し、**intrinsics**の元の**transform**に乗算して設定し直すという作例です。
**qmultiply**関数を使うことで、元の**transform**を考慮して回転できているのがミソですね。

## slerp
**slerp**関数によって、2つのベクトルをミックスした**Quaternion**を計算できます。
個人的に、dihedralと合わせてよく使う気がします。

関数|挙動
---|---
**slerp(q1**<sup><font color="BlueViolet">vector4</font></sup>**, q2**<sup><font color="BlueViolet">vector4</font></sup>**, bias**<sup><font color="Blue">float</font></sup>**)** | オイラー角を**Quaternion**に変換

- **作例**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1041568/057d1d3a-0e0d-49a5-3875-12ed6bdacab9.png)



**dihedral**関数を使って**rotate**を作成し、**slerp**関数でコピーの**transform**を補完するという作例です。
この二つの組み合わせは強い！

## qconvert
**qconvert**関数によって、**Quaternion**を**matrix**や**vector**に変換できます。
これも良く使いますね。

関数|挙動
---|---
**qconvert(quaternion**<sup><font color="BlueViolet">vector4</font></sup>**)** | **Quaternion**を**matrix3**に変換
**qconvert(quaternion**<sup><font color="BlueViolet">vector4</font></sup>**, offset**<sup><font color="BlueViolet">vector</font></sup>**)** | **Quaternion**と移動量**offset**を使って**matrix**を計算


- **作例**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1041568/78d47122-585b-45a9-f3a6-42e27511a1a8.png)




**quaternion**関数を使って**orient**を作成し、offsetをptnumごとに設定して、**qconvert**関数で**matrix**を作るという作例です。

## qinvert
**qinvert**関数によって、**Quaternion**を反転できます。
使いようによっては使えるときもある…

関数|挙動
---|---
**qinvert(quaternion**<sup><font color="BlueViolet">vector4</font></sup>**)** | 反転した**Quaternion**を計算

- **作例**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1041568/31ed71d4-2813-cbdf-aad6-488d024a7c4a.png)

**dihedral**関数を使って**orient**を作成し、それで回転したものと、反転したものを作るという作例です。
黄色がオリジナル、水色がそのまま**orient**、赤色が**invert**って感じですね。

## qmultiply
**qmultiply**関数によって、**Quaternion**同士を乗算できます。
使いようによっては使えるときもある…

関数|挙動
---|---
**qmultiply(q1**<sup><font color="BlueViolet">vector4</font></sup>**, q2**<sup><font color="BlueViolet">vector4</font></sup>**)** | ２つの**Quaternion**を乗算

- **作例**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1041568/53bd630d-1895-5f7d-ffec-71bc9ae61009.png)

**dihedral**関数を使ってアニメーションする**orient**を作成し、それを使ってアニメーションする作例です。
初期状態の**orient**を**qinvert**関数で反転させて、元の**orient**に**qmultiply**で乗算することで、無回転スタートをする方法をとっています。この方法を知っているとけっこう便利…！

## qdistance
**qdistance**関数によって、**Quaternion**同士の角度を計算できます。
使いようによっては使えるときもある…

関数|挙動
---|---
**qdistance(q1**<sup><font color="BlueViolet">vector4</font></sup>**, q2**<sup><font color="BlueViolet">vector4</font></sup>**)** | ２つの**Quaternion**間のおおよその角度をラジアンで返す

- **作例**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1041568/b4cd2ae5-344f-8cf1-b248-10de799cb1d8.png)


**slerp**関数の作例から、**quat**からの回転量を**qdistance**関数で計算して表示してみた作例です。
使いようによってはいろいろできそうですね！

## まとめ
**Quaternion**関数まとめいかがでしたでしょうか。
個人的にはちょっと分かりにくいような気もするので、しっかり勉強したい方はHIPファイルを開いてみてゆっくり中を覗いていただけると理解が深まるかと思います。
あと、ちなみにですが僕の場合は回転計算に**Quaternion**を使わずに**Matrix**を使います。理由としてはファイル中にもありますが何かと使い勝手がいいからです。**Quaternion**に慣れてきたら**Matrix**触ってみるのもいいと思います！