Mapping spaziale in UnitySpatial mapping in Unity

il mapping spaziale consente di recuperare mesh triangolari che rappresentano le superfici del mondo intorno a un dispositivo HoloLens.spatial mapping lets you retrieve triangle meshes that represent the surfaces in the world around a HoloLens device. È possibile usare i dati di superficie per l'analisi di posizionamento, occlusione e chat room per offrire ai progetti Unity una dose aggiuntiva di immersione.You can use surface data for placement, occlusion, and room analysis to give your Unity projects an extra dose of immersion.

Unity include il supporto completo per il mapping spaziale, esposto agli sviluppatori nei modi seguenti:Unity includes full support for spatial mapping, which is exposed to developers in the following ways:

  1. Componenti di mapping spaziale disponibili in MixedRealityToolkit, che offrono un percorso pratico e rapido per iniziare a usare il mapping spazialeSpatial mapping components available in the MixedRealityToolkit, which provide a convenient and rapid path for getting started with spatial mapping
  2. API di mapping spaziale di basso livello, che offrono il controllo completo e consentono una personalizzazione più sofisticata specifica dell'applicazioneLower-level spatial mapping APIs, which provide full control and enable more sophisticated application-specific customization

Per usare il mapping spaziale nell'app, è necessario impostare la funzionalità spatialPerception in AppxManifest.To use spatial mapping in your app, the spatialPerception capability needs to be set in your AppxManifest.

Supporto di dispositiviDevice support

FunzionalitàFeature HoloLens (prima generazione)HoloLens (first gen) HoloLens 2HoloLens 2 Visori VR immersiveImmersive headsets
Mapping spazialeSpatial mapping ✔️✔️ ✔️✔️

Impostazione della funzionalità SpatialPerceptionSetting the SpatialPerception capability

Per consentire a un'app di utilizzare i dati di mapping spaziale, è necessario abilitare la funzionalità SpatialPerception.In order for an app to consume spatial mapping data, the SpatialPerception capability must be enabled.

Come abilitare la funzionalità SpatialPerception:How to enable the SpatialPerception capability:

  1. Nell'editor di Unity aprire il riquadro "Impostazioni lettore" (modificare > impostazioni progetto > lettore)In the Unity Editor, open the "Player Settings" pane (Edit > Project Settings > Player)
  2. Selezionare nella scheda "Windows Store"Select on the "Windows Store" tab
  3. Espandere "impostazioni di pubblicazione" e selezionare la funzionalità "SpatialPerception" nell'elenco "funzionalità"Expand "Publishing Settings" and check the "SpatialPerception" capability in the "Capabilities" list

Nota

Se il progetto Unity è già stato esportato in una soluzione di Visual Studio, sarà necessario eseguire l'esportazione in una nuova cartella o impostare manualmente questa funzionalità in appxmanifest in Visual Studio.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.

Il mapping spaziale richiede anche un MaxVersionTested di almeno 10.0.10586.0:Spatial mapping also requires a MaxVersionTested of at least 10.0.10586.0:

  1. In Visual Studio fare clic con il pulsante destro del mouse su Package. appxmanifest nel Esplora soluzioni e selezionare Visualizza codice .In Visual Studio, right-click on Package.appxmanifest in the Solution Explorer and select View Code
  2. Trovare la riga che specifica TargetDeviceFamily e modificare MaxVersionTested = "10.0.10240.0" in MaxVersionTested = "10.0.10586.0"Find the line specifying TargetDeviceFamily and change MaxVersionTested="10.0.10240.0" to MaxVersionTested="10.0.10586.0"
  3. Salvare il pacchetto. appxmanifest.Save the Package.appxmanifest.

Introduzione ai componenti di mapping spaziale incorporati di UnityGetting started with Unity's built-in spatial mapping components

Unity offre due componenti per aggiungere facilmente il mapping spaziale all'app, al renderer di mapping spaziale e al mapping spaziale.Unity offers two components for easily adding spatial mapping to your app, Spatial Mapping Renderer and Spatial Mapping Collider.

Renderer mapping spazialeSpatial Mapping Renderer

Il renderer di mapping spaziale consente la visualizzazione della mesh di mapping spaziale.The Spatial Mapping Renderer allows for visualization of the spatial mapping mesh.

Renderer di mapping spaziale in Unity

Conflitto di mapping spazialeSpatial Mapping Collider

