Visão geral do SDK de reconhecimento de cena

A compreensão de cena transforma os dados do sensor de ambiente não estruturado que seu dispositivo Realidade Misturada captura e os converte em uma representação abstrata poderosa. O SDK atua como a camada de comunicação entre seu aplicativo e o runtime de Reconhecimento de Cena. Ele tem como objetivo imitar constructos padrão existentes, como grafos de cena 3D para representações 3D e retângulos e painéis 2D para aplicativos 2D. Embora os constructos que o Reconhecimento de Cena imita sejam mapeados para estruturas concretas, em geral SceneUnderstanding é a estrutura independente, permitindo a interoperabilidade entre estruturas variadas que interagem com ela. À medida que o Reconhecimento de Cena evolui, a função do SDK é garantir que novas representações e funcionalidades continuem a ser expostas em uma estrutura unificada. Neste documento, primeiro apresentaremos conceitos de alto nível que ajudarão você a se familiarizar com o ambiente/uso de desenvolvimento e, em seguida, forneceremos documentação mais detalhada para classes e constructos específicos.

Onde faço para obter o SDK?

O SDK SceneUnderstanding pode ser baixado por meio do Realidade Misturada Feature Tool.

Observação: a versão mais recente depende de pacotes de visualização e você precisará habilitar pacotes de pré-lançamento para vê-lo.

Para a versão 0.5.2022-rc e posterior, o Reconhecimento de Cena dá suporte a projeções de linguagem para C# e C++ permitindo que aplicativos desenvolvam aplicativos para plataformas Win32 ou UWP. A partir desta versão, SceneUnderstanding dá suporte ao suporte do unity no editor, barrando o SceneObserver, que é usado exclusivamente para se comunicar com o HoloLens2.

SceneUnderstanding requer o SDK do Windows versão 18362 ou superior.

Visão geral conceitual

A Cena

