Эта статья поможет разработчикам ознакомиться с возможностями подключаемого модуля RealSense для Unreal Engine 4, понять его архитектуру и устройство. Этот подключаемый модуль был разработан в корпорации Intel для поддержки пакета Intel® RealSense™ SDK. Эта статья предназначена для опытных разработчиков, использующих UE4, а также для разработчиков, знакомых с технологией RealSense. Если вы хотите приступить к изучению UE4, ознакомьтесь с документацией и учебными материалами. Также можно загрузить Epic Games Launcher здесь и просмотреть образцы проектов на вкладке Learn.

Базовые сведения и область этой работы


Unreal Engine 4 — это четвертое поколение игрового движка компании Epic Games. Впервые он был представлен ограниченной аудитории в 2012 году на конференции Game Developers Conference. В 2014 году уже все желающие разработчики могли получить исходный код этого движка, оплачивая небольшую ежемесячную подписку. Плата за подписку была отменена в 2015 году, теперь исходный код всего движка доступен для всех разработчиков бесплатно.

Исходный код Unreal Engine написан на C++. В версии UE4 разработчики Epic впервые применили визуальные сценарии Blueprint вместо использовавшейся в UE3 системы сценариев Kismet. На рис. 1 показан пример сценария Blueprint.


Рисунок 1. Пример сценария Blueprint в Unreal Engine* 4

Разработчики могут создавать узлы Blueprint для событий, функций, переменных, макросов и т. д. и увязывать их вместе с помощью логических цепочек процессов. Благодаря сценариям Blueprint упрощается работа начинающих разработчиков, обладающих ограниченным опытом программирования, и обеспечивается исключительно быстрое создание прототипов.

Многие игры на движке UE4 реализованы с помощью сочетания программного кода C++ и сценариев Blueprint. Визуальные сценарии позволяют управлять анимационными изображениями, определять сложные деревья поведения искусственного интеллекта и реализовать любые виды игровой логики.

Подключаемый модуль Intel RealSense SDK


Пакет Intel RealSense SDK изначально написан на C++, что дает разработчикам удобную возможность доступа к функциям SDK из кода игр, также написанных на C++. Описываемый подключаемый модуль расширяет возможности разработки в UE4, предоставляя доступ к функциональности SDK посредством сценариев Blueprint.
На момент написания этой статьи подключаемый модуль официально поддерживал следующие функции:
  • Передача необработанного цветного изображения и изображения глубины с камеры.
  • Трехмерное сканирование лиц и объектов.

Также ведется работа о реализации поддержки еще двух компонентов:
  • Отслеживание движений головы.
  • Восприятие сцены.

Конечная цель подключаемого модуля — поддержка всех функций и возможностей полной версии Intel RealSense SDK, применимых к играм. Полный список функций RealSense SDK с упорядочением по камерам и по степени готовности см. в заметках к выпуску RealSense SDK.

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

Кроме того, в папке проекта находится руководство «Приступая к работе», помогающее добавить подключаемый модуль к новому проекту. Эти же действия описываются и в следующем учебном видеоролике.


Компоненты RealSense


В этом разделе приводится более подробное описание каждого из компонентов RealSense.

Компоненты UE4


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

Чтобы получить представление о широте возможностей компонентов, рассмотрим для примера компонент Scene, применяющий преобразование к объекту, к которому он присоединен. Преобразование — это применение расположения, поворота и масштаба к какому-либо объекту. С помощью преобразования разработчик может разместить объект в каком-либо месте игрового мира. Данный компонент позволяет очень просто добавлять преобразование к чему угодно, даже к свету и звукам.

Подключаемый модуль RealSense устроен в виде набора компонентов, каждый из которых предоставляет доступ к определенным функциям RealSense SDK. Например, компонент Camera Streams предоставляет разработчику доступ к потоку цветного изображения и потоку глубины, передающимся с камеры. В редакторе UE4 список компонентов находится в раскрывающемся меню Add Component (Добавить компонент) в окне Components (Компоненты) в категории RealSense, как показано на рис. 2.


Рисунок 2. Компоненты подключаемого модуля RealSense в окне Components редактора Unreal Engine* 4

