Introducción al SDK de scene understanding

La comprensión de la escena transforma los datos del sensor de entorno no estructurados que captura el dispositivo Mixed Reality y lo convierte en una representación abstracta eficaz. El SDK actúa como la capa de comunicación entre la aplicación y el entorno de ejecución de Scene Understanding. Está destinado a imitar construcciones estándar existentes, como gráficos de escenas 3D para representaciones 3D y rectángulos y paneles 2D para aplicaciones 2D. Aunque las construcciones scene Understanding imitan se asignarán a marcos concretos, en general SceneUnderstanding es independiente del marco, lo que permite la interoperabilidad entre diversos marcos que interactúan con él. A medida que Scene Understanding evoluciona el rol del SDK es asegurarse de que las nuevas representaciones y funcionalidades se sigan exponiendo dentro de un marco unificado. En este documento, primero presentaremos conceptos de alto nivel que le ayudarán a familiarizarse con el entorno de desarrollo o el uso y, a continuación, proporcionaremos documentación más detallada para clases y construcciones específicas.

¿Dónde obtengo el SDK?

El SDK de SceneUnderstanding se puede descargar a través de la herramienta de características Mixed Reality.

Nota: la versión más reciente depende de los paquetes de versión preliminar y deberá habilitar los paquetes de versión preliminar para verlos.

Para la versión 0.5.2022-rc y posteriores, Scene Understanding admite proyecciones de lenguaje para C# y C++ que permiten a las aplicaciones desarrollar aplicaciones para plataformas Win32 o UWP. A partir de esta versión, SceneUnderstanding admite la compatibilidad con unity en el editor con la barra SceneObserver, que se usa únicamente para comunicarse con HoloLens2.

SceneUnderstanding requiere la versión 18362 o posterior de Windows SDK.

Información conceptual

La escena