Il mapping spaziale Collider consente l'interazione di contenuto (o carattere) olografico, ad esempio la fisica, con la mesh di mapping spaziale.The Spatial Mapping Collider allows for holographic content (or character) interaction, such as physics, with the spatial mapping mesh.

Conflitto di mapping spaziale in Unity

Uso dei componenti di mapping spaziale predefinitiUsing the built-in spatial mapping components

È possibile aggiungere entrambi i componenti all'app se si vuole visualizzare e interagire con le superfici fisiche.You may add both components to your app if you'd like to both visualize and interact with physical surfaces.

Per usare questi due componenti nell'app Unity:To use these two components in your Unity app:

  1. Selezionare un GameObject al centro dell'area in cui si desidera rilevare le mesh della superficie spaziale.Select a GameObject at the center of the area in which you'd like to detect spatial surface meshes.
  2. Nella finestra di controllo aggiungere Component > XR > Spatial mapping Spatial o renderer di mapping spaziale.In the Inspector window, Add Component > XR > Spatial Mapping Collider or Spatial Mapping Renderer.

Per altre informazioni su come usare questi componenti, vedere il sito della documentazione di Unity.You can find more details on how to use these components at the Unity documentation site.

Superamento dei componenti predefiniti di mapping spazialeGoing beyond the built-in spatial mapping components

Questi componenti rendono semplice il trascinamento della selezione per iniziare a usare il mapping spaziale.These components make it drag-and-drop easy to get started with Spatial Mapping. Quando si vuole proseguire, è possibile esplorare due percorsi principali:When you want to go further, there are two main paths to explore:

  • Per eseguire l'elaborazione della mesh di livello inferiore, vedere la sezione seguente sull'API script per il mapping spaziale di basso livello.To do your own lower-level mesh processing, see the section below about the low-level Spatial Mapping script API.
  • Per eseguire un'analisi della rete di livello superiore, vedere la sezione seguente sulla libreria SpatialUnderstanding in MixedRealityToolkit.To do higher-level mesh analysis, see the section below about the SpatialUnderstanding library in MixedRealityToolkit.

Uso dell'API di mapping spaziale di Unity di basso livelloUsing the low-level Unity Spatial Mapping API

Se è necessario un maggiore controllo rispetto al renderer del mapping spaziale e all'offerta dei componenti Collider del mapping spaziale, usare le API di mapping spaziale di basso livello.If you need more control than the Spatial Mapping Renderer and Spatial Mapping Collider components offer, use the low-level Spatial Mapping APIs.

Spazio dei nomi: UnityEngine. XR. WSANamespace: UnityEngine.XR.WSA
Tipi: SurfaceObserver, SurfaceChange, SurfaceData, SurfaceIdTypes: SurfaceObserver, SurfaceChange, SurfaceData, SurfaceId

Il flusso suggerito per un'applicazione che usa le API di mapping spaziale è stato descritto nelle sezioni seguenti.We've outlined the suggested flow for an application that uses the spatial mapping APIs in the sections below.

Configurare i SurfaceObserverSet up the SurfaceObserver(s)

Creare un'istanza di un oggetto SurfaceObserver per ogni area di spazio definita dall'applicazione per cui sono necessari dati di mapping spaziali.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();
 }

Specificare l'area di spazio a cui ogni oggetto SurfaceObserver fornirà i dati chiamando SetVolumeAsSphere, SetVolumeAsAxisAlignedBox, SetVolumeAsOrientedBox o SetVolumeAsFrustum.Specify the region of space that each SurfaceObserver object will provide data for by calling either SetVolumeAsSphere, SetVolumeAsAxisAlignedBox, SetVolumeAsOrientedBox, or SetVolumeAsFrustum. È possibile ridefinire l'area di spazio in futuro semplicemente richiamando uno di questi metodi.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));
}

Quando si chiama SurfaceObserver. Update (), è necessario fornire un gestore per ogni superficie spaziale nell'area di spazio di SurfaceObserver per cui il sistema di mapping spaziale dispone di nuove informazioni.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. Il gestore riceve, per una superficie spaziale:The handler receives, for one spatial surface:

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

Gestione delle modifiche di superficieHandling Surface Changes

