Asignación espacial en Unity

La asignación espacial permite recuperar mallas de triángulo que representan las superficies en todo el mundo de un dispositivo HoloLens. Puede usar datos de superficie para la selección de ubicación, la oclusión y el análisis de salas para proporcionar a los proyectos de Unity una dosis adicional de inmersión.

Unity incluye compatibilidad completa con la asignación espacial, que se expone a los desarrolladores de las siguientes maneras:

  1. Componentes de asignación espacial disponibles en MixedRealityToolkit, que proporcionan una ruta de acceso cómoda y rápida para empezar a trabajar con la asignación espacial.
  2. API de asignación espacial de nivel inferior, que proporcionan control total y permiten una personalización más sofisticada específica de la aplicación.

Para usar la asignación espacial en la aplicación, la funcionalidad SpatialPerception debe establecerse en appxManifest.

Compatibilidad con dispositivos

Característica HoloLens (primera generación) HoloLens 2 Cascos envolventes
Asignación espacial ✔️ ✔️

Establecimiento de la funcionalidad SpatialPerception

Para que una aplicación consuma datos de asignación espacial, se debe habilitar la funcionalidad SpatialPerception.

Habilitación de la funcionalidad SpatialPerception:

  1. En el Editor de Unity, abra el panel "Configuración del reproductor" (Editar > reproductor de configuración del > proyecto)
  2. Seleccione en la pestaña "Tienda Windows"
  3. Expanda "Configuración de publicación" y compruebe la funcionalidad "SpatialPerception" en la lista "Capabilities" (Funcionalidades).

Nota

Si ya ha exportado el proyecto de Unity a una solución de Visual Studio, deberá exportar a una nueva carpeta o establecer manualmente esta funcionalidad en AppxManifest en Visual Studio.

La asignación espacial también requiere maxVersionTested de al menos 10.0.10586.0:

  1. En Visual Studio, haga clic con el botón derecho en Package.appxmanifest en el Explorador de soluciones y seleccione Ver código.
  2. Busque la línea que especifica TargetDeviceFamily y cambie MaxVersionTested="10.0.10240.0" a MaxVersionTested="10.0.10586.0"
  3. Guarde Package.appxmanifest.

Adición de asignaciones en Unity

Sistema de reconocimiento espacial

En MRTK, consulte la guía de introducción de reconocimiento espacial para obtener información sobre cómo configurar varios observadores de malla espacial.

Para obtener información sobre los observadores del dispositivo, consulte la guía Configuración de observadores de malla para dispositivos .

Para obtener información sobre los observadores de comprensión de escenas, consulte la guía de observador de comprensión de la escena.

Análisis de malla de nivel superior: Spatial Understanding

Precaución

La comprensión espacial ha quedado en desuso en favor de Scene Understanding.

MixedRealityToolkit es una colección de código de utilidad para el desarrollo holográfico basado en las API holográficas de Unity.

Descripción espacial

Al colocar hologramas en el mundo físico, a menudo es conveniente ir más allá de los planos de malla y superficie de la asignación espacial. Cuando la colocación se realiza de forma procesal, es deseable un nivel más alto de comprensión ambiental. Esto normalmente requiere tomar decisiones sobre lo que es piso, techo y paredes. También tiene la capacidad de optimizar con un conjunto de restricciones de selección de ubicación para determinar las mejores ubicaciones físicas para objetos holográficos.

Durante el desarrollo de Young Conker y Fragments, Asobo Studios se enfrentó a este problema al desarrollar un solucionador de salas. Cada uno de estos juegos tenía necesidades específicas del juego, pero comparten la tecnología de comprensión espacial principal. La biblioteca HoloToolkit.SpatialUnderstanding encapsula esta tecnología, lo que te permite encontrar rápidamente espacios vacíos en las paredes, colocar objetos en el techo, identificar si hay caracteres para sentarse y una gran cantidad de otras consultas de comprensión espacial.

Se incluye todo el código fuente, lo que le permite personalizarlo a sus necesidades y compartir sus mejoras con la comunidad. El código del solucionador de C++ se ha encapsulado en un archivo DLL de UWP y se ha expuesto a Unity con una colocación en el objeto prefabricado incluido en MixedRealityToolkit.

