На CBRE Build мы изучаем новые технологии с потенциальными приложениями в сфере недвижимости, а также для развлечения! Дополненная реальность (AR) — одна из таких областей, которую мы недавно изучали. Мобильная AR приобрела популярность в последние годы с выпуском таких приложений, как Pokemon Go и Snapchat Lenses.

В прошлом году Apple и Google выпустили новые фреймворки ARKit и ARCore, чтобы удовлетворить растущий спрос на мобильные приложения дополненной реальности, а новые гарнитуры дополненной реальности, такие как Microsoft Hololens и Magic Leap, вызвали много шума. Мы решили поэкспериментировать с AR, создав забавный проект, который понравится многим! Этот пост в блоге будет описывать:

  1. наше приложение-охота за сокровищами в дополненной реальности: https://ar-builders.cbrebuild.com/ (чтобы играть в игру, вам нужно будет просмотреть или распечатать изображения здесь)
  2. наш опыт использования веб-фреймворков AR A-Frame и AR.js
  3. наш процесс разработки.

Мы надеемся, что этот пост будет вам полезен, если вы заинтересованы в работе с A-Frame и AR.js для создания веб-приложения AR!

AR Builders — охота за сокровищами

23 мая CBRE Build провел день открытых дверей для NYCxDESIGN, ежегодного праздника дизайна в Нью-Йорке, чтобы продемонстрировать наши продукты и процессы проектирования. В рамках этого мы создали поиск сокровищ в дополненной реальности, чтобы побудить посетителей взаимодействовать с нашими талисманами, Строителями CBRE. Кроме того, мы создали два приложения для iPad, чтобы показать наши 3D-модели зданий в дополненной реальности, о чем мы расскажем в следующем посте в блоге.

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

По всему офису мы разместили специальные изображения, распечатанные на бумаге, или «Маркеры», которые показывают Строитель, когда вы просматриваете Маркер через свой телефон (используя Safari на iOS и Chrome на Android, если на нем включены WebGL и WebRTC) . Другие маркеры показывают спрятанное «сокровище», например молоток или отвертку.

Когда вы нажимаете на Строителя, появляется диалоговое окно, в котором вас просят найти конкретное сокровище. Найдя правильный Маркер с сокровищами Строителя, игрок может разблокировать новый диалог! Ниже приведен пример этой диалоговой последовательности.

Рамки дополненной реальности

Первоначально мы создали прототип приложения с использованием популярного движка 3D-игр Unity и ведущей платформы дополненной реальности Vuforia, но мы хотели, чтобы пользователи могли играть в нашу игру на нашем мероприятии без необходимости загружать приложение. В конце концов мы остановились на A-Frame и AR.js, что позволило нам создать веб-приложение, которое мог просматривать любой, у кого есть телефон с поддержкой WebGL.

A-Frame — это веб-фреймворк для создания приложений виртуальной реальности, а AR.js — это библиотека javascript, основанная на ARToolKit, одном из первых AR SDK для мобильных устройств. Нам не понадобились какие-либо замысловатые функции Vuforia, такие как распознавание объектов или обнаружение плоскостей, и хотя обнаружение изображений в AR.js не такое мощное, как Vuforia, для наших целей оно помогло. A-Frame и AR.js также имеют открытый исходный код, и поддержка проектов с открытым исходным кодом важна для нашей команды.

Кроме того, установка была настолько простой, что ее невозможно было превзойти. Мы следовали учебнику Этот A-Frame и AR.js и получили пример, работающий с менее чем 10 строками HTML! Для краткости я опустил некоторые детали реализации, описанные в этом руководстве, поэтому, если вы не знакомы с A-Frame и AR.js, я рекомендую взглянуть на эту ссылку, прежде чем читать этот пост.

Разработка

Наш процесс разработки состоял из 4 частей:

  1. Создание изображений маркеров
  2. Добавление изображений маркеров и моделей Builder в HTML-шаблон A-Frame
  3. Реализация диалогового взаимодействия с речевым пузырем
  4. Отслеживание инвентаря игроков

Создание изображений маркеров

