Поделиться через


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

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

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

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

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

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

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

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

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

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

  1. В редакторе Unity откройте панель "Параметры проигрывателя" (изменение > проигрывателя параметров > проекта)
  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-см кубической воксели представления пространства воспроизведения. Каждый воксель содержит набор элементов поверхности с обработанными данными топологии (ака серфель). Серферы, содержащиеся в пересекаемой ячейке voxel, сравниваются и лучшее совпадение, используемое для поиска сведений топологии. Эти данные топологии содержат метки, возвращенные в виде перечисления SurfaceTypes, а также области поверхности пересекаемой поверхности.

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

Тип Surface помечен рядом с курсором
Тип 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.

Фигура прямоугольника найдена на этой поверхности
Фигура прямоугольника найдена на этой поверхности

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

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

Результаты размещения объектов
Рис. 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 каждый кадр. Когда запрос статистики сообщает о разумном охвате, пользователь может перезапустить запросFinish, чтобы указать конец этапа сканирования. UpdateScan продолжает вызываться до тех пор, пока его возвращаемое значение не указывает, что библиотека DLL завершила обработку.

Общие сведения о сетке

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

Созданная сетка, созданная из тома voxel
Созданная сетка, созданная из тома voxel

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

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

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

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

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

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

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

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

См. также