Descripción de los módulos

El módulo expone tres interfaces principales: topología para consultas de superficie simple y espaciales, forma para la detección de objetos y el solucionador de selección de ubicación de objetos para la colocación basada en restricciones de conjuntos de objetos. Cada uno de estos se describe a continuación. Además de las tres interfaces de módulo principal, se puede usar una interfaz de conversión de rayos para recuperar tipos de superficie etiquetados y se puede copiar una malla de espacio de reproducción hermética personalizada.

Conversión de rayos

Una vez completada la exploración de la sala, las etiquetas se generan internamente para superficies como el suelo, el techo y las paredes. La PlayspaceRaycast función toma un rayo y devuelve si el rayo entra en conflicto con una superficie conocida y, si es así, información sobre esa superficie en forma de .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, el raycast se calcula con la representación de vóxel en cubo calculada de 8 cm del espacio de reproducción. Cada vóxel contiene un conjunto de elementos de superficie con datos de topología procesados (también conocido como surfels). Las surfeles contenidas en la celda de vóxel intersecada se comparan y la mejor coincidencia usada para buscar la información de topología. Estos datos de topología contienen el etiquetado devuelto en forma de la enumeración "SurfaceTypes", así como el área expuesta de la superficie intersecda.

En el ejemplo de Unity, el cursor convierte un rayo cada fotograma. En primer lugar, contra los colisionadores de Unity. En segundo lugar, contra la representación mundial del módulo de comprensión. Y, por último, de nuevo elementos de la interfaz de usuario. En esta aplicación, la interfaz de usuario obtiene prioridad, junto al resultado de comprensión y, por último, los colisionadores de Unity. SurfaceType se notifica como texto junto al cursor.

El tipo de superficie se etiqueta junto al cursor
El tipo de superficie se etiqueta junto al cursor

Consultas de topología

Dentro del archivo DLL, el administrador de topologías controla el etiquetado del entorno. Como se mencionó anteriormente, gran parte de los datos se almacenan dentro de surfels, contenidos dentro de un volumen de vóxel. Además, la estructura "PlaySpaceInfos" se usa para almacenar información sobre el espacio de reproducción, incluida la alineación del mundo (más detalles sobre esto a continuación), el piso y el alto del techo. La heurística se usa para determinar el suelo, el techo y las paredes. Por ejemplo, la superficie horizontal más grande y más baja con más de 1 m2 superficie se considera el suelo.

Nota

La ruta de acceso de la cámara durante el proceso de examen también se usa en este proceso.

Un subconjunto de las consultas expuestas por el administrador de topologías se expone a través del archivo DLL. Las consultas de topología expuestas son las siguientes.

QueryTopology_FindPositionsOnWalls
QueryTopology_FindLargePositionsOnWalls
QueryTopology_FindLargestWall
QueryTopology_FindPositionsOnFloor
QueryTopology_FindLargestPositionsOnFloor
QueryTopology_FindPositionsSittable

Cada una de las consultas tiene un conjunto de parámetros, específicos del tipo de consulta. En el ejemplo siguiente, el usuario especifica el alto mínimo & ancho del volumen deseado, el alto de colocación mínimo por encima del piso y la cantidad mínima de espacio delante del volumen. Todas las medidas están en 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 una de estas consultas toma una matriz asignada previamente de estructuras "TopologyResult". El parámetro "locationCount" especifica la longitud de la matriz pasada. El valor devuelto informa del número de ubicaciones devueltas. Este número nunca es mayor que el parámetro pasado en "locationCount".

"TopologyResult" contiene la posición central del volumen devuelto, la dirección orientada (es decir, normal) y las dimensiones del espacio encontrado.

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

Nota

En el ejemplo de Unity, cada una de estas consultas está vinculada a un botón del panel de interfaz de usuario virtual. El ejemplo codifica de forma rígida los parámetros de cada una de estas consultas en valores razonables. Consulte SpaceVisualizer.cs en el código de ejemplo para obtener más ejemplos.

Consultas de formas