Seu dispositivo de realidade misturada está constantemente integrando informações sobre o que ele vê em seu ambiente. O Reconhecimento de Cena canaliza todas essas fontes de dados e produz uma única abstração coesa. O Reconhecimento de Cena gera Cenas, que são uma composição de SceneObjects que representam uma instância de uma única coisa, (por exemplo, uma parede/teto/piso.) Os objetos de cena em si são uma composição de [SceneComponents, que representam peças mais granulares que compõem esse SceneObject. Exemplos de componentes são quadras e malhas, mas no futuro podem representar caixas delimitadoras, malhas de colisão, metadados etc.

O processo de converter os dados brutos do sensor em uma Cena é uma operação potencialmente cara que pode levar segundos para espaços médios (~10x10m) em minutos para espaços grandes (~50x50m) e, portanto, não é algo que está sendo calculado pelo dispositivo sem solicitação de aplicativo. Em vez disso, a geração de cena é disparada pelo aplicativo sob demanda. A classe SceneObserver tem métodos estáticos que podem Computar ou Desserializar uma cena, com os quais você pode enumerar/interagir. A ação "Computação" é executada sob demanda e executada na CPU, mas em um processo separado (o driver Realidade Misturada). No entanto, enquanto fazemos computação em outro processo, os dados resultantes de Cena são armazenados e mantidos em seu aplicativo no objeto Scene.

Abaixo está um diagrama que ilustra esse fluxo de processo e mostra exemplos de dois aplicativos interfigurando com o runtime de Reconhecimento de Cena.

Diagrama de Processo

No lado esquerdo está um diagrama do runtime de realidade misturada, que está sempre ativado e em execução em seu próprio processo. Esse runtime é responsável por executar o rastreamento de dispositivos, o mapeamento espacial e outras operações que o Reconhecimento de Cena usa para entender e raciocinar sobre o mundo ao seu redor. No lado direito do diagrama, mostramos dois aplicativos teóricos que usam o Reconhecimento de Cena. As primeiras interfaces de aplicativo com o MRTK, que usa o SDK de Reconhecimento de Cena internamente, o segundo aplicativo calcula e usa duas instâncias de cena separadas. Todas as três Cenas neste diagrama geram instâncias distintas das cenas, o driver não está rastreando o estado global que é compartilhado entre aplicativos e Objetos de Cena em uma cena não são encontradas em outra. O Reconhecimento de Cena fornece um mecanismo para acompanhar ao longo do tempo, mas isso é feito usando o SDK. O código de acompanhamento já está em execução no SDK no processo do aplicativo.

Como cada Cena armazena seus dados no espaço de memória do aplicativo, você pode assumir que todas as funções do objeto Scene ou seus dados internos são sempre executadas no processo do aplicativo.

Layout

Para trabalhar com o Reconhecimento de Cena, pode ser importante saber e entender como o runtime representa componentes de forma lógica e física. A Cena representa dados com um layout específico que foi escolhido para ser simples, mantendo uma estrutura subjacente que é passível de atender a requisitos futuros sem a necessidade de revisões importantes. A Cena faz isso armazenando todos os Componentes (blocos de construção para todos os Objetos de Cena) em uma lista simples e definindo hierarquia e composição por meio de referências em que componentes específicos fazem referência a outros.

Abaixo, apresentamos um exemplo de uma estrutura em sua forma plana e lógica.

Layout lógicoLayout Físico
    Cena
    • SceneObject_1
      • SceneMesh_1
      • SceneQuad_1
      • SceneQuad_2
    • SceneObject_2
      • SceneQuad_1
      • SceneQuad_3
    • SceneObject_3
      • SceneMesh_3
  • SceneObject_1
  • SceneObject_2
  • SceneObject_3
  • SceneQuad_1
  • SceneQuad_2
  • SceneQuad_3
  • SceneMesh_1
  • SceneMesh_2

Esta ilustração realça a diferença entre o layout físico e lógico da Cena. À esquerda, vemos o layout hierárquico dos dados que seu aplicativo vê ao enumerar a cena. À direita, vemos que a cena é composta por 12 componentes distintos que são acessíveis individualmente, se necessário. Ao processar uma nova cena, esperamos que os aplicativos andem nessa hierarquia logicamente, no entanto, ao acompanhar entre atualizações de cena, alguns aplicativos só podem estar interessados em direcionar componentes específicos que são compartilhados entre duas cenas.

Visão geral da API

A seção a seguir fornece uma visão geral de alto nível dos constructos no Reconhecimento de Cena. Ler esta seção fornecerá uma compreensão de como as cenas são representadas e para que os vários componentes fazem/são usados. A próxima seção fornecerá exemplos de código concretos e detalhes adicionais que são relançados nesta visão geral.

Todos os tipos descritos abaixo residem no Microsoft.MixedReality.SceneUnderstanding namespace.

SceneComponents

Agora que você entende o layout lógico das cenas, podemos apresentar o conceito de SceneComponents e como elas são usadas para compor a hierarquia. SceneComponents são as decomposições mais granulares em SceneUnderstanding representando uma única coisa de núcleo, por exemplo, uma malha ou um quad ou uma caixa delimitadora. SceneComponents são coisas que podem ser atualizadas de forma independente e podem ser referenciadas por outros SceneComponents, portanto, eles têm uma única propriedade global, uma ID exclusiva, que permite esse tipo de mecanismo de acompanhamento/referência. As IDs são usadas para a composição lógica da hierarquia de cena, bem como para a persistência do objeto (o ato de atualizar uma cena em relação a outra).

Se você estiver tratando cada cena recém-computada como sendo distinta e simplesmente enumerando todos os dados dentro dela, as IDs serão amplamente transparentes para você. No entanto, se você estiver planejando rastrear componentes em várias atualizações, usará as IDs para indexar e localizar SceneComponents entre objetos Scene.

SceneObjects

Um SceneObject é um SceneComponent que representa uma instância de uma "coisa", por exemplo, uma parede, um piso, um teto etc.... expresso por sua propriedade Kind. SceneObjects são geométricos e, portanto, têm funções e propriedades que representam sua localização no espaço, no entanto, elas não contêm nenhuma estrutura geométrica ou lógica. Em vez disso, SceneObjects referenciam outros SceneComponents, especificamente SceneQuads e SceneMeshes, que fornecem as diversas representações compatíveis com o sistema. Quando uma nova cena for computada, seu aplicativo provavelmente enumerará Os SceneObjects da Cena para processar o que ele está interessado.

SceneObjects pode ter qualquer um dos seguintes:

SceneObjectKind Descrição
Tela de fundoO SceneObject é conhecido por não ser um dos outros tipos reconhecidos de objeto de cena. Esta classe não deve ser confundida com Unknown onde Background é conhecido por não ser parede/piso/teto etc.... enquanto desconhecido ainda não está categorizado.
ParedeUma parede física. Presume-se que as paredes sejam estruturas ambientais imóveis.
PisoPisos são quaisquer superfícies nas quais se pode andar. Observação: escadas não são pisos. Observe também que os pisos pressupõem qualquer superfície andável e, portanto, não há nenhuma suposição explícita de um piso singular. Estruturas de vários níveis, rampas etc.... todos devem ser classificados como piso.
CeilingA superfície superior de uma sala.
PlataformaUma superfície plana grande na qual você poderia colocar hologramas. Elas tendem a representar tabelas, bancadas e outras grandes superfícies horizontais.
World (Mundo)Um rótulo reservado para dados geométricos independentes de rotulagem. A malha gerada definindo o sinalizador de atualização EnableWorldMesh seria classificada como mundo.
UnknownEste objeto de cena ainda não foi classificado e atribuído a um tipo. Isso não deve ser confundido com Background, pois esse objeto pode ser qualquer coisa, o sistema simplesmente não criou uma classificação forte o suficiente para ele ainda.

SceneMesh

Um SceneMesh é um SceneComponent que aproxima a geometria de objetos geométricos arbitrários usando uma lista de triângulos. SceneMeshes são usados em vários contextos diferentes; eles podem representar componentes da estrutura de células impermeáveis ou como WorldMesh, que representa a malha de mapeamento espacial não associada associada à Cena. Os dados de índice e vértice fornecidos com cada malha usam o mesmo layout familiar que os buffers de vértice e índice usados para renderizar malhas de triângulo em todas as APIs de renderização modernas. No Reconhecimento de Cena, as malhas usam índices de 32 bits e podem precisar ser divididas em partes para determinados mecanismos de renderização.

Sistemas de ordem e coordenadas sinuosos

Espera-se que todas as malhas produzidas pelo Reconhecimento de Cena retornem malhas em um sistema de coordenadas Right-Handed usando a ordem de enrolamento no sentido horário.

Observação: os builds do sistema operacional antes de .191105 podem ter um bug conhecido em que as malhas "World" estavam retornando em Counter-Clockwise ordem de enrolamento, que foi corrigida posteriormente.

SceneQuad

Um SceneQuad é um SceneComponent que representa superfícies 2d que ocupam o mundo 3D. SceneQuads pode ser usado de forma semelhante a ARKit ARPlaneAnchor ou ARCore Planes, mas eles oferecem mais funcionalidade de alto nível como telas 2d a serem usadas por aplicativos simples ou UX aumentado. APIs específicas 2D são fornecidas para quadriciclos que tornam o posicionamento e o layout simples de usar, e o desenvolvimento (com exceção da renderização) com quads deve se sentir mais parecido com trabalhar com telas 2d do que malhas 3d.

Forma SceneQuad

SceneQuads define uma superfície retangular limitada em 2d. No entanto, SceneQuads estão representando superfícies com formas arbitrárias e potencialmente complexas (por exemplo, uma tabela em forma de rosca).) Para representar a forma complexa da superfície de um quadriciclo, você pode usar a API GetSurfaceMask para renderizar a forma da superfície em um buffer de imagem fornecido. Se o SceneObject que tem o quadriciclo também tiver uma malha, os triângulos de malha deverão ser equivalentes a essa imagem renderizada, ambos representam geometria real da superfície, seja em coordenadas 2d ou 3d.

