Mapeamento espacial no UnitySpatial mapping in Unity

o mapeamento espacial permite que você recupere malhas de triângulo que representam as superfícies do mundo em um dispositivo HoloLens.spatial mapping lets you retrieve triangle meshes that represent the surfaces in the world around a HoloLens device. Você pode usar dados de superfície para posicionamento, oclusão e análise de sala para dar a seus projetos de Unity um dose extra de imersão.You can use surface data for placement, occlusion, and room analysis to give your Unity projects an extra dose of immersion.

O Unity inclui suporte completo para o mapeamento espacial, que é exposto aos desenvolvedores das seguintes maneiras:Unity includes full support for spatial mapping, which is exposed to developers in the following ways:

  1. Componentes de mapeamento espacial disponíveis no MixedRealityToolkit, que fornecem um caminho conveniente e rápido para introdução ao mapeamento espacialSpatial mapping components available in the MixedRealityToolkit, which provide a convenient and rapid path for getting started with spatial mapping
  2. APIs de mapeamento espacial de nível inferior, que fornecem controle total e permitem uma personalização mais sofisticada específica do aplicativoLower-level spatial mapping APIs, which provide full control and enable more sophisticated application-specific customization

Para usar o mapeamento espacial em seu aplicativo, o recurso spatialPerception precisa ser definido em seu AppxManifest.To use spatial mapping in your app, the spatialPerception capability needs to be set in your AppxManifest.

Suporte a dispositivosDevice support

RecursoFeature HoloLens (primeira gen)HoloLens (first gen) HoloLens 2HoloLens 2 Headsets imersivosImmersive headsets
mapeamento espacialSpatial mapping ✔️✔️ ✔️✔️

Configurando o recurso SpatialPerceptionSetting the SpatialPerception capability

Para que um aplicativo consuma dados de mapeamento espacial, o recurso SpatialPerception deve ser habilitado.In order for an app to consume spatial mapping data, the SpatialPerception capability must be enabled.

Como habilitar o recurso SpatialPerception:How to enable the SpatialPerception capability:

  1. No editor do Unity, abra o painel "configurações do Player" (editar > configurações do projeto > Player)In the Unity Editor, open the "Player Settings" pane (Edit > Project Settings > Player)
  2. Selecione na guia "Windows Store"Select on the "Windows Store" tab
  3. Expanda "configurações de publicação" e verifique o recurso "SpatialPerception" na lista "recursos"Expand "Publishing Settings" and check the "SpatialPerception" capability in the "Capabilities" list

Observação

Se você já tiver exportado seu projeto do Unity para uma solução do Visual Studio, será necessário exportar para uma nova pasta ou definir manualmente esse recurso no AppxManifest no 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.

O mapeamento espacial também requer um MaxVersionTested de pelo menos 10.0.10586.0:Spatial mapping also requires a MaxVersionTested of at least 10.0.10586.0:

  1. No Visual Studio, clique com o botão direito do mouse em Package. appxmanifest na Gerenciador de soluções e selecione Exibir códigoIn Visual Studio, right-click on Package.appxmanifest in the Solution Explorer and select View Code
  2. Localize a linha especificando TargetDeviceFamily e altere MaxVersionTested = "10.0.10240.0" para MaxVersionTested = "10.0.10586.0"Find the line specifying TargetDeviceFamily and change MaxVersionTested="10.0.10240.0" to MaxVersionTested="10.0.10586.0"
  3. Salve o Package. appxmanifest.Save the Package.appxmanifest.

Introdução aos componentes de mapeamento espacial interno do UnityGetting started with Unity's built-in spatial mapping components

O Unity oferece dois componentes para adicionar facilmente o mapeamento espacial ao seu aplicativo, o renderizador de mapeamento espacial e o Colisor de mapeamento espacial.Unity offers two components for easily adding spatial mapping to your app, Spatial Mapping Renderer and Spatial Mapping Collider.

Renderizador de mapeamento espacialSpatial Mapping Renderer

O renderizador de mapeamento espacial permite a visualização da malha de mapeamento espacial.The Spatial Mapping Renderer allows for visualization of the spatial mapping mesh.

Renderizador de mapeamento espacial no Unity

