Unity の空間マッピング

空間マッピングを使用すると、デバイスの周囲の世界の表面を表す三角形HoloLensできます。 配置、オクルージョン、部屋の分析にサーフェス データを使用して、Unity プロジェクトに余分な量の水気を与えるのに使用できます。

Unity には、次の方法で開発者に公開される空間マッピングの完全なサポートが含まれています。

  1. MixedRealityToolkit で使用できる空間マッピング コンポーネント。空間マッピングを開始する際に便利で迅速なパスを提供します
  2. 完全な制御を提供し、より高度なアプリケーション固有のカスタマイズを可能にする下位レベルの空間マッピング API

アプリで空間マッピングを使用するには、SpatialPerception 機能を AppxManifest で設定する必要があります。

デバイス サポート

機能 HoloLens (第 1 世代) HoloLens 2 イマーシブ ヘッドセット
空間マッピング ✔️ ✔️

SpatialPerception 機能の設定

アプリで空間マッピング データを使用するには、SpatialPerception 機能を有効にする必要があります。

SpatialPerception 機能を有効にする方法:

  1. Unity エディターで、[Player設定] ウィンドウを開きます ([Edit > Project 設定 > Player]
  2. [ストア]タブWindows選択 します
  3. [Publishing 設定] を展開し、[機能] ボックスの一覧で [SpatialPerception] 機能 を確認 します

注意

Unity プロジェクトを Visual Studio ソリューションに既にエクスポートしている場合は、新しいフォルダーにエクスポートするか、または Visual Studio の AppxManifest でこの機能を手動で設定する必要があります

空間マッピングには、少なくとも 10.0.10586.0 の MaxVersionTested も必要です。

  1. このVisual Studioで、アプリの [Package.appxmanifest] を右クリックしソリューション エクスプローラーコードの表示]を選択します。
  2. TargetDeviceFamily を指定する行を見つけ 、MaxVersionTested="10.0.10240.0"MaxVersionTested="10.0.10586.0" に変更します
  3. Package.appxmanifest を保存します。

Unity でマッピングを追加する方法

空間認識システム

MRTK では、空間認識の開始ガイドを参照して、さまざまな空間メッシュ オブザーバーを設定する方法について確認します。

デバイス上のオブザーバーの詳細については、デバイスのメッシュ オブザーバー の構成に関するガイドを参照 してください。

オブザーバーを理解するシーンの詳細については、シーン理解オブザー バー ガイドを参照 してください。

上位レベルのメッシュ分析: Spatial Understanding

注意事項

Spatial Understanding は、Scene Understanding を使用して 非推奨とされました

MixedRealityToolkitは、Unity のホログラフィック API 上に構築されたホログラフィック開発用のユーティリティ コードのコレクションです。

Spatial Understanding

ホログラムを物理世界に配置する場合は、多くの場合、空間マッピングのメッシュと表面面を超えた方が望ましい場合があります。 配置を手続き的に行う場合は、より高いレベルの環境理解が望ましいです。 通常、これには、床、床、壁に関する決定が必要です。 また、ホログラフィック オブジェクトに最適な物理的な場所を決定するために、配置制約のセットに対して最適化することもできます。

Asobo スタジオは、Young Conker と Fragments の開発中に、ルーム ソルバーを開発することでこの問題に直面しました。 これらの各ゲームにはゲーム固有のニーズがありますが、コア空間理解テクノロジを共有しました。 HoloToolkit.SpatialUnderstanding ライブラリには、このテクノロジがカプセル化されています。これにより、壁に空のスペースをすばやく見つけ、オブジェクトを壁に配置し、文字を配置して識別し、その他の空間理解クエリのミリアドを識別できます。

すべてのソース コードが含まれているため、ニーズに合わせてカスタマイズし、改善点をコミュニティと共有することができます。 C++ ソルバーのコードは UWP dll にラップされ、MixedRealityToolkit 内に含まれるプレハブのドロップを使用して Unity に公開されています。

モジュールについて

