Unity での空間のマッピングSpatial mapping in Unity

このトピックでは、使用する方法を説明します空間マッピングUnity プロジェクトで、配置、オクルー ジョン、部屋の分析などの HoloLens デバイスの世界でサーフェスを表す三角形メッシュを取得します。This topic describes how to use spatial mapping in your Unity project, retrieving triangle meshes that represent the surfaces in the world around a HoloLens device, for placement, occlusion, room analysis and more.

Unity には、次の方法で開発者に公開される空間マッピングは、完全にサポートが含まれています。Unity includes full support for spatial mapping, which is exposed to developers in the following ways:

  1. 空間マッピング、MixedRealityToolkit で利用可能なコンポーネントが便利で高速のパスを指定空間マッピングの概要Spatial mapping components available in the MixedRealityToolkit, which provide a convenient and rapid path for getting started with spatial mapping
  2. 下位の空間マッピング Api では、完全に提供する制御しより高度なアプリケーション固有のカスタマイズを有効にします。Lower-level spatial mapping APIs, which provide full control and enable more sophisticated application specific customization

空間マッピングを使用して、アプリで、spatialPerception 機能は、AppxManifest で設定する必要があります。To use spatial mapping in your app, the spatialPerception capability needs to be set in your AppxManifest.

SpatialPerception 機能の設定Setting the SpatialPerception capability

アプリ データを空間マッピングを使用するためには、SpatialPerception 機能を有効にする必要があります。In order for an app to consume spatial mapping data, the SpatialPerception capability must be enabled.

SpatialPerception 機能を有効にする方法。How to enable the SpatialPerception capability:

  1. Unity エディターで開き、 「プレーヤー設定」 ウィンドウ (編集 > プロジェクトの設定 > Player)In the Unity Editor, open the "Player Settings" pane (Edit > Project Settings > Player)
  2. をクリックして、 "Windows Store" タブClick on the "Windows Store" tab
  3. 展開 「発行の設定」 を確認し、 "SpatialPerception" 機能、 「機能」 一覧Expand "Publishing Settings" and check the "SpatialPerception" capability in the "Capabilities" list

Visual Studio ソリューションに既に Unity プロジェクトをエクスポートした場合でも、新しいフォルダーに手動でまたはいずれかのエクスポートする必要がするVisual Studio で AppxManifest でこの機能を設定します。Note that if you have already exported your Unity project to a Visual Studio solution, you will need to either export to a new folder or manually set this capability in the AppxManifest in Visual Studio.

空間マッピングには、少なくとも 10.0.10586.0 の MaxVersionTested も必要です。Spatial mapping also requires a MaxVersionTested of at least 10.0.10586.0:

  1. Visual Studio で右クリックPackage.appxmanifestクリックし、ソリューション エクスプ ローラーでコードの表示In Visual Studio, right click on Package.appxmanifest in the Solution Explorer and select View Code
  2. 行を指定するように検索TargetDeviceFamily変更とMaxVersionTested =「10.0.10240.0」MaxVersionTested「=10.0.10586.0」Find the line specifying TargetDeviceFamily and change MaxVersionTested="10.0.10240.0" to MaxVersionTested="10.0.10586.0"
  3. 保存Package.appxmanifest します。Save the Package.appxmanifest.

Unity の組み込みの空間マッピング コンポーネントの概要Getting started with Unity's built-in spatial mapping components

Unity は、アプリを簡単に空間マッピングを追加するための 2 つのコンポーネントを提供空間マッピング レンダラー空間マッピング Colliderします。Unity offers 2 components for easily adding spatial mapping to your app, Spatial Mapping Renderer and Spatial Mapping Collider.

空間マッピングのレンダラーSpatial Mapping Renderer

空間マッピング レンダラーでは、空間マッピング メッシュの視覚化ができます。The Spatial Mapping Renderer allows for visualization of the spatial mapping mesh.

Unity での空間マッピング レンダラー

空間マッピング ColliderSpatial Mapping Collider

空間マッピング Collider で holographic コンテンツ (または文字) は、空間マッピングのメッシュと物理学などの対話します。The Spatial Mapping Collider allows for holographic content (or character) interaction, such as physics, with the spatial mapping mesh.

Unity での空間マッピング Collider