El dispositivo de realidad mixta está integrando constantemente información sobre lo que ve en su entorno. Scene Understanding embudo todos estos orígenes de datos y genera una única abstracción cohesiva. Scene Understanding genera escenas, que son una composición de SceneObjects que representa una instancia de una sola cosa (por ejemplo, una pared/techo/piso). Los objetos de escena son una composición de [SceneComponents, que representan partes más granulares que componen este SceneObject. Algunos ejemplos de componentes son quads y mallas, pero en el futuro podrían representar cuadros de límite, mallas de colisión, metadatos, etc.

El proceso de convertir los datos del sensor sin procesar en una escena es una operación potencialmente costosa que podría tardar segundos en espacios medianos (~10x10m) en minutos para espacios grandes (~50x50m) y, por lo tanto, no es algo que el dispositivo esté calculando sin solicitud de aplicación. En su lugar, la aplicación desencadena la generación de escenas a petición. La clase SceneObserver tiene métodos estáticos que pueden calcular o deserializar una escena, con la que puede enumerar o interactuar. La acción "Proceso" se ejecuta a petición y se ejecuta en la CPU, pero en un proceso independiente (el controlador de Mixed Reality). Sin embargo, mientras realizamos el proceso en otro proceso, los datos de escena resultantes se almacenan y mantienen en la aplicación en el objeto Scene.

A continuación se muestra un diagrama que ilustra este flujo de proceso y muestra ejemplos de dos aplicaciones que interconectan con el entorno de ejecución de Scene Understanding.

Diagrama de procesos

En el lado izquierdo se muestra un diagrama del entorno de ejecución de realidad mixta, que siempre está activado y en ejecución en su propio proceso. Este tiempo de ejecución es responsable de realizar el seguimiento de dispositivos, la asignación espacial y otras operaciones que Scene Understanding usa para comprender y razonar sobre el mundo que le rodea. En el lado derecho del diagrama, se muestran dos aplicaciones teóricas que usan Scene Understanding. La primera aplicación interfaces con MRTK, que usa el SDK de Scene Understanding internamente, la segunda aplicación calcula y usa dos instancias de escena independientes. Las tres escenas de este diagrama generan instancias distintas de las escenas, el controlador no realiza el seguimiento del estado global que se comparte entre las aplicaciones y los objetos de escena en una escena no se encuentran en otra. Scene Understanding proporciona un mecanismo para realizar un seguimiento a lo largo del tiempo, pero esto se hace mediante el SDK. El código de seguimiento ya se está ejecutando en el SDK en el proceso de la aplicación.

Dado que cada escena almacena sus datos en el espacio de memoria de la aplicación, puede suponer que todas las funciones del objeto Scene o sus datos internos siempre se ejecutan en el proceso de la aplicación.

Layout

Para trabajar con Scene Understanding, puede ser útil saber y comprender cómo el tiempo de ejecución representa los componentes de forma lógica y física. La escena representa los datos con un diseño específico que se eligió para ser sencillo al tiempo que mantiene una estructura subyacente que es confiable para cumplir los requisitos futuros sin necesidad de revisiones importantes. La escena lo hace almacenando todos los componentes (bloques de creación para todos los objetos de escena) en una lista plana y definiendo jerarquía y composición a través de referencias donde los componentes específicos hacen referencia a otros.

A continuación presentamos un ejemplo de una estructura en su forma plana y lógica.

Diseño lógicoDiseño físico
    Escena
    • 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

En esta ilustración se resalta la diferencia entre el diseño físico y lógico de la escena. A la izquierda, vemos el diseño jerárquico de los datos que ve la aplicación al enumerar la escena. A la derecha, vemos que la escena consta de 12 componentes distintos a los que se puede acceder individualmente si es necesario. Al procesar una nueva escena, esperamos que las aplicaciones pasen por esta jerarquía lógicamente, pero al realizar el seguimiento entre las actualizaciones de la escena, es posible que algunas aplicaciones solo estén interesadas en seleccionar componentes específicos que se comparten entre dos escenas.

Introducción a la API

En la sección siguiente se proporciona información general de alto nivel de las construcciones en Scene Understanding. Leer esta sección le proporcionará información sobre cómo se representan las escenas y para qué se usan los distintos componentes. En la sección siguiente se proporcionan ejemplos de código concretos y detalles adicionales que se describen en esta introducción.

Todos los tipos descritos a continuación residen en el Microsoft.MixedReality.SceneUnderstanding espacio de nombres .

SceneComponents

Ahora que comprende el diseño lógico de las escenas, podemos presentar el concepto de SceneComponents y cómo se usan para componer la jerarquía. SceneComponents son las descomposición más pormenorizadas de SceneUnderstanding que representan un único elemento principal, por ejemplo, una malla o un cuadrándulo o un rectángulo delimitador. SceneComponents son elementos que se pueden actualizar de forma independiente y que otros SceneComponents pueden hacer referencia a ellos, por lo que tienen una sola propiedad global, un identificador único, que permiten este tipo de mecanismo de seguimiento o referencia. Los identificadores se usan para la composición lógica de la jerarquía de escena, así como para la persistencia de objetos (el acto de actualizar una escena en relación con otra).

Si va a tratar cada escena recién calculada como distinta y simplemente enumerar todos los datos dentro de ella, los identificadores son en gran medida transparentes para usted. Sin embargo, si planea realizar un seguimiento de los componentes en varias actualizaciones, usará los identificadores para indexar y buscar SceneComponents entre objetos Scene.

SceneObjects

Un SceneObject es una sceneComponent que representa una instancia de una "cosa", por ejemplo, una pared, un piso, un techo, etc.... expresado por su propiedad Kind. SceneObjects son geométricos y, por lo tanto, tienen funciones y propiedades que representan su ubicación en el espacio, pero no contienen ninguna estructura geométrica o lógica. En su lugar, SceneObjects hace referencia a otros SceneComponents, específicamente SceneQuads y SceneMeshes, que proporcionan las diversas representaciones admitidas por el sistema. Cuando se calcula una nueva escena, la aplicación probablemente enumerará scene's SceneObjects para procesar lo que le interesa.

SceneObjects puede tener cualquiera de las siguientes opciones:

SceneObjectKind Descripción
Información previaSe sabe que SceneObject no es uno de los otros tipos reconocidos de objeto de escena. Esta clase no debe confundirse con Desconocido donde se sabe que Background no es pared/ suelo/techo, etc.... mientras que desconocido aún no está categorizado.
ParedUna pared física. Se supone que las paredes son estructuras ambientales inmóviles.
FloorLos pisos son superficies en las que se puede caminar. Nota: Las escaleras no son suelos. Tenga en cuenta también que los pisos asumen cualquier superficie caminable y, por lo tanto, no hay ninguna suposición explícita de un piso singular. Estructuras de varios niveles, rampas, etc.... debe clasificarse como piso.
CeilingSuperficie superior de una habitación.
PlataformaUna superficie plana grande en la que podrías colocar hologramas. Estos tienden a representar tablas, encimeras y otras superficies horizontales grandes.
WorldEtiqueta reservada para datos geométricos que son independientes del etiquetado. La malla generada estableciendo la marca de actualización EnableWorldMesh se clasificaría como mundo.
UnknownEste objeto de escena aún no se ha clasificado y asignado un tipo. Esto no debe confundirse con Background, ya que este objeto podría ser cualquier cosa, el sistema no acaba de encontrar una clasificación lo suficientemente fuerte para ello todavía.

SceneMesh

SceneMesh es una SceneComponent que aproxima la geometría de objetos geométricos arbitrarios mediante una lista de triángulos. SceneMeshes se utilizan en varios contextos diferentes; pueden representar componentes de la estructura de celdas herméticas o como WorldMesh, que representa la malla de asignación espacial sin enlazar asociada a la escena. Los datos de índice y vértice proporcionados con cada malla usan el mismo diseño conocido que los búferes de vértices e índices que se usan para representar mallas de triángulos en todas las API de representación modernas. En Scene Understanding, las mallas usan índices de 32 bits y es posible que deba dividirse en fragmentos para determinados motores de representación.

Sistemas de orden y coordenadas de desenlazamiento

Se espera que todas las mallas producidas por Scene Understanding devuelvan mallas en un sistema de coordenadas Right-Handed mediante el orden de devanado en el sentido de las agujas del reloj.

Nota: Las compilaciones del sistema operativo anteriores a .191105 pueden tener un error conocido en el que las mallas "World" regresaban en Counter-Clockwise orden de desvanado, que posteriormente se ha corregido.

SceneQuad

SceneQuad es una SceneComponent que representa superficies 2d que ocupan el mundo 3D. SceneQuads se puede usar de forma similar a ARKit ARPlaneAnchor o ARCore Planes, pero ofrecen una funcionalidad más de alto nivel como lienzos 2d que usarán las aplicaciones planas o la experiencia de usuario aumentada. Las API específicas de 2D se proporcionan para quads que hacen que la colocación y el diseño sean fáciles de usar, y el desarrollo (con la excepción de la representación) con quads debe sentirse más parecido a trabajar con lienzos 2d que mallas 3d.

Forma SceneQuad

SceneQuads define una superficie rectangular limitada en 2d. Sin embargo, SceneQuads representa superficies con formas arbitrarias y potencialmente complejas (por ejemplo, una tabla con forma de anillo). Para representar la forma compleja de la superficie de un quad, puede usar la API GetSurfaceMask para representar la forma de la superficie en un búfer de imágenes que proporcione. Si el SceneObject que tiene el quad también tiene una malla, los triángulos de malla deben ser equivalentes a esta imagen representada, ambos representan la geometría real de la superficie, ya sea en coordenadas 2d o 3d.

Detalles y referencia del SDK de descripción de la escena

Nota

Al usar MRTK, Tenga en cuenta que va a interactuar con el ['WindowsSceneUnderstandingObserver'](xref:Microsoft.MixedReality.Toolkit.WindowsSceneUnderstanding.Experimental.WindowsSceneUnderstandingObserver?view=mixed-reality-toolkit-unity-2020-dotnet-2.8.0&preserve-view=true) y, por tanto, puede omitir esta sección en la mayoría de las circunstancias. Consulte los documentos de [MRTK Scene Understanding](/windows/mixed-reality/mrtk-unity/features/spatial-awareness/scene-understanding) para obtener más información.

La siguiente sección le ayudará a familiarizarse con los conceptos básicos de SceneUnderstanding. Esta sección debe proporcionarle los conceptos básicos, en cuyo punto debe tener suficiente contexto para examinar las aplicaciones de ejemplo para ver cómo se usa SceneUnderstanding de forma holística.

Inicialización

El primer paso para trabajar con SceneUnderstanding es que la aplicación obtenga referencia a un objeto Scene. Esto se puede hacer de dos maneras: el controlador puede calcular una escena, o bien una escena existente que se calculó en el pasado se puede des serializar. Este último es útil para trabajar con SceneUnderstanding durante el desarrollo, donde las aplicaciones y experiencias se pueden crear prototipos rápidamente sin un dispositivo de realidad mixta.

Las escenas se calculan mediante sceneObserver. Antes de crear una escena, la aplicación debe consultar el dispositivo para asegurarse de que es compatible con SceneUnderstanding, así como para solicitar acceso de usuario para obtener información que SceneUnderstanding necesita.

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

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

Si no se llama a RequestAccessAsync(), se producirá un error al calcular una nueva escena. A continuación, calcularemos una nueva escena que se basa alrededor de los cascos de Mixed Reality y tiene un radio 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();

Inicialización de datos (también conocida como ruta de acceso del equipo)

Aunque las escenas se pueden calcular para su consumo directo, también se pueden calcular en forma serializada para su uso posterior. Esto ha demostrado ser útil para el desarrollo, ya que permite a los desarrolladores trabajar en y probar Scene Understanding sin necesidad de un dispositivo. El acto de serializar una escena es casi idéntico a calcularla, los datos se devuelven a la aplicación en lugar de ser deserializados localmente por el SDK. Después, puede deserializarlo usted mismo o guardarlo para su 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

SceneObject (enumeración)

Ahora que la aplicación tiene una escena, la aplicación buscará e interactuará con SceneObjects. Para ello, se obtiene acceso a la propiedad 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 actualización y refinación de componentes

Hay otra función que recupera los componentes de la escena denominada FindComponent. Esta función es útil al actualizar objetos de seguimiento y buscarlos en escenas posteriores. El código siguiente calculará una nueva escena relativa a una escena anterior y, a continuación, buscará el piso en la nueva escena.

// 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
}

