Mapeamento espacial na Unidade

O mapeamento espacial permite-lhe recuperar malhas triangulares que representam as superfícies do mundo em torno de um dispositivo HoloLens. Você pode usar dados de superfície para colocação, oclusão e análise de quarto para dar aos seus projetos de Unidade uma dose extra de imersão.

A unidade inclui o apoio total ao mapeamento espacial, que é exposto aos desenvolvedores das seguintes formas:

  1. Componentes de mapeamento espacial disponíveis no MixedRealityToolkit, que proporcionam um caminho conveniente e rápido para começar com mapeamento espacial
  2. APIs de mapeamento espacial de nível inferior, que fornecem controlo total e permitem uma personalização mais sofisticada específica da aplicação

Para utilizar o mapeamento espacial na sua aplicação, a capacidade de SpatialPerception precisa de ser definida no seu AppxManifest.

Suporte de dispositivos

Funcionalidade HoloLens (primeira geração) HoloLens 2 Auscultadores imersivos
Mapeamento espacial ✔️ ✔️

Definição da capacidade de Perceção Espacial

Para que uma aplicação consuma dados de mapeamento espacial, a capacidade de SpatialPerception deve ser ativada.

Como ativar a capacidade de Perceção Espacial:

  1. No Editor de Unidade, abra o painel "Player Definições" (Editar Project Definições > Player)
  2. Selecione no separador "Windows Store"
  3. Expanda a "Publicação Definições" e verifique a capacidade "EspacialPerception" na lista de "Capacidades"

Nota

Se já exportou o seu projeto Unidade para uma solução Visual Studio, terá de exportar para uma nova pasta ou definir manualmente esta capacidade no AppxManifest em Visual Studio.

O mapeamento espacial também requer um MaxVersionTested de pelo menos 10.0.10586.0:

  1. Em Visual Studio, clique à direita no Package.appxmanifest no Solution Explorer e selecione Ver Código
  2. Encontre a linha especificando TargetDeviceFamily e altere MaxVersionTested="10.0.10240.0" para MaxVersionTested="10.0.10586.0"
  3. Salve o Pacote.appxmanifest.

Como adicionar mapeamento na Unidade

Sistema de sensibilização espacial

No MRTK, veja-se a sensibilização do Spatial para obter informações sobre a criação de vários observadores de malha espacial.

Para obter informações sobre observadores no dispositivo, procure os observadores de malha configurante para o guia do dispositivo.

Para obter informações sobre os observadores de compreensão de cena, veja o guia de observadores da cena.

Análise de malha de nível superior: Compreensão espacial

Atenção

O Entendimento Espacial foi depreciado a favor da Compreensão da Cena.

O MixedRealityToolkit é uma coleção de código de utilidade para o desenvolvimento holográfico construído nas APIs holográficas da Unidade.

Compreensão espacial

Quando se colocam hologramas no mundo físico, é muitas vezes desejável ir além da malha espacial e dos planos de superfície. Quando a colocação é feita de forma processual, é desejável um maior nível de compreensão ambiental. Isto geralmente requer tomar decisões sobre o que é o chão, o teto e as paredes. Você também tem a capacidade de otimizar contra um conjunto de restrições de colocação para determinar os melhores locais físicos para objetos holográficos.

Durante o desenvolvimento de Young Conker e Fragments, a Asobo Studios enfrentou este problema de frente ao desenvolver um solucionador de quartos. Cada um destes jogos tinha necessidades específicas do jogo, mas partilhavam a tecnologia de compreensão espacial. A biblioteca HoloToolkit.SpatialUnderstanding encapsula esta tecnologia, permitindo-lhe encontrar rapidamente espaços vazios nas paredes, colocar objetos no teto, identificar colocado para o personagem sentar-se, e uma miríade de outras consultas de compreensão espacial.

Todo o código fonte está incluído, permitindo-lhe personalizá-lo às suas necessidades e partilhar as suas melhorias com a comunidade. O código para o solucionador C++ foi embrulhado num dll UWP e exposto à Unidade com uma queda no pré-fabricado contido no MixedRealityToolkit.

Compreender Módulos

Existem três interfaces primárias expostas pelo módulo: topologia para consultas simples de superfície e espacial, forma para deteção de objetos, e o solucionador de colocação de objetos baseado em restrições. Cada um destes é descrito abaixo. Além das três interfaces primárias do módulo, uma interface de fundição de raios pode ser usada para recuperar tipos de superfície marcados e uma malha de espaço estanque personalizada pode ser copiada.

Ray Casting

Após a verificação da sala, as etiquetas são geradas internamente para superfícies como o chão, teto e paredes. A PlayspaceRaycast função toma um raio e retorna se o raio colidir com uma superfície conhecida e, em caso afirmativo, informação sobre essa superfície sob a forma de um 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 contra a representação voxel de 8 cm computada do espaço de reprodução. Cada voxel contém um conjunto de elementos de superfície com dados de topologia processados (aka surfels). Os surfels contidos dentro da célula voxel intersecectada é comparado e o melhor par usado para procurar a informação de topologia. Estes dados de topologia contêm a rotulagem devolvida sob a forma do enum "SurfaceTypes", bem como a área de superfície da superfície intersectada.

