CrossRoad

XRを中心とした技術ブログ。 Check also "English" category.

Holographic Academyの解説とTips紹介「Hologram 210 - Gaze」

前回に引き続き、Holographic Academyについてです。前回の「Hologram 101」は、HoloLensの基本機能を網羅したシンプルな例でした。

2XX以降は、それぞれの機能について発展的な使い方を紹介しています。今回はGaze(見つめる)についてです。

0. 準備

Holograms 210」を開き、プロジェクトをダウンロードします。

Hologram101」が未完の場合、先にChapter2のGazeだけでも確認することをお勧めします。

こちらもご参考ください。

Holographic Academyの解説とTips紹介「Hologram 101」 - CrossRoad

1. Chapter 1 - Unity Setup

Unity settings for HoloLens

101のときとは異なり、ダウンロードしたチュートリアル用のデータはunitypackageで格納されています。そこで、まずは自分でUnityの新規プロジェクトを作り、名称をModelExplorerとします。この後のビルド用にUnityの基本設定をします。

Import art assets

ModelExplorerを開いたら、ModelExplorer.unitypackageをインポートします。

Setup the scene

  • Main CameraをHoloToolkitフォルダのprefabと差し替え
  • 指定モデルを並べる

などを実行します。

Build the project

これまでの手順と同じようにビルドします。ただし、なぜか今回はVisual Studioを開いたときにmanifestファイルでTargetDeviceFamilyをWindowsHolographicにしています。

これをWindows.Universalのままにしてもビルドはできました。Manifestファイルをxml形式で開くには、manifestファイルを右クリックして出てきた画面で「View Code」をクリックします。

「View」をクリックすれば選択式のmanifestが開きます。

Visual Studioプロジェクトでmanifestファイルを開く手順

ちなみに、日本でHoloLensの情報を多数提供されている@yuujiさんのブログによると、Windows Store申請の時に指定されているようです。

http://2vr.jp/2017/01/30/submitting-an-app-to-the-windows-store/#WindowsHolographic

なお、今回から Fitbox というオブジェクトを追加しています。これにより、HoloLens実機でアプリ起動すると、いわゆるスプラッシュスクリーンが表示されます。この画面が出ている時にAirTapを実行すると、アプリのメイン画面が表示されます。

ちなみに、今回のAstroman(宇宙飛行士)は、FitBoxが表示されている方向に出現します。

2. Chapter 2 - Cursor and target feedback

ここからは、Gaze Cursorに関する詳細機能を解説しています。まず、この章冒頭の説明によると、Cursorの表示ルールは下記のようになっています。

  • 1. 常に表示される
  • 2. 大きすぎず、小さすぎないようにする
  • 3. 他のコンテンツの妨げにならない

手順の概要です。ここでは、まずManagersという空のGameObjectを作り、そこにGazeManager.csを追加します。GazeManager.csは、HoloToolkit\Input\Prefabs フォルダの中にあります。ただし、ここのGazeManager.csは虫食いになっていて、いくつかの箇所を自分で考えて記述するようになっています。

「問題」には"2.a"と"3.a"あります。これはchapterのことです。ダウンロードしたサンプルプロジェクトには完成版のソースコードがあります。参考のため、下記に貼りました。

(長いのでこのブログには掲載していません。下記のリンクよりご確認ください)
giste17fc1687d5006f282e4ee65c0d12dc8

また、GazeManager.csはSingletonで構成されています。8行目の

 public class GazeManager : Singleton<GazeManager>

のように、Singletonを付加してGenericで宣言することで、別のクラスで、GazeManager.InstanceのようにしてPublic変数やメソッドを使うことができます。

こちらを参照させていただきました。

■ジェネリッククラスを使うSingletonの実装方法
C# でジェネリックスを使用したシングルトンパターンを実装する - チラシの裏でプログラミング

■Instance変数を使う例
Unity C# シングルトンパターンの実装 - Qiita