Acceso a mallas y cuadrantes desde objetos de escena

Una vez que se han encontrado SceneObjects, la aplicación probablemente querrá acceder a los datos contenidos en los quads o mallas de los que se compone. Se obtiene acceso a estos datos con las propiedades Quads y Meshes . El código siguiente enumerará todos los quads y mallas del 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 es sceneObject que tiene la transformación relativa al origen de la escena. Esto se debe a que SceneObject representa una instancia de una "cosa" y es locable en el espacio, los cuadrantes y las mallas representan la geometría que se transforma en relación con su elemento primario. Es posible que sceneObjects independiente haga referencia a los mismos SceneMesh/SceneQuad SceneComponents, y también es posible que un SceneObject tenga más de un SceneMesh/SceneQuad.

Tratar con transformaciones

Scene Understanding ha hecho un intento deliberado de alinearse con las representaciones tradicionales de la escena 3D al tratar con transformaciones. Por lo tanto, cada escena se limita a un único sistema de coordenadas, de forma muy similar a las representaciones ambientales 3D más comunes. SceneObjects proporciona cada uno su ubicación en relación con ese sistema de coordenadas. Si la aplicación se ocupa de escenas que amplían el límite de lo que proporciona un único origen, puede delimitar SceneObjects a SpatialAnchors, o generar varias escenas y combinarlas, pero por simplicidad se supone que existen escenas herméticas en su propio origen localizado por un NodeId definido por Scene.OriginSpatialGraphNodeId.

