久しぶりのHoloLens開発の進捗。
今回はSpatialUnderstandingです。
SpatialUnderstandingはクラス名、メソッド名が長くまた公式のサンプル
HoloToolkit-Examples > SpatialUnderstanding > SpatialUnderstanding-FeatureOverviewの
中のコードもかなり多めで解析が困難です。
ですから、まず空間検知と空間内の情報(天井、床、壁)の判定までを行っていきます。
今回は、Unity 5.6.1f1 (64-bit)
HoloToolKit-UnityはGitHubの最新を取得して行いました。
Unityのプロジェクトを作成し、
HoloToolKit-UnityとHoloToolkit-Testsのフォルダーを追加してください。
UnityにHoloToolKitのメニューが表示されますので
Configure > Apply HoloLens Project Settingsを選択
表示されたメニューをそのままApply > YES
プロジェクトの設定が終わったら再びUnityにHoloToolKitのメニューから
Configure > Apply HoloLens Capability Settingsを選択
Spatial PerceptionをチェックしApply
次に、 HierarchyのMain cameraを右クリック
メニューからDelelteで削除します
Project内のHoloToolkit > Input > PrefabのHoloLensCamera
続いてInputManager、
HoloToolkit > Input > Prefab > Cursorの中のCursor
HoloToolkit > SpatialMapping > Preabsの中のSpatialMapping
HoloToolkit > SpatialUnderstanding > Preabsの中のSpatialUnderstandingを
それぞれHierarchyに追加
HierarchyのSpatialMappingを選択し、Inspectorの
Object Surface Obsever Room Modelのプロパティをクリック
MediumRoomWithHomeFurnitureを選択しセット
Spatial Mapping ManagerのDraw Visual Meshesのチェックを外します。
この段階でいったんUnityを実行してみると。
こんな感じて空間検知が実行されメッシュが表示されます。
SpatialMapping同様、空間検知だけならノーコーディングでできてしまいます。
次にHierarchyのCreateから 3DObject > 3D Textを選択し追加
3D TextのInspectorで見やすい位置、設定にしてください。
今回はTransformのpositionをx:0 y:0 z;40
Text MehのAnchorをMiddle Cneter AlignmentをCenter
Font Sizeを30に設定しました。(ここはご自由にお好きな設定にしてください)
つづいて3D TextのInspector Add ComponentでTaglongと
BillboardのScriptを追加します
ProjectのCreateからC# Script、スクリプトの名前を
SpatialUnserstandingTestとします。
SpatialUnserstandingTestの中身はこんな感じ
using UnityEngine;
using HoloToolkit.Unity;
using System;
public class SpatialUnserstandingTest : MonoBehaviour {
public TextMesh textMesh = null;
public float kMinAreaForComplete = 50.0f;
public float kMinHorizAreaForComplete = 25.0f;
public float kMinWallAreaForComplete = 10.0f;
private void LateUpdate()
{
if (DoesScanMeetMinBarForCompletion)
{
SpatialUnderstanding.Instance.RequestFinishScan();
}
Vector3 rayPos = Camera.main.transform.position;
Vector3 rayVec = Camera.main.transform.forward * 10.0f;
IntPtr raycastResultPtr = SpatialUnderstanding.Instance.UnderstandingDLL.GetStaticRaycastResultPtr();
SpatialUnderstandingDll.Imports.PlayspaceRaycast(
rayPos.x,
rayPos.y,
rayPos.z,
rayVec.x,
rayVec.y,
rayVec.z,
raycastResultPtr);
SpatialUnderstandingDll.Imports.RaycastResult rayCastResult = SpatialUnderstanding.Instance.UnderstandingDLL.GetStaticRaycastResult();
textMesh.text = rayCastResult.SurfaceType.ToString();
}
private bool DoesScanMeetMinBarForCompletion
{
get
{
if ((SpatialUnderstanding.Instance.ScanState != SpatialUnderstanding.ScanStates.Scanning) ||
(!SpatialUnderstanding.Instance.AllowSpatialUnderstanding))
{
return false;
}
IntPtr statsPtr = SpatialUnderstanding.Instance.UnderstandingDLL.GetStaticPlayspaceStatsPtr();
if (SpatialUnderstandingDll.Imports.QueryPlayspaceStats(statsPtr) == 0)
{
return false;
}
SpatialUnderstandingDll.Imports.PlayspaceStats stats = SpatialUnderstanding.Instance.UnderstandingDLL.GetStaticPlayspaceStats();
if ((stats.TotalSurfaceArea > kMinAreaForComplete) ||
(stats.HorizSurfaceArea > kMinHorizAreaForComplete) ||
(stats.WallSurfaceArea > kMinWallAreaForComplete))
{
return true;
}
return false;
}
}
}
最後に、HierarchyのCreateからCreate EmptyでからのGameObjectを作成using HoloToolkit.Unity;
using System;
public class SpatialUnserstandingTest : MonoBehaviour {
public TextMesh textMesh = null;
public float kMinAreaForComplete = 50.0f;
public float kMinHorizAreaForComplete = 25.0f;
public float kMinWallAreaForComplete = 10.0f;
private void LateUpdate()
{
if (DoesScanMeetMinBarForCompletion)
{
SpatialUnderstanding.Instance.RequestFinishScan();
}
Vector3 rayPos = Camera.main.transform.position;
Vector3 rayVec = Camera.main.transform.forward * 10.0f;
IntPtr raycastResultPtr = SpatialUnderstanding.Instance.UnderstandingDLL.GetStaticRaycastResultPtr();
SpatialUnderstandingDll.Imports.PlayspaceRaycast(
rayPos.x,
rayPos.y,
rayPos.z,
rayVec.x,
rayVec.y,
rayVec.z,
raycastResultPtr);
SpatialUnderstandingDll.Imports.RaycastResult rayCastResult = SpatialUnderstanding.Instance.UnderstandingDLL.GetStaticRaycastResult();
textMesh.text = rayCastResult.SurfaceType.ToString();
}
private bool DoesScanMeetMinBarForCompletion
{
get
{
if ((SpatialUnderstanding.Instance.ScanState != SpatialUnderstanding.ScanStates.Scanning) ||
(!SpatialUnderstanding.Instance.AllowSpatialUnderstanding))
{
return false;
}
IntPtr statsPtr = SpatialUnderstanding.Instance.UnderstandingDLL.GetStaticPlayspaceStatsPtr();
if (SpatialUnderstandingDll.Imports.QueryPlayspaceStats(statsPtr) == 0)
{
return false;
}
SpatialUnderstandingDll.Imports.PlayspaceStats stats = SpatialUnderstanding.Instance.UnderstandingDLL.GetStaticPlayspaceStats();
if ((stats.TotalSurfaceArea > kMinAreaForComplete) ||
(stats.HorizSurfaceArea > kMinHorizAreaForComplete) ||
(stats.WallSurfaceArea > kMinWallAreaForComplete))
{
return true;
}
return false;
}
}
}
作成したGameObjectのAdd Componentで先ほど作成した
SpatialUnserstandingTestとのスクリプトをアタッチ
SpatialUnserstandingTestのText MeshにNew Textを設定
これでUnityを実行、マウスでぐりぐり視線を動かすとこんな感じで
Testに空間の情報が表示されます。
それでは、SpatialMappingとSpatialUnserstandingとの相違点は何かといことですが
僕の理解では下記の点かとおもいます。(間違っていた場合はご指摘ください。)
*メッシュの形状が異なる
これは一目瞭然なのですが、SpatialMappingは、かなり、
ガタガタなメッシュが表示されるのに対し
SpatialUnserstandingは場所によっては、
とても綺麗なグリッド状のメッシュが表示されます。
*メッシュの構築プロセスが異なる
これは文章で説明するとわかりにくいのですが、SpatialMappingは実行して
時間がたてば行動しなくてもメッシュの情報が構築されていきます。
SpatialUnserstandingは動画で示した通り、実行しただけでは、
少ししかメッシュが表示されず
積極的に視線を動かしていくことでメッシュの情報が構築されていきます。
*SpatialUnserstandingは直接、空間内の情報(天井、壁、床)を判別できる。
SpatialMappingはSurfaceMeshesToPlanes.csのMakePlanesメソッドを実行し
SurfacePlaneオブジェクトを生成しないと空間内の天井、壁、床を判別できませんが
SpatialUnserstandingは視線の先の情報を直接判別することができます。
*空間内で判別できる情報がSpatialUnserstandingの方が多い
SpatialMappingは、SurfacePlane.csにPlaneTypesのenumで定義されている
Wall、Floor、Ceiling、Table、Unknownの5種類しか判別できないのに対し
SpatialUnserstandingは、SpatialUnderstandingDll.csの
内部クラスRaycastResultのSurfaceTypesのenumで定義されている
Invalid、Other、Floor、FloorLike、Platform、Ceiling、WallExternal、WallLikeの8種類です
*SpatialUnserstandingでは定義以外の空間内情報を独自定義することができる
MicrosoftのSpatialUnserstanding公式のサンプルでは
ChairやCouch(ソファーのような長椅子)を独自定義し利用しています。
*SpatialUnserstandingでは空間内にオブジェクトを生成する便利関数が存在する
HoloToolkit > SpatialMapping > Script内に
SpatialUnderstandingDllObjectPlacement.csのスクリプトが用意されていて
Create_OnFloor、Create_OnWall、Create_OnCeilingという、
いかにもオブジェクトの生成を助けるような便利関数が存在しています。
これらを見ていくと、今回おこなった空間検知、空間内の情報の判別を行った後
最後のお便利関数を利用してオブジェクトを配置してくといった
処理の流れになるかと思います。
SpatialUnderstandingは、やはりコードも長く複雑な印象が強く
苦手意識が強くなりますが、今回くらいの内容であれば
意外と怖くないかも?っておもってくれる開発者が多くなるといいなぁと考えています。
SpatialUnderstandingは情報も少なかったので
個人的に参考にした記事のリンクも張っておきます
Indubitable Development
HoloLens Tutorial – Spatial Understanding
HoloLens Tutorial – Spatial Understanding
El Bruno
#Hololens – Spatial Understanding vs Spatial Mapping, and a step-by-step on how to use it
#Hololens – Spatial Understanding vs Spatial Mapping, and a step-by-step on how to use it
Mike Taulty
Hitchhiking the HoloToolkit-Unity, Leg 14–More with Spatial Understanding
https://mtaulty.com/2017/05/03/hitchhiking-the-holotoolkit-unity-leg-14-more-with-spatial-understanding/
Hitchhiking the HoloToolkit-Unity, Leg 14–More with Spatial Understanding
https://mtaulty.com/2017/05/03/hitchhiking-the-holotoolkit-unity-leg-14-more-with-spatial-understanding/