Referência e detalhes do SDK de reconhecimento de cena

Observação

Ao usar o MRTK, observe que você interagirá com o ['WindowsSceneUnderstandingObserver' do MRTK](xref:Microsoft.MixedReality.Toolkit.WindowsSceneUnderstanding.Experimental.WindowsSceneUnderstandingObserver?view=mixed-reality-toolkit-unity-2020-dotnet-2.8.0&preserve-view=true) e, portanto, pode ignorar esta seção na maioria das circunstâncias. Consulte [documentos de Reconhecimento de Cena do MRTK](/windows/mixed-reality/mrtk-unity/features/spatial-awareness/scene-understanding) para obter mais informações.

A seção a seguir ajudará você a se familiarizar com os conceitos básicos de SceneUnderstanding. Esta seção deve fornecer as noções básicas, momento em que você deve ter contexto suficiente para navegar pelos aplicativos de exemplo para ver como SceneUnderstanding é usado de forma holística.

Inicialização

A primeira etapa para trabalhar com SceneUnderstanding é que seu aplicativo obtenha referência a um objeto Scene. Isso pode ser feito de duas maneiras, uma Cena pode ser computada pelo driver ou uma Cena existente que foi computada no passado pode ser des serializada. Este último é útil para trabalhar com SceneUnderstanding durante o desenvolvimento, onde aplicativos e experiências podem ser protótipos rapidamente sem um dispositivo de realidade misturada.