空間マッピングの組み込みコンポーネントを使用します。Using the built-in spatial mapping components

視覚化して、物理画面と対話したい場合は、アプリに両方のコンポーネントを追加できます。You may add both components to your app if you'd like to both visualize and interact with physical surfaces.

Unity のアプリでは、これら 2 つのコンポーネントを使用します。To use these two components in your Unity app:

  1. 空間表面メッシュを検出するために領域を中心の GameObject を選択します。Select a GameObject at the center of the area in which you'd like to detect spatial surface meshes.
  2. Inspector ウィンドウで、コンポーネントの追加 > XR > 空間マッピング Collider または空間マッピング レンダラーします。In the Inspector window, Add Component > XR > Spatial Mapping Collider or Spatial Mapping Renderer.

これらのコンポーネントを使用する方法の詳細についての詳細を確認することができます、 Unity ドキュメント サイトします。You can find more details on how to use these components at the Unity documentation site.

組み込みの空間マッピング コンポーネントの先を行くGoing beyond the built-in spatial mapping components

これらのコンポーネントようにドラッグ アンド ドロップ簡単空間マッピングを開始します。These components make it drag-and-drop easy to get started with Spatial Mapping.  さらに移動する場合は、2 つのメイン パスを探索するがあります。 When you want to go further, there are two main paths to explore:

  • 下位レベルのメッシュ処理を行うには、低レベルの空間マッピング スクリプト API の詳細については、以下のセクションを参照してください。To do your own lower-level mesh processing, see the section below about the low-level Spatial Mapping script API.
  • メッシュのより高度な分析で SpatialUnderstanding ライブラリの詳細については、以下のセクションを参照してください。 MixedRealityToolkitします。To do higher-level mesh analysis, see the section below about the SpatialUnderstanding library in MixedRealityToolkit.

API を使用して、低レベル Unity 空間マッピングUsing the low-level Unity Spatial Mapping API

空間マッピングのレンダラーと空間マッピング コライダー コンポーネントから取得するよりも詳細に制御が必要な場合は、低レベルの空間マッピング スクリプト Api を使用できます。If you need more control than you get from the Spatial Mapping Renderer and Spatial Mapping Collider components, you can use the low-level Spatial Mapping script APIs.

名前空間: UnityEngine.XR.WSANamespace: UnityEngine.XR.WSA
:SurfaceObserverSurfaceChangeSurfaceDataSurfaceIdTypes: SurfaceObserver, SurfaceChange, SurfaceData, SurfaceId

空間マッピング Api を使用するアプリケーションの推奨されるフローの概要を次に示します。The following is an outline of the suggested flow for an application that uses the spatial mapping APIs.

設定する、SurfaceObserver(s)Set up the SurfaceObserver(s)

空間のマッピング データが必要な領域をアプリケーションで定義された地域ごとに 1 つの SurfaceObserver オブジェクトをインスタンス化します。Instantiate one SurfaceObserver object for each application-defined region of space that you need spatial mapping data for.

SurfaceObserver surfaceObserver;

 void Start () {
     surfaceObserver = new SurfaceObserver();
 }

各 SurfaceObserver オブジェクトは SetVolumeAsSphere、SetVolumeAsAxisAlignedBox、SetVolumeAsOrientedBox、または SetVolumeAsFrustum を呼び出すことでのデータを提供する領域の領域を指定します。Specify the region of space that each SurfaceObserver object will provide data for by calling either SetVolumeAsSphere, SetVolumeAsAxisAlignedBox, SetVolumeAsOrientedBox, or SetVolumeAsFrustum. これらのメソッドのいずれかをもう一度呼び出すだけで、将来の領域の領域を再定義できます。You can redefine the region of space in the future by simply calling one of these methods again.

void Start () {
    ...
     surfaceObserver.SetVolumeAsAxisAlignedBox(Vector3.zero, new Vector3(3, 3, 3));
}

SurfaceObserver.Update() を呼び出すときに、各空間のサーフェス空間マッピング システムが新しい情報の領域の SurfaceObserver のリージョンでのハンドラーを提供する必要があります。When you call SurfaceObserver.Update(), you must provide a handler for each spatial surface in the SurfaceObserver's region of space that the spatial mapping system has new information for. このハンドラーは、空間の 1 つの画面には。The handler receives, for one spatial surface:

