Идея

Все началось с книги. Один друг на свадьбе порекомендовал мне его. Я купил его на Kindle и открываю: Kindle показал «Осталось 120 часов на чтение». Этот ярлык заставил меня задуматься: наверное, последние 6 лет я полностью читаю из приложения Kindle, и когда вы покупаете цифровые книги на Amazon, вам все равно, насколько они велики, вы не визуализируете и не соотносите их с физическими размерами. все. Кроме того, я не помню, чтобы в следующие несколько недель много выходил из квартиры. После этого я погуглил. Выглядело круто!

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

Оглавление

В предыдущем посте я описал простую и понятную библиотеку для сбора данных из GoodReads. Здесь я покажу вам, как визуализировать реалистичные книжные объекты в AR, а в следующем посте мы обсудим архитектуру (и уберем весь беспорядок с прототипами, который мы сейчас здесь обнаружим).

  1. GoodReads API с Android с Kotlin
  2. Все мои книги в AR [Вы здесь!]
  3. От stuff.kt к архитектуре (Как переписать полноценный прототип, увеличить количество файлов на 20 и не волноваться)

Вы можете поиграть с полученным приложением в GooglePlay:



Полные исходники для текущего поста находятся в ветке руководства:



Настройте инструменты

Я начну там, где заканчивается большинство руководств: простой проект Android Studio с ArFragment, в котором вы можете разместить трехмерный объект на плоскости. Обратитесь к проекту Элло Sceneform от Google или к этой серии.

Устраивайтесь поудобнее. Эмулятор может быть полезен для выполнения некоторых быстрых изменений - это руководство поможет организовать настройку. Вы знали, что можете войти внутрь своего эмулятора или украсить его стены? Я этого не сделал. (Ну да, это для тестирования дополненных изображений, но все же).

Что касается реального устройства, убедитесь, что вы освоили adb wifi: короткие USB-кабели легко превратят вашу отладку в йогу.

Соберите данные

Я проделал некоторую предварительную работу (вы могли прочитать об этом в предыдущем посте: GoodReads API из Android с Kotlin) - короче говоря: весь процесс получения данных о книгах был помещен в небольшую библиотеку Android, я буду используя здесь. Процедура инициализации и входа в систему была описана ранее, поэтому здесь я сосредоточусь на использовании. Давайте определим наши структуры данных:

Я объявил два отдельных класса данных: BookModel - это как раз то, что мне нужно из данных GR, а ARBook - это все данные, которые мне нужны для визуализации книги в AR. Я сохраню их в экземпляре Application для простоты (не будьте слишком параноиками, я знаю, что это не лучший вариант, но для прототипа, я думаю, это совершенно верно):

Следующий фрагмент кода загружает данные, сортирует их и творит чудеса с URL-адресами изображений:

Сначала я старался обернуть все работы, требующие интенсивного использования ЦП, на Dispatcher.Default. Во-вторых, если вы пропустили первый пост - Goodreads API ужасен. Для большинства бестселлеров Goodreads получает изображения обложек от материнской компании (вы слышали об этой маленькой компании по имени Amazon?). По каким-то юридическим причинам они обязали не передавать такие данные третьим лицам через API. Для нас это означает, что для 80% книги вы получите это в качестве обложки:

К счастью, для таких случаев у нас есть OpenLibrary Covers API! Блок When в приведенном выше коде заменяет пустые обложки из GR на ссылки OpenLibrary. Конечно, все работает только в том случае, если у книги есть ISBN, а в OpenLib есть желаемое изображение.

Погружать

Зайдите в Поли и выберите модель книги. Что-то вроде этого: коричневая книга от Норберта Куруца (но, конечно, вы можете выбрать все, что захотите).

Процесс добавления трехмерных объектов в проект неоднократно объяснялся, поэтому я не буду останавливаться на достигнутом (см. Это). Единственное усовершенствование, которое я считаю подходящим, - это завернуть загрузку среды выполнения модели в сопрограмму (поскольку остальная часть моего асинхронного кода будет основана на сопрограммах, лучше сделать все похожим образом):

await - это расширение Kotlin для Java 8 CompletableFuture. Чтобы получить его, вам понадобится одна дополнительная зависимость помимо модулей сопрограмм - поддержка jdk8:

Шкала