As cenas são computadas usando um SceneObserver. Antes de criar uma Cena, seu aplicativo deve consultar seu dispositivo para garantir que ele dê suporte a SceneUnderstanding, bem como solicitar acesso do usuário para obter informações de que SceneUnderstanding precisa.

if (!SceneObserver.IsSupported())
{
    // Handle the error
}

// This call should grant the access we need.
await SceneObserver.RequestAccessAsync();

Se RequestAccessAsync() não for chamado, a computação de uma nova Cena falhará. Em seguida, calcularemos uma nova cena com raiz ao redor do fone de ouvido Realidade Misturada e tem um raio de 10 metros.

// Create Query settings for the scene update
SceneQuerySettings querySettings;

querySettings.EnableSceneObjectQuads = true;                                       // Requests that the scene updates quads.
querySettings.EnableSceneObjectMeshes = true;                                      // Requests that the scene updates watertight mesh data.
querySettings.EnableOnlyObservedSceneObjects = false;                              // Do not explicitly turn off quad inference.
querySettings.EnableWorldMesh = true;                                              // Requests a static version of the spatial mapping mesh.
querySettings.RequestedMeshLevelOfDetail = SceneMeshLevelOfDetail.Fine;            // Requests the finest LOD of the static spatial mapping mesh.

// Initialize a new Scene
Scene myScene = SceneObserver.ComputeAsync(querySettings, 10.0f).GetAwaiter().GetResult();

Inicialização de dados (também conhecido como caminho do computador)

Embora Cenas possam ser computadas para consumo direto, elas também podem ser computadas em formato serializado para uso posterior. Isso provou ser útil para o desenvolvimento, pois permite que os desenvolvedores trabalhem e testem o Reconhecimento de Cena sem a necessidade de um dispositivo. O ato de serializar uma cena é quase idêntico à computação, os dados são retornados ao aplicativo em vez de serem desserializados localmente pelo SDK. Em seguida, você pode desserializá-lo por conta própria ou salvá-lo para uso futuro.

// Create Query settings for the scene update
SceneQuerySettings querySettings;

// Compute a scene but serialized as a byte array
SceneBuffer newSceneBuffer = SceneObserver.ComputeSerializedAsync(querySettings, 10.0f).GetAwaiter().GetResult();

// If we want to use it immediately we can de-serialize the scene ourselves
byte[] newSceneData = new byte[newSceneBuffer.Size];
newSceneBuffer.GetData(newSceneData);
Scene mySceneDeSerialized = Scene.Deserialize(newSceneData);

// Save newSceneData for later

Enumeração SceneObject

Agora que seu aplicativo tem uma cena, seu aplicativo examinará e interagirá com SceneObjects. Isso é feito acessando a propriedade SceneObjects :

SceneObject firstFloor = null;

// Find the first floor object
foreach (var sceneObject in myScene.SceneObjects)
{
    if (sceneObject.Kind == SceneObjectKind.Floor)
    {
        firstFloor = sceneObject;
        break;
    }
}

Componentes de atualização e refinamento