private void OnSurfaceChanged(SurfaceId surfaceId, SurfaceChange changeType, Bounds bounds, System.DateTime updateTime)
 {
    //see Handling Surface Changes
 }

画面の変更の処理Handling Surface Changes

処理するためにいくつかの主要な場合があります。There are several main cases to handle. 追加 (&) 同じが使用できる更新コードのパスおよび削除します。Added & Updated which can use the same code path and Removed.

  • 例では、更新 (&)、追加された場合は、追加または取得ディクショナリからメッシュを必要なコンポーネントで SurfaceData 構造体を作成し、GameObject にメッシュのデータを設定する RequestMeshDataAsync を呼び出しますこの GameObject 表すこととシーンに配置します。In the Added & Updated cases in the example, we add or get the GameObject representing this mesh from the dictionary, create a SurfaceData struct with the necessary components, then call RequestMeshDataAsync to populate the GameObject with the mesh data and position in the scene.
  • 削除済みの場合は、ディクショナリからこのメッシュを表す GameObject を削除し、それを破棄します。In the Removed case, we remove the GameObject representing this mesh from the dictionary and destroy it.
System.Collections.Generic.Dictionary<SurfaceId, GameObject> spatialMeshObjects = 
    new System.Collections.Generic.Dictionary<SurfaceId, GameObject>();

   private void OnSurfaceChanged(SurfaceId surfaceId, SurfaceChange changeType, Bounds bounds, System.DateTime updateTime)
   {
       switch (changeType)
       {
           case SurfaceChange.Added:
           case SurfaceChange.Updated:
               if (!spatialMeshObjects.ContainsKey(surfaceId))
               {
                   spatialMeshObjects[surfaceId] = new GameObject("spatial-mapping-" + surfaceId);
                   spatialMeshObjects[surfaceId].transform.parent = this.transform;
                   spatialMeshObjects[surfaceId].AddComponent<MeshRenderer>();
               }
               GameObject target = spatialMeshObjects[surfaceId];
               SurfaceData sd = new SurfaceData(
                   //the surface id returned from the system
                   surfaceId,
                   //the mesh filter that is populated with the spatial mapping data for this mesh
                   target.GetComponent<MeshFilter>() ?? target.AddComponent<MeshFilter>(),
                   //the world anchor used to position the spatial mapping mesh in the world
                   target.GetComponent<WorldAnchor>() ?? target.AddComponent<WorldAnchor>(),
                   //the mesh collider that is populated with collider data for this mesh, if true is passed to bakeMeshes below
                   target.GetComponent<MeshCollider>() ?? target.AddComponent<MeshCollider>(),
                   //triangles per cubic meter requested for this mesh
                   1000,
                   //bakeMeshes - if true, the mesh collider is populated, if false, the mesh collider is empty.
                   true
                   );

               SurfaceObserver.RequestMeshAsync(sd, OnDataReady);
               break;
           case SurfaceChange.Removed:
               var obj = spatialMeshObjects[surfaceId];
               spatialMeshObjects.Remove(surfaceId);
               if (obj != null)
               {
                   GameObject.Destroy(obj);
               }
               break;
           default:
               break;
       }
   }

処理データの準備完了Handling Data Ready

OnDataReady ハンドラーは、SurfaceData オブジェクトを受け取ります。The OnDataReady handler receives a SurfaceData object. WorldAnchor、MeshFilter および (必要に応じて) MeshCollider オブジェクトが含まれている、関連付けられている空間画面の最新の状態を反映します。The WorldAnchor, MeshFilter and (optionally) MeshCollider objects it contains reflect the latest state of the associated spatial surface. 必要に応じて分析を実行または処理MeshFilter オブジェクトのメッシュのメンバーにアクセスしてメッシュ データ。Optionally perform analysis and/or processing of the mesh data by accessing the Mesh member of the MeshFilter object. 最新のメッシュに空間サーフェイスを描画して、(必要に応じて) 物理衝突と raycasts に使用します。Render the spatial surface with the latest mesh and (optionally) use it for physics collisions and raycasts. SurfaceData の内容が null でないことを確認するのには重要です。It's important to confirm that the contents of the SurfaceData are not null.

