Итак, начнем снова :)

Это второй пост о программировании эффектов дополненной реальности с помощью ARStudio. Если вы не читали первый, предлагаю вам увидеть его здесь.
Также неплохо загрузить код первого проекта (1. AR_Studio_Log_Monitor_Subscribe) с репозиторий, чтобы вы могли следовать инструкциям и самостоятельно видеть результаты.

В этом посте мы начнем использовать модуль анимации для создания некоторых анимаций в нашем «Эффекте облачной камеры». Наша цель - создать несколько базовых функций, которые можно будет использовать в любых дальнейших проектах. Вы также можете использовать одну функцию для одновременной анимации множества объектов с разными параметрами.

Как и в первом посте, я сосредоточусь на методах JavaScript с некоторыми математическими идеями. Проекты доступны в моей учетной записи GitHub:
https://github.com/marcostrinca/ARStudio-Tutorials

Официальную документацию для модуля анимации можно увидеть здесь.

1. Подготовка проекта

Давайте продублируем наш первый проект и лучше упорядочим его для этого урока:

После того, как вы загрузили репозиторий, откройте его в окне Finder, щелкните правой кнопкой мыши «1. AR_Studio_Log_Monitor_Subscribe »и выберите« Дублировать ». Затем переименуйте новую папку в «2. ARStudio_Animations ». Также переименуйте файл проекта ARStudio, чтобы он имел такое же имя:

Откройте новый проект в ARStudio. Найдите «plane0» внутри иерархии сцен и переименуйте его в «cloud0»:

Найдите «defaultMaterial0» внутри своей панели активов и переименуйте его в «mat_cloud»:

Дважды щелкните файл «скрипт», чтобы открыть его в редакторе. Удалите ненужные комментарии, если хотите, и сгруппируйте строки загрузки модулей в начале. Поскольку мы изменили имя нашего плоского объекта с «plane0» на «cloud0», нам также нужно изменить линию, ссылающуюся на этот объект. Я также изменил имя переменной с «my_plane» на «облако». Банкомат мой скрипт выглядит так:

Запустите проект и проверьте, нет ли журналов ошибок.

2. Драйверы и семплеры - немного теории.

По сути, для работы с анимацией в ARStudio нам нужны объект «Driver» и объект «SamplerFactory».

Давайте сначала импортируем наш модуль анимации, а затем углубимся в некоторые концепции.
Откройте файл сценария для проекта и введите следующие строки в начале сценария:

var Animation = require('Animation');
Diagnostics.log(Animation);

Если вы зарегистрировали переменную «Анимация», как это сделал я (помните, Диагностика - ваш друг), вы увидите в консоли, что у нее есть одно свойство «sampler» (объект «SamplerFactory») и три метода: «Animate ()», «valueDriver ()» и «timeDriver ()».

Давайте поговорим о каждом из этих парней:

Объект «sampler» является экземпляром класса «SamplerFactory» и создает различные типы сэмплеров анимации. Например, вы можете перемещать некоторые предметы из одной точки в другую линейно, я имею в виду, не изменяя его скорость. Или вы можете сделать это в конце. Возможно, вы хотите создать плавное ускорение в начале анимации и замедлить ее в конце. Чтобы настроить такое поведение, вы будете использовать разные семплеры.

«ValueDriver ()» и «timeDriver ()» возвращают объект «ValueDriver» и объект «TimeDriver» соответственно. Оба расширяют основной класс «Драйвер».

Класс Driver управляет потоком анимации. Вы можете настроить анимацию так, чтобы она повторялась столько раз, сколько захотите, или проверять, продолжается ли она, или даже запускать событие по окончании. Это примеры управления потоком. В нашем проекте мы будем использовать класс «TimeDriver».

Наконец, метод animate () объединяет драйвер и сэмплер для выполнения анимации в сцене.

3. Что мы хотим оживить?

Думая об эффекте облака, я вижу две анимации, над которыми мы можем начать работать:

Первое: облако перемещается только по оси «x», следуя положению головы пользователя. Что, если мы будем медленно двигать его вверх и вниз, как если бы он плыл? Мы можем создать для этого цикл, и результат будет классным.

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

4. Кодирование (наконец-то!)

Приступим к созданию нашей функции animateFloating () с тремя параметрами (obj, deltaY, ms):

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

var my_obj = Scene.root.find("object_name");

deltaY: это «расстояние», на которое вы перемещаете объект, другими словами, как далеко объект должен уйти от исходного положения по оси Y

