Пространственное сопоставление в Unity

Пространственное сопоставление позволяет получать сетки треугольников, представляющие поверхности в мире вокруг устройства HoloLens. Вы можете использовать данные поверхности для размещения, окклюзии и анализа помещений, чтобы дать проектам Unity дополнительную дозу погружения.

Unity включает полную поддержку пространственного сопоставления, которое предоставляется разработчикам следующими способами:

  1. Компоненты пространственного сопоставления, доступные в MixedRealityToolkit, которые предоставляют удобный и быстрый путь для начала работы с пространственным сопоставлением
  2. API пространственного сопоставления более низкого уровня, которые обеспечивают полный контроль и обеспечивают более сложную настройку для конкретного приложения.

Чтобы использовать пространственное сопоставление в приложении, необходимо задать возможность SpatialPerception в AppxManifest.

Поддержка устройств

Компонент HoloLens (1-го поколения) HoloLens 2 Иммерсивные гарнитуры
пространственное сопоставление ✔️ ✔️

Настройка возможности SpatialPerception

Чтобы приложение потребляло данные пространственного сопоставления, необходимо включить функцию SpatialPerception.

Как включить функцию SpatialPerception:

  1. В редакторе Unity откройте панель "Проигрыватель Параметры" (изменение > Project Параметры > проигрывателя)
  2. Выберите вкладку "Магазин Windows"
  3. Разверните раздел "Публикация Параметры" и проверьте возможность SpatialPerception в списке "Возможности"

Примечание

Если проект Unity уже экспортирован в решение Visual Studio, необходимо либо экспортировать в новую папку, либо вручную установить эту возможность в AppxManifest в Visual Studio.

Для пространственного сопоставления также требуется MaxVersionTested по крайней мере 10.0.10586.0:

  1. В Visual Studio щелкните правой кнопкой мыши Package.appxmanifest в Обозреватель решений и выберите "Просмотреть код"
  2. Найдите строку, указывающую TargetDeviceFamily и измените MaxVersionTested="10.0.10240.0" на MaxVersionTested="10.0.10586.0"
  3. Сохраните Package.appxmanifest.

Добавление сопоставления в Unity

Система отслеживания пространственного положения.

В MRTK ознакомьтесь с руководством по началу работы с пространственными сведениями о настройке различных наблюдателей пространственной сетки.

Дополнительные сведения об наблюдателях на устройстве см. в руководстве по настройке наблюдателей сетки для устройства .

Дополнительные сведения о наблюдателях распознавания сцен см. в руководстве наблюдателя о понимании сцены .

Анализ сетки более высокого уровня: пространственное понимание

Внимание!

Пространственное понимание было признано нерекомендуемой в пользу распознавания сцен.

MixedRealityToolkit — это коллекция кода служебной программы для голографической разработки, построенной на голографических API Unity.

Пространственное понимание

При размещении голограмм в физическом мире часто желательно выйти за рамки сетки пространственного сопоставления и плоскостей поверхности. Когда размещение выполняется процедурно, желательно более высокий уровень понимания окружающей среды. Обычно это требует принятия решений о том, что такое пол, потолок и стены. Кроме того, вы можете оптимизировать работу с набором ограничений размещения, чтобы определить оптимальные физические расположения для голографических объектов.

Во время разработки Молодых Конкеров и фрагментов, Asobo Studios столкнулись с этой проблемой головой, разработав решателя помещений. Каждая из этих игр имела особые потребности в игре, но они совместно используют основные технологии пространственного понимания. Библиотека HoloToolkit.SpatialUnderstanding инкапсулирует эту технологию, что позволяет быстро находить пустые пространства на стенах, размещать объекты на потолке, определять место для размещения символов и множество других запросов пространственного понимания.

Весь исходный код включен, что позволяет настраивать его в соответствии с вашими потребностями и делиться улучшениями с сообществом. Код для решателя C++ был упакован в библиотеку DLL UWP и предоставлен Unity с каплей в префабе, содержащейся в MixedRealityToolkit.

Основные сведения о модулях

Модуль предоставляет три основных интерфейса: топология для простых поверхностных и пространственных запросов, фигуры для обнаружения объектов и решателя размещения объектов для размещения наборов объектов на основе ограничений. Каждый из этих способов описан ниже. Помимо трех основных интерфейсов модуля, можно использовать интерфейс приведения лучей для получения помеченных типов поверхностей, а настраиваемую сетку пространства воспроизведения воды можно скопировать.

Рэй Кастинг

После завершения сканирования комнаты этикетки создаются внутренне для таких поверхностей, как пол, потолок и стены. Функция PlayspaceRaycast принимает луч и возвращает, если луч сталкивается с известной поверхностью и, если да, информация об этой поверхности в виде.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;
};