Na amostra de Unidade, o cursor lança um raio a cada quadro. Primeiro, contra os colisões da Unidade. Segundo, contra a representação mundial do módulo de compreensão. E finalmente, mais uma vez elementos da UI. Nesta aplicação, a UI recebe prioridade, a seguir o resultado do entendimento e, por último, os colisões da Unidade. O SurfaceType é reportado como texto ao lado do cursor.

O tipo de superfície é rotulado ao lado do cursor
O tipo de superfície é rotulado ao lado do cursor

Consultas de Topologia

Dentro do DLL, o gestor de topologia lida com a rotulagem do ambiente. Como mencionado acima, grande parte dos dados é armazenado dentro de surfels, contidos num volume voxel. Além disso, a estrutura "PlaySpaceInfos" é usada para armazenar informações sobre o espaço de jogo, incluindo o alinhamento mundial (mais detalhes neste abaixo), piso e altura do teto. A heurística é usada para determinar o chão, o teto e as paredes. Por exemplo, a maior e mais baixa superfície horizontal com maior área de superfície de 1-m2 é considerada o chão.

Nota

O caminho da câmara durante o processo de digitalização também é usado neste processo.

Um subconjunto das consultas expostas pelo gestor de Topologia são expostos através do dll. As consultas de topologia expostas são as seguintes.

QueryTopology_FindPositionsOnWalls
QueryTopology_FindLargePositionsOnWalls
QueryTopology_FindLargestWall
QueryTopology_FindPositionsOnFloor
QueryTopology_FindLargestPositionsOnFloor
QueryTopology_FindPositionsSittable

Cada uma das consultas tem um conjunto de parâmetros, específicos do tipo de consulta. No exemplo seguinte, o utilizador especifica a largura mínima de altura & do volume pretendido, a altura mínima de colocação acima do solo e a quantidade mínima de espaço livre à frente do volume. Todas as medições estão nos metros.

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 destas consultas requer uma matriz pré-atribuída de estruturas "TopologyResult". O parâmetro "locationCount" especifica o comprimento do passado na matriz. O valor de retorno reporta o número de locais devolvidos. Este número nunca é maior do que o passado no parâmetro "locationCount".

O "TopologyResult" contém a posição central do volume devolvido, a direção virada (ou seja, normal) e as dimensões do espaço encontrado.

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

Nota

Na amostra Unidade, cada uma destas consultas está ligada a um botão no painel virtual de UI. A amostra codifica os parâmetros para cada uma destas consultas a valores razoáveis. Consulte o SpaceVisualizer.cs no código da amostra para mais exemplos.

Consultas de forma

No dll, o analisador de forma ("ShapeAnalyzer_W") utiliza o analisador de topologia para combinar com as formas personalizadas definidas pelo utilizador. A amostra Unidade define um conjunto de formas e expõe os resultados através do menu de consulta in-app, dentro do separador forma. A intenção é que o utilizador possa definir as suas próprias consultas de forma de objeto e fazer uso dessas, conforme necessário pela sua aplicação.

A análise da forma funciona apenas em superfícies horizontais. Um sofá, por exemplo, é definido pela superfície do assento plano e pela parte superior plana do sofá de volta. A consulta de forma procura duas superfícies de tamanho, altura e intervalo de aspeto específicos, com as duas superfícies alinhadas e conectadas. Utilizando a terminologia APIs, o assento do sofá e a parte de trás são componentes de forma e os requisitos de alinhamento são restrições de componente de forma.

Uma consulta de exemplo definida na amostra de Unidade (ShapeDefinition.cs), para objetos "sittable" é a seguinte.

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 dependências entre os componentes. Este exemplo inclui três constrangimentos numa única definição de componente e nenhuma limitação de forma entre os componentes (uma vez que há apenas um componente).

Em contraste, a forma do sofá tem dois componentes de forma e quatro constrangimentos de forma. Os componentes são identificados pelo seu índice na lista de componentes do utilizador (0 e 1 neste exemplo).

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 invólucro são fornecidas no módulo Unidade para uma fácil criação de definições de forma personalizada. A lista completa de restrições de componente e forma pode ser encontrada em "SpatialUnderstandingDll.cs" dentro das estruturas "ShapeComponentConstraint" e "ShapeConstraint".

A forma do retângulo é encontrada nesta superfície
A forma do retângulo é encontrada nesta superfície

Solver de colocação de objetos

O solucionador de colocação de objetos pode ser usado para identificar locais ideais na sala física para colocar os seus objetos. O solucionador encontrará a localização mais adequada dadas as regras e constrangimentos do objeto. Além disso, as consultas de objetos persistem até que o objeto seja removido com chamadas "Solver_RemoveObject" ou "Solver_RemoveAllObjects", permitindo a colocação restrita de vários objetos. As consultas de colocação de objetos consistem em três partes: tipo de colocação com parâmetros, uma lista de regras e uma lista de constrangimentos. Para executar uma consulta, utilize a seguinte 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)