この内容は実質的にUnityの標準機能で構成されており、Hologram101のChapter2 Gazeで使われていたWorldCursor.csと大体同じなので、説明を省略します。

GazeManagerコンポーネントのRayCast Layer Maskからは、TransparentFXのチェックを外します。下記のようになります。

GazeManagerコンポーネントのRayCast Layer Mask設定例

次に、HoloToolkit\Input\Prefabsにある、Cursorオブジェクトを配置します。Cursorオブジェクトには、CursorManager.csを追加します。ここも虫食いになっています。完成版のコードは下記です。

(長いのでこのブログには掲載していません。下記のリンクよりご確認ください)
gist19ebea20cafa1c0e94a3d06ea94de766

ここもUnityのRaycastで処理が進んでいます。41行目では、先ほどのSingletonによりGazeManager.Instanceとして、GazaManagerクラスの変数Hitを取得しています。

この後は、Gazeカーソルが何かオブジェクトに当たった時用のカーソルオブジェクト(CursorOnHolograms)を表示し、何も当たっていない時のカーソルオブジェクト(CursorOffHolograms)を非表示しています。

CursorManagerコンポーネントには、このように子オブジェクトを対応させます。

CursorManagerコンポーネントに対応させる子オブジェクトの関係

この時点でビルドすると、このようになります。

続けて、以下に対応します。

  • ManagersオブジェクトにInteractibleManager.csを追加
  • AstroManオブジェクトにInteractible.csを追加

InteractibleManager.csは、FocusしたGameObjectに対してSendMessageを発行し、OnGazeEnteredを実行させています。また、Focusが外れたら同じくSendMessageを発行し、OnGazeExitを実行させています。


gist20315e3c112ba8ef55aa73cfc0cf4893

20から57行目のifの使い分けが少しややこしいですが、ここをうまく作ることで実現しています。Interactible.csでは、Focusが当たった時にOnGazeEnteredメソッドが呼ばれ、Focusが外れた時にOnGazeExitメソッドが呼ばれます。

それぞれのメソッドで書かれているMaterialのsetFloatを調整することで、フォーカスしたオブジェクトを少し光らせる、つまりハイライト表示を実現しています。

このようになります。


3. Chapter 3 - Targeting Techniques

ここはGazeカーソルをより安定して頭部の動きに追随させるための調整機能について紹介しています。作業としては、GazeStabilizer.csをGazeManagerオブジェクトに追加し、GazeStabilizerコンポーネントを使うための修正を追記するだけです。

Chapter2でGazeManager.csのソースコードを紹介した時にすでに書いてあるので、きになる方はソースコード中のコメントの3.aと書かれた記述を参照ください。

GazeStabilizerの調整項目は色々あります。

GazeStabilizerの調整項目の例
今のところカーソル調整を急いでやる必要性がないので今回は検証をパスしますが、そのうち試してみようと思います。

4. Chapter 4 - Directional indicator

これは、見てほしい方向を常に矢印で示す機能です。具体的には、今回のサンプルプロジェクトについているAstroman(宇宙飛行士)オブジェクトの中にDirectional Indicatorという空のオブジェクトがあります。

ここにDirectional Indicatorスクリプトを追加します。

(長いのでこのブログには掲載していません。下記のリンクよりご確認ください)
gistba3143160ed257f17316a99b8f2f2084

まず、矢印の色は19行目で簡単に変更できます。Update関数の98行目では、camToObjectDirectionによって、自分(gameobject=Astroman)とCamera(HoloLens被っている人)の方向を算出し、次の行でNormalize(単位ベクトル化)しています。

あとは、109行目のGetDirectionIndicatorPositionAndRotationで、最終的にUnity標準のLookRotationを呼ぶことで矢印の向きを調整します。

その後、このようにオブジェクトを追加します。