モジュールによって公開される主なインターフェイスは 3 つがあります。単純な表面クエリと空間クエリのトポロジ、物体検出の形状、オブジェクト セットの制約ベースの配置のためのオブジェクト配置ソルバーです。 以下で、これらのそれぞれについて説明します。 3 つの主要なモジュール インターフェイスに加えて、レイ キャスト インターフェイスを使用してタグ付けされたサーフェスの種類を取得し、カスタムの watertight プレイスペース メッシュをコピーできます。

レイ キャスト

部屋のスキャンが完了すると、床、壁、壁など、表面に対してラベルが内部的に生成されます。 関数は光線を受け取り、光線が既知の表面と衝突した場合は を返し、その場合は の形式でその表面に関する PlayspaceRaycast 情報を返します RaycastResult

struct RaycastResult
{
    enum SurfaceTypes
    {
        Invalid,    // No intersection
        Other,
        Floor,
        FloorLike,  // Not part of the floor topology,
                    //  but close to the floor and looks like the floor
        Platform,   // Horizontal platform between the ground and
                    //  the ceiling
        Ceiling,
        WallExternal,
        WallLike,   // Not part of the external wall surface,
                    //  but vertical surface that looks like a
                    //  wall structure
    };
    SurfaceTypes SurfaceType;
    float SurfaceArea;  // Zero if unknown
                        //  (i.e. if not part of the topology analysis)
    DirectX::XMFLOAT3 IntersectPoint;
    DirectX::XMFLOAT3 IntersectNormal;
};

内部的には、レイキャストは、プレイスペースの計算された 8 cm キューブ ボクセル表現に対して計算されます。 各ボクセルには、処理されたトポロジ データ (サーペル) を含むサーフェス要素のセットが含まれています。 交差するボクセル セル内に含まれるサーペルが比較され、トポロジ情報の検索に最適な一致が使用されます。 このトポロジ データには、"SurfaceTypes" 列挙型の形式で返されるラベル付けと、交差するサーフェスの表面領域が含まれる。

Unity サンプルでは、カーソルによって各フレームに光線がキャストされます。 まず、Unity のコライダーに対して。 2 つ目は、理解モジュールのワールド表現に対してです。 最後に、もう一度 UI 要素。 このアプリケーションでは、UI が優先度を取得し、次に理解結果を取得し、最後に Unity のコライダーを取得します。 SurfaceType は、カーソルの横にテキストとして報告されます。

Surface の種類はカーソルの横にラベル付けされます
Surface の種類はカーソルの横にラベル付けされます

トポロジ クエリ

DLL 内では、トポロジ マネージャーが環境のラベル付けを処理します。 前述のように、データの多くがボクセル ボリューム内に含まれるサーセル内に格納されます。 さらに、"PlaySpaceInfos" 構造体は、ワールドアラインメント (以下の詳細)、床、および高さなど、プレイスペースに関する情報を格納するために使用されます。 ヒューリスティックは、床、壁、壁を決定するために使用されます。 たとえば、表面積が 1 m2 を超える最大および最低の水平サーフェスは、床と見なされます。

注意

スキャン プロセス中のカメラ パスも、このプロセスで使用されます。

トポロジ マネージャーによって公開されるクエリのサブセットは、dll を介して公開されます。 公開されているトポロジ クエリは次のとおりです。

QueryTopology_FindPositionsOnWalls
QueryTopology_FindLargePositionsOnWalls
QueryTopology_FindLargestWall
QueryTopology_FindPositionsOnFloor
QueryTopology_FindLargestPositionsOnFloor
QueryTopology_FindPositionsSittable

各クエリには、クエリの種類に固有のパラメーターのセットがあります。 次の例では、ユーザーは、目的のボリュームの最小の高さ & 幅、床の上の最小配置の高さ、およびボリュームの前の最小のすき込み量を指定します。 すべての測定値はメートル単位です。

EXTERN_C __declspec(dllexport) int QueryTopology_FindPositionsOnWalls(
    _In_ float minHeightOfWallSpace,
    _In_ float minWidthOfWallSpace,
    _In_ float minHeightAboveFloor,
    _In_ float minFacingClearance,
    _In_ int locationCount,
    _Inout_ Dll_Interface::TopologyResult* locationData)

