Пример использования. расширение возможностей пространственного сопоставления HoloLens

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

Примечание

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

Просмотреть видео

За пределами пространственного сопоставления

несмотря на то, что мы работаем над фрагментами и конкерами, два из первых игр для HoloLens, мы обнаружили, что при выполнении процедурного размещения голограмм в физическом мире нам требовался более высокий уровень понимания среды пользователя. Каждая игра имеет свои собственные требования к размещению: в фрагментах, например, мы хотели иметь возможность отличать различные поверхности, например этаж или таблицу, чтобы разместить подсказки в соответствующих расположениях. Нам также хотелось бы иметь возможность определять поверхности, на которых может находился жизненный размер, например диван или кресло. В Титов Конкер мы хотели, чтобы Конкер и его соперники могли использовать порожденные поверхности в комнате проигрывателя как платформы.

Асобо Studios, наш партнер по разработке для этих игр, столкнулся с этой проблемой и создал технологию, расширяющую возможности пространственного сопоставления HoloLens. С помощью этого можно анализировать комнату игрока и выявление таких поверхностей, как стены, таблицы, стулья и пол. Это также дает нам возможность оптимизироваться по набору ограничений, чтобы определить наилучшее размещение для holographic объектов.

Код пространственного понимания

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

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

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

  • Фиксированный размер плайспаце: пользователь задает максимальный размер плайспаце в вызове init.
  • Процесс однократного сканирования. процесс требует наличия дискретного этапа сканирования, по истечении которого пользователь определяет плайспаце. Функции запросов не будут работать до завершения проверки.
  • Управляемая пользователем плайспаце "Рисование": на этапе сканирования пользователь перемещается и просматривает плайспаце, эффективно рисуя области, которые должны быть добавлены. Созданная сетка важна для предоставления отзывов пользователей на этом этапе.
  • Домашняя страница и программа установки Office. функции запросов разрабатываются вокруг плоских поверхностей и стен в правой части. Это мягкое ограничение. Однако на этапе сканирования выполняется анализ основной оси для оптимизации тесселяции сетки вдоль основной и вспомогательной осей.

Процесс сканирования комнаты

Когда вы загружаете модуль пространственного понимания, первое, что вы будете делать, — это сканирование пространства, поэтому все доступные поверхности, такие как пол, потолк и стены, определяются и помечаются меткой. В процессе сканирования вы просматриваете комнату и зарисуете области, которые должны быть добавлены в сканирование.

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

Spatial mapping mesh in white and understanding playspace mesh in green

Сетка пространственных сопоставлений в белом и знакомство с плайспаце сеткой зеленым цветом

Включаемый файл Спатиалундерстандинг. CS управляет процессом этапа сканирования. Он вызывает следующие функции:

  • SpatialUnderstanding_Init: вызывается один раз в начале.
  • GeneratePlayspace_InitScan: указывает, что должна начаться фаза сканирования.
  • GeneratePlayspace_UpdateScan_DynamicScan: вызывается каждый кадр для обновления процесса сканирования. Положение и ориентация камеры передаются в и используются для процесса рисования плайспаце, описанного выше.
  • GeneratePlayspace_RequestFinish: вызывается для завершения плайспаце. При этом для определения и блокировки плайспаце будут использоваться области "нарисованные" на этапе сканирования. Приложение может запрашивать статистику на этапе сканирования, а также запрашивать пользовательскую сетку для предоставления отзывов пользователей.
  • Import_UnderstandingMesh. во время сканирования поведение спатиалундерстандингкустоммеш , предоставляемое модулем и размещенное в понимании prefab, будет периодически запрашивать пользовательскую сетку, созданную процессом. Кроме того, это делается после завершения проверки.

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

Запросы

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

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

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

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

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

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

Подмножество запросов, предоставляемых диспетчером топологии, предоставляется через библиотеку 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)

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

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

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

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

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

В библиотеке DLL анализатор форм (ShapeAnalyzer_W) использует анализатор топологии для сопоставления с пользовательскими фигурами, определенными пользователем. Образец Unity имеет предварительно определенный набор фигур, которые отображаются в меню "запрос" на вкладке "Фигура".

Обратите внимание, что анализ фигур работает только на горизонтальных поверхностях. Например, диван определяется поверхностью плоского места и плоской вершиной на диване. Запрос Shape выполняет поиск двух поверхностей определенного размера, высоты и пропорций, при этом две поверхности Выровняйте и соединены. Используя терминологию API, место дивана и вершина задней части дивана являются компонентами фигур, а требования к выравниванию — ограничения компонента.

Пример запроса, определенный в примере Unity (шапедефинитион. CS) для объектов "ситтабле", выглядит следующим образом:

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

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

Напротив, фигура дивана имеет два компонента фигур и четыре ограничения фигуры. Обратите внимание, что компоненты определяются по индексу в списке компонентов пользователя (в этом примере 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 для простого создания пользовательских определений фигур. Полный список ограничений для компонентов и фигур можно найти в спатиалундерстандингдлл. CS в структурах шапекомпонентконстраинт и шапеконстраинт .

The blue rectangle highlights the results of the chair shape query.

Синий прямоугольник выделяет результаты запроса формы кресло.

Поиск решения о размещении объектов

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

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

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

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

The blue boxes show the result from three Place On Floor queries with

Синие поля показывают результат из трех мест в запросах этаже с правилами "от позиции камеры".

Советы

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

Приведение лучей

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

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

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

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

Raycast result reporting intersection with the floor.

Пересечение отчетов результатов райкаст с этажом.

Получите код

Код с открытым кодом доступен в микседреалититулкит. если вы используете код в проекте, сообщите нам об этом на форумах для разработчиков HoloLens . Мы не можем увидеть, что вы сделаете!

Об авторе

Jeff Evertt, Software Engineering Lead at Microsoft джефф евертт — это ведущий специалист по разработке программного обеспечения, который работал над HoloLens, начиная с первых дней, от руковожу группой создания до опыта разработки. прежде чем HoloLens, он работал на Kinect Xbox и в отрасли игр на самых разных платформах и играх. Джефф имеет дело с автоматизированными, графическими объектами и объектами, с которыми поступают звуковые индикаторы. Он изучает новые вещи и работу с программным обеспечением, оборудованием и особенно в пространстве, где два пересекаются.

См. также статью