読者です 読者をやめる 読者になる 読者になる

Holographic Academyの解説「Hologram 230- Spatial Mapping」

前回に引き続き、Holographic Academyについてです。

今回は順番を飛ばしますが、Hologram 230 のSpatial Mappingについて整理しました。

これまでの内容は下記にあります。


magicbullet.hatenablog.jp

magicbullet.hatenablog.jp

magicbullet.hatenablog.jp


==========

目次

0 準備

1 Unity Setup

2 Chapter 1 - Scanning

3 Chapter 2 - Visualization

4 Chapter 3 - Processing

5 Chapter 4 - Placement

6 Chapter 5 - Occlusion

Tips

終わりに

==========

0 準備

これまで通り、Windows 10のPCとHoloLensが必要です。
また、Windows 10 PCの中には、Visual Studio Update3とUnity5.5以上がインストールされていることが必要です。

私の場合は、下記の環境で動作確認しました。


・Windows10 Pro on Parallel Desktop 12.1.3
(MacOSX 10.12.3)

Visual Studio Update3 (上記のWindows10 Proで動作)

・Unity5.5.1f1 (上記のWindows10 Proで動作)

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

1 Unity Setup

まずは、「Holograms 230」を開き、下記の files をクリックしてプロジェクトをダウンロードします。

f:id:Takyu:20170215225617j:plain

211のときと異なり、今回はチュートリアル確認用のプロジェクトは、unitypackageの形で提供されています。
(完成版はUnityプロジェクトです)


そのため、Unityで新規プロジェクトを作り、

Downloads\HolographicAcademy-Holograms-230-SpatialMapping\Starting からPlanetarium.unitypackageをインポートします。

f:id:Takyu:20170216095701p:plain

これで始める準備は整いました。


1 Unity Setup

まずは一通りの環境を作ります。

すでに何度か出てきている手順は割愛し、異なる手順だけ説明します。

(1) Capabilitiesの設定

f:id:Takyu:20170216220106j:plain

赤枠の箇所は、AndroidでいうPermissionに相当します。今回の設定対象は、

InternetClientServer
PrivateNetworkClientServer
Microphone
SpatialPerception

です。

このように、Players Settingsの中で設定します。MicrophoneとSpatialPerceptionも同様です。

f:id:Takyu:20170216220206j:plain

また、チュートリアルにも記載がありますが、BuildするときはC# Project にチェックを入れておくことをお勧めします。

(2) Layerの設定

Cursor PrefabをHierarchy ViewにDrag & Dropしたら、Inspector ViewからLayer -> Add Layerを選びます。

f:id:Takyu:20170216220802p:plain

次に、指示に従ってUser Layer 31にSpatial Mapping と入力します。

f:id:Takyu:20170216221101p:plain

ただし、CursorのLayerは変更せずIgnore Raycastのままで良いです。

2 Chapter 1 - Scanning

ここでは、目の前でリアルタイムにメッシュを表示させる、という基本的な機能を解説しています。

以下、チュートリアルの記載に沿って、3つに分けて説明します。

Build and Deploy (part 1)

まず、SpatialMapping PrefabをHierarchy ViewにDrag & Dropします。

f:id:Takyu:20170216221747j:plain

この時点でビルドしてHoloLens実機にアプリを転送すると、以下のようになります。

Build and Deploy (part 2)

2つ目では、UnityのProfiler機能を使ってGPUの負荷を見る方法を説明しています。

Profilerは、UnityのWindow タブから開きます。

f:id:Takyu:20170216222752p:plain


開いたら、Active Profiler -> Enter IPを選択し、HoloLensのIPアドレスを入力します。

f:id:Takyu:20170216223039p:plain

f:id:Takyu:20170216223116p:plain

すると、このようなグラフができます。

f:id:Takyu:20170219150333j:plain


GPUの波形は、HoloLensが静止していれば穏やかですが、HoloLensが動けば(HoloLensを着けて辺りを見回せば)波形が変化します。


次に、Spatial Mapping Observerクラスの TrianglesPerCubicMeterを500から1200に変更してみます。

Cubic単位のTriangleの数を変更、ということで、値を大きくするほどメッシュが細かくなりますが、モデル化するときのデータ量も多くなります。

SpatialMappingObserver.csを開いて、Awake()の先頭に下記を追加してビルドします。


gist5b6ac87c4bb728363469ed1054e40310

HoloLensで見てみると、よりメッシュが細かくなっていることが確認できます。

Save and load in Unity


3つ目の最後は、部屋の空間モデルをHoloLensから取得し、Unity Editorで見る方法を説明しています。

まず、SpatialMappingObserver.csのAwakeに書いた下記は削除します。


gistc23a7b9a17cf7eb703d96fb36ccdc573


この状態で再度ビルドしてHoloLensにDeployします。

