Естественно-интуитивное взаимодействие с компьютером с использованием Intel RealSense SDK

Возможности использования Intel Perceptual Computing SDK в игровых приложениях

Показывать лекцию целиком

Цель лабораторной работы

Разработка учебного приложения в Unity с реализацией жестового управления игровыми объектами, используя Intel Perceptual Computing SDK

Задачи лабораторной работы

  • создать учебный проект в Unity и настроить его на работу с Intel Perceptual Computing SDK;
  • разработать скрипт, реализующий жестовое управление игровым объектом
  • Введение (постановка задачи)

    В данной работе не стоит цели создать настоящее игровое приложение, основная задача научиться реализовывать жестовое управление игровыми объектами. Поэтому для достижения цели лабораторной работы, настроим простые игровые объекты в Unity, в нашем случае ограничимся плоскостью и шариком. Далее реализуем управление шариком, заключающееся в следующем: пользователь перед камерой воспроизводит воображаемый руль (см. рис 6.1), шарик на экране двигается в соответствии с движениями руля.

    (рис 6.1) Воображаемый руль, основные движения

    Создание проекта в Unity и настройка на работу с Intel Perceptual Computing SDK

    1. Создание проекта

  • Запустим Unity и создадим новый проект, зададим ему подходящее имя.
  • Сохраним сцену File->Save Scene, зададим ей имя, например, MiniGame. Можно проверить в папке, в которой расположен Unity проект, должна быть папка Assets, а в ней файл MiniGame.unity.
  • Создадим плоскость, по которой будет кататься наш шарик: Game Object- >Create Other->Plane.
  • Создадим, собственно, сам шарик: Game Object- >Create Other->Sphere.

    На данном этапе создания проекта окно . Справа вкладка Inspector, в которой отображаются основные свойства игровых объектов. Имеет смысл обратить внимание на расположение координатных осей в Unity.

    (рис 6.2) Окно Unity после настройки простых игровых объктов
  • добавим освещение: вкладка Inspector (рис 6.3) Окно Unity, настройка освещения и теней
  • для большей реалистичности настроим тени: во вкладке .
  • На этом собственно создание игровых объектов в Unity закончим, такого простого решения для наших целей вполне достаточно.

    2. Настройка на работу с Intel Perceptual Computing SDK

    Intel Perceptual Computing SDK работает в Unity, как плагин и его использование ограничено версией Unity Pro. Существует возможность получить бесплатно пробную версию Unity Pro на 30 дней, этого времени достаточно для экспериментов с SDK. Как показал опыт, после окончания этого срока тоже можно работать с Intel Perceptual Computing SDK, если каждый раз при проверке работы приложения выполнять его построение и запускать получившийся исполняемый файл (т. е. использовать File->Build Run).

    Чтобы настроить приложение на работу с Intel Perceptual Computing SDK, необходимо в директории <project>/Assets/ создать папку Plugins и скопировать в эту папку три файла:

  • libpxcupipeline.dll
  • pxcm-structures.cs
  • pxcupipeline.cs
  • Эти файлы можно найти в папке: $(PCSDK_DIR)/framework/Unity/hellounity/Assets/Plugins, где $(PCSDK_DIR) путь к директории, в которой установлен SDK.

    Разработка скрипта, реализующего жестовое управление игровым объектом

    Создадим C# скрипт: Assets->Create->C# Script, назовем его, например, SphereControl. Скрипт создан для управления шариком, для этого свяжем его с игровым объектом Sphere. Во вкладке Inspector, для объекта Sphere, необходимо нажать кнопку Add Component, далее выбрать Scripts и выбрать нужный скрипт из списка (в нашем случае в списке ровно один, только что созданный скрипт).

    Непосредственно после создания скрипт выглядит, как на рис 6.4.

    (рис 6.4) С# скрипт сразу после создания

    Скрипт описывает класс SphereControl (имя класса должно совпадать с названием скрипта). Для работы с жестами необходимо объявить две переменные, как поля класса SphereControl:

    private PXCUPipeline.Mode mode = PXCUPipeline.Mode.GESTURE; 
    private PXCUPipeline pp;
        

    первая из них сообщает, что будет использоваться жестовый режим, вторая - является экземпляром класса PXCUPipeline, являющегося C# оболочкой класса UtilPipeline.

    1. Настройка метода Start()

    В этом методе выполним первоначальные настройки:

  • создадим экземпляр класса PXCUPipeline и присвоим его переменной pp;
    pp = new PXCUPipeline();
              
  • настроим объект pp на работу в режиме, указанном в переменной mode, в режиме распознавания жестов.
    pp.Init(mode);
              
  • Полностью метод Start() представлен в листинге 6.1.

    2. Настройка метода Update()

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

    PXCMGesture.GeoNode mainHand; //главная рука
    PXCMGesture.GeoNode secondaryHand;
            

    Нам необходимо запрашивать данные, которые может предоставить Intel Perceptual Computing SDK, в нашем случае данные о положении рук. Чтобы получать данные от SDK в каждом фрейме, используем следующую конструкцию:

    if (!pp.AcquireFrame(true)) return;
            

    Получать данные будем с помощью метода класса PXCUPipeline:

    bool QueryGeoNode(PXCMGesture.GeoNode.Label body, 
    	out PXCMGesture.GeoNode data);
            

    Первый аргумент метода задает объект, который необходимо отслеживать, в нашем случае - рука.

    Второй аргумент после выполнения метода содержит данные о местоположении объекта.

    Получим данные о положении рук:

    pp.QueryGeoNode(PXCMGesture.GeoNode.Label.LABEL_BODY_HAND_LEFT |
     	PXCMGesture.GeoNode.Label.LABEL_HAND_MIDDLE, out mainHand);
    
    pp.QueryGeoNode(PXCMGesture.GeoNode.Label.LABEL_BODY_HAND_RIGHT |
     	PXCMGesture.GeoNode.Label.LABEL_HAND_MIDDLE, out secondaryHand);
            

    После получения данных от SDK необходимо освободить фрейм, используя следующий метод:

    pp.ReleaseFrame();
            

    Отвлечемся от программирования и обсудим, как определяется положение рук в пространстве. В трехмерном пространстве для задания положения объекта чаще всего используется трехмерный радиус-вектор (вектор, направленный из начала координат к объекту). Следует иметь ввиду, что координаты объектов вычисляются в системе координат, определяемой камерой. На рис 6.5 хорошо видно, как направлены координатные оси в этой системе координат.

    (рис 6.5) Система координат, используемая в Intel Perceptual Computing SDK

    Вернемся к задаче, нам необходимо определять поворот воображаемого руля. В рассмотренной системе координат поворот будет определяться изменением координаты z. На рис 6.6 показано, как математически можно описать поворот "воображаемого" руля. Становится понятным зачем мы определяли главную и не главную руки, поворот вычисляется, как разность z-координат главной и второй руки. Если разность положительная, то поворот направо, если отрицательная - налево.

    (рис 6.6) Вычисление поворота руля

    Вернемся к программированию, нам необходимо как-то получить z-координаты рук. Для этого воспользуемся переменными mainHand и secondaryHand. Каждая из этих переменных получила сведения о положении соответствующей руки, во время запроса данных от SDK. Чтобы вытащить координаты z, воспользуемся следующими конструкциями:

    float mainHandZ = mainHand.positionWorld.z; 
    	float secondaryHandZ = secondaryHand.positionWorld.z;
            

    Теперь эти координаты можно использовать по назначению, передав их в метод:

    controlTurn(mainHandZ, secondaryHandZ);
            

    На этом метод Update() можно закончить.

    Рассмотрим реализацию метода controlTurn(), в нашем случае эта реализация очень простая.

    void controlTurn(float mainHandZ, float secondaryHandZ){
    		float turn = mainHandZ - secondaryHandZ;
    		Vector3 move = new Vector3 (turn, 0, 0);
    		transform.Translate (move);
    		
    	}
            

    В первой строке находим разность z-координат главной и не главной рук.

    Во второй строке создаем вектор, который задает смещение шарика.

    В третьей строке выполняем смещение.

    Возможные пути развития задачи

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

  • В созданное приложение добавить жестов для управления шариком, например, движение рук вверх и вниз заставляло бы шарик двигаться вперед-назад (возможны, разумеется, другие варианты).
  • Для создания реалистичных игр, необходимо использовать возможности Unity, задавать физические свойства объектов, сцен. Но данный курс не предусматривает серьезного изучения Unity, поэтому создание реалистичных игр с использованием возможностей Intel Perceptual Computing SDK оставим в качестве самостоятельной работы.
  • Самый простой вариант развития полученного приложения видится в создании на плоскости некоторого лабиринта, добавление правильного физического поведения (например, шарик отскакивает от стен, а не проходит сквозь них) и программирование управления доской (плоскостью) с помощью жестов. В результате должен появиться аналог детской игры "Лабиринт" с задачей загнать шарик в лунку.
  • Раз уж в приложении использовался воображаемый руль, явным продолжением развития идей подобного управления было бы создание игры "Гонки". Для создания этой игры необходимо научиться использовать возможности Unity, а также продумать систему жестов для торможения и разгона.
  • Нельзя пройти мимо существующего решения, в котором реализовано управление самолетом с помощью жестов: https://www.youtube.com/watch?v=KPE332rX5Yc#t=20. Данный проект может служить источником идей для вдохновения, а также предлагает некоторые мысли, необходимые для реализации взаимодействия с Intel Perceptual Computing SDK при разработке похожих приложений: описание.
  • using UnityEngine;
    using System.Collections;
    
    public class SphereControl : MonoBehaviour {
    private PXCUPipeline.Mode mode = PXCUPipeline.Mode.GESTURE; 
    private PXCUPipeline pp; 
    
    // Use this for initialization
    void Start () {
    pp = new PXCUPipeline();
    pp.Init(mode);
    }
    	
    // Update is called once per frame
    void Update () {
    PXCMGesture.GeoNode mainHand; //главная рука
    PXCMGesture.GeoNode secondaryHand;
    
    if (!pp.AcquireFrame(true)) return; 
    
    pp.QueryGeoNode(PXCMGesture.GeoNode.Label.LABEL_BODY_HAND_LEFT
     | PXCMGesture.GeoNode.Label.LABEL_HAND_MIDDLE, out mainHand);
    
    pp.QueryGeoNode(PXCMGesture.GeoNode.Label.LABEL_BODY_HAND_RIGHT |
    PXCMGesture.GeoNode.Label.LABEL_HAND_MIDDLE, out secondaryHand);
    
    pp.ReleaseFrame();
    
    float mainHandZ = mainHand.positionWorld.z; 
    float secondaryHandZ = secondaryHand.positionWorld.z; 
    controlTurn(mainHandZ, secondaryHandZ);
    
    }
    
    void controlTurn(float mainHandZ, float secondaryHandZ){
    float turn = mainHandZ - secondaryHandZ;
    Vector3 move = new Vector3 (turn, 0, 0);
    transform.Translate (move);
    
    }
    
    }
        
    Вернуться к учебному плану