UE4でVR用のIKを実装してみる話

##はじめに
Unityで言うところのFinalIKを使用したVRIKをUE4で実装してみたので覚書です。
環境は4.17.1。
使用するスケルタルメッシュはAnimationStaterPackに同梱されているGrayマンです。
##目指すもの
<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">ぷちコンで作ったVRIK、グレイマン版作ってみた。<a href="https://t.co/tnJyK8sxPh">https://t.co/tnJyK8sxPh</a></p>&mdash; 暇厨 (@HImaJin_Tw) <a href="https://twitter.com/HImaJin_Tw/status/911695268353007616">2017年9月23日</a></blockquote>
<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>
###準備
・MotionControllerPawn
VROriginの子にGrayマンを追加します。
Rotate Z:-90のオフセットを設定し、Cameraの視線方向と合わせます。
![スクリーンショット 2017-09-24 01.45.15.png](https://qiita-image-store.s3.amazonaws.com/0/139188/9117833d-062f-add1-7dd6-9431ca3c1417.png)

このままではポジトラの恩恵を受けられないので、
カメラの位置を反映するようにします。
Offsetは感覚値で設定しています。
![スクリーンショット 2017-09-24 01.55.17.png](https://qiita-image-store.s3.amazonaws.com/0/139188/1e34f3d1-7093-f74f-c6f2-95dc4636cc25.png)


・Map
自分のポーズを確認する必要があるので、SceneCaptureとレンダリングターゲットを用意します。
レベルにパネルを置きマテリアルとして適応します。
![スクリーンショット 2017-09-24 02.18.03.png](https://qiita-image-store.s3.amazonaws.com/0/139188/c04ba5b7-70cc-19d6-dac4-f3cb9d961ff8.png)


・AnimationBP
IK用に必要なので生成してGrayマンに設定します。

###腕IK
・AnimationBP
L・R用のtransformを変数として用意し、FABRIKに使用します。
FABRIKの設定変更点は以下の通りです。
Effector Transform : World Space
Effector RotationSource : Copy Target Rotation
Tip Bone : hand_"x"
Root Bone : clavicle_"x"
"x"はlかrが入ります。
![スクリーンショット 2017-09-24 02.32.15.png](https://qiita-image-store.s3.amazonaws.com/0/139188/cbcab04d-5ae8-37aa-8dcb-0d39a96b52ca.png)

・MotionControllerPawn
AnimationBPで用意したtransformに両手の値をセットします。
値はBP_MotionController:HandMeshのworldTransformです。
しかし、そのまま値をセットするとズレが生じるのでオフセットを考慮します。
右手と左手で演算が違うので注意してください。
![スクリーンショット 2017-09-24 02.54.03.png](https://qiita-image-store.s3.amazonaws.com/0/139188/bede4538-1f1d-d196-7ccd-75e3408f317f.png)
![スクリーンショット 2017-09-24 02.54.13.png](https://qiita-image-store.s3.amazonaws.com/0/139188/52abfe2f-571a-f38c-0e8b-8253ee5b3dca.png)


BP_MotionController:HandMeshはオフセットの演算補助のために描画していたので、
この設定が終わり次第描画を止めて下さい（Meshは削除しないでください）。

###指IK
手の部分だけBP_MotionController:HandMeshのアニメーションを適応できればいいのですが、やり方がわからないので強引に実装していきます。
BP_MotionController:HandMeshのBone情報を元にIKを行います。

・AnimationBP
Vector3配列を両指分用意し、腕同様FABRIKを使用していきます。
エラー回避のためデフォルト値を用意してください。
FABRIKの設定変更点は以下の通りです。
Effector Transform : World Space
Effector RotationSource : Maintain Local Rotation Relative to Parent
Tip Bone : "finger"_03_"x"
Root Bone : "finger"_01_"x"
"finger"にはindex/middle/pinky/ring/thumbのいずれかが、"x"はlかrが入ります。
![スクリーンショット 2017-09-24 05.12.08.png](https://qiita-image-store.s3.amazonaws.com/0/139188/1c586f5c-7a40-11df-cad2-6f021d2e738f.png)

・MotionControllerPawn
BP_MotionController:HandMeshからBone情報をAnimationBPに渡していきます。
![スクリーンショット 2017-09-24 03.38.49.png](https://qiita-image-store.s3.amazonaws.com/0/139188/a144590b-4078-973d-2636-d0d253f34b96.png)
![スクリーンショット 2017-09-24 03.38.37.png](https://qiita-image-store.s3.amazonaws.com/0/139188/0cdae1f4-569d-5f61-35bf-b775f88aa6d9.png)

###顔と体
残るは顔の向きです。
上下傾きは素直反映できるのですが、横回転はそうは行きません。
顔が回ったのか体が回ったのか判定できないからです。
今回は顔の横回転＝＝体の横回転として実装していきます。

・AnimationBP
これまで同様、頭用のtransformを変数として用意しFABRIKに使用します。
FABRIKの設定変更点は以下の通りです。
Effector Transform : World Space
Effector RotationSource : Copy Target Rotation
Tip Bone : head
Root Bone : neck_01
![スクリーンショット 2017-09-24 03.47.52.png](https://qiita-image-store.s3.amazonaws.com/0/139188/8374a4f2-43f5-3d30-27d7-a14baa21625a.png)

・MotionControllerPawn
オフセットを考慮したTransformをAnimationBPに渡していきます。
前を向くoffset(90,60,0)に傾きと上下回転を加味しています。
横回転はコンポーネントを回転させるため固定値です。
![スクリーンショット 2017-09-24 03.49.18.png](https://qiita-image-store.s3.amazonaws.com/0/139188/dc3d7a18-cabd-1090-f34d-465f093ead42.png)


カメラの横回転をオフセットを考慮して反映させます。
![スクリーンショット 2017-09-24 03.55.41.png](https://qiita-image-store.s3.amazonaws.com/0/139188/cc0f70f5-11ee-9faf-5087-23c6673e1168.png)


##まとめ
Pawn側でオフセット考慮した情報をAnimationBPに渡し、
FABRIKで反映していくとそれっぽくできる。
メッシュ依存する事が多いので共通化が難しい。

##備考
今回のプロジェクトは[ここ](https://github.com/Himatyu/Qiita)にて公開しています。