Esistono diversi casi principali per la gestione dell'aggiunta e dell'aggiornamento, che possono utilizzare lo stesso percorso di codice e rimossi.There are several main cases to handle - added and updated, which can use the same code path, and removed.

  • Nei casi aggiunti e aggiornati, si aggiunge o si ottiene il GameObject che rappresenta la mesh dal dizionario, si crea uno struct SurfaceData con i componenti necessari, quindi si chiama RequestMeshDataAsync per popolare il GameObject con i dati della mesh e la posizione nella scena.In the added and updated cases, 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.
  • Nel caso rimosso, viene rimosso il GameObject che rappresenta il mesh dal dizionario ed eliminarlo.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;
       }
   }

Gestione dei dati prontiHandling Data Ready

Il gestore OnDataReady riceve un oggetto SurfaceData.The OnDataReady handler receives a SurfaceData object. Gli oggetti WorldAnchor, MeshFilter e (facoltativamente) MeshCollider che contiene riflettono lo stato più recente della superficie spaziale associata.The WorldAnchor, MeshFilter, and (optionally) MeshCollider objects it contains reflect the latest state of the associated spatial surface. Facoltativamente, analizzare e/o elaborare i dati mesh accedendo al membro mesh dell'oggetto MeshFilter.Optionally, analyze and/or process the mesh data by accessing the Mesh member of the MeshFilter object. Eseguire il rendering della superficie spaziale con la mesh più recente e, facoltativamente, usarla per collisioni fisiche e raycasts.Render the spatial surface with the latest mesh and (optionally) use it for physics collisions and raycasts. È importante verificare che il contenuto di SurfaceData non sia null.It's important to confirm that the contents of the SurfaceData aren't null.

Avviare l'elaborazione degli aggiornamentiStart processing on updates

SurfaceObserver. Update () deve essere chiamato su un ritardo, non su tutti i frame.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;
        }
    }

Analisi mesh di livello superiore: SpatialUnderstandingHigher-level mesh analysis: SpatialUnderstanding

MixedRealityToolkit è una raccolta di codice di utilità per lo sviluppo olografico basato sulle API olografiche di Unity.The MixedRealityToolkit is a collection of utility code for holographic development built on Unity's holographic APIs.

Conoscenza spazialeSpatial Understanding

Quando si posizionano gli ologrammi nel mondo fisico, è spesso consigliabile andare oltre i piani di rete e di superficie del mapping spaziale.When placing holograms in the physical world, it's often desirable to go beyond spatial mapping’s mesh and surface planes. Quando il posizionamento viene eseguito in maniera procedurale, è auspicabile un livello superiore di comprensione ambientale.When placement is done procedurally, a higher level of environmental understanding is desirable. Questa operazione richiede in genere le decisioni relative a pavimenti, massimali e muri.This usually requires making decisions about what is floor, ceiling, and walls. È anche possibile eseguire l'ottimizzazione rispetto a un set di vincoli di posizionamento per determinare le posizioni fisiche migliori per gli oggetti olografici.You also have the ability to optimize against a set of placement constraints to determine the most best physical locations for holographic objects.

Durante lo sviluppo di Conker e frammenti giovani, Asobo Studios ha affrontato questo problema sviluppando un risolutore di spazio.During development of Young Conker and Fragments, Asobo Studios faced this problem head on by developing a room solver. Ognuno di questi giochi ha esigenze specifiche del gioco, ma ha condiviso la tecnologia principale per la comprensione spaziale.Each of these games had game-specific needs, but they shared core spatial understanding technology. La libreria HoloToolkit. SpatialUnderstanding incapsula questa tecnologia, consentendo di trovare rapidamente gli spazi vuoti sulle pareti, posizionare gli oggetti sul soffitto, identificare posizionati per il carattere da collocare e una miriade di altre query di comprensione spaziale.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.

Tutto il codice sorgente è incluso, consentendo di personalizzarlo in base alle proprie esigenze e condividere i miglioramenti con la community.All of the source code is included, allowing you to customize it to your needs and share your improvements with the community. Il codice per il Risolutore C++ è stato sottoposto a incapsulamento in una DLL di UWP ed esposto a Unity con una riduzione della prefabbricata contenuta all'interno di MixedRealityToolkit.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.

Informazioni sui moduliUnderstanding Modules

Sono disponibili tre interfacce primarie esposte dal modulo: topologia per query di superficie e spaziali semplici, forma per il rilevamento di oggetti e il Risolutore di posizionamento degli oggetti per il posizionamento basato sui vincoli dei set di oggetti.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. Ogni modalità è illustrata di seguito.Each of these is described below. Oltre alle tre interfacce del modulo principale, è possibile usare un'interfaccia di cast di tipo Ray per recuperare i tipi di superficie con tag ed è possibile copiare una mesh playspace stermetica personalizzata.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.