El código de Unity siguiente, por ejemplo, muestra cómo usar las API de Windows Perception y Unity para alinear los sistemas de coordenadas juntos. Consulta SpatialCoordinateSystem y SpatialGraphInteropPreview para obtener más información sobre las API de Percepción de Windows y Mixed Reality objetos nativos en Unity para obtener más información sobre cómo obtener un SpatialCoordinateSystem que corresponda al origen mundial de 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 tiene una transformación, que luego se aplica a ese objeto. En Unity, se convierten en coordenadas a la derecha y se asignan transformaciones locales como se indica a continuación:

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

Cuádruple

Los quads se diseñaron para ayudar a los escenarios de colocación 2D y deben considerarse como extensiones para los elementos de la experiencia de usuario del lienzo 2D. Aunque quads son componentes de SceneObjects y se pueden representar en 3D, las API quad asumen que los quads son estructuras 2D. Ofrecen información como la extensión, la forma y proporcionan API para la colocación.

Los cuadráculos tienen extensiones rectangulares, pero representan superficies 2D con forma arbitraria. Para habilitar la colocación en estas superficies 2D que interactúan con los quads del entorno 3D, ofrecen utilidades para que esta interacción sea posible. Actualmente Scene Understanding proporciona dos funciones de este tipo, FindCentermostPlacement y GetSurfaceMask. FindCentermostPlacement es una API de alto nivel que localiza una posición en el cuadrante donde se puede colocar un objeto y intentará encontrar la mejor ubicación para el objeto que garantiza que el rectángulo de límite que proporcione permanecerá en la superficie subyacente.