アプリを起動後、PCのブラウザからDevice Portalを開きます。

■USB接続の場合

 http://127.0.0.1:10080

Wifi接続の場合

https://<HoloLensのIPアドレス


Portalの3D ViewのSpatial Mappingという項目にあるUpdateをクリックします。

1回クリックすると、空間のCG化が始まります。Portal上では何も変化が見られませんが、

f:id:Takyu:20170219150403j:plain

再度Updateをクリックすると、その間に取得したモデルデータが反映されます。

f:id:Takyu:20170219150413j:plain

次に、Saveをクリックすると、SpatialMapping.objという名前でダウンロードができます。

f:id:Takyu:20170219150430j:plain

次に、SpatialMapping.objを先ほどのUnityのプロジェクトにドラッグします。

続けて、SpatialMapping オブジェクトのObject Surface Observer コンポーネントのRoom Modelにドラッグします。

f:id:Takyu:20170219150442j:plain

Unity Editorで再生すると、モデルを表示させることができます。

ちなみに、WireFrameというshaderではこのように真っ暗ですが、

f:id:Takyu:20170219150453p:plain

ShaderをStandardFastに変えると、見え方が変わります。

f:id:Takyu:20170219150505j:plain


Shaderの設定箇所は下記です。

f:id:Takyu:20170219150516j:plain

3 Chapter 2 - Visualization

ここでは、Shaderの加工によって、壁に相当する箇所だけ異なる表示にすることを説明しています。

方法は簡単で、Spatial Mapping Manager コンポーネントSurface Materialを、BlueLinesOnWallsに変更するだけです。

Editorで見るとこうなります。

f:id:Takyu:20170220003134j:plain

このShaderに設定してからHoloLensにビルドすると、壁が青く見えます。

Chapter4で紹介する動画でBlueLinesOnWalls Shaderを使ってますので、見え方はそちらをご確認ください。


BlueLinesOnWallsのプロパティでは、線の太さと密度を変更できます。

■LineScaleを変更した場合

■LinesPerMeterを変更した場合

4 Chapter 3 - Processing

ここでは、Spatial Mappingで取得したモデルの中から壁と床を認識する処理を説明しています。

今度は、SpatialProcessingと SpaceCollection Prefabを追加します。

また、SpatialProcessingにアタッチされているPlaySpaceManager.csをチュートリアルに記載のコードと差し替え、Unity Editorで実行します。


最初はこのように真っ暗ですが、

f:id:Takyu:20170219234726p:plain


10秒たつと、壁と床を認識した箇所が別のGameObjectに置き換わり、かつプラネタリウムのようなモデルが中心に現れます。

f:id:Takyu:20170219234751p:plain

実機でビルドしても同様です。

5 Chapter 4 - Placement

ここでは、AirTapによって、スキャンした空間の壁に、オブジェクトを配置する処理を説明しています。


SpatialProcessingオブジェクトのSurface Meshes To Planes コンポーネントのInspectorを見ます。

このように、Draw Planeの対象を修正し、Draw PlanesをEverythingからWallのみに変更します。

f:id:Takyu:20170219235737p:plain


なお、Destroy PlanesをUnknownから変更すると、今回のデモが動きませんのでご注意ください。


ここでは、Placeable.csを修正します。チュートリアルに記載の完全版と差し替えます。

なお、Placeable.csはすでにProjecter、RocketPoster、AstronautPosterのPrefabにアタッチされています。


ビルドしてHoloLensで見てみます。

これまでのように10秒たってプラネタリウムが出たら、PosterとProjecterはGazeしてAirTapすることで移動させることができます。


このように、Placeable.csがアタッチされたオブジェクトであれば、AirTap後に自分の視線方向に移動させることができます。

移動開始と終了はAirTapです。

6 Chapter 5 - Occlusion

occludeの元々の意味は、塞ぐ、です。このChapterではHologramオブジェクトがSpatial Mappingのmeshにふさがれてしまう時に、どんな方法で表示させれば良いか、をデモで説明しています。


まず、HoloLensの世界ではオブジェクト同士が重なった時に4つの表現手段があります。

f:id:Takyu:20170218235453j:plain

ここでは、4つの表現手段を確認できるデモを作ります。


まず、SpatialProcessing オブジェクトのPlay Space Manager コンポーネントでSecondary MaterialをOcclusionに変更します。

f:id:Takyu:20170220000551j:plain

次に、Solar System Prefabの中にあるEarthだけ、ShaderをOcculusionRimに変更します。

f:id:Takyu:20170220000812j:plain


さらに、PlanetOcclusion.csを変更します。これは、SolarSystemの子オブジェクトである、それぞれの惑星Prefabにアタッチされています。

Holographic Academy230の該当箇所に完成版のコードがあります。



ビルドしてHoloLensで動作を見てみます。