Casting RayRay Casting

Al termine dell'analisi della chat, le etichette vengono generate internamente per superfici quali il piano, il soffitto e i muri.After the room scan is completed, labels are internally generated for surfaces like the floor, ceiling, and walls. La funzione "PlayspaceRaycast" accetta un raggio e restituisce se il raggio è in conflitto con una superficie nota e, in tal caso, le informazioni su tale superficie sotto forma di "RaycastResult".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;
};

Internamente, il Raycast viene calcolato rispetto alla rappresentazione voxel a cubi di 8 cm calcolata del playspace.Internally, the raycast is computed against the computed 8-cm cubed voxel representation of the playspace. Ogni voxel contiene un set di elementi Surface con dati della topologia elaborati (noto anche come surfels).Each voxel contains a set of surface elements with processed topology data (aka surfels). Il surfels contenuto all'interno della cella voxel intersecata viene confrontato e la migliore corrispondenza utilizzata per cercare le informazioni sulla topologia.The surfels contained within the intersected voxel cell is compared and the best match used to look up the topology information. Questi dati della topologia contengono l'etichettatura restituita nel formato dell'enumerazione "SurfaceTypes", nonché la superficie di attacco della superficie intersecata.This topology data contains the labeling returned in the form of the “SurfaceTypes” enum, as well as the surface area of the intersected surface.

Nell'esempio Unity il cursore esegue il cast di un raggio per ogni fotogramma.In the Unity sample, the cursor casts a ray each frame. In primo luogo, rispetto ai Collider di Unity.First, against Unity’s colliders. In secondo luogo, sulla rappresentazione mondiale del modulo di informazioni.Second, against the understanding module’s world representation. Infine, di nuovo gli elementi dell'interfaccia utente.And finally, again UI elements. In questa applicazione, l'interfaccia utente ottiene la priorità, successivamente il risultato della comprensione e infine i Collider di Unity.In this application, UI gets priority, next the understanding result, and lastly, Unity’s colliders. SurfaceType viene segnalato come testo accanto al cursore.The SurfaceType is reported as text next to the cursor.

Il tipo di superficie è contrassegnato accanto al cursoreSurface type is labeled next to the cursor
Il tipo di superficie è contrassegnato accanto al cursoreSurface type is labeled next to the cursor

Query sulla topologiaTopology Queries

All'interno della DLL, Gestione topologia gestisce l'assegnazione di etichette all'ambiente.Within the DLL, the topology manager handles labeling of the environment. Come indicato in precedenza, gran parte dei dati viene archiviata in surfels, contenuta in un volume voxel.As mentioned above, much of the data is stored within surfels, contained within a voxel volume. Inoltre, la struttura "PlaySpaceInfos" viene usata per archiviare le informazioni relative a playspace, incluso l'allineamento internazionale (altre informazioni su questo argomento), il piano e l'altezza del soffitto.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. Vengono usate le regole euristiche per determinare il piano, il soffitto e i muri.Heuristics are used for determining floor, ceiling, and walls. Ad esempio, la superficie orizzontale più grande e più bassa con una superficie di attacco maggiore di 1-m2 viene considerata il piano.For example, the largest and lowest horizontal surface with greater than 1-m2 surface area is considered the floor.

Nota

Il percorso della fotocamera durante il processo di analisi viene usato anche in questo processo.The camera path during the scanning process is also used in this process.

Un subset delle query esposte dal gestore della topologia viene esposto tramite la dll.A subset of the queries exposed by the Topology manager are exposed out through the dll. Di seguito sono riportate le query topologia esposte.The exposed topology queries are as follows.

QueryTopology_FindPositionsOnWalls
QueryTopology_FindLargePositionsOnWalls
QueryTopology_FindLargestWall
QueryTopology_FindPositionsOnFloor
QueryTopology_FindLargestPositionsOnFloor
QueryTopology_FindPositionsSittable

Ogni query ha un set di parametri, specifico del tipo di query.Each of the queries has a set of parameters, specific to the query type. Nell'esempio seguente l'utente specifica l'altezza minima & larghezza del volume desiderato, l'altezza minima di posizionamento sopra il piano e la quantità minima di spazio di autorizzazione davanti al volume.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. Tutte le misurazioni sono in metri.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)