мс: продолжительность анимации в миллисекундах.

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

// animate the cloud 10 units in Y axis in 1 second (eg.: 1000 milliseconds)
animateFloating(cloud, 10, 1000);

Запустив свой проект, вы можете увидеть, как облако поднимается за одну секунду и останавливается. Это не совсем то, что мы хотим. Мы хотим, чтобы он постоянно двигался вверх и вниз. Для этого нам нужно передать некоторые другие параметры методу timeDriver ().

Если вы вспомните в журнале сообщение нашей переменной «Анимация», вы можете найти внутри:

timeDriver(timeDriverParams: {durationMilliseconds: number, loopCount: ?number, mirror: ?boolean}): TimeDriver
`loopCount` defines the number of iterations before the time driver stops; this can be infinity.
When `mirror` is `TRUE`, the time driver follows a *yoyo* effect with every odd iteration going forwards and every even iteration going backwards.

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

// create time driver mirroring the animation
// loop 999 times
obj.animy_driver = Animation.timeDriver({durationMilliseconds: ms, loopCount: 999, mirror: true});

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

Это задача сэмплера. Таким образом, вместо использования linear в нашем сэмплере мы можем использовать другой тип сэмплера: easyInOutSine. Этот сэмплер будет плавно ускорять облако в начале и замедлять в конце анимации - SDK предоставляет множество сэмплеров, чтобы узнать больше обо всех из них, проверьте документацию.

Нет ничего лучше, чем проверить это, чтобы понять это. Еще раз внутри функции «animate ()» измените строку, которая устанавливает сэмплер, как это:

// create sampler
// now with easy in and out to smooth the transition
obj.animy_sampler = Animation.samplers.easeInOutSine(y0, y0 + deltaY);

Последняя настройка, которую я хочу сделать, - это уменьшить расстояние по оси Y, а также сделать анимацию немного медленной, и теперь это просто, нам просто нужно изменить значения для «distance» и «ms» при вызове нашего «animateFloating». () »Функция:

// animate the cloud 4 units in Y axis in 3 seconds
animateFloating(cloud, 3, 2000);

Бум! У нас есть хорошее движение для облака над головой, и оно движется независимо от движения головы. И что еще лучше, у вас есть функция для анимации любого количества облаков или объектов! Вы можете играть, добавляя больше облаков и вызывая их с разными параметрами расстояния и миллисекунд :)

Последний шаг - создать функции для постепенного появления / исчезновения, и мы закончили.

Это очень похоже на «animateFloating ()», но теперь мы меняем свойство материала, в данном случае «непрозрачность». Для работы с материалами из кода нам нужно импортировать «Модуль материалов», а затем создать переменную для хранения нашего облачного материала.

Перейдите к первому блоку кода и добавьте следующий код - сразу под строкой, импортирующей модуль анимации:

var Materials = require("Materials");
// get the cloud material
var mat_cloud = Materials.get("mat_cloud");

Не забудьте дважды проверить имя, которое вы задали для материала, который вы используете на плоскости облака. Вы можете найти его внутри панели «Assets» в ARStudio. В моем случае я установил его как «mat_cloud» и использую то же имя для своей переменной.

Когда у нас есть материал в переменной, мы можем получить доступ к любому свойству в нем. Не стесняйтесь зайти в «Diagnostics.log (mat_cloud)» и проверить, что предоставляет этот модуль. Одно из свойств, которое вы обнаружите, если сделаете это, - «непрозрачность».

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

Функции FadeIn и FadeOut следующие:

Теперь нам нужно вызвать функцию «fadeIn ()», когда камера обнаруживает лицо, и «fadeOut ()», когда камера теряет лицо. Для этого нам нужно вернуться к началу скрипта внутри нашей функции монитора FaceTracking и вызвать ее оттуда.

Мы закомментируем строки, которые устанавливают скрытое значение облачного объекта, и вместо этого вызовем функции «fadeIn ()» и «fadeOut ()»:

// monitor the FaceTracking to detect faces
FaceTracking.count.monitor().subscribe( function(e) {
 if (e.newValue > 0) {
// show the cloud in case there is a face
  // cloud.hidden = false; <- comment this line
  fadeIn(cloud, mat_cloud);
// function to track the head's position
  trackHead()
 } else {
  
  // cloud.hidden = true; <- comment this line
  fadeOut(cloud, mat_cloud);
 }
})

И на этот раз все.

Не стесняйтесь комментировать, если у вас есть вопросы. Я постараюсь ответить как можно скорее.