Há outra função que recupera componentes na Cena chamada FindComponent. Essa função é útil ao atualizar objetos de rastreamento e encontrá-los em cenas posteriores. O código a seguir calculará uma nova cena em relação a uma cena anterior e, em seguida, encontrará o chão na nova cena.

// Compute a new scene, and tell the system that we want to compute relative to the previous scene
Scene myNextScene = SceneObserver.ComputeAsync(querySettings, 10.0f, myScene).GetAwaiter().GetResult();

// Use the Id for the floor we found last time, and find it again
firstFloor = (SceneObject)myNextScene.FindComponent(firstFloor.Id);

if (firstFloor != null)
{
    // We found it again, we can now update the transforms of all objects we attached to this floor transform
}

Acessando malhas e quads de objetos de cena

Depois que SceneObjects tiver sido encontrado, seu aplicativo provavelmente desejará acessar os dados contidos nos quadriciclos/malhas dos quais ele é composto. Esses dados são acessados com as propriedades Quads e Meshes . O código a seguir enumerará todos os quadris e malhas do nosso objeto floor.


// Get the transform for the SceneObject
System.Numerics.Matrix4x4 objectToSceneOrigin = firstFloor.GetLocationAsMatrix();

// Enumerate quads
foreach (var quad in firstFloor.Quads)
{
    // Process quads
}

// Enumerate meshes
foreach (var mesh in firstFloor.Meshes)
{
    // Process meshes
}

Observe que é o SceneObject que tem a transformação relativa à origem da cena. Isso ocorre porque o SceneObject representa uma instância de uma "coisa" e é localizado no espaço, os quadriciclos e as malhas representam a geometria que é transformada em relação ao pai. É possível que SceneObjects separados referencie os mesmos SceneMesh/SceneQuad SceneComponents, e também é possível que um SceneObject tenha mais de uma SceneMesh/SceneQuad.

Lidando com transformações

O Reconhecimento de Cena fez uma tentativa deliberada de se alinhar com as representações tradicionais de cena 3D ao lidar com transformações. Cada Cena é, portanto, confinada a um único sistema de coordenadas, assim como as representações ambientais 3D mais comuns. SceneObjects cada um fornece sua localização em relação a esse sistema de coordenadas. Se seu aplicativo estiver lidando com Cenas que ampliam o limite do que uma única origem fornece, ele pode ancorar SceneObjects para SpatialAnchors ou gerar várias cenas e mescla-las, mas, para simplificar, assumimos que existem cenas impermeáveis em sua própria origem localizadas por um NodeId definido por Scene.OriginSpatialGraphNodeId.

O código do Unity a seguir, por exemplo, mostra como usar as APIs do Windows Perception e do Unity para alinhar sistemas de coordenadas. Consulte SpatialCoordinateSystem e SpatialGraphInteropPreview para obter detalhes sobre as APIs de Percepção do Windows e Realidade Misturada objetos nativos no Unity para obter detalhes sobre como obter um SpatialCoordinateSystem que corresponde à origem mundial do Unity.

private System.Numerics.Matrix4x4? GetSceneToUnityTransformAsMatrix4x4(SceneUnderstanding.Scene scene)
{
    System.Numerics.Matrix4x4? sceneToUnityTransform = System.Numerics.Matrix4x4.Identity;

    
    Windows.Perception.Spatial.SpatialCoordinateSystem sceneCoordinateSystem = Microsoft.Windows.Perception.Spatial.Preview.SpatialGraphInteropPreview.CreateCoordinateSystemForNode(scene.OriginSpatialGraphNodeId);
    Windows.Perception.Spatial.SpatialCoordinateSystem unityCoordinateSystem = Microsoft.Windows.Perception.Spatial.SpatialCoordinateSystem.FromNativePtr(UnityEngine.XR.WindowsMR.WindowsMREnvironment.OriginSpatialCoordinateSystem);

    sceneToUnityTransform = sceneCoordinateSystem.TryGetTransformTo(unityCoordinateSystem);

    if (sceneToUnityTransform != null)
    {
        sceneToUnityTransform = ConvertRightHandedMatrix4x4ToLeftHanded(sceneToUnityTransform.Value);
    }
    else
    {
        return null;
    }
            
    return sceneToUnityTransform;
}