これらの各クエリは、事前に割り当てられた "TopologyResult" 構造体の配列を受け取っています。 "locationCount" パラメーターは、渡された配列の長さを指定します。 戻り値は、返された場所の数を報告します。 この数値は、渡された "locationCount" パラメーターより大きくすることはできません。

"TopologyResult" には、返されたボリュームの中心位置、向き方向 (通常)、検出された空間の寸法が含まれる。

struct TopologyResult
{
    DirectX::XMFLOAT3 position;
    DirectX::XMFLOAT3 normal;
    float width;
    float length;
};

注意

Unity サンプルでは、これらの各クエリが仮想 UI パネルのボタンにリンクされています。 サンプルでは、これらの各クエリのパラメーターを妥当な値にハード コードします。 その他の例については、サンプル コードの SpaceVisualizer.cs を参照してください。

クエリの整形

dll では、シェイプ アナライザー ("ShapeAnalyzer_W") は、トポロジ アナライザーを使用して、ユーザーによって定義されたカスタム図形と一致します。 Unity サンプルでは、一連の図形を定義し、アプリ内クエリ メニューの [図形] タブ内で結果を公開します。その目的は、ユーザーが独自のオブジェクト シェイプ クエリを定義し、アプリケーションの必要に応じてそれらのクエリを利用できるという意図です。

図形分析は、水平サーフェスでのみ機能します。 たとえば、テーブルは、フラットシート サーフェスと、シート バックのフラットな上部によって定義されます。 シェイプ クエリは、特定のサイズ、高さ、および縦横比の 2 つのサーフェスを検索し、2 つのサーフェスをアラインして接続します。 API の用語を使用すると、シートシートとバック トップはシェイプ コンポーネントであり、配置要件はシェイプ コンポーネントの制約です。

"sittable" オブジェクトの Unity サンプル (ShapeDefinition.cs) で定義されているクエリの例を次に示します。

shapeComponents = new List<ShapeComponent>()
{
    new ShapeComponent(
        new List<ShapeComponentConstraint>()
        {
            ShapeComponentConstraint.Create_SurfaceHeight_Between(0.2f, 0.6f),
            ShapeComponentConstraint.Create_SurfaceCount_Min(1),
            ShapeComponentConstraint.Create_SurfaceArea_Min(0.035f),
        }
    ),
};
AddShape("Sittable", shapeComponents);

各図形クエリは、一連の図形コンポーネントによって定義されます。各図形コンポーネントには、コンポーネント制約のセットと、コンポーネント間の依存関係を一覧化する一連の図形制約があります。 この例には、1 つのコンポーネント定義に 3 つの制約が含まれています。また、コンポーネント間のシェイプ制約はありません (コンポーネントは 1 つのみである)。

これに対し、テーブルの図形には 2 つの図形コンポーネントと 4 つの図形の制約があります。 コンポーネントは、ユーザーのコンポーネント 一覧 (この例では 0 と 1) のインデックスによって識別されます。

shapeConstraints = new List<ShapeConstraint>()
{
    ShapeConstraint.Create_RectanglesSameLength(0, 1, 0.6f),
    ShapeConstraint.Create_RectanglesParallel(0, 1),
    ShapeConstraint.Create_RectanglesAligned(0, 1, 0.3f),
    ShapeConstraint.Create_AtBackOf(1, 0),
};

ラッパー関数は、カスタムシェイプ定義を簡単に作成できる Unity モジュールで提供されています。 コンポーネントとシェイプの制約の完全な一覧は、"ShapeComponentConstraint" 構造体と "ShapeConstraint" 構造体内の "SpatialUnderstandingDll.cs" で確認できます。

この表面に四角形の図形が見つかる
この表面に四角形の図形が見つかる

オブジェクト配置ソルバー