Colisor de mapeamento espacialSpatial Mapping Collider

O colisor de mapeamento espacial permite a interação de conteúdo Holographic (ou caractere), como a física, com a malha de mapeamento espacial.The Spatial Mapping Collider allows for holographic content (or character) interaction, such as physics, with the spatial mapping mesh.

Colisor de mapeamento espacial no Unity

Usando os componentes internos de mapeamento espacialUsing the built-in spatial mapping components

Você pode adicionar ambos os componentes ao seu aplicativo se desejar visualizar e interagir com superfícies físicas.You may add both components to your app if you'd like to both visualize and interact with physical surfaces.

Para usar esses dois componentes em seu aplicativo do Unity:To use these two components in your Unity app:

  1. Selecione um gameobject no centro da área na qual você gostaria de detectar malhas de superfície espacial.Select a GameObject at the center of the area in which you'd like to detect spatial surface meshes.
  2. Na janela Inspetor, adicione o processador de > > mapeamento espacial do componente XR ou o renderizador de mapeamento espacial.In the Inspector window, Add Component > XR > Spatial Mapping Collider or Spatial Mapping Renderer.

Você pode encontrar mais detalhes sobre como usar esses componentes no site de documentação do Unity.You can find more details on how to use these components at the Unity documentation site.

Indo além dos componentes internos de mapeamento espacialGoing beyond the built-in spatial mapping components

Esses componentes o tornam fácil de arrastar e soltar para começar a usar o mapeamento espacial.These components make it drag-and-drop easy to get started with Spatial Mapping. Quando quiser ir além, há dois caminhos principais a serem explorados:When you want to go further, there are two main paths to explore:

  • Para fazer seu próprio processamento de malha de nível inferior, consulte a seção abaixo sobre a API de script de mapeamento espacial de baixo nível.To do your own lower-level mesh processing, see the section below about the low-level Spatial Mapping script API.
  • Para fazer uma análise de malha de nível superior, consulte a seção abaixo sobre a biblioteca SpatialUnderstanding em MixedRealityToolkit.To do higher-level mesh analysis, see the section below about the SpatialUnderstanding library in MixedRealityToolkit.

Usando a API de mapeamento espacial do Unity de nível baixoUsing the low-level Unity Spatial Mapping API

Se você precisar de mais controle do que o renderizador de mapeamento espacial e a oferta de componentes do colisor de mapeamento espacial, use as APIs de mapeamento espacial de nível baixo.If you need more control than the Spatial Mapping Renderer and Spatial Mapping Collider components offer, use the low-level Spatial Mapping APIs.

Namespace: UnityEngine. XR. WSANamespace: UnityEngine.XR.WSA
Tipos: SurfaceObserver, SurfaceChange, SurfaceData, surfaceidTypes: SurfaceObserver, SurfaceChange, SurfaceData, SurfaceId

Descrevemos o fluxo sugerido para um aplicativo que usa as APIs de mapeamento espacial nas seções a seguir.We've outlined the suggested flow for an application that uses the spatial mapping APIs in the sections below.

Configurar SurfaceObserver (s)Set up the SurfaceObserver(s)

Crie uma instância de um objeto SurfaceObserver para cada região de espaço definida pelo aplicativo para a qual você precisa de dados de mapeamento espacial.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();
 }

Especifique a região de espaço para a qual cada objeto SurfaceObserver fornecerá dados chamando SetVolumeAsSphere, SetVolumeAsAxisAlignedBox, SetVolumeAsOrientedBox ou SetVolumeAsFrustum.Specify the region of space that each SurfaceObserver object will provide data for by calling either SetVolumeAsSphere, SetVolumeAsAxisAlignedBox, SetVolumeAsOrientedBox, or SetVolumeAsFrustum. Você pode redefinir a região do espaço no futuro simplesmente chamando um desses métodos novamente.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));
}

Ao chamar SurfaceObserver. Update (), você deve fornecer um manipulador para cada superfície espacial na região de espaço do SurfaceObserver para a qual o sistema de mapeamento espacial tem novas informações.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. O manipulador recebe, para uma superfície espacial:The handler receives, for one spatial surface:

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

Lidando com alterações de superfícieHandling Surface Changes

