UE4によるOculus Quest ハンドトラッキング 自前対応への道


UE4+OculusQuest ハンドトラッキングを待ちきれない人へ

お断り

UE4でのOculusQuestハンドトラッキングの対応は「in the first half of 2020」とアナウンスされています。
この記事の実装は数カ月後には役立たずになります。
https://developer.oculus.com/blog/hand-tracking-sdk-for-oculus-quest-available/
またUnity向けには既にインテグレートされたSDKが提供されています

それでも… あなたは 本当に… UE4で試したいですか…?

良いでしょう… 私は止めません。前のめりに実装しましょう!

UE4によるOculus Quest ハンドトラッキング 自前対応への道

準備&覚悟

  • SSD空き容量200GBくらい(HDDの場合は作業時間が数倍伸びます)
  • 作業時間1~2日程度の余裕(それなりな個人PC&慣れていれば半日程度で完了します)
  • UE4およびVRへの熱意(長時間のビルド/シェーダコンパイル、意味不明なエラーに耐えられる心)

手順 概要

  • Oculusのgithubからソースをcloneする
  • ↑をビルドし、UE4エディタからc++のプロジェクトを作成する
  • Engine側、プロジェクト側のソースを書き換え、ハンドトラッキングを有効にする
  • 再度UE4エディタに戻り設定、Blueprintを組んでQuestに転送する

手順 具体的に

Oculusのgithubからソースをcloneする

githubアカウントを、EpicGamesアカウントに紐付けする。
https://www.unrealengine.com/ja/ue4-on-github

以下をcloneする。(404ページが出る場合は、上記の紐付けを確認ください)
https://github.com/Oculus-VR/UnrealEngine/tree/4.24

ビルドする

cloneしたパスより、以下の手順で操作する。
※UnityのMobile作業環境と競合することがあるらしいのでご注意ください。(自分は該当しないので伝聞です)

  • UnrealEngine/Setup.bat を実行する
  • UnrealEngine/Engine/Extras/AndroidWorks/Win64/CodeWorksforAndroid-1R7u1-windows.exeをインストールする。設定はデフォルトでOK
  • UnrealEngine/GenerateProjectFiles.bat を実行する。UnrealEngine/UE4.sln が生成される。
  • 上記slnをVisualStudio(私はVS2017を利用)で開いて、そのままF5キーを押してビルドを開始する。そのまま数時間放置。

ビルドに数時間、その後シェーダコンパイルに数十分、そしてエディタ起動画面が表示される。

タイトルバーが青いエディタが起動すればOK!

そのエディタで任意のプロジェクトを作成(ここではVirtualRealityを選択)する。
起動後にC++クラスを追加して任意の名前(ここではMyActor)を付けて保存。ビルドが完了するのを待つ

C++プロジェクト設定を追加

ソースを書き換え、ハンドトラッキングを有効にする

日本語のコメント部分は削除してください。。

エンジン側
マニフェストファイルの変更は プロジェクト側でも必要です。後述します。
また、謝辞に貼ったリンク先にも解説があるので 気になる方はそちらも参照ください。

UnrealEngine/Engine/Plugins/Runtime/Oculus/OculusVR/Source/OculusHMD/OculusMobile_APL.xml

<if condition="bOculus6Dof">
  <true>
    <addFeature android:name="android.hardware.vr.headtracking" android:version="1" android:required="$B(bNotOculus3Dof)" />
>> ここを追加    <addFeature android:name="oculus.software.handtracking" android:required="false" />
  </true>
</if>

プロジェクト側ビルド設定(プロジェクト名はoc_handとしています)
OVRPluginの関数を直接呼び出せるようにします。

UnrealProjects/oc_hand/Source/oc_hand/oc_hand.Build.cs
PublicDependencyModuleNames.AddRange(new string[] {
    "Core", "CoreUObject", "Engine", "InputCore",
>>これ    "OVRPlugin",
>>これ    "OculusHMD",
});

プロジェクト側ハンドトラッキング呼び出し(MyActorに実装)
大変シンプルなので、ヘッダを眺めればだいたい使い方が予想できます。

MyActor.cpp
#include "OVR_Plugin.h"