Cada SceneObject uma tem uma transformação, que é então aplicada a esse objeto. No Unity, convertemos em coordenadas destros e atribuimos transformações locais da maneira que:

private System.Numerics.Matrix4x4 ConvertRightHandedMatrix4x4ToLeftHanded(System.Numerics.Matrix4x4 matrix)
{
    matrix.M13 = -matrix.M13;
    matrix.M23 = -matrix.M23;
    matrix.M43 = -matrix.M43;

    matrix.M31 = -matrix.M31;
    matrix.M32 = -matrix.M32;
    matrix.M34 = -matrix.M34;

    return matrix;
}

 private void SetUnityTransformFromMatrix4x4(Transform targetTransform, System.Numerics.Matrix4x4 matrix, bool updateLocalTransformOnly = false)
 {
    if(targetTransform == null)
    {
        return;
    }

    Vector3 unityTranslation;
    Quaternion unityQuat;
    Vector3 unityScale;

    System.Numerics.Vector3 vector3;
    System.Numerics.Quaternion quaternion;
    System.Numerics.Vector3 scale;

    System.Numerics.Matrix4x4.Decompose(matrix, out scale, out quaternion, out vector3);

    unityTranslation = new Vector3(vector3.X, vector3.Y, vector3.Z);
    unityQuat        = new Quaternion(quaternion.X, quaternion.Y, quaternion.Z, quaternion.W);
    unityScale       = new Vector3(scale.X, scale.Y, scale.Z);

    if(updateLocalTransformOnly)
    {
        targetTransform.localPosition = unityTranslation;
        targetTransform.localRotation = unityQuat;
    }
    else
    {
        targetTransform.SetPositionAndRotation(unityTranslation, unityQuat);
    }
}

// Assume we have an SU object called suObject and a unity equivalent unityObject

System.Numerics.Matrix4x4 converted4x4LocationMatrix = ConvertRightHandedMatrix4x4ToLeftHanded(suObject.GetLocationAsMatrix());
SetUnityTransformFromMatrix4x4(unityObject.transform, converted4x4LocationMatrix, true);
        

Quad

Os quads foram projetados para ajudar em cenários de posicionamento 2D e devem ser considerados como extensões para elementos UX de tela 2D. Embora os Quads sejam componentes de SceneObjects e possam ser renderizados em 3D, as APIs quad pressupõem que Quads são estruturas 2D. Eles oferecem informações como extensão, forma e fornecem APIs para posicionamento.

Os quads têm extensões retangulares, mas representam superfícies 2D arbitrariamente moldada. Para habilitar o posicionamento nessas superfícies 2D que interagem com os quads de ambiente 3D, ofereça utilitários para tornar essa interação possível. Atualmente, o Reconhecimento de Cena fornece duas dessas funções, FindCentermostPlacement e GetSurfaceMask. FindCentermostPlacement é uma API de alto nível que localiza uma posição no quadriciclo em que um objeto pode ser colocado e tentará encontrar o melhor local para seu objeto, garantindo que a caixa delimitadora fornecida permanecerá na superfície subjacente.

Observação

As coordenadas da saída são relativas ao quad em "espaço quádruplo" com o canto superior esquerdo sendo (x = 0, y = 0), assim como seria com outros tipos de Rect do Windows. Lembre-se de levar isso em conta ao trabalhar com as origens de seus próprios objetos.

O exemplo a seguir mostra como encontrar o local mais centralizável e ancorar um holograma no quadriciclo.

// This code assumes you already have a "Root" object that attaches the Scene's Origin.

// Find the first quad
foreach (var sceneObject in myScene.SceneObjects)
{
    // Find a wall
    if (sceneObject.Kind == SceneObjectKind.Wall)
    {
        // Get the quad
        var quads = sceneObject.Quads;
        if (quads.Count > 0)
        {
            // Find a good location for a 1mx1m object  
            System.Numerics.Vector2 location;
            if (quads[0].FindCentermostPlacement(new System.Numerics.Vector2(1.0f, 1.0f), out location))
            {
                // We found one, anchor something to the transform
                // Step 1: Create a new game object for the quad itself as a child of the scene root
                // Step 2: Set the local transform from quads[0].Position and quads[0].Orientation
                // Step 3: Create your hologram and set it as a child of the quad's game object
                // Step 4: Set the hologram's local transform to a translation (location.x, location.y, 0)
            }
        }
    }
}

