![](https://habrastorage.org/webt/kt/vw/t3/ktvwt3fszmbdmwgb2_vnlovp5iy.png)
В этой заметке я хочу рассказать об идее и Proof-Of-Concept добавления объектов реального мира в Виртуальную Реальность.
На мой взгляд, описанная идея в ближайшее время будет реализована всеми игроками VR-рынка. ИМХО, единственная причина, по которой это до сих пор не сделано — желание выкатить идеальное решение, а это не так-то просто.
Уже много лет я продумываю конструкцию гидравлической кабины для симулятора МехВоина.
Но это не мешает периодически обдумывать всевозможные варианты конструкции.
Раньше я планировал размещать внутри кабины множество дисплеев, часть из которых будет работать по назначению, а вторая часть будет эмулировать «окна»/бойницы.
Однако в современном мире в голову приходит другое решение — VR-шлем (Head-Mounted Display). Добиваться качественного погружения гораздо проще, работая со шлемом, т.к. не требуется тщательно вылизывать интерьер реальной кабины. Да и переделывать дизайн в разы проще, но есть НО.
Нормальный пульт управления мехом — сложная и интересная штука. Самый простой аутентичный контроллер выглядит вот так:
![image](https://habrastorage.org/getpro/habr/post_images/a58/494/fef/a58494fef35f54501a77baddbf6b07d4.png)
Делать в серьезном симуляторе что-то проще (например управление с геймпада) — не вариант.
Предположим, замоделить панель управления и поместить её в VR-мир не составляет проблемы.
Однако, управление таким количеством мелких тумблеров «наощупь» — очень плохая идея.
Но как же быть, ведь пользователь не видит своих рук в VR-мире.
Конечно, есть
![image](https://habrastorage.org/getpro/habr/post_images/d19/f27/32a/d19f2732a5d6c831c53aebca0e4d5c7c.jpg)
но сегодня не о них…
На данный момент активно развиваются камеры глубины. Первыми о них заявили Microsoft со своим Кинектом. К сожалению, МС решили что Кинект экономически не оправдан и закрыли проект. Однако дело не умерло, как можно было подумать. Apple внедрила камеру глубины в последний iPhone, именно такая камера отвечает за распознавание лица владельца.
MS тоже не отказалась от технологии, VR-шлемы на платформе Windows Mixed Reality используют технологию inside-out tracking на основе камер глубины.
Очевидным решением является прикрутить камеру глубины на VR шлем и накладывать полученную геометрию на VR-мир. Но почему-то этого никто не делает.
ZED Mini вроде бы умеют строить 3Д-мир и крепятся на шлем, но вживую я их не видел, а все проморолики используют информацию о мире только для наложения 3Д моделей на него, но не наоборот. Полагаю, проблема в низком качестве полученной модели, что будет сразу видно при попытке визуализации.
К сожалению, возможности прикрутить Кинект на шлем у меня нет. Кинект огромный и тяжелый, без инвазивного вмешательства в конструкцию шлема нормальное крепление не сделать. А шлем одолженный и портить я его не могу.
Поэтому для этого мини-проекта я разместил кинект вертикально над столом.
Этот вариант меня полностью устраивает, т.к. в случае размещения кинекта внутри кабины виртуального меха он тоже был бы размещен над панелью управления для детекта исключительно рук игрока и отсечения всех остальных объектов.
Перейдем к проекту (разбора кода не будет, только теория и немного картинок)
С помощью libfreenect2 и OpenNI — получаем карту высот.
Как визуализировать эту карту высот?
Очевидных вариантов в Unreal Engine три.
Меш с картой высот, задающей Z смещение вершины.
Очевидный и самый быстрый вариант. Меш полностью статический, меняется только текстуры (что очень быстро).
К сожалению у этого метода есть серьезный недостаток: отсутствие возможниости прикрутить физику. С точки зрения физики такой меш — абсолютно плоский и цельный. Простой прямоугольник. То что у нас часть вершин прозрачные и отрезаны альфа тестом — физика не видит. То, что у нас вершины модифицируются по Z координате — физика не видит.
Построение меша вручную на низком уровне.
Для этого нам нужно перекрыть UPrimitiveComponent и реализовать новый компонент с использованием SceneProxy. Это низкоуровневый подход, дающий лучшую скорость.
Основной недостаток — достаточно высокая сложность реализации.
Если делать полноценно — именно этот вариант и стоит избрать.
Но т.к. передо мной стояла задача сделать быстро и просто, я воспользовался третьим вариантом.
Реализация на базе UProceduralMeshComponent
Это встроенный в UE компонент, который позволяет легко и просто создавать меш и даже сразу считать объект для рассчета коллизий.
Почему нужно использовать второй вариант, а не этот?
Потому что данный компонент не предназначен для работы с динамической геометрией. Он заточен под то, чтобы мы один раз (или как минимум не очень часто и желательно не в реалтайме) передаем ему геометрию, она медленно считается и дальше мы с ней быстро работаем. У нас не тот случай…
Но для теста сойдет. Тем более сцена пустая и компьютеру больше нечего считать, так что ресурсов с запасом.
Визуализировать объекты их изображением с камеры — вариант не очень. Очень сильно выделяются реальные фото на фоне виртуального мира.
Поэтому решил визуализировать по аналогии с SteamVR — линиями. Наложил текстуру голубой сетки без заполнения. Плюс по контуру сделал обводку. Получилось вполне приемлемо. Правда с полной прозрачностью руки воспринимались чуть хуже, поэтому заполнение квадратов сделал слегка заметно голубоватым.
![](https://habrastorage.org/webt/iv/3q/la/iv3qlag9lh7jcw3n_kxaa1eya1i.png)
На скриншоте видно эффект «стекания» геометрии. Это связано с неспособностью камер глубины нормально обрабатывать грани с углом близким к 90 градусов к камере. Явно вырожденные пиксели кинект помечает значением 0, но, к сожалению, не все и часть из них «шумит», не вырождаясь. Я сделал набор несложных манипуляций, чтобы убрать основной шум, но полностью избавиться от «стекания» не получилось.
Стоит отметить, что этот эффект сильно заметен при взгляде сбоку (сидим перед столом, а кинект сверху). Если же камера глубины будет направлена параллельно взгляду и исходить из точки, близкой к реальным органам зрения пользователя — этот эффект будет направлен вперед и значительно менее заметен.
Как можно заметить на видео — реальные руки вполне работают внутри VR-мира. Единственный серьезный недостаток — дискретность перемещения.
Меш не морфирует плавно в новое состояние, а удаляется и создается заново. Из-за чего при резком движении физические объекты проваливаются сквозь него, поэтому двигаем медленно и аккуратно:
Прошу прощения за темное видео — занимался проектом по вечерам после работы, на превью видео показалось нормальным, когда уже всё оборудование снял и перенес видео на комп — оказалось, что оно очень темное.
Выкладываю в виде архива исходники плагина.
Добавляем как обычный плагин в любой UE проект.
Я не стал разбираться как подключить lib файл с помощью относительного пути, поэтому в OpenNI2CameraAndMesh.Build.cs прописываем полный путь до OpenNI2.lib
Далее размещаем ADepthMeshDirect в нужном нам месте.
При старте уровня вызываем метод startOpenNICamera из UTools.
Не забываем, что для работы с кинектом используется libfreenect2, а значит драйвер на кинект надо переопределить на libusbK в соответствии с инструкцией на странице libfreenect2
UPD:
В начале статьи я сказал, что такая система скоро будет во всех VR шлемах. Но в процессе написания как-то упустил из виду этот момент и не раскрыл его.
Поэтому процитирую свой комментарий, который написал ниже для раскрытия этой темы:
Если же говорить — зачем такая система нужна во всех VR системах без исключения — это безопасность.
Сейчас границы игровой зоны отмечаются условным кубом.
Но редко кто из нас может позволить себе выделить абсолютно пустое пространство под VR. В итоге в комнате остаются предметы, иногда опасные.
Основное, что, я уверен, будет сделано — это виртуальное отображение всей комнаты перед игроком в виде едва различимого призрака, который с одной стороны не мешает восприятию игры, а с другой — позволяет не споткнуться и не умереть.
P.S.:
Хочу выразить огромную благодарность компании <которую нельзя называть вне корпоративного блога>, руководство которой выделило мне техническую базу для работы над этим проектом.
Комментарии (25)
pavel_kudinov
16.04.2018 00:55> Очевидным решением является прикрутить камеру глубины на VR шлем и накладывать полученную геометрию на VR-мир. Но почему-то этого никто не делает.
Microsoft Hololens вроде делает именно это. Пробовал это девайс сам: он сканирует помещение и сканирует жесты рук именно камерой глубины, в некоторых режимах он её показывает в полигональном представлении, очень круто выглядит дополненная реальность, когда все реальные объекты начинают быть обтекаемыми своей картой глубины. Полный VR режим там тоже есть (когда видно только виртуальное изображение)AllexIn Автор
16.04.2018 08:03Давненько мечатю добраться до Hololens, но к сожалению возможности такой пока не представилось. Дорогой, блин.
3aicheg
16.04.2018 04:46Если я правильно понял постановку задачи, то у вас какой-то овер-инжиниринг 80-го уровня. Почему не натянуть зелёный экран для хромакея на стол и стену за ним, не поставить джойстики на него, брать тупо видео с дешёвой веб-камеры и накладывать поверх 3Д-сцены, обрезая по зелёному? Веб-камера — не кинект, можно маленькую взять и без проблем прикрутить на шлем или на лицо куда-нибудь. Собственно, идея не нова — вот есть такой, к примеру, кэноновский девайс антигуманной ценовой категории:
ebragim
Если цель в совмещении реального контроллера (как я понимаю, для большей полноты погружения и обратной связи) и модели в HMD — то это как-то очень сложно и мудрёно выходит.
Окулусы давно такие реализовали в своей гарнитуре: ставим на пальцы метки (да хотя бы обычной краской, светящейся в ИК), камеры привязаны к кабине, а значит позиция джоя относительно камер статична. По положению меток на пальцах можно достроить остальную руку. Трекать всю физику совершенно излишне, так как физика реальной руки жёстко ограниченна доступными углами суставов.
Да, с вашим способом можно внести в систему предмет из реального мира… но только если он запрограммирован заранее. То есть снова проще сделать несколько точек для трекинга на нём.
AllexIn Автор
Ну так и речь идет о том, что предметы запрограммированы заранее. Типа того же пульта управления мехом. И задача сориентирвоать игрока — где тумблер, А где его пальцы относительно тумблера.
По факту физика рукам вообще не нужна, я её сделал просто «потому что могу».
Если же говорить — зачем такая система нужна во всех VR системах без исключения — это безопасность.
Сейчас границы игровой зоны отмечаются условным кубом.
Но редко кто из нас может позволить себе выделить абсолютно пустое пространство под VR.
В итоге в комнате остаются предметы, иногда опасные.
Основное что, я уверен, будет сделано — это виртуальное отображение всей комнаты перед игроком в виде едва различимого призрака, который с одной стороны не мешает восприятию игры, а с другой — позволяет не споткнуться и не умереть.
Goodkat
В очках забываешь, что находишься в комнате, и её изображение будет только мешать и отвлекать от игры. Система и так предупреждает, когда выходишь из относительно небольшого куба, в котором камера отслеживает шлем и контроллеры.
Но камера в шлеме не помешает — иногда нужно в игре поменять контроллер или просто попить, тут бы пригодилось опционально включаемое изображение с камеры в шлеме, чтобы не снимать его. Хотя мне хватило бы и изображения с существующей камеры — оно включается в самом начале, вместе с предупреждением освободить место, чтобы не убиться в виртуальности.
AllexIn Автор
Как думаете, чувака со стеклянным столом она предупредила?
Спойлер:
Скорее всего нет. ПОтому что вполне частая ситуация — если куб не помещается в комнате — заехать им на предметы типа дивана, стола, чтобы всё таки иметь возможность играть. Как итог — можно споткнуться, ударить контроллер и т.п.
Мешать ничего не будет. Если у вас пустая комната — вы ничего и не увидите, если у вас комната не пустая — лучше видеть чем не видеть. Да и стенки куба же не мешают, почему увеличение детализации должно мешать?