На внутреннем сервере рекаст вычисляется по вычисляемой 8-cm кубической воксел-представлению пространства воспроизведения. Каждый voxel содержит набор элементов поверхности с обработанными данными топологии (ака серферов). Серферы, содержащиеся в пересекаемой ячейке voxel, сравниваются и лучшее совпадение, используемое для поиска сведений о топологии. Эти данные топологии содержат метки, возвращенные в виде перечисления SurfaceTypes, а также поверхностной области пересекаемой поверхности.

В примере Unity курсор приводит к лучу каждого кадра. Во-первых, против коллайдеров Unity. Во-вторых, по отношению к представлению в мире модуля понимания. И, наконец, снова элементы пользовательского интерфейса. В этом приложении пользовательский интерфейс получает приоритет, следующий результат понимания и, наконец, коллайдеры Unity. SurfaceType отображается как текст рядом с курсором.

Surface type is labeled next to the cursor
Тип Surface помечается рядом с курсором

Запросы топологии

В библиотеке DLL диспетчер топологии обрабатывает метки среды. Как упоминалось выше, большая часть данных хранится в серферах, содержащихся в томе voxel. Кроме того, структура PlaySpaceInfos используется для хранения сведений о пространстве воспроизведения, включая выравнивание мира (дополнительные сведения об этом ниже), этаже и высоте потолка. Эвристика используется для определения пола, потолка и стен. Например, самая большая и самая низкая горизонтальная поверхность с площадью более 1 м2 считается полом.

Примечание

Путь к камере во время сканирования также используется в этом процессе.

Подмножество запросов, предоставляемых диспетчером топологий, предоставляется через библиотеку DLL. Ниже приведены запросы к открытой топологии.

QueryTopology_FindPositionsOnWalls
QueryTopology_FindLargePositionsOnWalls
QueryTopology_FindLargestWall
QueryTopology_FindPositionsOnFloor
QueryTopology_FindLargestPositionsOnFloor
QueryTopology_FindPositionsSittable

Каждый из запросов имеет набор параметров, относящихся к типу запроса. В следующем примере пользователь задает минимальную & ширину нужного тома, минимальную высоту размещения над полом и минимальный объем зазора перед томом. Все измерения находятся в метрах.

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)

Каждый из этих запросов принимает предварительно выделенный массив структур TopologyResult. Параметр locationCount указывает длину переданного массива. Возвращаемое значение сообщает количество возвращаемых расположений. Это число никогда не превышает переданное в параметре locationCount.

TopologyResult содержит центральное положение возвращаемого тома, направление ориентации (т. е. нормальное) и размеры найденного пространства.

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

Примечание

В примере Unity каждый из этих запросов связан с кнопкой на панели виртуального пользовательского интерфейса. Пример жестко кодирует параметры для каждого из этих запросов с разумными значениями. Дополнительные примеры см. в файле SpaceVisualizer.cs в примере кода.

Запросы фигур

В библиотеке DLL анализатор фигур ("ShapeAnalyzer_W") использует анализатор топологии для сопоставления с пользовательскими фигурами, определенными пользователем. Пример Unity определяет набор фигур и предоставляет результаты в меню запросов в приложении на вкладке фигуры. Цель состоит в том, что пользователь может определять собственные запросы фигуры объектов и использовать их по мере необходимости в приложении.

Анализ фигур работает только на горизонтальных поверхностях. Диван, например, определяется плоской поверхностью сиденья и плоской верхней частью дивана назад. Запрос фигуры ищет две поверхности определенного размера, высоты и диапазона аспектов, с двумя поверхностями, выровненными и соединенными. Используя терминологию API, диванное сиденье и задняя часть являются компонентами фигуры, а требования к выравниванию являются ограничениями компонентов фигуры.

Ниже приведен пример запроса, определенного в примере Unity (ShapeDefinition.cs) для объектов sittable.

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

Каждый запрос фигуры определяется набором компонентов фигуры, каждый из которых содержит набор ограничений компонентов и набор ограничений фигур, которые перечисляют зависимости между компонентами. Этот пример включает три ограничения в определении одного компонента и отсутствие ограничений фигур между компонентами (так как только один компонент).

В отличие от этого, фигура дивана имеет два компонента фигуры и четыре ограничения фигуры. Компоненты идентифицируются по индексу в списке компонентов пользователя (0 и 1 в этом примере).

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

Функции-оболочки предоставляются в модуле Unity для простого создания пользовательских определений фигур. Полный список ограничений компонентов и фигур можно найти в файле SpatialUnderstandingDll.cs в структурах ShapeComponentConstraint и ShapeConstraint.

Rectangle shape is found on this surface
Фигура прямоугольника найдена на этой поверхности

Решатель размещения объектов

Решатель размещения объектов можно использовать для определения идеальных расположений в физической комнате для размещения объектов. Решатель найдет оптимальное расположение, учитывая правила и ограничения объекта. Кроме того, запросы объектов сохраняются до тех пор, пока объект не будет удален с вызовами "Solver_RemoveObject" или "Solver_RemoveAllObjects", что позволяет ограничить размещение нескольких объектов. Запросы на размещение объектов состоят из трех частей: типа размещения с параметрами, списка правил и списка ограничений. Чтобы выполнить запрос, используйте следующий 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)