Direction Indicatorへのオブジェクト追加画面
ちょっと注意が必要なのが、Inspector上でDrag & DropするDirectional Indicatorがなぜか二つあることです。

Directional Indicatorが2つある例

AstroManの子であるDirectional IndicatorのInspectorは、このように何もありません。

Directional IndicatorのInspector

一方、単体でPrefabになっているDirectional Indicatorは、このようにMesh情報を持っているので区別は可能です。
PrefabになっているDirectional Indicatorの例

今回Astromanに追加するのは後者の方です。実装すると、このようになります。青い矢印(実際は三次元的な円錐形)が、Astromanの中心を指しています。


5. Chapter 5 - Billboarding

これは、常に自分の正面にオブジェクトを向かせる機能です。やることはシンプルで、事前に準備されているBillBoard.csをAstromanにくっつけるだけです。

BillBoard.csをくっつけたオブジェクトは、常に自分の目の前に配置されます。

(長いのでこのブログには掲載していません。下記のリンクよりご確認ください)
gist657c769b3ae2af66fef0c1fa64ea09d2

実装方法はとてもわかりやすく、46行目の

Vector3 directionToTarget = Camera.main.transform.position - gameObject.transform.position;

で、CameraとBillBoard間のベクトルを取得し、

66行目にある、FixedUpdate()内部にある

gameObject.transform.rotation = Quaternion.LookRotation(-directionToTarget) * DefaultRotation;

によって、LookRotationで常にカメラ方向を向くようにしています。DefaultRotationについては、Awakeで初期位置を取得しています。

このようになります。

この動画だとわかりづらいですが、これまで静止していたAstromanがHoloLensのカメラの向きに応じて、向きを変えています。

このままChapter6を実施する場合は、BillBoardは使わないので削除します。

6. Chapter 6 - Tag-Along

最後の機能は、自分で指定したオブジェクトが常時一定範囲内についてくるものです。まず最初に、ManagersオブジェクトにGesture Manager.csを追加します。

ManagersオブジェクトにGesture Manager.csを追加する例

次に、Hierarchy ViewでChestButton_Centerを表示します。この言葉を検索すればすぐ出てきます。

ChestButton_Centerを検索して表示させた例
このオブジェクトに、Assets/Scripts以下のInteractibleAction.csを追加します。完成版は下記です。

(長いのでこのブログには掲載していません。下記のリンクよりご確認ください)
gistbe76818631aa133e7810764717b4736a

ここでは、39行目でSimpleTagAlongというコンポーネントを呼んでいます。SimpleTagAlongは、TagAlongの基本機能を提供しています。

例えば、SimpleTagAlong.csの12行目にあるEnforceDiscanceに設定した値によって、HoloLensとの距離が一定になります。一定にする距離を初期値の2.0f(=2m)にしているため、近づくと離れていき、遠ざかると近づいてきます。

次に、ChestButton_Centerに付けたTagalong のPrefabを追加します。これはHologramsフォルダの中にあります。

InteractibleAction コンポーネントにTagalong のPrefabを追加する例
実行してみます。

このように、Chest部分をAirTapすると、なんだかかっこいいホログラム(TagAlongオブジェクト)が出てきます。撮影の都合上あまり動き回れていませんが、自分が動き回ると、TagAlong オブジェクトが付いてきます。また、距離を一定に保とうとするので、TagAlongオブジェクトに近づくと遠ざかります。

7. 終わりに

今回は「Gaze」という観点でのチュートリアルでしたが、どの機能も重要で、一度は試してみるべきだと思いました。また、今回からHoloTool kitが出て来ましたが、基本的にはUnity標準機能で実装されているので、Unityに慣れていると理解がしやすいです。

もちろん、HoloTool kitを使えば既にできるものも多いですが、機能を絞ったスクリプトを読み解くと結果的に理解が早まるので、ちょっと遠回りなのは承知の上で、引き続きHolographic Academyの勉強を続けていこうと思います。