Первое, с чем вы столкнетесь (если вы похожи на меня и не живете во дворце) - почти все активы из Poly или любого другого магазина активов чрезвычайно ОГРОМНЫ!

Большинство руководств просто регулируют значение шкалы в файлах sfa \ sfb:

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

Поскольку я использовал только одну модель, после ее измерения я жестко запрограммировал ее размер для будущего повторного использования (это после предварительного масштабирования в sfb):

После измерения исходного размера вашей модели пришло время уменьшить ее до нужного нам размера:

Кстати, система координат, используемая в сцене, следующая:

А теперь вы можете убедиться, что размер соответствует вашим ожиданиям:

Раскрасить

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

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

Во время выполнения вы можете получить доступ к таким разделам и назначить им следующие свойства:

Поэкспериментируйте, и вы найдете нужные разделы:

Крышка

Далее идут красивые обложки! Загружать изображение во время размещения объекта на сцене не имеет смысла - никому не нравятся глюки и задержки. Лучше заранее загрузить все нужные изображения. На данный момент я предполагаю, что у вас заранее есть растровое изображение (позже я покажу, как предварительно получить обложки). Мы могли бы создать текстурную карту из обложки, а затем назначить ее объекту, но это требует создания большого растрового изображения во время выполнения для каждой книги (и я надеюсь визуализировать целую стопку книг).

Чтобы визуализировать пользовательский интерфейс в форме сцены, нужно понимать ViewRenderable и помнить, что каждые 250 dp для вида превращаются в 1 метр для визуализируемого (не спрашивайте). Дочерний узел размещается по умолчанию в нулевых родительских координатах, поэтому для точного выравнивания изображения обложки поверх модели книги нам необходимо настроить локальное положение, размер и поворот.

Вращение несложно, хотя и включает Quanterion: нам просто нужно повернуть на 90 градусов вокруг оси X:

Масштаб немного сложен, так как сначала нам нужно вычислить, в каком размере изображение будет отображаться в масштабе 1 (помните правило: 250 dp— 1 м):

Затем мы могли бы уменьшить его, чтобы он соответствовал размеру объекта родительской книги (уже масштабирован). Также немного скорректирую полученный масштаб, чтобы учесть края моделей.

Внезапно опасной зоной для меня стало позиционирование. После программного поворота модели книги на 180 градусов вокруг оси Y (а вы не можете сделать это в sfa) ось вашего дочернего узла (обложки) также поворачивается. Итак, полученный код выглядит так:

Раскрасьте с шармом

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

Вероятно, вы могли бы добиться аналогичных результатов с Android Palette. Для корешка нам понадобится только цвет фона:

И теперь наши книги выглядят более естественно:

Размещение

А теперь пора навести беспорядок! Давайте представим всю книгу, которая у нас есть, в виде сетки. Ранее мы загрузили массив booksModel, а теперь давайте заполним список ARBooks всеми данными, которые нам нужны для правильного размещения книг в 3D:

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

Как я уже упоминал ранее, я поворачиваю книги на 180 градусов и вносю некоторую дисперсию (я никогда не видел, чтобы стопка книг была идеально выровнена):

Что касается размеров, так как я не нашел ни одного открытого API с такими данными, я использовал некоторое приближение. Согласно Basford, K.E., G.J. Маклахлан и М. Йорк в Моделирование распределения толщины штамповой бумаги с помощью конечных нормальных смесей: «Как отметили Изенменд и Зоммер, существует некоторая кластеризация вокруг значений 0,07, 0,08, 0,09, 0,10, 0,11, 0,12 и 0,13 мм, при этом примерно половина данные от 0,06 до 0,08 ”. Добавив 2 мм на обложки и стандартный размер мягкой обложки, мы получим:

И, как и обещал, код для предварительной загрузки обложек (я использовал Glide):

Полученное размещение выглядит так:

Представление

На моем Nexus 6P где-то около 200 книжных узлов с обложками сцена начинает давать сбои. Чтобы повысить производительность, вы можете удалить узлы обложки для нижних книг (так как они все равно перекрываются). См. Главную ветку ARFragment.kt для этого.

Описанные здесь приемы, используемые в моем приложении с открытым исходным кодом под названием bookar. Вы можете получить это в Google Play.



Все источники доступны здесь.