更新プログラムの処理を開始します。Start processing on updates

SurfaceObserver.Update() は、遅延、すべてのフレームに呼び出す必要があります。SurfaceObserver.Update() should be called on a delay, not every frame.

void Start () {
    ...
     StartCoroutine(UpdateLoop());
}

 IEnumerator UpdateLoop()
    {
        var wait = new WaitForSeconds(2.5f);
        while(true)
        {
            surfaceObserver.Update(OnSurfaceChanged);
            yield return wait;
        }
    }

高度なメッシュ分析:SpatialUnderstandingHigher-level mesh analysis: SpatialUnderstanding

MixedRealityToolkit holographic Unity Api に基づいて構築された holographic の開発のための便利なユーティリティ コードのコレクションです。The MixedRealityToolkit is a collection of helpful utility code for holographic development built upon the holographic Unity APIs.

空間の理解Spatial Understanding

現実の世界でホログラムを配置するときに、空間のマッピングを超えるメッシュし、平面の画面を移動することが望ましいは多くの場合です。When placing holograms in the physical world it is often desirable to go beyond spatial mapping’s mesh and surface planes. 配置が完了したら手続きより高いレベルの環境の理解をお勧めします。When placement is done procedurally, a higher level of environmental understanding is desirable. 通常、このエラーは、floor、ceiling、および壁についての決定が必要です。This usually requires making decisions about what is floor, ceiling, and walls. さらに、holographic オブジェクトの最も望ましいの物理的な場所を確認する配置の制約のセットに対して最適化するために機能します。In addition, the ability to optimize against a set of placement constraints to determining the most desirable physical locations for holographic objects.

、Young Conker とフラグメントの開発中に、この目的のルーム問題を解くプログラムの開発には、この問題ヘッドが Asobo スタジオに直面しています。During the development of Young Conker and Fragments, Asobo Studios faced this problem head on, developing a room solver for this purpose. これらのゲームのゲームの特定のニーズがテクノロジの空間についてのコアを共有しています。Each of these games had game specific needs, but they shared core spatial understanding technology. 配置するには、文字と、多種多様な空間についての他のクエリを識別するとすばやく検索空白には、壁、オブジェクトの切り上げを配置することができます。 このテクノロジがライブラリにカプセル化します HoloToolkit.SpatialUnderstanding が配置されます。The HoloToolkit.SpatialUnderstanding library encapsulates this technology, allowing you to quickly find empty spaces on the walls, place objects on the ceiling, identify placed for character to sit, and a myriad of other spatial understanding queries.

すべてのソース コードは、ニーズに合わせてカスタマイズし、改善をコミュニティで共有することができます、含まれています。All of the source code is included, allowing you to customize it to your needs and share your improvements with the community. コードをC++ソルバーが UWP dll にラップされの場合は、MixedRealityToolkit 内に含まれるプレハブを Unity に公開します。The code for the C++ solver has been wrapped into a UWP dll and exposed to Unity with a drop in prefab contained within the MixedRealityToolkit.

モジュールについてUnderstanding Modules

モジュールによって公開される 3 つのプライマリ インターフェイスがあります。 単純な画面と空間クエリ、オブジェクト検出では、図形、および制約ベースの配置オブジェクトのセットのオブジェクト配置のソルバーのトポロジ。There are three primary interfaces exposed by the module: topology for simple surface and spatial queries, shape for object detection, and the object placement solver for constraint based placement of object sets. これらのそれぞれについて、次に示します。Each of these is described below. 3 つのプライマリ モジュール インターフェイスに加えて、ray キャスト インターフェイスを使用して、タグが付けられたサーフェイスのタイプを取得することし、カスタムのような厳重な playspace メッシュをコピーすることができます。In addition to the three primary module interfaces, a ray casting interface can be used to retrieve tagged surface types and a custom watertight playspace mesh can be copied out.

光線のキャストRay Casting

ルームをスキャンされ、完了した後、ラベルは floor、ceiling、壁のようなサーフェイス内部的に生成されます。After the room has been scanned and finalized, labels are internally generated for surfaces like the floor, ceiling, and walls. "RaycastResult"の形式で表示される情報、"PlayspaceRaycast"関数が光線に受け取り、ray が既知の画面と競合している場合であればを返します。The “PlayspaceRaycast” function takes a ray and returns if the ray collides with a known surface and if so, information about that surface in the form of a “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;
};