As etapas 1 a 4 são altamente dependentes de sua estrutura/implementação específica, mas os temas devem ser semelhantes. É importante observar que o Quad simplesmente representa um plano 2D limitado localizado no espaço. Ao fazer com que seu mecanismo/estrutura saiba onde está o quadriciclo e enraize seus objetos em relação ao quadriciclo, seus hologramas estarão localizados corretamente em relação ao mundo real.

Malha

As malhas representam representações geométricas de objetos ou ambientes. Assim como o mapeamento espacial, o índice de malha e os dados de vértice fornecidos com cada malha de superfície espacial usam o mesmo layout familiar que os buffers de vértice e índice usados para renderizar malhas de triângulo em todas as APIs de renderização modernas. As posições de vértice são fornecidas no sistema de coordenadas do Scene. As APIs específicas usadas para fazer referência a esses dados são as seguintes:

void GetTriangleIndices(int[] indices);
void GetVertices(System.Numerics.Vector3[] vertices);

O código a seguir fornece um exemplo de geração de uma lista de triângulos da estrutura de malha:

uint[] indices = new uint[mesh.TriangleIndexCount];
System.Numerics.Vector3[] positions = new System.Numerics.Vector3[mesh.VertexCount];

mesh.GetTriangleIndices(indices);
mesh.GetVertexPositions(positions);

Os buffers de índice/vértice devem ser >= as contagens de índice/vértice, mas, caso contrário, podem ser dimensionados arbitrariamente, permitindo a reutilização eficiente da memória.

ColliderMesh

Os objetos de cena fornecem acesso aos dados de malha de malha e colisor por meio das propriedades Meshes e ColliderMeshes. Essas malhas sempre corresponderão, o que significa que o i'th índice da propriedade Meshes representa a mesma geometria que o índice i'th da propriedade ColliderMeshes. Se o runtime/objeto der suporte a malhas de colisor, você terá a garantia de obter o polígono mais baixo, a aproximação de ordem mais alta e é uma boa prática usar ColliderMeshes onde quer que seu aplicativo use colisores. Se o sistema não der suporte a colisores, o objeto Mesh retornado em ColliderMeshes será o mesmo objeto que a malha que reduz as restrições de memória.

Desenvolvendo com a compreensão da cena

Neste ponto, você deve entender os principais blocos de construção da cena que compreendem o runtime e o SDK. A maior parte da potência e complexidade está em padrões de acesso, interação com estruturas 3D e ferramentas que podem ser escritas sobre essas APIs para realizar tarefas mais avançadas, como planejamento espacial, análise de sala, navegação, física e assim por diante. Esperamos capturá-los em exemplos que devem guiá-lo na direção adequada para fazer seus cenários brilharem. Se houver exemplos ou cenários que não estamos abordando, informe-nos e tentaremos documentar/protótipo o que você precisa.

Onde posso obter o código de exemplo?

O código de exemplo de Reconhecimento de Cena para Unity pode ser encontrado em nossa página Página de Exemplo do Unity . Esse aplicativo permitirá que você se comunique com seu dispositivo e renderize os vários objetos de cena ou permitirá que você carregue uma cena serializada em seu computador e permitirá que você experimente o Reconhecimento de Cena sem um dispositivo.

Onde posso obter cenas de exemplo?

Se você tiver um HoloLens2, poderá salvar qualquer cena capturada salvando a saída de ComputeSerializedAsync para arquivar e desserializá-la em sua própria conveniência.

Se você não tiver um dispositivo HoloLens2, mas quiser jogar com o Reconhecimento de Cena, precisará baixar uma cena pré-capturada. O exemplo de Reconhecimento de Cena atualmente é fornecido com cenas serializadas que podem ser baixadas e usadas por sua própria conveniência. Você pode encontrá-los aqui:

Cenas de exemplo de compreensão de cena

Veja também