Há vários casos principais para manipular-adicionados e atualizados, que podem usar o mesmo caminho de código e removidos.There are several main cases to handle - added and updated, which can use the same code path, and removed.

  • Nos casos adicionados e atualizados, adicionamos ou obtemos o gameobject que representa essa malha do dicionário, criamos uma estrutura SurfaceData com os componentes necessários e chamamos RequestMeshDataAsync para preencher o gameobject com os dados de malha e a posição na cena.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.
  • No caso removido, removemos o gameobject que representa a malha do dicionário e o destruimos.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;
       }
   }

Manipulando dados prontosHandling Data Ready

O manipulador OnDataReady recebe um objeto SurfaceData.The OnDataReady handler receives a SurfaceData object. Os objetos WorldAnchor, MeshFilter e (opcionalmente) MeshCollider que ele contém refletem o estado mais recente da superfície espacial associada.The WorldAnchor, MeshFilter, and (optionally) MeshCollider objects it contains reflect the latest state of the associated spatial surface. Opcionalmente, analise e/ou processe os dados de malha acessando o membro de malha do objeto MeshFilter.Optionally, analyze and/or process the mesh data by accessing the Mesh member of the MeshFilter object. Renderize a superfície espacial com a malha mais recente e (opcionalmente) Use-a para colisões de física e raycasts.Render the spatial surface with the latest mesh and (optionally) use it for physics collisions and raycasts. É importante confirmar que o conteúdo de SurfaceData não é nulo.It's important to confirm that the contents of the SurfaceData aren't null.

Iniciar processamento em atualizaçõesStart processing on updates

SurfaceObserver. Update () deve ser chamado em um atraso, e não em todos os quadros.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;
        }
    }

Análise de malha de nível superior: SpatialUnderstandingHigher-level mesh analysis: SpatialUnderstanding

O MixedRealityToolkit é uma coleção de código do utilitário para o desenvolvimento do Holographic criado nas APIs Holographic do Unity.The MixedRealityToolkit is a collection of utility code for holographic development built on Unity's holographic APIs.

Compreensão espacialSpatial Understanding

Ao colocar os hologramas no mundo físico, muitas vezes é desejável ir além dos planos de malha e superfície do mapeamento espacial.When placing holograms in the physical world, it's often desirable to go beyond spatial mapping’s mesh and surface planes. Quando o posicionamento é feito de procedimento, um nível mais alto de compreensão ambiental é desejável.When placement is done procedurally, a higher level of environmental understanding is desirable. Isso geralmente requer tomar decisões sobre o que é andar, teto e paredes.This usually requires making decisions about what is floor, ceiling, and walls. Você também tem a capacidade de otimizar em relação a um conjunto de restrições de posicionamento para determinar a melhor localização física para objetos Holographic.You also have the ability to optimize against a set of placement constraints to determine the most best physical locations for holographic objects.

Durante o desenvolvimento de jovens conkers e fragmentos, Asobo estúdios enfrentou esse problema ao desenvolver um solucionador de sala.During development of Young Conker and Fragments, Asobo Studios faced this problem head on by developing a room solver. Cada um desses jogos teve necessidades específicas do jogo, mas eles compartilharam a tecnologia de compreensão espacial principal.Each of these games had game-specific needs, but they shared core spatial understanding technology. A biblioteca HoloToolkit. SpatialUnderstanding encapsula essa tecnologia, permitindo que você encontre rapidamente espaços vazios nas paredes, coloque os objetos no teto, identifique-os com relação ao caractere a ser colocado e uma infinidade de outras consultas de compreensão espacial.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.

Todo o código-fonte está incluído, permitindo personalizá-lo às suas necessidades e compartilhar suas melhorias com a Comunidade.All of the source code is included, allowing you to customize it to your needs and share your improvements with the community. O código para o resolvedor de C++ foi encapsulado em uma DLL UWP e exposto ao Unity com uma queda no pré-fabricado contido no 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.

Noções básicas sobre módulosUnderstanding Modules

Há três interfaces primárias expostas pelo módulo: topologia para consultas espaciais e de superfície simples, forma de detecção de objeto e o resolvedor de posicionamento de objetos para o posicionamento baseado em restrição de conjuntos de objetos.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. Veja a descrição das duas maneiras abaixo.Each of these is described below. Além das três interfaces de módulo principais, uma interface de conversão Ray pode ser usada para recuperar tipos de superfície marcada e uma malha Watertight Playspace personalizada pode ser copiada.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.