Esta função tem um nome de objeto, definição de colocação, e uma lista de regras e restrições. Os invólucros C# proporcionam funções de ajudante de construção para facilitar a construção de regras e restrições. A definição de colocação contém o tipo de consulta – isto é, uma das seguintes.

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 colocação tem um conjunto de parâmetros exclusivos do tipo. A estrutura "ObjectPlacementDefinition" contém um conjunto de funções estáticas de ajudante para a criação destas definições. Por exemplo, para encontrar um lugar para colocar um objeto no chão, pode utilizar a seguinte função. Objeto estático públicoDefinição Create_OnFloor (Vetor3 halfDims) Além do tipo de colocação, você pode fornecer um conjunto de regras e restrições. As regras não podem ser violadas. Possíveis locais de colocação que satisfaçam o tipo e as regras são então otimizados contra o conjunto de restrições de modo a selecionar o local ideal de colocação. Cada uma das regras e constrangimentos pode ser criada pelas funções de criação estática fornecidas. Uma função de construção de regra e restrição de exemplo é fornecida abaixo.

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 colocação de objetos abaixo está à procura de um lugar para colocar um cubo de meio metro na borda de uma superfície, longe de outros objetos anteriormente colocados e perto do centro da sala.

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, é devolvida uma estrutura "ObjectPlacementResult" que contém a posição, dimensões e orientação de colocação. Além disso, a colocação é adicionada à lista interna do dll de objetos colocados. As consultas de colocação subsequentes terão em conta este objeto. O ficheiro "LevelSolver.cs" na amostra Unidade contém mais perguntas de exemplo.

Resultados da colocação de objetos
Figura 3: As caixas azuis como o resultado de três lugares em consultas de piso com longe das regras de posição da câmara

Ao resolver para a localização de vários objetos necessários para um cenário de nível ou aplicação, primeiro resolva objetos indispensáveis e grandes de forma a maximizar a probabilidade de um espaço ser encontrado. A ordem de colocação é importante. Se não forem encontradas colocações de objetos, experimente configurações menos restritas. Ter um conjunto de configurações de recuo é fundamental para suportar a funcionalidade em muitas configurações de sala.

Processo de digitalização de quartos

Enquanto a solução de mapeamento espacial fornecida pelo HoloLens é projetada para ser genérica o suficiente para satisfazer as necessidades de toda a gama de espaços problemáticos, o módulo de compreensão espacial foi construído para suportar as necessidades de dois jogos específicos. A sua solução está estruturada em torno de um processo específico e conjunto de pressupostos, resumidos abaixo.

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" do espaço de reprodução orientada pelo utilizador – Durante a fase de digitalização, o utilizador move-se e olha em torno do ritmo das peças, pintando efetivamente as áreas, que devem ser incluídas. A malha gerada é importante para fornecer feedback do utilizador durante esta fase. Instalação de casa ou escritório interior - As funções de consulta são projetadas em torno de superfícies planas e paredes em ângulos retos. Esta é uma limitação suave. No entanto, durante a fase de digitalização, é concluída uma análise do eixo primário para otimizar a tessellação da malha ao longo do eixo principal e menor. O ficheiro SpatialUnderstanding incluído.cs gere o processo de fase de digitalização. Chama as seguintes funções.

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 digitalização, impulsionado pelo comportamento "SpatialUnderstanding" chama InitScan, em seguida, UpdateScan cada frame. Quando a consulta estatística reporta uma cobertura razoável, o utilizador é autorizado a ligar para RequestFinish para indicar o fim da fase de digitalização. UpdateSCan continua a ser chamado até que o seu valor de devolução indique que o dll completou o processamento.

Compreender a Malha

O dll de compreensão armazena internamente o espaço de reprodução como uma grelha de cubos voxel de 8 cm de tamanho. Durante a parte inicial da digitalização, uma análise de componente primário é concluída para determinar os eixos da sala. Internamente, armazena o seu espaço voxel alinhado com estes eixos. Uma malha é gerada aproximadamente a cada segundo extraindo o isossurface do volume voxel.

Malha gerada produzida a partir do volume voxel
Malha gerada produzida a partir do volume voxel

Resolução de problemas

  • Certifique-se de que definiu a capacidade de Perceção Espacial
  • Quando o rastreio é perdido, o próximo evento OnSurfaceChanged removerá todas as malhas.

Mapeamento espacial em kit de ferramentas de realidade mista

Para obter mais informações sobre a utilização do Mapial Mapping com O Kit de Ferramentas de Realidade Mista, consulte a secção de sensibilização espacial dos docs MRTK.

Próximo checkpoint de desenvolvimento

Se está a seguir a jornada de desenvolvimento da Unidade que estabelecemos, está no meio de explorar os blocos de construção do MRTK. A partir daqui, pode continuar até ao próximo bloco de construção:

Ou saltar para as capacidades da plataforma de realidade mista e APIs:

Pode sempre voltar aos postos de controlo de desenvolvimento da Unidade a qualquer momento.

Ver também