内部的には、playspace の計算の 8 cm cubed voxel 表現に対して、raycast が計算されます。Internally, the raycast is computed against the computed 8cm cubed voxel representation of the playspace. 各 voxel には、一連画面要素に処理されたトポロジのデータ (surfels とも呼ばれます) にはが含まれています。Each voxel contains a set of surface elements with processed topology data (aka surfels). Voxel が交差するセル内に含まれる surfels が比較され、最も一致するトポロジ情報を検索するために使用します。The surfels contained within the intersected voxel cell are compared and the best match used to look up the topology information. このトポロジのデータを含む"SurfaceTypes"列挙型のフォームと交差する画面の表面領域で返される、ラベル付けします。This topology data contains the labeling returned in the form of the “SurfaceTypes” enum, as well as the surface area of the intersected surface.

Unity のサンプルでは、カーソルは各フレームに伸びる射線をキャストします。In the Unity sample, the cursor casts a ray each frame. Unity のコライダーに対して最初に。First, against Unity’s colliders. Understanding モジュールの世界の表現に対して第 2 に。Second, against the understanding module’s world representation. 最後に、もう一度 UI 要素。And finally, again UI elements. このアプリケーションで UI は、理解の結果と Unity のコライダーの最後に、次に、優先順位を取得します。In this application, UI gets priority, next the understanding result, and lastly, Unity’s colliders. カーソルの横にあるテキストとして、SurfaceType が報告されます。The SurfaceType is reported as text next to the cursor.

画面の種類のカーソルの横にあるラベルはSurface type is labeled next to the cursor
画面の種類のカーソルの横にあるラベルはSurface type is labeled next to the cursor

トポロジのクエリTopology Queries

DLL 内では、トポロジのマネージャーは、環境のラベル付けを処理します。Within the DLL, the topology manager handles labeling of the environment. 前述のように、surfels、voxel ボリューム内に含まれるデータの多く格納されます。As mentioned above, much of the data is stored within surfels, contained within a voxel volume. さらに、"PlaySpaceInfos"構造を使用して、世界中の配置 (詳細については後述)、floor、ceiling 高さなど、playspace についての情報を格納します。In addition, the “PlaySpaceInfos” structure is used to store information about the playspace, including the world alignment (more details on this below), floor, and ceiling height. ヒューリスティックは、floor、ceiling、壁を決定するために使用されます。Heuristics are used for determining floor, ceiling, and walls. たとえば、1 m2 のサーフェス領域よりも大きいと、最大および最小の水平方向の画面は、床面と見なされます。For example, the largest and lowest horizontal surface with greater than 1 m2 surface area is considered the floor. スキャン プロセス中にカメラのパスがこのプロセスで使用されるもことに注意してください。Note that the camera path during the scanning process is also used in this process.

トポロジのマネージャーによって公開されているクエリのサブセットは、出力 dll を介して公開されます。A subset of the queries exposed by the Topology manager are exposed out through the dll. 公開されているトポロジのクエリは次のとおりです。The exposed topology queries are as follows.

QueryTopology_FindPositionsOnWalls
QueryTopology_FindLargePositionsOnWalls
QueryTopology_FindLargestWall
QueryTopology_FindPositionsOnFloor
QueryTopology_FindLargestPositionsOnFloor
QueryTopology_FindPositionsSittable

各クエリは、クエリの種類に固有のパラメーターのセットがあります。Each of the queries has a set of parameters, specific to the query type. 次の例では、ユーザーは、高さの最小値と最小の配置、フロア、クリアランスの前に、ボリュームの最小量の高さ、目的のボリュームの幅を指定します。In the following example, the user specifies the minimum height & width of the desired volume, minimum placement height above the floor, and the minimum amount of clearance in front of the volume. すべての測定値では、メートル単位で。All measurements are in meters.

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"構造体の配列を受け取る。Each of these queries takes a pre-allocated array of “TopologyResult” structures. "LocationCount"パラメーターには、渡された配列の長さを指定します。The “locationCount” parameter specifies the length of the passed in array. 戻り値は、返される位置の数を報告します。The return value reports the number of returned locations. この数値が渡されたを超えることはありません"locationCount"パラメーターにします。This number is never greater than the passed in “locationCount” parameter.