Conversão de RayRay Casting

Após a conclusão da verificação de sala, os rótulos são gerados internamente para superfícies como o piso, o teto e as paredes.After the room scan is completed, labels are internally generated for surfaces like the floor, ceiling, and walls. A função "PlayspaceRaycast" usa um raio e retorna se o raio colide com uma superfície conhecida e, nesse caso, informações sobre essa superfície na forma de um "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, o Raycast é calculado em relação à representação de VOXEL cúbico de 8 cm computada do Playspace.Internally, the raycast is computed against the computed 8-cm cubed voxel representation of the playspace. Cada voxel contém um conjunto de elementos Surface com dados de topologia processados (também conhecido como surfels).Each voxel contains a set of surface elements with processed topology data (aka surfels). As surfels contidas na célula VOXEL interseccionada são comparadas e a melhor correspondência usada para pesquisar as informações de topologia.The surfels contained within the intersected voxel cell is compared and the best match used to look up the topology information. Esses dados de topologia contêm o rótulo retornado na forma da enumeração "SurfaceTypes", bem como a área de superfície da superfície interseccionada.This topology data contains the labeling returned in the form of the “SurfaceTypes” enum, as well as the surface area of the intersected surface.

No exemplo de Unity, o cursor converte um raio cada quadro.In the Unity sample, the cursor casts a ray each frame. Primeiro, em relação aos conflitantes da Unity.First, against Unity’s colliders. Em segundo lugar, em relação à representação Mundial do módulo de compreensão.Second, against the understanding module’s world representation. E, finalmente, os elementos da interface do usuário.And finally, again UI elements. Neste aplicativo, a interface do usuário obtém prioridade, em seguida o resultado da compreensão e, por fim, os coliders do Unity.In this application, UI gets priority, next the understanding result, and lastly, Unity’s colliders. O Surfacetype é relatado como texto ao lado do cursor.The SurfaceType is reported as text next to the cursor.

O tipo de superfície é rotulado ao lado do cursorSurface type is labeled next to the cursor
O tipo de superfície é rotulado ao lado do cursorSurface type is labeled next to the cursor

Consultas de topologiaTopology Queries

Dentro da DLL, o Gerenciador de topologia lida com a rotulagem do ambiente.Within the DLL, the topology manager handles labeling of the environment. Conforme mencionado acima, grande parte dos dados é armazenada no surfels, contido em um volume VOXEL.As mentioned above, much of the data is stored within surfels, contained within a voxel volume. Além disso, a estrutura "PlaySpaceInfos" é usada para armazenar informações sobre o Playspace, incluindo o alinhamento Mundial (mais detalhes sobre isso abaixo), piso e altura do teto.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. A heurística é usada para determinar piso, teto e paredes.Heuristics are used for determining floor, ceiling, and walls. Por exemplo, a maior e menor superfície horizontal com área de superfície maior que 1 m2 é considerada a base.For example, the largest and lowest horizontal surface with greater than 1-m2 surface area is considered the floor.

Observação

O caminho da câmera durante o processo de verificação também é usado nesse processo.The camera path during the scanning process is also used in this process.

Um subconjunto das consultas expostas pelo Gerenciador de topologia é exposto por meio da dll.A subset of the queries exposed by the Topology manager are exposed out through the dll. As consultas de topologia expostas são as seguintes.The exposed topology queries are as follows.

QueryTopology_FindPositionsOnWalls
QueryTopology_FindLargePositionsOnWalls
QueryTopology_FindLargestWall
QueryTopology_FindPositionsOnFloor
QueryTopology_FindLargestPositionsOnFloor
QueryTopology_FindPositionsSittable

Cada uma das consultas tem um conjunto de parâmetros, específico ao tipo de consulta.Each of the queries has a set of parameters, specific to the query type. No exemplo a seguir, o usuário especifica a altura mínima & largura do volume desejado, a altura mínima de posicionamento acima do andar e a quantidade mínima de espaço livre na frente do 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. Todas as medidas estão em metros.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)