Ognuna di queste query accetta una matrice pre-allocata di strutture "TopologyResult".Each of these queries takes a pre-allocated array of “TopologyResult” structures. Il parametro "locationCount" specifica la lunghezza della matrice passata.The “locationCount” parameter specifies the length of the passed in array. Il valore restituito indica il numero di posizioni restituite.The return value reports the number of returned locations. Questo numero non è mai superiore al parametro "locationCount" passato.This number is never greater than the passed in “locationCount” parameter.

"TopologyResult" contiene la posizione centrale del volume restituito, la direzione (ovvero normale) e le dimensioni dello spazio trovato.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;
};

Nota

Nell'esempio Unity ogni query è collegata a un pulsante nel pannello dell'interfaccia utente virtuale.In the Unity sample, each of these queries is linked up to a button in the virtual UI panel. L'esempio codifica in modo rigido i parametri per ognuna di queste query in valori ragionevoli.The sample hard codes the parameters for each of these queries to reasonable values. Per altri esempi, vedere SpaceVisualizer.cs nel codice di esempio.See SpaceVisualizer.cs in the sample code for more examples.

Query di formaShape Queries

Nella dll, l'analizzatore di forme ("ShapeAnalyzer_W") utilizza l'analizzatore della topologia per trovare la corrispondenza con le forme personalizzate definite dall'utente.In the dll, the shape analyzer (“ShapeAnalyzer_W”) uses the topology analyzer to match against custom shapes defined by the user. L'esempio Unity definisce un set di forme ed espone i risultati tramite il menu query in-app, all'interno della scheda Shape. L'intenzione è che l'utente possa definire le proprie query di forma oggetto e utilizzarle, in base alle esigenze dell'applicazione.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.

L'analisi delle forme funziona solo su superfici orizzontali.The shape analysis works on horizontal surfaces only. Un divano, ad esempio, viene definito dalla superficie della postazione piatta e dalla parte superiore piatta del divano.A couch, for example, is defined by the flat seat surface and the flat top of the couch back. La query Shape cerca due superfici di dimensioni, altezze e intervalli di aspetto specifici, con le due superfici allineate e connesse.The shape query looks for two surfaces of a specific size, height, and aspect range, with the two surfaces aligned and connected. Con la terminologia relativa alle API, il divano e la parte superiore sono componenti di forma e i requisiti di allineamento sono vincoli dei componenti della forma.Using the APIs terminology, the couch seat and back top are shape components and the alignment requirements are shape component constraints.

Di seguito è riportata una query di esempio definita nell'esempio Unity (ShapeDefinition.cs) per gli oggetti "SitTable".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);

Ogni query di forma è definita da un set di componenti di forma, ognuno con un set di vincoli di componente e un set di vincoli di forma che elencano le dipendenze tra i componenti.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. Questo esempio include tre vincoli in una definizione di componente singolo e nessun vincolo di forma tra i componenti (poiché esiste un solo componente).This example includes three constraints in a single component definition and no shape constraints between components (as there's only one component).

Al contrario, la forma Couch presenta due componenti di forma e quattro vincoli Shape.In contrast, the couch shape has two shape components and four shape constraints. I componenti sono identificati dal relativo indice nell'elenco dei componenti dell'utente (0 e 1 in questo esempio).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),
};

Le funzioni wrapper sono disponibili nel modulo Unity per semplificare la creazione di definizioni di forme personalizzate.Wrapper functions are provided in the Unity module for easy creation of custom shape definitions. L'elenco completo dei vincoli relativi a componenti e forme si trova in "SpatialUnderstandingDll.cs" all'interno delle strutture "ShapeComponentConstraint" e "ShapeConstraint".The full list of component and shape constraints can be found in “SpatialUnderstandingDll.cs” within the “ShapeComponentConstraint” and the “ShapeConstraint” structures.

Forma rettangolo individuata in questa superficieRectangle shape is found on this surface
Forma rettangolo individuata in questa superficieRectangle shape is found on this surface

Risolutore posizionamento oggettiObject Placement Solver