En el archivo dll, el analizador de formas ("ShapeAnalyzer_W") usa el analizador de topologías para buscar coincidencias con las formas personalizadas definidas por el usuario. El ejemplo de Unity define un conjunto de formas y expone los resultados a través del menú de consulta en la aplicación, dentro de la pestaña forma. La intención es que el usuario pueda definir sus propias consultas de formas de objeto y hacer uso de ellas, según sea necesario para su aplicación.

El análisis de formas solo funciona en superficies horizontales. Un sofá, por ejemplo, está definido por la superficie del asiento plano y la parte superior plana del sofá atrás. La consulta de formas busca dos superficies de un tamaño, alto y rango de aspecto específicos, con las dos superficies alineadas y conectadas. Con la terminología de las API, el asiento del sofá y la parte superior posterior son componentes de forma y los requisitos de alineación son restricciones de componente de forma.

Una consulta de ejemplo definida en el ejemplo de Unity (ShapeDefinition.cs), para los objetos "sittable" es la siguiente.

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 formas se define mediante un conjunto de componentes de forma, cada uno con un conjunto de restricciones de componentes y un conjunto de restricciones de formas que enumeran las dependencias entre los componentes. En este ejemplo se incluyen tres restricciones en una única definición de componente y ninguna restricción de forma entre componentes (ya que solo hay un componente).

En cambio, la forma del sofá tiene dos componentes de forma y cuatro restricciones de forma. Los componentes se identifican mediante su índice en la lista de componentes del usuario (0 y 1 en este ejemplo).

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

Las funciones contenedoras se proporcionan en el módulo de Unity para facilitar la creación de definiciones de formas personalizadas. La lista completa de restricciones de componentes y formas se puede encontrar en "SpatialUnderstandingDll.cs" dentro de las estructuras "ShapeComponentConstraint" y "ShapeConstraint".

La forma rectángulo se encuentra en esta superficie
La forma rectángulo se encuentra en esta superficie

Solucionador de selección de ubicación de objetos

El solucionador de selección de ubicación de objetos se puede usar para identificar ubicaciones ideales en la sala física para colocar los objetos. El solucionador encontrará la mejor ubicación de ajuste dadas las restricciones y las reglas de objetos. Además, las consultas de objeto se conservan hasta que el objeto se quita con llamadas "Solver_RemoveObject" o "Solver_RemoveAllObjects", lo que permite la selección limitada de ubicación de varios objetos. Las consultas de selección de ubicación de objetos constan de tres partes: tipo de selección de ubicación con parámetros, una lista de reglas y una lista de restricciones. Para ejecutar una consulta, use la SIGUIENTE 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 función toma un nombre de objeto, una definición de ubicación y una lista de reglas y restricciones. Los contenedores de C# proporcionan funciones auxiliares de construcción para facilitar la construcción de reglas y restricciones. La definición de selección de ubicación contiene el tipo de consulta, es decir, uno de los siguientes.

public enum PlacementType
{
    Place_OnFloor,
    Place_OnWall,
    Place_OnCeiling,
    Place_OnShape,
    Place_OnEdge,
    Place_OnFloorAndCeiling,
    Place_RandomInAir,
    Place_InMidAir,
    Place_UnderFurnitureEdge,
};

Cada uno de los tipos de selección de ubicación tiene un conjunto de parámetros únicos para el tipo. La estructura "ObjectPlacementDefinition" contiene un conjunto de funciones auxiliares estáticas para crear estas definiciones. Por ejemplo, para buscar un lugar para colocar un objeto en el suelo, puede usar la siguiente función. public static ObjectPlacementDefinition Create_OnFloor(Vector3 halfDims) Además del tipo de selección de ubicación, puede proporcionar un conjunto de reglas y restricciones. Las reglas no se pueden infringir. Las posibles ubicaciones de ubicación que satisfacen el tipo y las reglas se optimizan con respecto al conjunto de restricciones para seleccionar la ubicación de ubicación óptima. Las funciones de creación estática proporcionadas pueden crear cada una de las reglas y restricciones. A continuación se proporciona un ejemplo de regla y función de construcción de restricciones.

public static ObjectPlacementRule Create_AwayFromPosition(
    Vector3 position, float minDistance)
public static ObjectPlacementConstraint Create_NearPoint(
    Vector3 position, float minDistance = 0.0f, float maxDistance = 0.0f)