"TopologyResult"には、返されるボリュームに接続する方向 (つまり標準)、および検索の領域の大きさの中央の位置が含まれています。The “TopologyResult” contains the center position of the returned volume, the facing direction (i.e. normal), and the dimensions of the found space.

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

Unity のサンプルでは、これらの各クエリがリンクされている仮想 UI パネルのボタンに注意してください。Note that in the Unity sample, each of these queries is linked up to a button in the virtual UI panel. ハードのサンプル コードは妥当な値にこれらのクエリの各パラメーター。The sample hard codes the parameters for each of these queries to reasonable values. 例については、サンプル コードでは、SpaceVisualizer.cs を参照してください。See SpaceVisualizer.cs in the sample code for more examples.

Shape クエリShape Queries

Dll 内では、図形アナライザー ("ShapeAnalyzer_W") は、ユーザーが定義したカスタム図形と照合するトポロジ アナライザーを使用します。Inside of the dll, the shape analyzer (“ShapeAnalyzer_W”) uses the topology analyzer to match against custom shapes defined by the user. Unity のサンプルでは、図形のセットを定義し、アプリ内のクエリ メニューの 図形 タブ内からの結果を生成を公開します。ユーザーが独自オブジェクト図形のクエリを定義しを加えることは、アプリケーションの必要に応じて、それらの使用します。The Unity sample defines a set of shapes and exposes the results out through the in-app query menu, within the shape tab. The intention is that the user can define their own object shape queries and make use of those, as needed by their application.

形状の分析が水平方向のサーフェスのみで機能するに注意してください。Note that the shape analysis works on horizontal surfaces only. たとえば、ソファーは、戻るカウチのフラットの上端とフラット seat 画面によって定義されます。A couch, for example, is defined by the flat seat surface and the flat top of the couch back. Shape クエリは、特定のサイズ、高さ、および縦横範囲の配置し、接続されている 2 つのサーフェスの 2 つのサーフェスを探します。The shape query looks for two surfaces of a specific size, height, and aspect range, with the two surfaces aligned and connected. Api の用語を使用するには、ソファ シートとバック上部は、図形のコンポーネントと、アラインメント要件は次の図形のコンポーネントの制約。Using the APIs terminology, the couch seat and back top are shape components and the alignment requirements are shape component constraints.

"Sittable"オブジェクトの Unity サンプル (ShapeDefinition.cs) で定義されているクエリの例は次のとおりです。An example query defined in the Unity sample (ShapeDefinition.cs), for “sittable” objects is as follows.

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);

各図形のクエリは、一連の図形コンポーネントは、それぞれに、一連のコンポーネントの制約と、一連の図形の制約によって定義されるコンポーネント間の依存関係を一覧表示します。Each shape query is defined by a set of shape components, each with a set of component constraints and a set of shape constraints which listing dependencies between the components. この例には、(1 つだけのコンポーネントであるため)、1 つのコンポーネントの定義とコンポーネント間で制約のない図形で次の 3 つの制約が含まれます。This example includes three constraints in a single component definition and no shape constraints between components (as there is only one component).

これに対し、ソファ図形は、2 つのコンポーネントの図形と図形の 4 つの制約をが。In contrast, the couch shape has two shape components and four shape constraints. コンポーネントが (0 からこの例では 1) のユーザーのコンポーネントの一覧で、インデックスで識別されることに注意してください。Note that components are identified by their index in the user’s component list (0 and 1 in this example).

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 モジュールで提供されます。Wrapper functions are provided in the Unity module for easy creation of custom shape definitions. コンポーネントと図形の制約の完全な一覧は、"SpatialUnderstandingDll.cs"、"ShapeComponentConstraint"および"ShapeConstraint"構造内で確認できます。The full list of component and shape constraints can be found in “SpatialUnderstandingDll.cs” within the “ShapeComponentConstraint” and the “ShapeConstraint” structures.

四角形がこの画面で見つかったRectangle shape is found on this surface
四角形がこの画面で見つかったRectangle shape is found on this surface

オブジェクト配置のソルバーObject Placement Solver

