Compartir a través de


Asignación espacial en Unity

La asignación espacial permite recuperar mallas de triángulo que representan las superficies del mundo alrededor de un dispositivo HoloLens. Puede usar datos de superficie para la colocació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 "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 un 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.

Cómo agregar asignación en Unity

Sistema de reconocimiento espacial

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

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

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

Análisis de malla de nivel superior: Reconocimiento espacial

Precaución

Spatial Understanding ha quedado en desuso en favor de La comprensión de la escena.

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

Reconocimiento espacial

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

Durante el desarrollo de Young Conker y Fragments, Asobo Studios se enfrentó a este problema de frente mediante el desarrollo de un solucionador de salas. Cada uno de estos juegos tenía necesidades específicas del juego, pero compartían la tecnología básica de comprensión espacial. La biblioteca HoloToolkit.SpatialUnderstanding encapsula esta tecnología, lo que le permite encontrar rápidamente espacios vacíos en las paredes, colocar objetos en el techo, identificar el carácter para sentarse y un sinfín de otras consultas de comprensión espacial.

Todo el código fuente está incluido, lo que le permite personalizarlo según 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 un elemento prefabricado incluido en MixedRealityToolkit.

Descripción de los módulos

El módulo expone tres interfaces principales: topología para consultas espaciales y de superficie sencillas, forma para la detección de objetos y solucionador 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 los tipos de superficie etiquetados y se puede copiar una malla de espacio de juego hermética personalizada.

Ray Casting

Una vez completado el examen 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 colisiona 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 en función de la representación voxel en cubo de 8 cm calculada del espacio de juego. Cada voxel contiene un conjunto de elementos de superficie con datos de topología procesados (también conocidos como surfels). Se comparan las tablas contenidas en la celda voxel intersecada y se usa la mejor coincidencia para buscar la información de topología. Estos datos de topología contienen el etiquetado devuelto en forma de enumeración "SurfaceTypes", así como el área expuesta de la superficie intersecada.

En el ejemplo de Unity, el cursor convierte un rayo en cada fotograma. En primer lugar, contra los colisionadores de Unity. En segundo lugar, en contra de 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, después del 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 en tablas de surf, contenidas en un volumen voxel. Además, la estructura "PlaySpaceInfos" se usa para almacenar información sobre el espacio de juego, incluida la alineación del mundo (más detalles en este ejemplo), el suelo y la altura 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 de superficie se considera el suelo.

Nota:

La ruta de acceso de la cámara durante el proceso de escaneo 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 mínimo de colocación por encima del suelo y la cantidad mínima de espacio libre 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 notifica el número de ubicaciones devueltas. Este número nunca es mayor que el pasado en el parámetro "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 se vincula hasta un botón en el panel de la 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 que coincida 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 desde la aplicación, dentro de la pestaña de formas. 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, se define por la superficie del asiento plano y la parte superior plana de la parte posterior del sofá. La consulta de formas busca dos superficies de un tamaño, altura y intervalo 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 componentes 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).

Por el contrario, la forma del sofá tiene dos componentes de forma y cuatro restricciones de forma. Los componentes se identifican por 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 del rectángulo se encuentra en esta superficie
La forma del rectángulo se encuentra en esta superficie

Solucionador de ubicación de objetos

El solucionador 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 ubicación de mejor ajuste dadas las reglas y restricciones del objeto. Además, las consultas de objetos persisten hasta que el objeto se quita con llamadas "Solver_RemoveObject" o "Solver_RemoveAllObjects", lo que permite la colocación restringida 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, una de las 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 donde 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. No se pueden infringir las reglas. Las posibles ubicaciones de ubicación que cumplen el tipo y las reglas se optimizan con el 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 una regla de ejemplo y una 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 siguiente consulta de selección de ubicación de objetos busca un lugar para colocar un cubo de medio metro en el borde de una superficie, lejos de otros objetos colocados anteriormente 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 ubicación se agrega a la lista interna de objetos colocados del archivo DLL. 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 colocación de objetos
Figura 3: Los cuadros azules muestra cómo el resultado de tres consultas en el piso con reglas de posición fuera de la cámara

Al resolver para la ubicación de ubicación de varios objetos necesarios para un escenario de nivel o aplicación, resuelva primero objetos indispensables y grandes con el fin de maximizar la probabilidad de que se pueda encontrar un espacio. El orden de selección de ubicación es importante. Si no se pueden encontrar ubicaciones de objetos, pruebe con configuraciones menos 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 satisfacer 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.

"pintura" del espacio de juego controlado por el usuario: durante la fase de escaneo, el usuario se mueve y mira alrededor del ritmo de juego, pintando eficazmente las áreas, que deben incluirse. La malla generada es importante para proporcionar comentarios al usuario durante esta fase. Instalación en el hogar o la oficina en interiores: 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, a UpdateScan cada fotograma. Cuando la consulta de estadísticas informa de una cobertura razonable, el usuario puede llamar 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 la malla

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

Malla generada a partir del volumen voxel
Malla generada a partir del volumen voxel

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 comprobación 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 creación:

O vaya a las API y las funcionalidades de la plataforma de Mixed Reality:

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

Vea también