通常のオブジェクトはそのまま見えます。 (Occlusion)

Earthの場合、他のオブジェクトの裏になると、青いふちだけに見えます。(Rim Shader)


他の惑星オブジェクトの場合、チュートリアルではX-rayと呼ばれる表示になります。 (Grid Shader)


また、惑星を取り巻く隕石は、壁の向こうに移動したり、何かの影になると隠れます。 (Occlusion)

Tips

いくつか気になるところがあったので、備忘録を兼ねて残しておきました。

(1) Unity C#スクリプトは、HoloLens向けdeploy前のVisual Studioからも修正可能


Chapter1のBuild and Deploy (part 2)で出たTrianglesPerCubicMeterは、Spatial Mapping Observerクラスのpublic変数として指定されています。

通常のUnityでのアプリ開発の場合、Inspector Viewから値を変更します。

しかし、Inspector Viewから変更すると、

1. UnityでビルドしてVisual Studioプロジェクトを生成

2, Visual Studio プロジェクトを開いて、HoloLensにDeploy

の2段階の手順が必要になります。

しかし、UnityでVisual Studioプロジェクトを生成する時に、Unity C# Project にチェックを入れておくと、Visual Studioで開いたときのプロジェクトにUhityで作ったソースコードが残ります。

f:id:Takyu:20170216223743p:plain

さらに、ここでUnity C#のコードを修正してHoloLens向けにdeployすると変更が反映されます。

Unityの画面でしかできない処理は対象外ですが、ある程度はこの方法でカバーできるので、ビルドの手間を減らす方法としてお勧めです。

(2) Visual Studioで大量のエラーが出た場合、Nuget Packageの復元で修正できることがある

既存のVisual Studioプロジェクトからソースコードを開くと、自分が何もしていないのに大量のエラーメッセージが出ることがあります。

f:id:Takyu:20170220001603p:plain

この場合、Nuget Packageの復元を実行することで直ります。

f:id:Takyu:20170220001614j:plain

これの原因はまだ調べきれてないですが、以前 Windows 10 Mobile向けのアプリを作ったときや、Microsoft提供のUWPサンプルプロジェクトを開いたときは、ほぼ100%発生しました。


(3) 実空間をSpatial Mappingで計測した結果を使って、オブジェクトを配置する方法

HoloLensアプリで、特定の壁や床から何かが飛び出してくるゲームを作る時は、あらかじめゲームを行う部屋をモデル化し、壁や床の位置を特定することが必要です。

それができれば、例えばこのように、指定した床の位置からクジラを出現させる、ということもできるようになります。

f:id:Takyu:20170220002206j:plain

引用:http://joy-q.com/?d=9954

(これはMagicLeapの提供映像ですが、、)


そこで、今回取得したSpatialMapping.objを使うことで、オブジェクトの配置位置を決められるのかを試して見ました。

まず、Unity上で取得したobjをHierarchy Viewにドラッグします。

objになっている部屋の中に適当なgameobjectを配置します。今回は少し赤く色付けしたCubeを配置しました。

f:id:Takyu:20170220002610p:plain

UWPビルドしてHoloLens実機に転送してみます。

f:id:Takyu:20170218050304j:plain

Cubeの配置位置は、先ほどUnity上で配置した辺りと一致していました。
特定の場所を使ったアプリを作りたい時は、こうやって事前スキャンした部屋モデルをUnityに読み込ませてから配置を検討すれば良さそうです。


ただし、注意点として、この方法を使う時は、アプリ起動時にUnityのCameraオブジェクトの向きとHoloLens実機の向きを一致させておく必要があります。

理由はわかりませんが、CameraとHoloLensの向きが不一致状態でアプリを起動すると、Cubeが見えませんでした。


ちなみに、先ほどObject Surface Observer コンポーネントにドラッグしたSpatialMapping.objは、そのままでビルドしても、HoloLensで見た時は表示されません。

(4) Parallel DesktopではShaderにwarningが出ることがある

Chapter5では、OcculusionというShaderを使いました。これはParallel Desktop上のWindows10ではwarningを表示していました。

f:id:Takyu:20170220001214p:plain

Windows 10 デスクトップPCでは出ませんでした。

f:id:Takyu:20170220001232p:plain

ただし、Warningは出ますが、Parallel Desktopで作ってHoloLensにdeployしても動作は問題ありません。



終わりに

Spatial Mappingは、HoloLensの最も分かりやすい特徴だと思います。実際、今回のデモではかなり色々と分かりました。

ところで、今回、ざっとですがソースコードを見たところ、機能実現に必要なSpatialMappingObserver.csや、SpatialMappingManager.csは、具体的な処理を実行している部分は隠れていて、APIを呼び出すような形になっていました。

とはいえ、できることは色々あるはずなので、機能面ではもう少し調べた方が良いかもしれません。