Сегодня мы совершим прыжок в область Spatial Awareness с помощью очков Hololens от Microsoft и поговорим о развитии Windows Mixed Reality (WMR), а также о том, чего стоит ожидать от второго поколения. Статья рассчитана на тех, кто занимается разработкой под Hololens с использованием среды Unity и Mixed Reality Toolkit (MRTK). На всякий случай оставим здесь руководство по UWP от Microsoft. Одна их отличительных черт Hololens – это потенциал в области смешанной реальности (Mixed Reality), то есть возможность воспринимать пространство и взаимодействовать с ним (Spatial Awareness). Не только Microsoft стремится занять данную нишу. Недавно вышел EasyAR SDK 4.0 с поддержкой Sparse & Dense SpatialMap, которые решают аналогичные задачи. Для Microsoft важно представить «сильное» решение (25 февраля вышел очередной анонс): под второе поколение очков разработана отдельная Scene Understanding SDK. Вероятно, основой этой идеи является Spatial Understanding, который можно встретить в Holotoolkit 2017.4.1.0 (сейчас – MRTK) под Unity версии 2017.4. На тот момент был актуален отличный материал – «How-To: Use Spatial Understanding to Query your Room with HoloLens». Для того чтобы лучше разобраться в теме, рассмотрим очки Hololens подробнее и приведем описание их работы. Для восприятия пространства в Hololens используется ToF-камера глубины.
Камера глубины принимает отраженный от объектов свет и может за счет этого определить объем объекта и расстояние до него. На основании данных, полученных от камеры, Hololens выстраивают меш (как на изображении ниже): Стандартный меш в Hololens Spatial Awareness Меш – объект в Unity, описывающий 3D-модель. Статью с описанием терминов можно почитать здесь. Полученные «сырые» данные поступают в виде набора поверхностей (entry) и образуют итоговый меш пространства, который также привязан к якорной системе. В Hololens данная технология используется для взаимодействия с пространством: объекты, имеющие коллайдеры, могут быть размещены на поверхности. При включении Hololens автоматически подгружают сохраненное пространство в зависимости от его якоря.  Получаемое пространство не претендует на чрезмерную детальность (погрешность составляет 5–10 см минимум, но для расположения предметов на полу / не за стеной этого достаточно). При этом угловатость получаемой в итоге модели в любом случае будет высокой. Шум, который появляется при сканировании, может мешать как при взаимодействии с внешней средой, так и при построении модели объекта.  Для работы со Spatial Awareness мы будем использовать MRTK в среде Unity.
MRTK также является проектом Microsoft. Если есть необходимость посмотреть, как проходит установка в Unity и что там можно делать, то добро пожаловать на github. В экспериментальных целях возьмем следующие параметры для сканирования: За две минуты сканирования с такими параметрами мы получили следующее:  Основные параметры, задающие объемную фигуру в Unity: Сначала применим к полученной поверхности алгоритм Лапласа, который сводится к довольно простому принципу: каждая вершина центруется относительно смежных ей по всем координатам:   где: На Wiki Unity имеется набор скриптов, которые отвечают за сглаживание меша по Лапласу. Исходники были написаны MarkGX еще в 2011 году (тем не менее они до сих пор остаются актуальными). Вышеописанный алгоритм реализован в виде функции laplacianFilter, которой на вход подаются: Для каждой вершины мы сначала находим смежные (соседние) вершины. Делается это следующим образом: Саму функцию поиска смежных вершин можете посмотреть здесь. Далее, если смежные вершины найдены, для каждой из координат вычисляется среднее значение по x, y, z, которое присваивается данной вершине. Код основной функции сглаживания по Лапласу: Результат подобного преобразования выглядит следующим образом: С перегородкой ситуация стала лучше, но на более «тонких» объектах меш стал значительно разорван. Дело в том, что сглаживание по Лапласу приводит к сильному сжатию объекта. Чтобы этого не происходило, после сглаживания скорректируем положение вершин на среднее значение от разницы. Для коррекции сглаживания по Лапласу может быть применен алгоритм Классов Хамфри (HC-algorithm).
С целью предотвращения сжатия фигуры в точку будем сдвигать полученные после сглаживания по Лапласу вершины  назад к их предыдущим позициям  и (или) оригинальным позициям  на среднее значение разниц  между ними. Полученное положение  будет вычисляться следующим образом:   где  – то есть корректировка происходит на . Получается, что разница , которая вычисляется как среднее взвешенное значение разниц, равна:   Для того чтобы учитывать и сдвиг для нужной нам вершины , включим в расчет  с весом :   Скаляр  отвечает за степень жесткости привязки к изначальным позициям.  Поскольку сглаживание достаточно трудоемкая операция, мы будем использовать одну итерацию . А для баланса между более гладкой стенкой и не сильно «рваной» лампой установим . Получилась следующая картинка: Даже сокращение числа итераций сглаживания до одного не отменит того, что во время обработки не самого большого меша (сканировали не всю комнату) происходит «заморозка» приложения. Базовая точность сканирования и ограниченные ресурсы самих Hololens представляют собой довольно серьезное ограничение для работы с пространством, поэтому работа с представленными подходами пока не выйдет за рамки эксперимента. Самым полезным для нашей работы оказалось написание шейдера материала, о котором, возможно, мы расскажем в следующей статье.  Если же брать небольшие значения Extents и обрабатывать только часть объектов, то описанным выше подходом можно решать интересные задачи, например реконструкцию частей тела. Мы очень надеемся, что если когда второе поколение все же выйдет на российский рынок, точность и возможность обработки существенно возрастут (привет, Azure Kinect и Snapdragon). А пока лучше обращать внимание на отдельные камеры глубины или же работать в рамках существенных ограничений.