Компонент RealSense


Этот компонент является абстрактным родительским классом всех прочих компонентов RealSense. Он предоставляет общую функциональность, необходимую каждому компоненту, но его самого невозможно присоединить к какому-либо объекту в Unreal.
Данные, предоставляемые этим классом, включают следующие (рис. 3).

float ColorHorizontalFOV; // Поле зрение цветной камеры по горизонтали
float ColorVerticalFOV; // Поле зрения цветной камеры по вертикали
float DepthHorizontalFOV; // Поле зрения камеры глубины по горизонтали
float DepthVerticalFOV; // Поле зрения камеры глубины по вертикали
ECameraModel CameraModel; // Модель подключенной камеры: F200, R200 или SR300
FString CameraFirmware; // Версия микропрограммы подключенной камеры



Рисунок 3. Члены-переменные компонента RealSense

Компонент RealSense также предоставляет следующие функции (рис. 4).

void StartCamera(); // Включение камеры RealSense
void StopCamera(); // Включение камеры RealSense

bool IsCameraRunning(); // Возвращает значение true, если камера работает

// Получение и установка разрешения цветной камеры 
FStreamResolution GetColorCameraResolution();
virtual void SetColorCameraResolution(EColorResolution);

// Получение и установка разрешения камеры глубины
FStreamResolution GetDepthCameraResolution();
virtual void SetDepthCameraResolution(EDepthResolution);

// Возвращает значение true, если разрешения входного изображения являются допустимым набором.
bool IsStreamSetValid(EColorResolution, EDepthResolution);



Рисунок 4. Члены-функции компонента RealSense

Компонент Camera Streams


Этот компонент предоставляет доступ к необработанному цветному изображению и данным глубины с камеры Intel RealSense, а также удобные объекты Texture для отображения этих изображений.
Данные, предоставляемые этим классом, включают следующие (рис. 5).

TArray<FSimpleColor> ColorBuffer; // Массив 32-разрядных значений цвета (RGBA)
TArray<int32> DepthBuffer; // Массив 16-разрядных значений глубины (в миллиметрах)
UTexture2D* ColorTexture; // Размер равен разрешению цветной камеры.
UTexture2D* DepthTexture; // Размер равен разрешению камеры глубины.



Рисунок 5. Члены-переменные компонента Camera Streams

Компонент Camera Streams также предоставляет следующие функции, переопределяемые из компонента RealSense:

// Переопределяет функцию компонента RealSense, инициализирует ColorBuffer и ColorTexture с нужным размером.
virtual void SetColorCameraResolution(EColorResolution) override;

// Переопределяет функцию компонента RealSense, инициализирует DepthBuffer и DepthTexture с нужным размером.
virtual void SetDepthCameraResolution(EDepthResolution) override;

Существует небольшая библиотека вспомогательных функций, она называется RealSense Utilities. Одна из таких функций принимает в качестве входных данных буфер цвета (объект Color Buffer) и цветовую текстуру (объект Color Texture) и заполняет эту текстуру данными из буфера. Также существует функция сравнения, работающая с буфером глубины (объект Depth Buffer) и текстурой глубины (объект Depth Texture). Использование этой функции показано на рис. 6.


Рисунок 6. Пример использования функции Color Buffer to Texture

Посмотрите это краткое учебное руководство, чтобы узнать, как использовать компонент Camera Streams подключаемого модуля RealSense, чтобы получить доступ к потоку цветного изображения с камеры и вывести это изображение на экран.



Компонент Scan 3D


Этот компонент предоставляет доступ к промежуточному модулю трехмерного сканирования в Intel RealSense SDK. В настоящее время подключаемый модуль поддерживает сканирование лиц и объектов, но не поддерживает вывод текстур, выводятся только цвета вертексов.
Данные, предоставляемые этим классом, включают следующие (рис. 7).

TArray<FSimpleColor> ScanBuffer; // Массив 32-разрядных значений цвета (RGBA), представляющий предварительный просмотр изображения, полученного от промежуточного модуля трехмерного сканирования.
UTexture2D* ScanTexture; // Размер равен размеру ScanBuffer

