Upgrade to Pro — share decks privately, control downloads, hide ads and more …

CodeFest 2019. Иван Порошин (Яндекс) — Android....

CodeFest
April 06, 2019

CodeFest 2019. Иван Порошин (Яндекс) — Android. ARCore + Sceneform: как создавать дополненную реальность

Несмотря на то, что прошёл уже почти год с момента релиза ArCore, есть разработчики, которые до сих пор не работали с этой технологией. В докладе мы посмотрим, какие возможности открывает ArCore не только в сфере развлечений, но и перед бизнесом, и какие изменения претерпел фреймворк с момента первого релиза. Также я расскажу о процессе создания Android-приложения с дополненной реальностью и о проблемах, с которыми можно при этом столкнуться.

CodeFest

April 06, 2019
Tweet

More Decks by CodeFest

Other Decks in Technology

Transcript

  1. 1 Примеры использования AR 2 ARCore и Sceneform 3 Как

    сделать своё приложение с AR Содержание
  2. Что умеет ARCore › Вычисление позиции устройства › Поиск ключевых

    объектов › Трекинг ключевых объектов › Оценка уровня освещения 11
  3. Требования › minSdkVersion >= 24 › Доступ к камере ›

    Приложение ARCore › Устройство из списка поддерживаемых 12
  4. 19

  5. 20

  6. 23

  7. Cloud anchors: ограничения › Anchor жив только в течение 24

    часов › Матчинг происходит на серверах Google › Нельзя получить назад облако точек › Нет привязки к геоданным 38
  8. 46

  9. 47

  10. Sceneform › Позволяет делать AR без глубоких знаний OpenGL ›

    Достаточно гибкий для тех, кто знаком с OpenGL 54
  11. 60

  12. ArFragment › Проверяет наличие ArCore › Запрашивает runtime permissions ›

    Инициализирует ArCore › Содержит ArSceneView 66
  13. Граф объектов › У каждого узла есть Pose › При

    отрисовке применяются Pose всех родителей › Это эффективно реализовано с помощью матриц 73
  14. Сборка графа объектов val anchor /* пусть Anchor уже существует

    */ val portalNode = Node() val speedNode = Node() val ballonNode = Node().apply { addChild(speedNode) } val anchorNode = AnchorNode(anchor).apply { addChild(portalNode); addChild(balloonNode) } mArFragment.arSceneView.scene.addChild(anchorNode) 79
  15. Где взять 3d модели? › Найти художника › Google Poly

    › Unity Asset Store › И другие подобные ресурсы › 85
  16. 86

  17. 87

  18. Где взять 3d модели? › Найти художника › Google Poly

    › Unity Asset Store › И другие подобные ресурсы › 88
  19. Где взять 3d модели? › Найти художника › Google Poly

    › Unity Asset Store › И другие подобные ресурсы › Сделать самому 89
  20. Где взять 3d модели? › *.obj - формат без анимаций

    › *.glTF - анимации есть, но импортировать нельзя › *.fbx - анимации есть и импортировать можно 91
  21. 96

  22. Загрузка моделей в приложении val balloonRenderable = ModelRenderable.builder() .setSource(context, R.raw.balloon)

    .build() /* returns CompletableFuture */ val portalRenderable = ModelRenderable.builder() .setSource(context, R.raw.portal) .build() 98
  23. Получение Anchor class MyArFragment : ArFragment() { override fun getSessionConfiguration(session:

    Session?): Config { val config = super.getSessionConfiguration(session) val inputStream = context!!.assets.open("images.imgdb") config.augmentedImageDatabase = AugmentedImageDatabase.deserialize(session, inputStream) return config } ... } 109
  24. Получение Anchor class MyArFragment : ArFragment() { override fun getSessionConfiguration(session:

    Session?): Config { val config = super.getSessionConfiguration(session) val inputStream = context!!.assets.open("images.imgdb") config.augmentedImageDatabase = AugmentedImageDatabase.deserialize(session, inputStream) return config } ... } 110
  25. Получение Anchor class MyArFragment : ArFragment() { override fun getSessionConfiguration(session:

    Session?): Config { val config = super.getSessionConfiguration(session) val inputStream = context!!.assets.open("images.imgdb") config.augmentedImageDatabase = AugmentedImageDatabase.deserialize(session, inputStream) return config } ... } 111
  26. Получение Anchor class MyArFragment : ArFragment() { ... override fun

    onUpdate(frameTime: FrameTime?) { super.onUpdate(frameTime) val frame = arSceneView.arFrame ?: return val images = frame.getUpdatedTrackables(AugmentedImage::class.java) .filter { it.trackingState == TrackingState.TRACKING } .firstOrNull { it.name == "balloon.png" } ?.let { it.createAnchor(it.centerPose) } ?.apply { buildSceneGraph(this) } } } 112
  27. Получение Anchor class MyArFragment : ArFragment() { ... override fun

    onUpdate(frameTime: FrameTime?) { super.onUpdate(frameTime) val frame = arSceneView.arFrame ?: return val images = frame.getUpdatedTrackables(AugmentedImage::class.java) .filter { it.trackingState == TrackingState.TRACKING } .firstOrNull { it.name == "balloon.png" } ?.let { it.createAnchor(it.centerPose) } ?.apply { buildSceneGraph(this) } } } 113
  28. Получение Anchor class MyArFragment : ArFragment() { ... override fun

    onUpdate(frameTime: FrameTime?) { super.onUpdate(frameTime) val frame = arSceneView.arFrame ?: return val images = frame.getUpdatedTrackables(AugmentedImage::class.java) .filter { it.trackingState == TrackingState.TRACKING } .firstOrNull { it.name == "balloon.png" } ?.let { it.createAnchor(it.centerPose) } ?.apply { buildSceneGraph(this) } } } 114
  29. Получение Anchor class MyArFragment : ArFragment() { ... override fun

    onUpdate(frameTime: FrameTime?) { super.onUpdate(frameTime) val frame = arSceneView.arFrame ?: return val images = frame.getUpdatedTrackables(AugmentedImage::class.java) .filter { it.trackingState == TrackingState.TRACKING } .firstOrNull { it.name == "balloon.png" } ?.let { it.createAnchor(it.centerPose) } ?.apply { buildSceneGraph(this) } } } 115
  30. Получение Anchor class MyArFragment : ArFragment() { ... override fun

    onUpdate(frameTime: FrameTime?) { super.onUpdate(frameTime) val frame = arSceneView.arFrame ?: return val images = frame.getUpdatedTrackables(AugmentedImage::class.java) .filter { it.trackingState == TrackingState.TRACKING } .firstOrNull { it.name == "balloon.png" } ?.let { it.createAnchor(it.centerPose) } ?.apply { buildSceneGraph(this) } } } 116
  31. Получение Anchor class MyArFragment : ArFragment() { ... override fun

    onUpdate(frameTime: FrameTime?) { super.onUpdate(frameTime) val frame = arSceneView.arFrame ?: return val images = frame.getUpdatedTrackables(AugmentedImage::class.java) .filter { it.trackingState == TrackingState.TRACKING } .firstOrNull { it.name == "balloon.png" } ?.let { it.createAnchor(it.centerPose) } ?.apply { buildSceneGraph(this) } } } 117
  32. Получение Anchor class MyArFragment : ArFragment() { ... override fun

    onUpdate(frameTime: FrameTime?) { super.onUpdate(frameTime) val frame = arSceneView.arFrame ?: return val images = frame.getUpdatedTrackables(AugmentedImage::class.java) .filter { it.trackingState == TrackingState.TRACKING } .firstOrNull { it.name == "balloon.png" } ?.let { it.createAnchor(it.centerPose) } ?.apply { buildSceneGraph(this) } } } 118
  33. Затраченное время › 4 часа на внимательное чтение документации ›

    10 часов на написание кода игры › Из них 4 часа – код, работающий с Sceneform 120
  34. Заключение › Благодаря ARCore AR стала намного более доступной ›

    Но от этого AR не перестала быть захватывающей 121