Cada uma dessas consultas usa uma matriz pré-configurada de estruturas "TopologyResult".Each of these queries takes a pre-allocated array of “TopologyResult” structures. O parâmetro "locationCount" especifica o comprimento da matriz passada.The “locationCount” parameter specifies the length of the passed in array. O valor de retorno informa o número de locais retornados.The return value reports the number of returned locations. Esse número nunca é maior que o passado no parâmetro "locationCount".This number is never greater than the passed in “locationCount” parameter.

O "TopologyResult" contém a posição central do volume retornado, a direção oposta (ou seja, normal) e as dimensões do espaço encontrado.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;
};

Observação

No exemplo de Unity, cada uma dessas consultas é vinculada a um botão no painel de interface do usuário virtual.In the Unity sample, each of these queries is linked up to a button in the virtual UI panel. Os códigos de exemplo codificam os parâmetros de cada uma dessas consultas para valores razoáveis.The sample hard codes the parameters for each of these queries to reasonable values. Consulte SpaceVisualizer.cs no código de exemplo para obter mais exemplos.See SpaceVisualizer.cs in the sample code for more examples.

Consultas de formaShape Queries

Na DLL, o analisador de forma ("ShapeAnalyzer_W") usa o analisador de topologia para corresponder às formas personalizadas definidas pelo usuário.In the dll, the shape analyzer (“ShapeAnalyzer_W”) uses the topology analyzer to match against custom shapes defined by the user. O exemplo de Unity define um conjunto de formas e expõe os resultados por meio do menu consulta no aplicativo, dentro da guia forma. A intenção é que o usuário possa definir suas próprias consultas de forma de objeto e usá-las, conforme a necessidade de seu aplicativo.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.

A análise de forma funciona apenas em superfícies horizontais.The shape analysis works on horizontal surfaces only. Um sofá, por exemplo, é definido pela superfície de estação plana e a parte superior do sofá de volta.A couch, for example, is defined by the flat seat surface and the flat top of the couch back. A consulta de forma procura duas superfícies de um tamanho, altura e intervalo de aspecto específicos, com as duas superfícies alinhadas e conectadas.The shape query looks for two surfaces of a specific size, height, and aspect range, with the two surfaces aligned and connected. Usando a terminologia de APIs, a estação de sofá e a parte superior são componentes de forma e os requisitos de alinhamento são restrições de componente de forma.Using the APIs terminology, the couch seat and back top are shape components and the alignment requirements are shape component constraints.

Uma consulta de exemplo definida no exemplo de Unity (ShapeDefinition.cs) para objetos "sittable" é a seguinte: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);

Cada consulta de forma é definida por um conjunto de componentes de forma, cada um com um conjunto de restrições de componente e um conjunto de restrições de forma que listam as dependências entre os componentes.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. Este exemplo inclui três restrições em uma única definição de componente e nenhuma restrição de forma entre os componentes (já que há apenas um componente).This example includes three constraints in a single component definition and no shape constraints between components (as there's only one component).

Por outro lado, a forma de sofá tem dois componentes Shape e quatro restrições Shape.In contrast, the couch shape has two shape components and four shape constraints. Os componentes são identificados por seu índice na lista de componentes do usuário (0 e 1 neste exemplo).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),
};

As funções de wrapper são fornecidas no módulo do Unity para facilitar a criação de definições de formas personalizadas.Wrapper functions are provided in the Unity module for easy creation of custom shape definitions. A lista completa de restrições de componente e forma pode ser encontrada em "SpatialUnderstandingDll.cs" nas estruturas "ShapeComponentConstraint" e "ShapeConstraint".The full list of component and shape constraints can be found in “SpatialUnderstandingDll.cs” within the “ShapeComponentConstraint” and the “ShapeConstraint” structures.

A forma de retângulo foi encontrada nesta superfícieRectangle shape is found on this surface
A forma de retângulo foi encontrada nesta superfícieRectangle shape is found on this surface

Resolvedor de posicionamento de objetoObject Placement Solver