Эта функция принимает имя объекта, определение размещения и список правил и ограничений. Оболочки C# предоставляют вспомогательные функции для создания правил и ограничений. Определение размещения содержит тип запроса, то есть один из следующих.

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

Каждый из типов размещения имеет набор параметров, уникальных для типа. Структура ObjectPlacementDefinition содержит набор статических вспомогательных функций для создания этих определений. Например, чтобы найти место для размещения объекта на полу, можно использовать следующую функцию. public static ObjectPlacementDefinition Create_OnFloor(Vector3 halfDims) В дополнение к типу размещения можно предоставить набор правил и ограничений. Правила не могут быть нарушены. Возможные расположения размещения, удовлетворяющие типу и правилам, затем оптимизированы для набора ограничений, чтобы выбрать оптимальное расположение размещения. Каждое из правил и ограничений можно создать с помощью предоставленных функций статического создания. Ниже приведен пример функции построения правил и ограничений.

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

Приведенный ниже запрос на размещение объектов ищет место для размещения куба полуметра на краю поверхности, вдали от других ранее размещаемых объектов и вблизи центра комнаты.

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

В случае успешного выполнения возвращается структура ObjectPlacementResult, содержащая положение размещения, измерения и ориентацию. Кроме того, размещение добавляется во внутренний список размещенных объектов dll. Последующие запросы размещения будут учитывать этот объект. Файл LevelSolver.cs в примере Unity содержит дополнительные примеры запросов.

Results of object placement
Рис. 3. Синие поля, как результат из трех мест на запросах пола, не имеющих правил положения камеры

При решении задачи размещения нескольких объектов, необходимых для сценария уровня или приложения, сначала необходимо решить незаменимые и крупные объекты, чтобы максимизировать вероятность того, что пространство можно найти. Порядок размещения важен. Если не удается найти размещение объектов, попробуйте использовать менее ограниченные конфигурации. Наличие набора резервных конфигураций крайне важно для поддержки функциональных возможностей во многих конфигурациях помещений.

Процесс сканирования помещений

Хотя решение пространственного сопоставления, предоставляемое HoloLens, должно быть достаточно универсальным для удовлетворения потребностей всего набора проблемных пространств, модуль пространственного понимания был создан для поддержки потребностей двух конкретных игр. Его решение структурировано вокруг определенного процесса и набора допущений, приведенных ниже.

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.

Управляемое пользователем пространство воспроизведения "рисование" — во время этапа сканирования пользователь перемещается и смотрит вокруг воспроизведения темпа, эффективно рисуя области, которые должны быть включены. Созданная сетка важна для предоставления отзывов пользователей на этом этапе. Настройка дома или офиса в помещении — функции запроса разработаны вокруг плоских поверхностей и стен в правых углах. Это мягкое ограничение. Однако на этапе сканирования выполняется анализ основной оси для оптимизации тесселяции сетки вдоль основной и дополнительной оси. Включенный файл SpatialUnderstanding.cs управляет процессом этапа сканирования. Он вызывает следующие функции.

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.

Поток сканирования, управляемый поведением SpatialUnderstanding, вызывает InitScan, а затем UpdateScan каждый кадр. Когда запрос статистики сообщает о разумном охвате, пользователь может перезапустить запрос RequestFinish, чтобы указать конец этапа сканирования. UpdateScan продолжает вызываться до тех пор, пока его возвращаемое значение не указывает, что библиотека DLL завершила обработку.

Основные сведения о Mesh

Библиотека DLL внутренне хранит пространство воспроизведения в виде сетки размером 8 см кубов voxel. Во время начальной части сканирования выполняется анализ основных компонентов, чтобы определить оси комнаты. На внутреннем сервере сохраняется пространство voxel, выровненное по этим осям. Сетка создается приблизительно каждую секунду путем извлечения isosurface из тома voxel.

Generated mesh produced from the voxel volume
Созданная сетка, созданная из тома voxel

Устранение неполадок

  • Убедитесь, что вы задали возможность SpatialPerception
  • При потере отслеживания следующее событие OnSurfaceChanged удалит все сетки.

Пространственное сопоставление в Смешанная реальность набор средств

Дополнительные сведения об использовании пространственного сопоставления с Смешанная реальность набор средств см. в разделе о пространственной осведомленности документации MRTK.

Следующий этап разработки

Если вы следите за процессом разработки Unity, который мы изложили, вы находитесь в разгар изучения основных стандартных блоков MRTK. Отсюда вы можете перейти к следующему стандартному блоку:

Или перейдите к возможностям и API платформы смешанной реальности:

Вы можете в любой момент вернуться к этапам разработки для Unity.

См. также раздел