Il Risolutore posizionamento oggetti può essere usato per identificare le posizioni ideali nella stanza fisica per inserire gli oggetti.The object placement solver can be used to identify ideal locations in the physical room to place your objects. Il Risolutore troverà il percorso più adatto in base alle regole e ai vincoli dell'oggetto.The solver will find the best fit location given the object rules and constraints. Inoltre, le query di oggetto vengono mantenute fino a quando l'oggetto non viene rimosso con chiamate "Solver_RemoveObject" o "Solver_RemoveAllObjects", consentendo il posizionamento di più oggetti vincolato.In addition, object queries persist until the object is removed with “Solver_RemoveObject” or “Solver_RemoveAllObjects” calls, allowing constrained multi-object placement. Le query di posizionamento degli oggetti sono costituite da tre parti: tipo di posizionamento con parametri, un elenco di regole e un elenco di vincoli.Objects placement queries consist of three parts: placement type with parameters, a list of rules, and a list of constraints. Per eseguire una query, usare l'API seguente.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)

Questa funzione accetta un nome di oggetto, una definizione di selezione host e un elenco di regole e vincoli.This function takes an object name, placement definition, and a list of rules and constraints. Il wrapper C# fornisce funzioni di supporto per la costruzione per semplificare la costruzione di regole e vincoli.The C# wrappers provides construction helper functions to make rule and constraint construction easy. La definizione di selezione host contiene il tipo di query, ovvero uno dei seguenti.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,
            };

Ognuno dei tipi di posizionamento dispone di un set di parametri univoco per il tipo.Each of the placement types has a set of parameters unique to the type. La struttura "ObjectPlacementDefinition" contiene un set di funzioni di supporto statiche per la creazione di queste definizioni.The “ObjectPlacementDefinition” structure contains a set of static helper functions for creating these definitions. Ad esempio, per trovare una posizione in cui posizionare un oggetto, è possibile usare la funzione seguente.For example, to find a place to put an object on the floor, you can use the following function. public static ObjectPlacementDefinition Create_OnFloor (Vector3 halfDims) oltre al tipo di posizionamento, è possibile fornire un set di regole e vincoli.public static ObjectPlacementDefinition Create_OnFloor(Vector3 halfDims) In addition to the placement type, you can provide a set of rules and constraints. Impossibile violare le regole.Rules cannot be violated. Le posizioni di posizionamento possibili che soddisfano il tipo e le regole vengono quindi ottimizzate rispetto al set di vincoli per selezionare la posizione ottimale per la selezione host.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. Ognuna delle regole e dei vincoli può essere creata dalle funzioni di creazione statiche fornite.Each of the rules and constraints can be created by the provided static creation functions. Di seguito è riportata una funzione di costruzione di regole e vincoli di esempio.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)

La query di posizionamento degli oggetti seguente sta cercando una posizione per inserire un cubo a metà metro sul bordo di una superficie, lontano dagli altri oggetti posizionati in precedenza e vicino al centro della stanza.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());

In caso di esito positivo, viene restituita una struttura "ObjectPlacementResult" che contiene la posizione, le dimensioni e l'orientamento del posizionamento.If successful, a “ObjectPlacementResult” structure containing the placement position, dimensions, and orientation is returned. Inoltre, la selezione host viene aggiunta all'elenco interno della dll degli oggetti inseriti.In addition, the placement is added to the dll’s internal list of placed objects. Questo oggetto verrà preso in considerazione dalle query di posizionamento successive.Subsequent placement queries will take this object into account. Il file "LevelSolver.cs" nell'esempio Unity contiene altre query di esempio.The “LevelSolver.cs” file in the Unity sample contains more example queries.

Risultati del posizionamento degli oggettiResults of object placement
Figura 3: le caselle blu come il risultato di tre posizioni nelle query sul pavimento con le regole di posizione della fotocameraFigure 3: The blue boxes how the result from three place on floor queries with away from camera position rules

Quando si risolve la posizione di selezione host di più oggetti richiesti per uno scenario di livello o di applicazione, risolvere prima di tutto gli oggetti indispensabili e di grandi dimensioni per ottimizzare la probabilità che uno spazio venga trovato.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. L'ordine di posizionamento è importante.Placement order is important. Se non è possibile trovare le posizioni degli oggetti, provare a eseguire meno configurazioni vincolate.If object placements cannot be found, try less constrained configurations. Avere un set di configurazioni di fallback è fondamentale per supportare le funzionalità in molte configurazioni di chat room.Having a set of fallback configurations is critical to supporting functionality across many room configurations.

Processo di analisi chat roomRoom Scanning Process