O resolvedor de posicionamento de objetos pode ser usado para identificar locais ideais no espaço físico para colocar seus objetos.The object placement solver can be used to identify ideal locations in the physical room to place your objects. O solucionador encontrará o local mais adequado, considerando as regras e restrições do objeto.The solver will find the best fit location given the object rules and constraints. Além disso, as consultas de objeto persistem até que o objeto seja removido com chamadas "Solver_RemoveObject" ou "Solver_RemoveAllObjects", permitindo o posicionamento restrito de vários objetos.In addition, object queries persist until the object is removed with “Solver_RemoveObject” or “Solver_RemoveAllObjects” calls, allowing constrained multi-object placement. As consultas de posicionamento de objetos consistem em três partes: tipo de posicionamento com parâmetros, uma lista de regras e uma lista de restrições.Objects placement queries consist of three parts: placement type with parameters, a list of rules, and a list of constraints. Para executar uma consulta, use a API a seguir.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)

Essa função usa um nome de objeto, uma definição de posicionamento e uma lista de regras e restrições.This function takes an object name, placement definition, and a list of rules and constraints. Os wrappers do C# fornecem funções auxiliares de construção para facilitar a construção da regra e da restrição.The C# wrappers provides construction helper functions to make rule and constraint construction easy. A definição de posicionamento contém o tipo de consulta – ou seja, uma das opções a seguir.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,
            };

Cada um dos tipos de posicionamento tem um conjunto de parâmetros exclusivos para o tipo.Each of the placement types has a set of parameters unique to the type. A estrutura "ObjectPlacementDefinition" contém um conjunto de funções auxiliares estáticas para a criação dessas definições.The “ObjectPlacementDefinition” structure contains a set of static helper functions for creating these definitions. Por exemplo, para encontrar um local para colocar um objeto no chão, você pode usar a função a seguir.For example, to find a place to put an object on the floor, you can use the following function. ObjectPlacementDefinition Create_OnFloor público estático (Vector3 halfDims) Além do tipo de posicionamento, você pode fornecer um conjunto de regras e restrições.public static ObjectPlacementDefinition Create_OnFloor(Vector3 halfDims) In addition to the placement type, you can provide a set of rules and constraints. As regras não podem ser violadas.Rules cannot be violated. Os locais de posicionamento possíveis que atendem ao tipo e às regras são então otimizados em relação ao conjunto de restrições para selecionar o local de posicionamento ideal.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. Cada uma das regras e restrições pode ser criada pelas funções de criação estática fornecidas.Each of the rules and constraints can be created by the provided static creation functions. Uma regra de exemplo e uma função de construção de restrição são fornecidas abaixo.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)

A consulta de posicionamento de objeto abaixo está procurando um local para colocar um cubo de meio medidor na borda de uma superfície, longe de outros objetos anteriormente posicionados e perto do centro da sala.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());

Se for bem-sucedida, uma estrutura "ObjectPlacementResult" que contém a posição, as dimensões e a orientação do posicionamento será retornada.If successful, a “ObjectPlacementResult” structure containing the placement position, dimensions, and orientation is returned. Além disso, o posicionamento é adicionado à lista interna de objetos posicionados da dll.In addition, the placement is added to the dll’s internal list of placed objects. As consultas de posicionamento subsequentes levarão esse objeto à conta.Subsequent placement queries will take this object into account. O arquivo "LevelSolver.cs" no exemplo de Unity contém mais consultas de exemplo.The “LevelSolver.cs” file in the Unity sample contains more example queries.

Resultados da colocação do objetoResults of object placement
Figura 3: as caixas azuis como o resultado de três lugares em consultas de piso com afastamento das regras de posição da câmeraFigure 3: The blue boxes how the result from three place on floor queries with away from camera position rules

Ao resolver o local de posicionamento de vários objetos necessários para um cenário de nível ou aplicativo, primeiro resolva os objetos indispensável e grandes para maximizar a probabilidade de que um espaço possa ser encontrado.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. A ordem de posicionamento é importante.Placement order is important. Se os posicionamentos de objeto não puderem ser encontrados, tente configurações menos restritas.If object placements cannot be found, try less constrained configurations. Ter um conjunto de configurações de fallback é essencial para dar suporte à funcionalidade em várias configurações de sala.Having a set of fallback configurations is critical to supporting functionality across many room configurations.

Processo de verificação de salaRoom Scanning Process