TArray<FVector> Vertices; // Массив структур Vector3, соответствующих вершинам трехмерной модели
TArray<int32> Triangles; // Массив индексов вертексов, соответствующих треугольникам
TArray<FColor> Colors; // Массив цветов, соответствующих цветам вертексов



Рисунок 7. Члены-переменные компонента Scan 3D

Компонент Scan 3D также предоставляет следующие функции (рис. 8).
// Устанавливает режим сканирования (съемка лица или съемка объектов) и флаг, указывающий, следует ли создать полную трехмерную модель 
void ConfigureScanning(EScan3DMode, bool);

void StartScanning(); // Запуск модуля сканирования
void StopScanning(); // Остановка модуля сканирования
void ResetScanning(); // Сброс модуля сканирования
bool IsScanning();// Возвращает значение true, если модуль сканирования запущен

void SaveScan(FString); // Сохранить результат сканирования в OBJ-файл с указанным именем файла.
void LoadScan(FString); // Загрузить результат сканирования из указанного OBJ-файла



Рисунок 8. Члены-функции компонента Scan 3D

И наконец, компонент Scan 3D предоставляет одно событие Blueprint (рис. 9).

OnScanComplete(); // Переключается, когда модуль сканирования завершает сохранение



Рисунок 9. Узел события Blueprint OnScanComplete

Функция SaveScan() дает модулю сканирования команду на сохранение с немедленным возвратом после этого. Несколько позже (в новом кадре камеры) поток подключаемого модуля RealSense выполнит операцию сохранения. Разработчики должны использовать событие OnScanComplete() для получения уведомления о том, что сохранение при сканировании завершено.

Архитектура


RealSense Session Manager


Когда в UE4 к объекту присоединяется компонент, этот объект получает новый экземпляр этого класса компонентов. Можно создать множество экземпляров одного и того же класса компонентов и присоединить их к множеству объектов в рамках одного проекта. Но для компонентов RealSense из-за этого возникает проблема. Дело в том, что в системе существует всего одна камера Intel® RealSense™, которой необходимо управлять разработчику. Но поскольку можно создавать множество экземпляров одного и того же класса компонентов, каждый экземпляр компонента RealSense будет получать свою собственную копию данных с камеры.

Для решения этой проблемы в подключаемом модуле RealSense используется объект RealSense Session Manager. Это одноэлементный класс, экземпляр которого автоматически создается при добавлении первого компонента RealSense к какому-либо объекту в игре. Все последующие экземпляры компонента RealSense получают ссылку на RealSense Session Manager при их инициализации. RealSense Session Manager является владельцем главной копии всех данных Intel RealSense SDK. Каждый компонент RealSense прочитывает данные из RealSense Session Manager и записывает данные в него.

Многопоточность


RealSense Session Manager отвечает за управление выделенным потоком подключаемого модуля RealSense. Этот поток обеспечивает работу модулей RealSense SDK с тем, чтобы в игре использовались классы компонента RealSense, основанные на возможностях SDK. Этот поток находится там, где работает цикл AcquireFrame() / ReleaseFrame() SDK. Все задействованные модули обрабатывают полученные кадры.

RealSense Session Manager использует тройной буфер для управления обменом данными между потоком подключаемого модуля RealSense и основным потоком игры UE4. Поток подключаемого модуля RealSense записывает все новые данные в фоновый буфер. После вызова ReleaseFrame() фоновый буфер обменивается данными со средним буфером, заблокированным с помощью взаимоисключающих блокировок (мьютексов). После этого в каждом такте игрового потока кадр переднего плана обменивается со средним буфером, предоставляя свежие данные в Session Manager и во все компоненты RealSense.

Заключение


Подключаемый модуль RealSense предоставляет разработчикам, использующим UE4, простой и удобный интерфейс к Intel RealSense SDK. Возможности пакета SDK становятся доступными для системы сценариев Blueprint, что существенно ускоряет разработку. Благодаря архитектуре на основе набора компонентов разработчики могут добавлять возможности трехмерной съемки практически к любым объектам в игре.

Комментарии (0)