Nota

Las coordenadas de la salida son relativas al cuádulo en "espacio cuádruple" con la esquina superior izquierda siendo (x = 0, y = 0), igual que lo haría con otros tipos de Rect de windows. Asegúrese de tener esto en cuenta al trabajar con los orígenes de sus propios objetos.

En el ejemplo siguiente se muestra cómo buscar la ubicación colocable más central y anclar un holograma al cuadrante.

// 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)
            }
        }
    }
}

Los pasos 1 a 4 dependen en gran medida de su marco o implementación concretos, pero los temas deben ser similares. Es importante tener en cuenta que el quad simplemente representa un plano 2D delimitado que se localiza en el espacio. Al hacer que el motor o marco sepa dónde está el cuádular y la raíz de los objetos en relación con el cuadrángulo, los hologramas se ubicarán correctamente con respecto al mundo real.

En malla

Las mallas representan representaciones geométricas de objetos o entornos. Al igual que la asignación espacial, los datos de índice de malla y vértice proporcionados con cada malla de superficie espacial usa el mismo diseño conocido que los búferes de vértices e índices que se usan para representar mallas de triángulos en todas las API de representación modernas. Las posiciones de vértice se proporcionan en el sistema de coordenadas de Scene. Las API específicas que se usan para hacer referencia a estos datos son las siguientes:

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

El código siguiente proporciona un ejemplo de generación de una lista de triángulos a partir de la estructura de malla:

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

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

Los búferes de índice/vértice deben ser >= los recuentos de índices o vértices, pero, de lo contrario, pueden tener un tamaño arbitrario que permite una reutilización eficaz de la memoria.

ColisionadorMesh

Los objetos de escena proporcionan acceso a los datos de malla y malla colisionadora a través de las propiedades Meshes y ColliderMeshes. Estas mallas siempre coincidirán, lo que significa que el índice i'és de la propiedad Meshes representa la misma geometría que el índice i'és de la propiedad ColliderMeshes. Si el tiempo de ejecución o el objeto admite mallas colisionadoras, se garantiza que obtiene el polígono más bajo, la aproximación de orden más alta y se recomienda usar ColliderMeshes donde la aplicación use colisionadores. Si el sistema no admite colisionadores, el objeto Mesh devuelto en ColliderMeshes será el mismo objeto que la malla que reduce las restricciones de memoria.

Desarrollo con comprensión de la escena

En este momento, debe comprender los bloques de creación principales del entorno de ejecución y el SDK de descripción de la escena. La mayor parte de la potencia y la complejidad radica en patrones de acceso, interacción con marcos 3D y herramientas que se pueden escribir sobre estas API para realizar tareas más avanzadas, como la planificación espacial, el análisis de salas, la navegación, la física, etc. Esperamos capturarlos en ejemplos que, con suerte, le guiarán en la dirección adecuada para que sus escenarios brillen. Si hay ejemplos o escenarios que no estamos abordando, háganoslo saber y intentaremos documentar o crear prototipos de lo que necesita.

¿Dónde puedo obtener código de ejemplo?

El código de ejemplo de Scene Understanding para Unity se puede encontrar en nuestra página de ejemplo de Unity . Esta aplicación te permitirá comunicarte con tu dispositivo y representar los distintos objetos de escena, o bien, te permitirá cargar una escena serializada en tu PC y te permitirá experimentar Scene Understanding sin un dispositivo.

¿Dónde puedo obtener escenas de ejemplo?

Si tienes un HoloLens2, puedes guardar cualquier escena que hayas capturado guardando la salida de ComputeSerializedAsync en el archivo y deserializándola a tu propia comodidad.

Si no tienes un dispositivo HoloLens2, pero quieres jugar con Scene Understanding, tendrás que descargar una escena capturada previamente. El ejemplo scene Understanding se distribuye actualmente con escenas serializadas que se pueden descargar y usar en su propia comodidad. Puede encontrarlos aquí:

Escenas de ejemplo de descripción de escenas

Consulta también