Как только мы заработали наш первый пример AR, нашим следующим шагом было разработать маркеры, которые будут представлять наших строителей и сокровища. Эта статья Николо Карпиньоли представляет собой отличный обзор AR.js и создание собственных маркеров. В частности, маркеры имеют строгие правила для их правильного обнаружения:

  • Максимальное разрешение маркера 16x16 пикселей.
  • Они должны быть квадратной формы
  • У них не может быть белых/прозрачных областей, только светло-серые (например, #F0F0F0)
  • Они не могут содержать цвета, только черный и светло-серый.
  • Они должны содержать простой текст, например одну букву, цифру или символ.

Этот список должен быть первым, к чему вы обращаетесь, если у вас возникли проблемы с обнаружением маркера. Изначально мы создали маркеры с белым фоном и цветами и недоумевали, почему они не работают, пока не нашли этот список.

В конце концов, мы остановились на использовании простых форм для наших маркеров, а также имени строителя или вопросительного знака для сокровищ (поскольку мы не хотели, чтобы местонахождение сокровищ было очевидным). Мы использовали этот инструмент, предоставленный AR.js, для создания файлов данных изображения маркера (.patt) для алгоритма обнаружения изображения. Каждый маркер должен однозначно идентифицировать Строителя (или сокровище), поэтому нам пришлось создать отдельный маркер для каждого Строителя (и сокровища). Ниже приведен пример маркеров для строителя Пиры и ее молота.

Добавление маркеров и 3D-моделей в HTML-шаблон A-Frame

После разработки изображений маркеров пришло время поместить их в шаблон A-Frame, чтобы их мог использовать AR.js. Нам также нужно было добавить 3D-модели (разработанные нашей производственной командой) в шаблон, чтобы они отображались на экране, когда вы просматриваете маркеры на своем телефоне. Это достигается за 3 шага для каждой 3D-модели:

// 1
<a-asset-item id="pyra-obj" src="builder-models/Pyra.obj"></a-asset-
item>
// 2
<a-marker id="pyra-marker" type="pattern" url="builder-markers/pyra.patt"></a-marker>
// 3
<a-entity id="pyra" obj-model="obj: #pyra-obj;" material="color: green" rotation="0 180 0" position="0 0 0.5" scale="0.15 0.15 0.15"></a-entity>
  1. Добавьте источник (<a-asset-item>) 3D-актива в узел <a-assets> шаблона.
  2. Добавьте src (<a-marker>) файла данных маркера в узел <a-scene> шаблона.
  3. Чтобы «связать» Маркер и 3D-модель, добавьте узел <a-entity> со ссылкой на 3D-модель внутри узла <a-marker>, созданного на предыдущем шаге.

Мы настроили материал, вращение, положение и масштаб модели, чтобы получить правильный вид для нашей игры.

Собранный вместе, HTML для всей сцены с одним Builder выглядит так:

<a-scene embedded arjs>
  <a-assets>
    <a-asset-item id="pyra-obj" src="builder-models/Pyra.obj"></a-asset-item>
  </a-assets>
  <a-marker id="pyra-marker" type="pattern" url="builder-markers/pyra.patt">
    <a-entity id="pyra" obj-model="obj: #pyra-obj;" material="color: green" rotation="0 180 0" position="0 0 0.5" scale="0.15 0.15 0.15">
    </a-entity>
  </a-marker>
  <a-entity camera></a-entity>
</a-scene>

Это очень похоже на код, использованный в учебнике, которому мы следовали, с добавлением 3D-модели в формате obj. На этом этапе наше приложение могло распознавать маркеры и отображать строители, но пользователь еще не мог взаимодействовать с строителями.

Реализация диалогового взаимодействия с речевым пузырем

Когда пользователь нажимает на экран с определенным Builder, мы хотим, чтобы приложение показывало диалог этого Builder. Это оказалось самой сложной частью проекта, потому что нам нужно было решить две проблемы:

  1. Как обнаружить кран
  2. Как определить, какой Строитель был задействован

Пока невозможно добавить обработчик тапа непосредственно в <a-entity> Builder. Поэтому сначала мы попытались выполнить тест на пересечение лучей, когда пользователь касался экрана, чтобы определить, пересекается ли луч, выходящий из точки касания, с моделью Builder. Это работало в большинстве случаев, но были некоторые крайние случаи, когда проверка пересечения не удалась.

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

Мы реализовали функцию касания, определив новый компонент с именем accepts-clicks:

AFRAME.registerComponent('accepts-clicks', {
  init: function() {
    this.el.addEventListener('touchend', handleClickEvent);
    this.el.addEventListener('click', handleClickEvent);
  }
});

а затем добавить его как атрибут к <a-scene>:

<a-scene embedded arjs accepts-clicks>

Обратите внимание, что accepts-clicks не является стандартным компонентом A-Frame/AR.js — мы определили его специально для этого приложения.

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

Первоначально мы думали, что при успешном обнаружении маркера может возникнуть событие. Мы могли бы использовать это, чтобы установить значение, указывающее, какой Builder в данный момент находится на экране. Однако после некоторых исследований мы поняли, что это еще не поддерживаемая функция AR.js.

К счастью, HTML-объект каждого маркера имеет свойство object3D.visible. Это значение указывает, видна ли 3D-модель, связанная с этим маркером, на экране или нет. Основываясь на нашем дизайне поиска сокровищ, на экране одновременно был бы виден только один Маркер, поэтому все, что нам нужно было сделать, это прокручивать Строителей каждый раз, когда вы нажимали на экран, и использовать диалог Строителя, чье object3D.visible верно.

function handleClickEvent() {
  for (var i = 0; i < builders.length; i++) {
    var builder = builders[i];
    var builderMarker = document.querySelector("#" + builder.name + "-marker");
    if (builderMarker && builderMarker.object3D.visible) {
      if (searchForBuilderTool(builder)) {
        toggleSpeechBubble(builder.successDialogue);
      } else {
        toggleSpeechBubble(builder.dialogue);
      }
      break;
    }
  }
}

Последней деталью было то, что мы хотели, чтобы всплывающая подсказка исчезала, если пользователь отодвигал свой телефон от маркера. Для этого мы определили обработчик «tick» (который вызывается для каждого цикла рендеринга A-Frame).

AFRAME.registerComponent('accepts-clicks', {
  init: function() {
    this.el.addEventListener('touchend', handleClickEvent);
    this.el.addEventListener('click', handleClickEvent);
  },
  tick: function() {
    hideSpeechBubbleIfNoMarker();
  }
});

Функция hideSpeechBubbleIfNoMarker() использует аналогичный тест с object3D.visible, чтобы определить, следует ли скрывать всплывающую подсказку. Если все Строители скрыты, также скройте всплывающую подсказку, но если какой-либо Строитель виден, сохраните подсказку.

function hideSpeechBubbleIfNoMarker() {
  var shouldHide = true;
  for (var i = 0; i < builders.length; i++) {
    var builderMarker = document.querySelector("#" + builders[i].name + "-marker");
    if (builderMarker && builderMarker.object3D.visible) {
      shouldHide = false;
      break;
    }
  }
  // hide speech bubble
};

Теперь речевой пузырь исчезнет, ​​как только исчезнет Строитель.

Отслеживание инвентаря игрока

Последней частью нашей охоты за сокровищами было отслеживание того, какие сокровища нашел игрок. Мы определили несколько классов: Builder, Tool (сокровища) и UserState.

В классе Builder были поля для имени, инструмента, начального диалога и альтернативного диалога после того, как пользователь нашел сокровище. Поле «инструмент» было сокровищем, связанным с этим Строителем. Класс Tool имел поля для имени и диалога. И, наконец, у UserState был массив, содержащий инвентарь сокровищ, на который кликнул игрок.

Каждый раз, когда игрок нажимал на инструмент, этот инструмент добавлялся в список UserState. И каждый раз, когда игрок нажимал на Строителя, мы проверяли, находится ли инструмент, связанный с этим Строителем, в папке UserState. Если это так, мы покажем альтернативный диалог.

Теперь, когда мы отслеживаем инвентарь, приложение для поиска сокровищ практически готово! Мы упустили некоторые детали того, как показать всплывающую подсказку, но это довольно стандартный HTML/CSS. Полный код можно посмотреть здесь (кроме 3D-моделей).

Выводы

Наша охота за сокровищами в дополненной реальности увенчалась успехом! Многим людям понравилось общаться со строителями и искать их сокровища в офисе во время дня открытых дверей. Это был увлекательный экскурс в мир дополненной реальности, и на создание готового продукта ушло всего несколько дней. Мы настоятельно рекомендуем использовать A-Frame и AR.js для простых проектов дополненной реальности на основе маркеров!