La consulta de selección de ubicación de objetos siguiente busca un lugar para colocar un cubo de medio metro en el borde de una superficie, lejos de otros objetos de posición anteriores y cerca del centro de la 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());

Si se ejecuta correctamente, se devuelve una estructura "ObjectPlacementResult" que contiene la posición de colocación, las dimensiones y la orientación. Además, la colocación se agrega a la lista interna del archivo DLL de objetos colocados. Las consultas de selección de ubicación posteriores tendrán en cuenta este objeto. El archivo "LevelSolver.cs" del ejemplo de Unity contiene más consultas de ejemplo.

Resultados de la selección de ubicación de objetos
Figura 3: Los cuadros azules cómo el resultado de tres lugares en las consultas de suelo con reglas de posición de cámara fuera de las reglas de posición de la cámara

Al resolver la ubicación de ubicación de varios objetos necesarios para un escenario de nivel o aplicación, primero resuelva objetos indispensables y grandes para maximizar la probabilidad de que se pueda encontrar un espacio. El orden de selección de ubicación es importante. Si no se encuentran las ubicaciones de objetos, pruebe con menos configuraciones restringidas. Tener un conjunto de configuraciones de reserva es fundamental para admitir la funcionalidad en muchas configuraciones de sala.

Proceso de examen de salas

Aunque la solución de asignación espacial proporcionada por HoloLens está diseñada para ser lo suficientemente genérica como para satisfacer las necesidades de toda la gama de espacios problemáticos, el módulo de comprensión espacial se creó para admitir las necesidades de dos juegos específicos. Su solución se estructura en torno a un proceso específico y un conjunto de suposiciones, que se resumen a continuación.

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.

Espacio de reproducción controlado por el usuario "pintura": durante la fase de examen, el usuario se mueve y mira alrededor del ritmo de reproducción, pintando eficazmente las áreas, que se deben incluir. La malla generada es importante para proporcionar comentarios de los usuarios durante esta fase. Configuración interior de la casa o de la oficina: las funciones de consulta están diseñadas alrededor de superficies planas y paredes en ángulos rectos. Se trata de una limitación temporal. Sin embargo, durante la fase de examen, se completa un análisis del eje principal para optimizar la teselación de malla a lo largo del eje principal y secundario. El archivo SpatialUnderstanding.cs incluido administra el proceso de fase de examen. Llama a las siguientes funciones.

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.

El flujo de examen, controlado por el comportamiento "SpatialUnderstanding" llama a InitScan y, a continuación, UpdateScan cada fotograma. Cuando la consulta de estadísticas notifica una cobertura razonable, se permite al usuario que llame a RequestFinish para indicar el final de la fase de examen. Se sigue llamando a UpdateScan hasta que su valor devuelto indica que el archivo dll ha completado el procesamiento.

Descripción de mesh

El archivo dll de comprensión almacena internamente el espacio de reproducción como una cuadrícula de 8 cm de cubos de vóxel de tamaño. Durante la parte inicial del examen, se completa un análisis de componentes principal para determinar los ejes de la sala. Internamente, almacena su espacio de vóxel alineado con estos ejes. Una malla se genera aproximadamente cada segundo mediante la extracción del isosurface del volumen de vóxel.

Malla generada generada a partir del volumen de vóxel
Malla generada generada a partir del volumen de vóxel

Solución de problemas

  • Asegúrese de que ha establecido la funcionalidad SpatialPerception .
  • Cuando se pierde el seguimiento, el siguiente evento OnSurfaceChanged quitará todas las mallas.

Asignación espacial en Mixed Reality Toolkit

Para obtener más información sobre el uso de la asignación espacial con Mixed Reality Toolkit, consulte la sección de reconocimiento espacial de los documentos de MRTK.

Siguiente punto de control de desarrollo

Si sigue el recorrido de desarrollo de Unity que hemos diseñado, está en medio de explorar los bloques de creación principales de MRTK. Desde aquí, puede continuar con el siguiente bloque de compilación:

O bien puede saltar a las funcionalidades y las API de la plataforma de realidad mixta:

Puede volver a los puntos de control de desarrollo de Unity en cualquier momento.

Consulte también