Dev日記

プログラミング学習のまとめなど

WWDC2017 Introducing ARKit まとめ

iOS11の大きなウリの一つ、ARKitのセッションです。

動画はこちら

Introducing ARKit

ARとは?

  • Virtualな物体をPhysicalな世界に配置すること
  • ポケモンGOを始めとするデモ

ARKit

  • 概要

    • Mobile用AR Platform
    • High level API
    • A9以降搭載のiOSバイスに対応(6s以降)
  • 3つの機能がある

    • Tracking
      • 実世界の座標追跡
      • カメラ画像からの移動変化量
      • 特殊なセットアップ不要
    • Scene Understanding
    • Rendering
      • 楽に組み込める
      • ARViewを使えば、SceneKit/SpriteKitから作成できる(?)
      • Metalによるカスタムレンダリング
  • Unityに組み込まれている

API概要

  • ProcessingとRenderingに分かれる

    • RenderingがMetalやSceneKit
    • ProcessingがAR-Kit
      • 内部でAVFoundationやCoreMotionを用いる
  • ARKit

    • Session-based API
    • ARSessionConfiguration → ARSession と作成する
    • ARSession が ARFrame を生成
    • ARFrame からレンダリングに必要な情報を取得する
  • ARSessionConfiguration

    • ラッキングしたい情報を設定する
    • ARSessionConfigurationは回転情報のみ
    • Subclassに ARWorldTrackingSessionConfiguration
      • 座標移動も検出可能
    • バイスによるサポート情報も取得できるので切り分ける
if ARWorldTrackingSessionConfiguration.isSupported {
  configuration = ARWorldTrackingSessionConfiguration()
} else {
  configuration = ARSessionConfiguration()
}

** ARSession * ARプロセスの管理 * run / pause など * ARSessionDelegate で更新された ARFrame を受け取る

** ARFrame * ARレンダリングに必要な情報がある * カメラ画像 * トラッキング情報 * Scene情報 * ARAnchor * 実世界のポジション * ARSessionに追加/削除する

Traking

  • ARKitは座標だけでなく、「実世界の距離」も計測する

    • セッション開始時点からの位置になる
    • カメラから複数の特徴点を抽出、その位置差分で位置を出す
      • 加速度センサも活用している
  • サンプルコード

let session = ARSession()
session.delegate = self

let configuration = ARWorldTrackingSessionConfiguration()
sesison.run(configuration)
  • ARCamera
    • 仮想的なカメラ情報を提供するオブジェクト
    • Transform/TrackingState/Camera intrinsics

Demo

  • デモで気になったクラスをピックアップ

    • ARSCNView : ARシーンレンダリングの便利クラス
      • SceneKitをはめることができる
      • arScnView.scene = scnView
    • UITapGestureでタップ判定可能
  • タップでスクリーンキャプチャを画像としてSceneに追加するサンプル

func handleTap(...) {
    guard let currentFrame = sceneView.session.currentFrame else {
        return
    }
    //キャプチャした平面Object作成
    let imagePlane = SCNPlane(width: sceneView.bounds.width / 6000,
              height: sceneView.bounds.height / 6000)
    imgPlane.firstMaterial?.diffuse.contents = sceneView.snapshot()
    imgPlane.firstMaterial?.lightingModel = .constant

    //シーンに追加
    let planeNode = SCNNode(geometry: imagePlane)
    sceneView.scene.rootNode.addChildNode(planeNode)

    //カメラの10cm先に配置
    var translation = matrix_identity_float4x4
    translation.column.3.z = -0.1
    planeNode.simdTransform = matrix_multiply(currentFrame.camera.transform, translation)
}

Trackingの品質

  • カメラの環境に大きく左右される

    • カメラに何もうつっていないとトラッキングが中止
    • 「品質のいい」適度に複雑なカメラ画像が必要
    • 動きのあるシーンに弱い
      • 子供が動き回るなど
  • Trackingの状態

    • Not available : 開始直後はコレ。トラッキングの情報が不足してる
    • Normal : トラッキング可能
    • Limited : 真っ白壁など、一部情報がうまく取れない
    • Delegateで検出可能
func session(.., cameraDidChangeTrackingState camera: ARCamera) {
    if case .limited(let reason) = camera.trackingState {
        ...
    }
}
  • Trackingの中断
    • アプリがBackgroundに移動、iPadのMulti-Taskingで中断する
    • Delegateで検出し、表示を切り替える
func sessionWasInterrupted(...) {
    showOverlay()
}
func sessionInterruptionEnded(...) {
    hideOverlay()
    //必要に応じAR処理を再開
}

Scene Understanding

  • バーチャルな物体を配置するときに必要な情報のこと

    • 平面検出
    • ヒットテスト
    • 光量推定
  • 平面検出

    • テーブルのような水平面を検出できる
    • 複数のフレーム情報から計算する
    • 広さを測定できる
    • 面をマージできる
    • ARWorldTrackingSessionConfigurationの planeDetection を使う
      • 現状、 .horizontal しか値がない模様
  • ARPlaneAnchor

    • 平面が検出されるとDelegateが呼び出される?
    • 3軸回転、中央、広さを保持している
  • HitTest

    • カメラからのみた特定の直線が実世界平面のどこに位置するかを調べる
    • 4つの種類がある
      • Existing Plane Using Extent: 平面の位置/広さを考慮したヒット位置
      • Existing Plane : 平面の広さが無限とした場合のヒット位置
      • Estimated Plane : まだ平面が検出されてないときに使う
      • Feature Point : 面が小さいときに用いる(イレギュラーなケースらしい)
    • 画面の座標ベースでテスト可能(0,0が左上、1,1が右下)
  • 光量推定

  • 画像ベースの光量推定
  • 1000ルーメンがデフォルト
  • Configurationで設定する

構成

  • SceneKit/SpriteKit/Metalのいずれか

  • SceneKit

    • ARSCNView
    • カメラ画像を表示する
    • SCNCameraが人にあわせ移動する
    • 自動でLightingされる
    • SCNNode が ARAncher にマップされる
  • SpriteKit

    • ARSKView
    • SKNode が ARAnchor にマップされる
    • SpriteKitは2D描画用
    • 物理計算にテーブルを使うなどが出来る(?)
  • Metal


SceneKitで配置するだけで動くのは良さそうですね。3Dはあまり経験がないので厳しいと思っていたのですが、結構簡単にできそうでちょっと興味わいてきました