オブジェクトの配置を対象としてプログラムは、オブジェクトを配置する物理的な部屋に理想的な場所を識別するために使用できます。The object placement solver can be used to identify ideal locations in the physical room to place your objects. オブジェクトの規則と制約を指定した位置に最適なソルバーが見つかります。The solver will find the best fit location given the object rules and constraints. さらに、オブジェクト クエリは、"Solver_RemoveObject"により、オブジェクトが削除されますか、複数のオブジェクトの配置の制約付き"Solver_RemoveAllObjects"呼び出しを許可するまで保持されます。In addition, object queries persist until the object is removed with “Solver_RemoveObject” or “Solver_RemoveAllObjects” calls, allowing constrained multi-object placement. オブジェクト配置のクエリは、3 つの部分で構成されています: パラメーター、一連の規則、制約のリストと配置の種類。Objects placement queries consist of three parts: placement type with parameters, a list of rules, and a list of constraints. クエリを実行するには、次の API を使用します。To run a query, use the following 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)

この関数は、オブジェクトの名前、配置の定義と規則と制約の一覧を受け取ります。This function takes an object name, placement definition, and a list of rules and constraints. C#ラッパーは構築の規則と制約の構築を簡単にヘルパー関数を提供します。The C# wrappers provides construction helper functions to make rule and constraint construction easy. 配置の定義には、次の 1 つは、クエリの種類 – が含まれています。The placement definition contains the query type – that is, one of the following.

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

パラメーターの型に固有の各配置の種類があります。Each of the placement types has a set of parameters unique to the type. "ObjectPlacementDefinition"構造体には、これらの定義を作成するための静的なヘルパー関数のセットが含まれています。The “ObjectPlacementDefinition” structure contains a set of static helper functions for creating these definitions. たとえば、床の上にオブジェクトを配置する場所を検索するには、次の関数を使用できます。For example, to find a place to put an object on the floor, you can use the following function. パブリック静的 ObjectPlacementDefinition Create_OnFloor(Vector3 halfDims) でさらに、配置の種類を一連の規則と制約を行うことができます。public static ObjectPlacementDefinition Create_OnFloor(Vector3 halfDims) In addition to the placement type, you can provide a set of rules and constraints. 規則に違反することはできません。Rules cannot be violated. 型とルールに適合するような配置場所は、最適な配置場所を選択するには、一連の制約に対して最適化されています。Possible placement locations that satisfy the type and rules are then optimized against the set of constraints in order to select the optimal placement location. 指定された静的作成関数によって各規則と制約を作成できます。Each of the rules and constraints can be created by the provided static creation functions. 規則と制約の構築関数の例を以下に示します。An example rule and constraint construction function is provided below.

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

オブジェクトの下の配置のクエリは、画面の端に半分メーター キューブを配置から他のオブジェクトを配置前およびルームの中央の近くの場所を確保検索します。The below object placement query is looking for a place to put a half meter cube on the edge of a surface, away from other previously place objects and near the center of the room.

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());

成功した場合、配置の位置を含む"ObjectPlacementResult"構造体のサイズや方向が返されます。If successful, a “ObjectPlacementResult” structure containing the placement position, dimensions and orientation is returned. さらに、配置は、配置されたオブジェクトの dll の内部一覧に追加されます。In addition, the placement is added to the dll’s internal list of placed objects. 後続の配置のクエリ アカウントにこのオブジェクトになります。Subsequent placement queries will take this object into account. Unity のサンプルでは、"LevelSolver.cs"ファイルより多くの例のクエリが含まれています。The “LevelSolver.cs” file in the Unity sample contains more example queries.

オブジェクトの配置の結果Results of object placement
図 3:青いボックスでカメラの位置の規則から床の上の 3 つの場所からの結果のクエリFigure 3: The blue boxes how the result from three place on floor queries with away from camera position rules

レベルまたはアプリケーションのシナリオに必要な複数のオブジェクトの配置場所を解決するときに最初に、領域に含まれる確率を最大化するための順序で欠かせないと大きなオブジェクトを解決します。When solving for placement location of multiple objects required for a level or application scenario, first solve indispensable and large objects in order to maximizing the probability that a space can be found. 配置の順序が重要です。Placement order is important. オブジェクトへの配置が見つからない場合は、あまりに制約付きの構成をお試しください。If object placements cannot be found, try less constrained configurations. フォールバック構成のセットは、ルーム構成で多くの機能をサポートしているに不可欠です。Having a set of fallback configurations is critical to supporting functionality across many room configurations.