オブジェクト配置ソルバーを使用して、オブジェクトを配置する物理的な部屋内の理想的な位置を識別できます。 ソルバーは、オブジェクトのルールと制約を指定して最適な場所を見つけます。 また、オブジェクトクエリは、オブジェクトが "Solver_RemoveObject" または "Solver_RemoveAllObjects" の呼び出しで削除されるまで保持され、制約された複数オブジェクトの配置が可能になります。 オブジェクト配置クエリは、3つの部分で構成されます。パラメーターを持つ配置の種類、規則の一覧、および制約の一覧です。 クエリを実行するには、次の API を使用します。

public static int Solver_PlaceObject(
            [In] string objectName,
            [In] IntPtr placementDefinition,        // ObjectPlacementDefinition
            [In] int placementRuleCount,
            [In] IntPtr placementRules,             // ObjectPlacementRule
            [In] int constraintCount,
            [In] IntPtr placementConstraints,       // ObjectPlacementConstraint
            [Out] IntPtr placementResult)

この関数は、オブジェクト名、配置定義、および規則と制約の一覧を受け取ります。 C# ラッパーは、規則と制約の構築を簡単にするための構築ヘルパー関数を提供します。 配置定義には、次のいずれかのクエリの種類が含まれます。

public enum PlacementType
{
    Place_OnFloor,
    Place_OnWall,
    Place_OnCeiling,
    Place_OnShape,
    Place_OnEdge,
    Place_OnFloorAndCeiling,
    Place_RandomInAir,
    Place_InMidAir,
    Place_UnderFurnitureEdge,
};

各配置型には、型に固有のパラメーターのセットがあります。 "ObjectPlacementDefinition" 構造体には、これらの定義を作成するための静的ヘルパー関数のセットが含まれています。 たとえば、床にオブジェクトを配置する場所を見つけるには、次の関数を使用します。 public static Objectplacement Ementdefinition Create_OnFloor (Vector3 半 Dims) 配置の種類に加えて、一連のルールと制約を指定することができます。 規則に違反することはありません。 型とルールを満たす配置場所は、最適な配置場所を選択するために、一連の制約に対して最適化されます。 各ルールと制約は、指定された静的作成関数によって作成できます。 ルールと制約の構築関数の例を以下に示します。

public static ObjectPlacementRule Create_AwayFromPosition(
    Vector3 position, float minDistance)
public static ObjectPlacementConstraint Create_NearPoint(
    Vector3 position, float minDistance = 0.0f, float maxDistance = 0.0f)

次のオブジェクト配置クエリは、表面の端に半分のメーターキューブを配置する場所を探しています。これは、以前に配置された他のオブジェクトから、部屋の中心付近に向かっています。

List<ObjectPlacementRule> rules =
    new List<ObjectPlacementRule>() {
        ObjectPlacementRule.Create_AwayFromOtherObjects(1.0f),
    };

List<ObjectPlacementConstraint> constraints =
    new List<ObjectPlacementConstraint> {
        ObjectPlacementConstraint.Create_NearCenter(),
    };

Solver_PlaceObject(
    “MyCustomObject”,
    new ObjectPlacementDefinition.Create_OnEdge(
        new Vector3(0.25f, 0.25f, 0.25f),
        new Vector3(0.25f, 0.25f, 0.25f)),
    rules.Count,
    UnderstandingDLL.PinObject(rules.ToArray()),
    constraints.Count,
    UnderstandingDLL.PinObject(constraints.ToArray()),
    UnderstandingDLL.GetStaticObjectPlacementResultPtr());

成功した場合は、配置位置、次元、および向きを含む "Objectplacement Ementresult" 構造体が返されます。 また、配置は、配置されたオブジェクトの dll の内部リストに追加されます。 後続の配置クエリでは、このオブジェクトが考慮されます。 Unity サンプルの "LevelSolver .cs" ファイルには、クエリの例が多数含まれています。

オブジェクトの配置の結果
図 3: 青色のボックスを使用して、カメラの位置ルールから離れた場所にあるフロアクエリの結果を確認する