void AMyActor::Tick(float DeltaTime)
{
  Super::Tick(DeltaTime);

  // ハンドトラッキングが有効か調べる
  {
    ovrpBool handTrackingEnabled = false;
    auto res = ovrp_GetHandTrackingEnabled(&handTrackingEnabled);
  }

  // 左手のスケルトン情報を得る
  // おそらくこれは固定値。後述の回転角度を適用して初めて手指のトラッキング結果となる。
  ovrpSkeleton skeleton;
  ovrp_GetSkeleton(ovrpSkeletonType_HandLeft, &skeleton);

  // 左手のトラッキング情報を得る
  ovrpHandState handState;
  auto res = ovrp_GetHandState(ovrpStep_Render, ovrpHand_Left, &handState);

  // handState.RootPose にてSkeletonの原点(手首付近)の姿勢が取得できる
  // handState.BoneRotations[boneID] にて手指の各関節の回転角度が取得できる
  // これらをskeletonに沿って姿勢適用すればOK

  // 座標系の変換には、
  // OculusHMD::ToFQuat や OculusHMD::ToFVector を利用できる
  // 最後にBlueprint側でskeletonをx100スケールすればUE4の座標と一致する

  // 追記ぶん skeleton計算
  ovrpHandState handState;
  auto res = ovrp_GetHandState(ovrpStep_Render, ovrpHand_Left, &handState);

  TArray<FTransform> leftTrans;
  ovrpSkeleton skeleton;
  if (ovrp_GetSkeleton(ovrpSkeletonType_HandLeft, &skeleton) == 0) {
    leftTrans.SetNum(skeleton.NumBones);
    for (uint32_t i = 0; i < skeleton.NumBones; ++i) {
      int boneID = skeleton.Bones[i].BoneId;

      auto aa = OculusHMD::ToFQuat(handState.BoneRotations[boneID]);
      auto q = aa;
      auto p = OculusHMD::ToFVector(skeleton.Bones[i].Pose.Position);

      auto t = FTransform(q, p);
      int tmp = skeleton.Bones[i].ParentBoneIndex;
      if (tmp >= 0) {
        t = t * leftTrans[tmp];
      } else {
        auto qq = OculusHMD::ToFQuat(handState.RootPose.Orientation);
        auto pp = OculusHMD::ToFVector(handState.RootPose.Position);

        t = t * FTransform(qq, pp);
      }

      leftTrans[i] = t;
    }
  }

UE4エディタから設定、Blueprintを組んでQuestに転送する

一般的なOculusQuest用の設定をする。以下のリンク参照。
https://developer.oculus.com/documentation/quest/latest/concepts/unreal-quick-start-guide-quest/

上記に加えて、マニフェストファイルにoculus.permission.handtracking を追加する。

マニフェストファイルに追記

MyActorをBlueprintで継承したMyActorBPを作成、デバッグにprintfやメッシュ配置用のノードを組んでレベルへ配置

配置します
転送します

完了です。

まとめ

OculusのリポジトリにあるUE4ソースに追記することで、一足早くハンドトラッキングを実装できました。
UnrealC++に慣れている方であれば簡単かもしれません。ややこしいのは指の姿勢反映あたりでしょうか。

解説はスキップしましたが、Pinch操作(親指と他の指をくっつける操作)や、現在のトラッキング精度パラメータなども取得できます。
是非ドキュメントを読んだり、ヘッダを眺めて利用してみましょう!

今後のハンドトラッキングの公式対応には、以下のような工程があると思われます。
少なくとも数ヶ月の間はOculusリポジトリを利用することになるでしょう。

ハンドトラッキング公式対応までの工程(予想) 補足 対応状況(気がついたら追記)
OculusリポジトリでSDKが更新される 自前実装が必要 2019/12/26:UE4.24.1
2020/02/11:UE4.24.2。PCからハンドトラッキング利用できるようになった
OculusリポジトリでハンドトラッキングがBlueprintに対応 自前実装は不要
EpicリポジトリのVRブランチにマージ 開発ブランチのため不安定
リリースブランチにマージ previewとしてリリース UE4.25やUE4.26に合わせるならpreviewへ。UE4.25.1などで対応する場合はそのまま本番へ
リリース 本番リリース

勝手に謝辞

Unityでハンドトラッキングをしている人達が羨ましく悶々としていたところ、
こちらのマニフェストの記述を見てUE4側の対応を思い立ちました。ありがとうございました。上手く動作しました。
https://qiita.com/shiena/items/0b7735a80e7d4358e5fb#%E3%83%8F%E3%83%B3%E3%83%89%E3%83%88%E3%83%A9%E3%83%83%E3%82%AD%E3%83%B3%E3%82%B0%E8%A8%AD%E5%AE%9A