Embora a solução de mapeamento espacial fornecida pelo HoloLens seja projetada para ser genérica o suficiente para atender às necessidades de toda a gama de espaços problemáticos, o módulo de compreensão espacial foi criado para dar suporte às necessidades de dois jogos específicos.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. Sua solução é estruturada em um processo específico e um conjunto de suposições, resumido abaixo.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.

"Pintura" Playspace orientada por usuário – durante a fase de verificação, o usuário se move e procura o ritmo das jogas, pintando efetivamente as áreas, que devem ser incluídas.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. A malha gerada é importante para fornecer comentários do usuário durante essa fase.The generated mesh is important to provide user feedback during this phase. Inportações domésticas ou de configuração do Office – as funções de consulta são projetadas em relação a superfícies simples e paredes em ângulos retos.Indoors home or office setup – The query functions are designed around flat surfaces and walls at right angles. Essa é uma limitação flexível.This is a soft limitation. No entanto, durante a fase de verificação, uma análise de eixo primário é concluída para otimizar o mosaico de malha ao longo do eixo principal e secundário.However, during the scanning phase, a primary axis analysis is completed to optimize the mesh tessellation along major and minor axis. O arquivo SpatialUnderstanding.cs incluído gerencia o processo da fase de verificação.The included SpatialUnderstanding.cs file manages the scanning phase process. Ele chama as funções a seguir.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.

O fluxo de verificação, controlado pelo comportamento "SpatialUnderstanding", chama InitScan e, em seguida, UpdateScan cada quadro.The scanning flow, driven by the “SpatialUnderstanding” behavior calls InitScan, then UpdateScan each frame. Quando a consulta de estatísticas relata cobertura razoável, o usuário tem permissão para airtap chamar RequestFinish para indicar o fim da fase de verificação.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 sendo chamado até que seu valor de retorno indique que a dll concluiu o processamento.UpdateScan continues to be called until its return value indicates that the dll has completed processing.

Entendendo a malhaUnderstanding Mesh

A DLL de compreensão armazena internamente o Playspace como uma grade de oito cubos VOXEL de tamanho 8 cm.The understanding dll internally stores the playspace as a grid of 8 cm sized voxel cubes. Durante a parte inicial da verificação, uma análise de componente primário é concluída para determinar os eixos da sala.During the initial part of scanning, a primary component analysis is completed to determine the axes of the room. Internamente, ele armazena seu espaço VOXEL alinhado a esses eixos.Internally, it stores its voxel space aligned to these axes. Uma malha é gerada aproximadamente a cada segundo, extraindo o isosurface do volume VOXEL.A mesh is generated approximately every second by extracting the isosurface from the voxel volume.

Malha gerada produzida a partir do volume VOXELGenerated mesh produced from the voxel volume
Malha gerada produzida a partir do volume VOXELGenerated mesh produced from the voxel volume

Solução de problemasTroubleshooting

  • Verifique se você definiu o recurso SpatialPerceptionEnsure you have set the SpatialPerception capability
  • Quando o rastreamento for perdido, o próximo evento onsurfacechanged removerá todas as malhas.When tracking is lost, the next OnSurfaceChanged event will remove all meshes.

Mapeamento espacial no kit de ferramentas de realidade misturadaSpatial Mapping in Mixed Reality Toolkit

Para obter mais informações sobre como usar o mapeamento espacial com o kit de ferramentas de realidade misturada v2, consulte a seção reconhecimento espacial do docs MRTK.For more information on using Spatial Mapping with Mixed Reality Toolkit v2, see the Spatial Awareness section of the MRTK docs.

Próximo ponto de verificação de desenvolvimentoNext Development Checkpoint

Se você estiver seguindo a jornada de desenvolvimento do Unity que apresentamos, você está no meio da exploração dos blocos de construção do 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. Deste ponto, você pode prosseguir para o próximo bloco de construção:From here, you can continue to the next building block:

Ou vá diretamente para as funcionalidades e APIs da plataforma de Realidade Misturada:Or jump to Mixed Reality platform capabilities and APIs:

Você sempre pode voltar para os pontos de verificação de desenvolvimento do Unity a qualquer momento.You can always go back to the Unity development checkpoints at any time.

Veja tambémSee also