ルームのスキャン プロセスRoom Scanning Process

あらゆる問題領域のニーズを満たすのに十分なジェネリック、HoloLens によって提供される空間マッピング ソリューションを設計中に、空間理解モジュールは、2 つの特定のゲームのニーズをサポートするために構築されました。While the spatial mapping solution provided by the HoloLens is designed to be generic enough to meet the needs of the entire gamut of problem spaces, the spatial understanding module was built to support the needs of two specific games. そのソリューションは、特定のプロセスと前提条件、以下の集計のセットを中心に構成されます。Its solution is structured around a specific process and set of assumptions, summarized below.

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「描画」– スキャン フェーズでは、ユーザーが移動し、ペースの再生に関する次の必要があります領域を効果的に描画します。User driven playspace “painting” – During the scanning phase, the user moves and looks around the plays pace, effectively painting the areas which should be included. 生成したメッシュは、このフェーズ中にユーザーからのフィードバックを提供する必要があります。The generated mesh is important to provide user feedback during this phase. 屋内ホームまたは office セットアップ – 関数がフラット サーフェスと直角に交わって壁を中心に設計されたクエリ。Indoors home or office setup – The query functions are designed around flat surfaces and walls at right angles. これは、ソフト制限です。This is a soft limitation. ただし、スキャン フェーズでは、プライマリ軸の分析がメジャーおよびマイナーの軸に沿ったメッシュ テセレーションを最適化するために完了します。However, during the scanning phase, a primary axis analysis is completed to optimize the mesh tessellation along major and minor axis. インクルード SpatialUnderstanding.cs ファイルは、スキャン フェーズの処理を管理します。The included SpatialUnderstanding.cs file manages the scanning phase process. 次の関数を呼び出します。It calls the following functions.

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、し UpdateScan を呼び出します。The scanning flow, driven by the “SpatialUnderstanding” behavior calls InitScan, then UpdateScan each frame. 統計情報のクエリが妥当なカバレッジを報告したとき、ユーザーは、スキャン フェーズの終了を示す RequestFinish を呼び出す airtap にできます。When the statistics query reports reasonable coverage, the user is allowed to airtap to call RequestFinish to indicate the end of the scanning phase. UpdateScan の継続が戻り値になるまでに呼び出される値は、dll の処理が完了したことを示します。UpdateScan continues to be called until it’s return value indicates that the dll has completed processing.

Understanding メッシュUnderstanding Mesh

Understanding dll は、サイズ 8 cm voxel キューブのグリッドとして、playspace を内部的に格納します。The understanding dll internally stores the playspace as a grid of 8cm sized voxel cubes. スキャンの初期段階では、部屋の軸を決定する主要なコンポーネントの分析が完了しました。During the initial part of scanning, a primary component analysis is completed to determine the axes of the room. 内部的には、これらの軸に配置されたその voxel 領域を格納します。Internally, it stores its voxel space aligned to these axes. メッシュには、voxel ボリュームからアイソサーフェスを抽出することによって毎秒約が生成されます。A mesh is generated approximately every second by extracting the isosurface from the voxel volume.

Voxel ボリュームから生成したメッシュが生成されます。Generated mesh produced from the voxel volume
Voxel ボリュームから生成したメッシュが生成されます。Generated mesh produced from the voxel volume

トラブルシューティングTroubleshooting

  • 設定することを確認、 SpatialPerception機能Ensure you have set the SpatialPerception capability
  • 追跡が失われると、次の OnSurfaceChanged イベントはすべてのメッシュを削除します。When tracking is lost, the next OnSurfaceChanged event will remove all meshes.

Mixed Reality toolkit 空間マッピングSpatial Mapping in Mixed Reality Toolkit

空間マッピングを使用して、Mixed Reality Toolkit v2 での詳細については、次を参照してください。、空間認識セクションMRTK docs の。For more information on using Spatial Mapping with Mixed Reality Toolkit v2, see the Spatial Awareness section of the MRTK docs.

関連項目See also