レベルまたはアプリケーションのシナリオで必要とされる複数のオブジェクトの配置場所を解決する場合、は、領域が見つかる確率を最大化するために、最初に不可欠なオブジェクトとラージオブジェクトを解決します。 配置順序は重要です。 オブジェクトの配置が見つからない場合は、制限の少ない構成を試してください。 一連のフォールバック構成を設定することは、多くの部屋構成で機能をサポートするために不可欠です。

ルームスキャンプロセス

HoloLens によって提供される空間マッピングソリューションは、問題のある領域全体のニーズに対応できるように設計されていますが、空間を理解するためのモジュールは、2つの特定のゲームのニーズをサポートするように構築されています。 このソリューションは、次に示すように、特定のプロセスと想定のセットに基づいて構築されています。

Fixed size playspace – The user specifies the maximum playspace size in the init call.

One-time scan process –
    The process requires a discrete scanning phase where the user walks around,
    defining the playspace.
    Query functions will not function until after the scan has been finalized.

ユーザー駆動型の playspace "描画" –スキャンフェーズ中に、ユーザーは再生速度を移動して見て、含まれる必要がある領域を効果的に描画します。 生成されたメッシュは、このフェーズでユーザーからのフィードバックを提供するために重要です。 屋内で home または office セットアップ–クエリ関数は、フラットなサーフェイスと壁面を中心に設計されています。 これは、ソフトな制限です。 ただし、スキャンフェーズでは、主要軸と補助軸に沿ってメッシュテセレーションを最適化するために、主軸分析が完了します。 含まれている SpatialUnderstanding ファイルは、スキャンフェーズプロセスを管理します。 次の関数を呼び出します。

SpatialUnderstanding_Init – Called once at the start.

GeneratePlayspace_InitScan – Indicates that the scan phase should begin.

GeneratePlayspace_UpdateScan_DynamicScan –
    Called each frame to update the scanning process. The camera position and
    orientation is passed in and is used for the playspace painting process,
    described above.

GeneratePlayspace_RequestFinish –
    Called to finalize the playspace. This will use the areas “painted” during
    the scan phase to define and lock the playspace. The application can query
    statistics during the scanning phase as well as query the custom mesh for
    providing user feedback.

Import_UnderstandingMesh –
    During scanning, the “SpatialUnderstandingCustomMesh” behavior provided by
    the module and placed on the understanding prefab will periodically query the
    custom mesh generated by the process. In addition, this is done once more
    after scanning has been finalized.

"SpatialUnderstanding" 動作によって実行されるスキャンフローは、InitScan を呼び出し、その後、各フレームに対してアップデートを実行します。 統計クエリによって適切なカバレッジが報告されると、ユーザーは、ユーザーが RequestFinish を呼び出して、スキャンフェーズの終了を示すことができます。 戻り値が dll の処理を完了したことを示すまで、アップデートを引き続き呼び出すことができます。

メッシュについて

Dll を理解することで、内部的には、playspace を 8 cm サイズの voxel キューブのグリッドとして格納します。 スキャンの初期部分では、主要なコンポーネント分析が完了して、部屋の軸が決定されます。 内部的には、これらの軸に合わせて voxel 領域を格納します。 メッシュは、voxel ボリュームから isosurface を抽出することによって、約1秒ごとに生成されます。

Voxel ボリュームから生成されたメッシュを生成しました
Voxel ボリュームから生成されたメッシュを生成しました

トラブルシューティング

  • SpatialPerception機能が設定されていることを確認します。
  • 追跡が失われると、次の OnSurfaceChanged イベントによってすべてのメッシュが削除されます。

Mixed Reality Toolkit での空間マッピング

混合現実 Toolkit での空間マッピングの使用の詳細については、mrtk ドキュメントの「空間認識」セクションを参照してください。

次の開発チェックポイント

Unity の開発に関する体験に従っている場合は、MRTK コアのビルディングブロックを調べています。 ここから、次の構成要素を続けることができます。

または、Mixed Reality プラットフォームの機能と API に移動します。

いつでも Unity 開発チェックポイントに戻ることができます。

関連項目