Sebbene la soluzione di mapping spaziale fornita da HoloLens sia progettata per essere sufficientemente generica per soddisfare le esigenze dell'intera gamma di spazi di problemi, il modulo di comprensione spaziale è stato creato per supportare le esigenze di due giochi specifici.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. La soluzione è strutturata in base a un processo e a un set di presupposti specifici, riepilogati di seguito.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.

"Disegno" di playspace basato sull'utente: durante la fase di analisi, l'utente si sposta ed esamina la velocità di riproduzione, disegnando in modo efficace le aree, che devono essere incluse.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. La mesh generata è importante per fornire commenti e suggerimenti degli utenti durante questa fase.The generated mesh is important to provide user feedback during this phase. Installazione domestica o di Office: le funzioni di query sono progettate per le superfici piane e i muri con angoli corretti.Indoors home or office setup – The query functions are designed around flat surfaces and walls at right angles. Si tratta di una limitazione flessibile.This is a soft limitation. Tuttavia, durante la fase di analisi, viene completata un'analisi dell'asse primaria per ottimizzare lo schema a mosaico mesh lungo l'asse principale e secondario.However, during the scanning phase, a primary axis analysis is completed to optimize the mesh tessellation along major and minor axis. Il file SpatialUnderstanding.cs incluso gestisce il processo della fase di analisi.The included SpatialUnderstanding.cs file manages the scanning phase process. Chiama le funzioni seguenti.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.

Il flusso di analisi, determinato dal comportamento "SpatialUnderstanding", chiama InitScan e quindi UpdateScan ogni frame.The scanning flow, driven by the “SpatialUnderstanding” behavior calls InitScan, then UpdateScan each frame. Quando la query Statistics segnala una ragionevole copertura, l'utente è autorizzato a AirTap per chiamare RequestFinish per indicare la fine della fase di analisi.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 continua a essere chiamato fino a quando il relativo valore restituito non indica che l'elaborazione della dll è stata completata.UpdateScan continues to be called until its return value indicates that the dll has completed processing.

Informazioni su meshUnderstanding Mesh

La dll di informazioni archivia internamente il playspace come griglia di voxel cubi di dimensioni 8 cm.The understanding dll internally stores the playspace as a grid of 8 cm sized voxel cubes. Durante la fase iniziale di analisi, viene completata un'analisi del componente principale per determinare gli assi della stanza.During the initial part of scanning, a primary component analysis is completed to determine the axes of the room. Internamente, archivia lo spazio voxel allineato a questi assi.Internally, it stores its voxel space aligned to these axes. Una mesh viene generata approssimativamente ogni secondo estraendo oggetto isosurface dal volume voxel.A mesh is generated approximately every second by extracting the isosurface from the voxel volume.

Mesh generata prodotta dal volume voxelGenerated mesh produced from the voxel volume
Mesh generata prodotta dal volume voxelGenerated mesh produced from the voxel volume

Risoluzione dei problemiTroubleshooting

  • Assicurarsi di aver impostato la funzionalità SpatialPerceptionEnsure you have set the SpatialPerception capability
  • Quando il rilevamento viene perso, l'evento OnSurfaceChanged successivo rimuoverà tutte le mesh.When tracking is lost, the next OnSurfaceChanged event will remove all meshes.

Mapping spaziale nel Toolkit per realtà mistaSpatial Mapping in Mixed Reality Toolkit

Per altre informazioni sull'uso del mapping spaziale con Mixed Reality toolkit V2, vedere la sezione relativa alla conoscenza spaziale della documentazione di MRTK.For more information on using Spatial Mapping with Mixed Reality Toolkit v2, see the Spatial Awareness section of the MRTK docs.

Successivo checkpoint di sviluppoNext Development Checkpoint

Se si sta seguendo il percorso di sviluppo di Unity, si sta per esplorare i blocchi predefiniti di MRTK core.If you're following the Unity development journey we've laid out, you're in the midst of exploring the MRTK core building blocks. Da qui è possibile passare al blocco predefinito successivo:From here, you can continue to the next building block:

In alternativa, passare alle API e funzionalità della piattaforma di realtà mista:Or jump to Mixed Reality platform capabilities and APIs:

È sempre possibile tornare ai checkpoint per lo sviluppo con Unity in qualsiasi momento.You can always go back to the Unity development checkpoints at any time.

Vedere ancheSee also