Apple Engine

Apple, iPhone, iOS, その周辺のことについて

ARKit 3 の更新内容(Xcode 11 Beta 2)

Beta 2 では AR の機能変更はない。

 

変更 / 追加

RealityKit の ARView なので厳密には ARKit ではないのだが、
ARView の Scene で Combine の Publisher 関連の関数が増えた。

Combine の Publisher で追加されたものがこちらでも適応されている。

  • publisher(for:)
  • publisher(for:_:)
  • publisher(for:::)
func publisher<T>(for: KeyPath<E, T>) -> Publishers.ValueForKey<Scene.Publisher<E>, T>
func publisher<T0, T1>(for: KeyPath<E, T0>, KeyPath<E, T1>) -> Publishers.ValueForKeys2<Scene.Publisher<E>, T0, T1>
func publisher<T0, T1, T2>(for: KeyPath<E, T0>, KeyPath<E, T1>, KeyPath<E, T2>) -> Publishers.ValueForKeys3<Scene.Publisher<E>, T0, T1, T2>

 

以上

SceneKit の変更点 (Xcode 11 Beta 2)

追加

SCNMaterial、LightingModel で shadowOnly が追加された。
多分、AR などで影だけ表示するためのジオメトリのマテリアル用に追加されたのだろうと思う。

developer.apple.com

 

変更

修飾子 が unowned(unsafe) から weak に変更されたもの。

  • SCNParticlePropertyController の inputOrigin
  • SCNSceneRenderer の delegate

 

以上

SwiftUI でカスタムビューの SceneKit を表示する (Xcode 11 Beta 1)

以下の変更が行われた。
記事のままでは動かず、書き直すのが面倒なので、
リンク先のサンプルコードの ContentView.swift を参照。

 

Beta 4
  • BindableObject が ObservableObject に変更
  • BindableObject が didChange から willChange へ変更
  • List や ForEach で id パラメーターが必須に変更
Beta 5
  • ObservableObject の willChange が @Published のアノテーション記述へ変更

 

サンプルコード

github.com

 


 

基本的には SwiftUI Tutorials で MKMapView を実装しているのと同じ。

環境は Xcode 11.0 Beta 1 を使用しているので、今後動かなくなる可能性があるので注意。

 

今回つくるもの

f:id:x67x6fx74x6f:20190617041655p:plain
完成予想図

SceneKit の SCNView を上部、リストをその下に配置する。
そして、リストをタップすると SceneKit のシーンのカメラポジションを変更される。

ちなみに今回つくるのは iOS 版。
あと、ランドスケープ時の処理を特に入れてないので、横に傾けると描画がおかしくなるので注意。

 

プロジェクトを作成する

Xcode 11.0 の Beta 版を起動し、iOS のテンプレートから「Single View App」を選択し右下の「Next」ボタンを押し、Use SwiftUI のチェックボタンを押してプロジェクトを保存。

ContentView.swift の中身を編集していく。

とりあえず、今回は SceneKit と Combine を使用するので以下を書く。

import SceneKit
import Combine

 

また、今回は ContentView.swift へ全てコードを書いていため、
デバッグも ContentView 部分の記載しかない。

個別でプレビューやデバッグをしたい場合は、個々の View の設定をする。

 

カスタムビューの SCNView をつくる

カスタムビューの概要

カスタムビューを作成する場合は UIViewRepresentable を使用して SwiftUI をの body で使えるカスタムの View にする。
カスタムの View の振る舞いは以下の 4 つ

  • View の値やデリゲートを結びつけるコーディネーター設定
  • View の初期化処理
  • View の更新処理
  • View が破棄される際に行う View やコーディネーターのクリーンナップ処理

 

これに合わせて関数が用意されている。

  • makeCoordinator()
  • makeUIView(context:)
  • updateUIView(_:context:)
  • dismantleUIView(_:coordinator:)

 

今回は makeCoordinator と dismantleUIView 使用しないのでコードを書かないが、makeUIView と updateUIView は設定しないとビルドエラーになるので注意。

 

カスタムビューのコード書く

SceneView という構造体に UIViewRepresentable を準拠させ、makeUIView の関数で SCNView とその中身を書く。

makeUIView の中身はいつも通り SCNView を設定し、シーンをシーンファイルから読み込んでいる。

struct SceneView: UIViewRepresentable {
    
    func makeUIView(context: Context) -> SCNView {
        let view = SCNView(frame: .zero)
        let scene = SCNScene(named: "main.scn")

        view.allowsCameraControl = true
        view.scene = scene

        return view
    }

    func updateUIView(_ view: SCNView, context: Context) {
    }
}

 

起点のビューで先ほど作った SceneView を表示させる

ここでは、アプリ起動の際に最初に実行されるビューコントローラー UIHostingController のビューとなる ContentView の body に SceneView を表示させるよう設定する。

ただ SceneView を設定して高さを設定するだけ。

struct ContentView : View {
    var body: some View {
        
        // SceneKit
        SceneView()
            .frame(height: 300)

    }
}

 

これをプレビューか実行すると中央に SceneKit の内容が描画される。

 

下にリストを表示するコードを書く

はじめに TableView となる List のカスタムセル TableRow 作成する。
固定文字と数値を渡して文字を表示する。

struct TableRow: View {
    var number:Int

    var body: some View {
        VStack(alignment: .leading) {
            Text("Camera: \(number)")
                .font(.title)
            Text("description: !!!!!!!")
                .font(.subheadline)
        }
        .padding(8)
    }
}

 

VStack を使用し、View を縦並びに表示できるようにし、先ほどの SceneView と TableRow を使用した List のコードを書き表示させる。
先ほどの ContentView を以下のように修正する。

struct ContentView : View {
    var body: some View {
        VStack(alignment: .leading) {

            // SceneKit
            SceneView()
                .frame(height: 300)
            
            // TableView
            List(0...2){ i in
                TableRow(number: i)
            }

        }
    }
}

 

これをプレビューか実行すると SceneKit の内容の下にリスト(TableView)が描画される。

 

リストをタップしてシーンのカメラ位置を変更する

今回は Combine フレームワークを使用して BindableObject を作成する。

こちらを使用するとビューの階層に関係無く、値の入出力を紐付け、 どこかで変更が起こった場合はその変化を伝播させる。
今までは通知を使用していたものなどをこちらで代用できる。

ちなみに今回は双方向かつ即更新されるが、一方のみや時間をおいて更新したり、本来は細かい設定ができる。

 

BindableObject を作成する

カメラの位置を Combine を使用し CameraInfo.cameraNumber の UInt 値で保持する。
didChange で値の変更 PassthroughSubject でそのまま渡し、
cameraNumber の didSet で、didChange の send で変更を保存する。

以下、BindableObject で CameraInfo を設定する

final class CameraInfo: BindableObject  {
    let didChange = PassthroughSubject<CameraInfo, Never>()

    var cameraNumber:UInt = 0 {
        didSet {
            didChange.send(self)
        }
    }
}

 

SceneView に値をバインディングさせカメラ位置を変更させるコードを書く

@Binding を使用してカスタムビューに BindableObject と紐づけ、BindableObject の値が変更されるとカメラ位置が変更される。

@Binding のコードを追加して、バインドされた値が変更された時、 updateUIView でカメラ位置を変更するアニメーションを行う。

カメラはシーンファイルに「Camera0」「Camera1」「Camera2」と設定されており、childNode から探し、移動するアニメーションを設定する。

以下、SceneView を変更する。

struct SceneView: UIViewRepresentable {
    @Binding var cameraNumber:UInt

    func makeUIView(context: Context) -> SCNView {
        let view = SCNView(frame: .zero)
        let scene = SCNScene(named: "main.scn")

        view.allowsCameraControl = true
        view.scene = scene

        return view
    }

    func updateUIView(_ view: SCNView, context: Context) {
        let camera = view.scene?.rootNode.childNode(withName: "Camera\( cameraNumber)", recursively: true)!

        SCNTransaction.begin()
        SCNTransaction.animationDuration = 1.0

        view.pointOfView = camera

        SCNTransaction.commit()

    }
}

 

ContentView に BindableObject の設定をする

@EnvironmentObject で BindableObject を使用できるようにして、 SceneView には BindableObject の変更を渡し、List の中身をボタンにする。

それをタップすると BindableObject の中身を変更するようにする。

バインドする際には $ を先頭につけ Binding<UInt> として渡し、リスト内のボタンではアクションのブロックになっているため参照する際には self をつける。

struct ContentView : View {
    @EnvironmentObject var cameraInfo: CameraInfo

    var body: some View {
        VStack(alignment: .leading) {

            // SceneKit
            SceneView(cameraNumber: $cameraInfo.cameraNumber)
                .frame(height: 300)

            // TableView
            List(0...2){ i in
                Button(action: {
                    self.cameraInfo.cameraNumber = UInt(i)
                }) {
                    TableRow(number: i)
                }

            }

        }
    }
}

 

仕上げ

このまま、プレビューや実行をしてもエラーが起きる。

ContentView で「@EnvironmentObject var cameraInfo: CameraInfo」を設定しているため、呼び出す際には EnvironmentObject となる BindableObject (CameraInfo) を設定する必要がある。

SceneDelegate.swift や ContentView.swift の「ContentView()」の箇所を以下のように変更する。

ContentView().environmentObject(CameraInfo())

 

面倒であれば Command + Shift + F でプロジェクト内検索を行い「ContentView()」を「ContentView().environmentObject(CameraInfo())」に書き換えても良いだろう。

 

サンプルコード

github.com

 

まとめ

割と簡単にカスタムのビューの追加とバインディングできたと思われる。

今回は画面が遷移しないので Combine を使用する必要性が薄く、@State で代用できるのだがバインディングが簡単にできるということを示してみた。

ARKit 3 で追加された ARCoachingOverlayView

f:id:x67x6fx74x6f:20190613002222p:plain

iOS 13 から ARKit に ARCoachingOverlayView が実装された。

ARCoachingOverlayView は AR でのセッション初期化中やリミテッドトラッキング状況で、ユーザーに視覚的な指示を表示する UI を提供する。
これまでは自力で実装していたものだが、iOS 13 では頑張ってつくらなくてもよい。

実装的には ARSCNView や ARView に ARCoachingOverlayView を addChild して delegate と各種設定をするだけ。

一応、UIView 継承し、親の View の最上部で表示されるため、ARSCNView や ARView ではなくても使用できる。
ただ、ARKit 用であり ARSession が必要なため ARKit の機能が必要になる。

お約束だが、現状はまだ Beta 版なので今後機能の追加、変更、削除される可能性があるので、その点は注意してほしい。

 

ARCoachingOverlayView のコーチング状態

f:id:x67x6fx74x6f:20190613002247p:plain

初期表示 (Phase 1 〜 3)

アプリを起動すると、ARKit はトラッキングを確立するため役立つコーチングオーバーレイが表示。
ユーザーへデバイスを移動するような表示が出る。

コーチングのゴール表示

平面を見つけるなどのコーチングのゴールを選択していると、 コーチングオーバーレイはそれに従って指示を変更する。

完了

平面認識など目標が達成され、それ以上コーチングが必要とされていないと判断した場合はコーチングオーバーレイが非表示になる。

再検出

ARKit の中断などで再度ワールドトラッキングの状態を回復させるなど、ARKit でリローカライズする必要がある場合、
コーチングオーバーレイはリローカライズを支援するようなユーザーをガイドするコーチングオーバーレイを表示する。

 

ARCoachingOverlayView の実装の流れ

以下を設定すると自動的にオーバーレイの UI が表示される。

  • ARCoachingOverlayView を初期化し、ARSCNView などから session を設定。
  • 平面認識など認識準備や完了で使用するゴールを設定する
  • デリゲートを設定する
  • 表示するビューへ ARCoachingOverlayView を addSubView する

デリゲートでは、ARCoachingOverlayView のアクティブになる前、非アクティブになった時、セッションがリセットされた時の関数が要されている。

 

ARCoachingOverlayView の API

ARCoachingOverlayView

クラスとクラスの使用とイニシャライズ

class ARCoachingOverlayView : UIView

 

goal

検知したい状態をゴールとして設定し、 コーチングオーバーレイがユーザーに指示する表示が決定される。

var goal: ARCoachingOverlayView.Goal { get set }

 

表示で設定できる ARCoachingOverlayView.Goal は以下のもので、 垂直/水平平面の両方、水平平面、トラッキング、垂直平面。

  • anyPlane
  • horizontalPlane
  • tracking
  • verticalPlane
enum Goal : Int

 

session

コーチングを表示するために使用するセッション。
ARSession が更新された場合、このプロパティが使用されセッションからコーチングビューも表示される。

var session: ARSession? { get set }

 

sessionProvider でセッションのデータソースをアクセスできるが、多分直接アクセスすることはあまりないと思う。

@IBOutlet weak var sessionProvider: ARSessionProviding? { get set }

 

delegate

コーチングイベントのコールバックを設定を実装する。

@IBOutlet weak var delegate: ARCoachingOverlayViewDelegate? { get set }

 

ARCoachingOverlayViewDelegate のプロトコルは以下の3つで、
アクティブになる前、非アクティブになった時、セッションがリセットされた時に設定する。

func coachingOverlayViewWillActivate(ARCoachingOverlayView)

func coachingOverlayViewDidDeactivate(ARCoachingOverlayView)

func coachingOverlayViewDidRequestSessionReset(ARCoachingOverlayView)

 

activatesAutomatically

現在のセッション状態に応じて、コーチングビューが自動的にアクティブにするかどうか設定するフラグ。

このフラグ有効になっている場合は、 セッションが初期化されてた時、またはトラッキング条件が特定のしきい値を低下している場合、コーチングオーバーレイがアクティブになり表示される。

デフォルトは true。 false の場合は isActive で調べ、setActive(_:animated:) を使用してマニュアルで非表示にする。

var activatesAutomatically: Bool { get set }

 

isActive

コーチングが行われているかどうかを示すフラグ。
activatesAutomatically が有効な場合、このフラグは自動で変化する。

var isActive: Bool { get set }

 

setActive(_:animated:)

コーチングを行う否かを制御する。

func setActive(_ active: Bool, 
      animated: Bool)

 

サンプルプロジェクトから実装方法を学ぶ

Placing Objects and Handling 3D Interaction のサンプルは以前あったものを ARKit 3 用に若干修正したもの。

ARCoachingOverlayView の実装されているのでこちらを見ながら説明をしてみる。

 

実装概要

このプロジェクトで ARCoachingOverlayView が使用されているのは、ViewController+CoachingOverlay.swift 。

この Swift ファイルは Storyboard で initail View Controller となる ViewController クラスのエクステンションで、ARCoachingOverlayViewDelegate プロトコルを使用し delegete を読み込んでいる。

 

ViewController+CoachingOverlay.swift

このファイルで設定されていないもの
  • coachingOverlay は ARCoachingOverlayView
  • sceneView は ARSCNView
  • upperControlsView は sceneView の上に配置されているボタンの UI(仮想オブジェクトを選択するボタン)
  • restartExperience は別の swift ファイルで実装されている AR のリセット処理

 

初期設定

ARKit をインポートし、ARCoachingOverlayViewDelegate を設定する。

import UIKit
import ARKit

extension ViewController: ARCoachingOverlayViewDelegate {
    ...
}

 

デリゲート

coachingOverlayViewWillActivate は ARCoachingOverlayView がアクティブになる前に実行される。

ARCoachingOverlayView が sceneView に表示されるため、その上にある UI である upperControlsView を非表示にする。

func coachingOverlayViewWillActivate(_ coachingOverlayView: ARCoachingOverlayView) {
    upperControlsView.isHidden = true
}

 

coachingOverlayViewDidDeactivate は ARCoachingOverlayView が非アクティブになった時に実行される。

AR が使用できる状況になるため、使用する UI である upperControlsView を表示する。

func coachingOverlayViewDidDeactivate(_ coachingOverlayView: ARCoachingOverlayView) {
    upperControlsView.isHidden = false
}

 

coachingOverlayViewDidRequestSessionReset はセッションがリセットされた時に実行される。

ここでは restartExperience() が呼ばれ AR の状態がリセットされ、その後 coachingOverlayViewWillActivate が呼ばれる

func coachingOverlayViewDidRequestSessionReset(_ coachingOverlayView: ARCoachingOverlayView) {
    restartExperience()
}

 

メインで呼ばれる関数

setupCoachingOverlay() は ViewController の viewDidLoad() で呼ばれため、この関数はアプリ実行時に呼ばれる。

coachingOverlay.session で sceneView.session を渡し、
coachingOverlay.delegate で ViewController の self を渡す。
その後各関数を呼ぶ。

(わかりやすくするため、元のコードから Auto Layout のコンストレイントの記述は省略している)

func setupCoachingOverlay() {
    coachingOverlay.session = sceneView.session
    coachingOverlay.delegate = self

    setActivatesAutomatically()
    setGoal()
}

 

activatesAutomatically で true に設定している。 デフォルトで true なので明示的に設定している理由は不明。

func setActivatesAutomatically() {
    coachingOverlay.activatesAutomatically = true
}

 

平面認識を行うため goal で .horizontalPlane を指定し、 平面認識を促す UI を表示する様に設定する。

func setGoal() {
    coachingOverlay.goal = .horizontalPlane
}

 

まとめ

そもそも ARCoachingOverlayView クラス自体の機能があまりないため、デリゲートを含めても書く部分は少ない。

認識やトラッキングを行う場合、この様な UI の実装を必ずする必要があるので、iOS 13 からはこちらを使用してみるのも良いかもしれない。

アプリ開発から見る ARKit 3 の新機能

f:id:x67x6fx74x6f:20190612023117p:plain

WWDC 2019 で ARKit 3 が発表された。

ARKit 3 に関する他の記事は Keynote と SwiftStrike を体験した範囲で書かれているものが多いため、アプリ開発側からどのような機能が増えたか公式ドキュメントセッション動画から調べて書いてみた。

 

ARKit 3 で端末制限がある機能 

実は以下の目玉機能が A12 / A12 X Bionic 以降でしか使えない。

  • 仮想オブジェクトで現実空間にいる人を遮蔽するピープル・オクルージョン
  • 人の骨格の動きをトレースするボディトラッキング(モーションキャプチャ)
  • 前面/背面カメラを同時に使用するマルチカム

 

iOS 13 がリリースされる時には、新しい iPhone が発売されるのである程度は増えるが、iOS 13 対応の以下の端末では使用できないこととなる。

  • iPhone X
  • 8/8 Plus
  • 7/7 Plus
  • 6s/6s Plus
  • 7世代目の iPod Touch
  • 3世代目の iPad Pro 以前の iPad

 

別に「A12 / A12 X Bionic 以降でなくても動くのでは?」と思うかもしれないが併用して機能が使用されたり、バッテリー持ちなど Apple の言い分もあると思われ。
まぁ、わからんでもない。

 

ARKit 3 での新機能

  • ピープルオクルージョン
  • ボディトラッキング
  • ARKit でのマルチカムの使用
  • フェイストラッキングの上限増加
  • イメージトラッキングの強化
  • VR 用のトラッキングモード
  • リアルタイムでの HDR テクスチャキューブマップの生成
  • カメラノイズを仮想オブジェクトへの適応
  • レイキャスト
  • AR Coaching UI
  • Multipeer AR Experience(マルチユーザー AR)

 

ピープルオクルージョン

今までの ARKit ではカメラ映像の上に仮想オブジェクトを配置していた。
机の上を認識後、仮想オブジェクトをそこに配置した時、机より前に人がいても仮想オブジェクトが人の前に表示されてしまう。

ARKit 3 からはカメラアプリのポートレートと同じような機能使用し、機械学習で映像から人の部分を切り取り合成し、この問題を解決する。

f:id:x67x6fx74x6f:20190612024028p:plain
左:オクルージョンなし 右:オクルージョンあり

 

iOS SDK 的には、人の部分を切り取るだけのモードと、Z 軸を含んだ奥行き情報(深度情報)を持つ切り取りと2つの機能あり、Metal でカスタムレンダラーを書かずに RealityKit や SceneKit を使用する場合は数行書くだけでこの機能が使用できる。

f:id:x67x6fx74x6f:20190612024606p:plain
深度情報なし

f:id:x67x6fx74x6f:20190612024647p:plain
深度情報あり

 

ボディトラッキング

f:id:x67x6fx74x6f:20190612033410p:plain f:id:x67x6fx74x6f:20190612024755p:plain

バックカメラのカメラ映像から人体を検出し、ARKit で設定されている 93 の骨(スケルトン)を割り当て、仮想キャラクタを動かしたり、モーションキャプチャデータとして使用することができる。
画面座標となる 2D 座標も同時に設定されるため、2次元のキャラにも適応可能。

予想では先のピープルオクルージョンで人体の形状を取得しそこからスケルトンを割り当てているのだと思われる。
(雑に説明すると手や足など画像領域の中間地点が骨の部分になるため、それを繰り返す)

 

iOS SDK 的には、腰骨を中心に各骨が階層構造になっており、3DCG でリグを組んだり触った人は簡単に想像がつくと思われる。
スケルトンの各ボーン(ジョイント)はローカル座標と腰骨からのモデル座標と2つある。

また、既存のワールドトラッキングのラップなので、平面認識やイメージトラッキングを併用することもできる。

 

ARKit でのマルチカムの使用

f:id:x67x6fx74x6f:20190612025145p:plain
セッションでのデモ

iOS 13 前面背面カメラを同時に使用することが可能になったが、ARKit でも使用することができる。

ARKit 3 のセッションでは背面カメラに顔のオブジェクトを置き、前面カメラのフェイストラッキングから動かすデモを行っていた。
例えば、顔や視線でコントロールする AR ゲームなど、使用できる幅は広そう。

この逆のフェイストラッキングで前面カメラ画像を使用している状態からワールドトラッキングを使用することもできる。

iOS SDK でいう ARImageTrackingConfiguration で設定する画像のみのトラッキングでは、この機能を使用することはできない。

 

フェイストラッキングの上限増加

f:id:x67x6fx74x6f:20190612031102p:plain

今までの ARKit はひとりの顔のみの認識可能だったが、iOS 13 から最大3人までの顔を認識できるようになった。

開発的な話だが、顔に対して ID が振り当てられ、途中で1人抜けても ID 保持される。
多分、カメラ画像に対して顔の位置で判別している。

 

イメージトラッキングの強化

一度に最大100枚の画像を検出するようになった。

また、画像自体の物理的なサイズの違いを自動的に判別できるようになった。

 

VR 用のトラッキングモード

VR の様なカメラ画像を使用せず、仮想コンテンツのみで構成する画面用のトラッキング設定が追加された。

カメラ画像は可能な限り荒い解像度を使用し、6DoF で端末が今どこに位置しているかなどの位置推定を行う。

平面認識を使用することは可能。

 

リアルタイムでの HDR テクスチャキューブマップの生成

ARKit 2.0 で機械学習から周囲の画像を推論しキューブマップを作成して、物体の鏡面反射や光を表現をしていた。

ARKit 3.0 ではこれを応用して HDR テクスチャを生成し、光の強さがより現実に近いものになったと思われる。

f:id:x67x6fx74x6f:20190612031739p:plain
右が HDR が適応されているマテリアル

 

カメラノイズを仮想オブジェクトへの適応

iPhone / iPad はハード上仕方ないのだが、カメラで暗い場所を撮ると多くのノイズがのる。
写真では画像調整されるため気付きにくいが、動画を撮ると割とノイズが乗っているのがわかると思う。

そのため、カメラ画像のノイズから推論しそのノイズと同等のものを仮装オブジェクトへ適応するカメラエフェクトが追加され適応できるようになった。

f:id:x67x6fx74x6f:20190612031827p:plain
分かりにくいが、右は仮想オブジェクトにノイズを加えたもの

 

レイキャスト

今までは、画像から推定するヒットテストで画面から仮想オブジェクトへのタッチを検知していたが、光線を飛ばしてぶつかった場所を調べるレイキャストが実装された。

正直、処理が軽いヒットテストでも良いと思っており、RealityKit 側にもヒットテストが実装されているため、導入された理由が次期機能のためにあるのではと思っている。

 

AR Coaching UI

ユーザー側にはあまり関係ない機能だが、 AR を始める際にデバイスを動かして周囲を検知させる状態や、平面認識を促すなどの UI が実装された。

今までは開発者が自前で実装していた。

f:id:x67x6fx74x6f:20190612031154p:plain

 

Multipeer AR Experience(マルチユーザー AR)

同じアプリを起動している複数のデバイスでの空間共有が簡単にできるようになった。
リアルタイムかつ近くにある端末同士の処理なので、2.0 で追加された空間の情報を保存/復元するものとは異なる。

かなり簡単に実装できるため、空間をリアルタイムで共有するゲームや何らかの操作をコラボレーションするアプリが今後増えると思われる。

f:id:x67x6fx74x6f:20190612033806p:plain

 

まとめ

RealityKit への対応、平面認識の高速化、物体認識の精度が上がったりなど他にも機能はあり、かなりの進化を遂げたと思われる。

日本ではオリンピックが開催される流れで日本でも早い段階でマップアプリの Look Around が使える可能性高く、オリンピックに伴い ARKit の機能も強化される可能性もある。

また、今後期待される AR グラスなど、何かあるような期待をさせてくれたのが今回のアップデートのような感じはしている。

 

ARKit で新しく追加された API に関してはこちらを参照。

 

ARKit 3 の更新内容(Xcode 11 Beta 1)

ARKit 3 の API の更新内容を調べてみた。
API の翻訳であるため新機能の詳しい説明はない。

新機能の概要に関しては別記事を参照。

 

ARView について

今回は書く量が多いので、ARView に関しては RealityKit の API を調べる際に書くかもしれないので割愛。

ARView の内容的には、イニシャライズやビュー操作、シーン、エンティティ、音や物理シミュレーションやライトなどの環境設定、カメラ、ARSession、座標変換、レイキャストやヒットテスト、タッチ/マウス/キーなどレスポンダー関連、スナップショット、デバッグオプションが設定できる。

 

注意点

  • Beta であるため今後、変更、追加、削除が行われる可能性がある。
  • 今回のジョイントは、3DCG DCC ツールでいうボーンやスケルトンは同じもの。
    ドキュメント上、スケルトンはジョイントが集まったものとして記載されている。
  • 基本的には support や enable がつくものを命令を実行する前に使用できるか調べる必要がある。(しないと動かないものがある)

英語が得意なわけではないので、翻訳内容が間違っていたらすみません。

 

以下、API の更新内容。

 

Essentials

ARSession

ARSession からコラボレーション用の識別 ID を取得する。

var identifier: UUID { get }

 

ARSession.RunOptions

変更不明。

init(rawValue: UInt)

 

ARSessionObserver

セッションでコラボレーションデータを作成したときに呼び出されるメソッド。

optional func session(_ session: ARSession, 
didOutputCollaborationData data: ARSession.CollaborationData)

以下、コラボレーション用のエラー判別用。

 

ARError
static var collaborationDataUnavailable: ARError.Code { get }
ARError.Code
case collaborationDataUnavailable = 304

 

ARSession でのレイキャスト関連
raycast(_:)

レイと実世界の表面との交差を1回のみ調べる。
スクリーン上からレイを飛ばし、カメラから近い順にレイキャストに関する情報の配列を返し、無い場合は空の配列を返す。

func raycast(_ query: ARRaycastQuery) -> [ARRaycastResult]

 

trackedRaycast(_:updateHandler:)

レイキャストクエリを繰り返し現実環境内で更新されたサーフェスを通知する。

セッションが繰り返し呼び出すレイキャストクエリをラップしている。

停止する準備ができたら stopTracking() を呼び出す。

func trackedRaycast(_ query: ARRaycastQuery, updateHandler: @escaping ([ARRaycastResult]) -> Void) -> ARTrackedRaycast?

 

ARSession でのマルチユーザー関連
update(with:)

他のユーザーが収集された現実環境に関する情報で更新を行う。
Multiuser AR に参加している他のユーザーからコラボレーションデータを受信した時、セッションを更新するにはこの関数を呼び出す。

func update(with collaborationData: ARSession.CollaborationData)

 

ARSession.CollaborationData

ユーザーによって収集された現実環境に関する情報を保持するオブジェクト。

class CollaborationData : NSObject

 

init(data: Data)

シリアルライズされたコラボレーションデータからコラボレーションデータオブジェクトを作成する。

別のユーザーからネットワーク経由でシリアル化されたコラボレーションデータを受け取ると、ARSession が作成され、
それを使用して CollaborationData オブジェクトを作成し、update(with:) を呼び出してセッションを更新する。

init(data: Data)

 

var data: Data { get }

このセッションのワールドデータやアンカーなどに関するシリアル化された情報をもつ。

var data: Data { get }

 

ARSessionProviding

セッションのデータソース。

ARCoachingOverlayView はセッションへのアクセスを必要とし、そのために sessionProvider を公開する。

protocol ARSessionProviding

 

session

必須項目。

var session: ARSession { get }

 

ARConfiguration

supportsFrameSemantics(_:)

特定の機能がサポートされているかどうかを確認する。

class func supportsFrameSemantics(_ frameSemantics: ARConfiguration.FrameSemantics) -> Bool

 

frameSemantics

アクティブなフレームセマンティクス。
フレームセマンティクスは ARKit がフレームから抽出する2次元情報を表す。

  • 2Dボディ検出 (bodyDetection)
  • ピープルオクルージョン(personSegmentation)
  • 深度情報を含んだピープルオクルージョン (personSegmentationWithDepth)

 

独自レンダラーでピープルオクルージョンを実装する場合は segmentationBuffer と EstimatedDepthData を使用する。

 

ARConfiguration.FrameSemantics

アプリで有効にできるオプションのフレーム機能。

struct FrameSemantics

 

フレームセマンティクス機能を作成する

init(rawValue: UInt)

 

上記 frameSemantics 参照。

static var bodyDetection: ARConfiguration.FrameSemantics
static var personSegmentation: ARConfiguration.FrameSemantics
static var personSegmentationWithDepth: ARConfiguration.FrameSemantics

 

ARConfiguration.VideoFormat

キャプチャデバイスの位置を調べる。
詳しくは AVCaptureDevice.Position を参照。

var captureDevicePosition: AVCaptureDevice.Position { get }

 

ARAnchor

sessionIdentifier

アンカーがもつセッションのユニーク ID。
アンカーがセッションに追加された時 ARKit によって設定される。

var sessionIdentifier: UUID? { get }

 

カメラ(ARFrame と カメラ設定)

ARFrame

スクリーンポイントに対するレイキャストクエリを取得する。

func raycastQuery(from point: CGPoint, 
        allowing target: ARRaycastQuery.Target, 
        alignment: ARRaycastQuery.TargetAlignment) -> ARRaycastQuery

 

detectedBody

ARKit がカメラ画像内で認識する人物の画面位置情報。

var detectedBody: ARBody2D? { get }

 

segmentationBuffer

仮想コンテンツを隠すために使用するカメラフィードからのオブジェクトの形状を識別するピクセル情報を含むバッファ。

カメラフィードを処理することによってバッファの内容を生成し、
カスタムレンダラで ARMatteGenerator から提供されているアルファマットとデプスマットを使用してこのプロパティを適用する。

var segmentationBuffer: CVPixelBuffer? { get }

 

estimatedDepthData

仮想コンテンツを隠すために使用するカメラフィードから推定した深度値を表すバッファ。

segmentationBuffer と同様にカスタムレンダラで ARMatteGenerator から提供されているアルファマットとデプスマットを使用してこのプロパティを適用する。

var estimatedDepthData: CVPixelBuffer? { get }

 

ARFrame.SegmentationClass

仮想コンテンツを隠すために使用するピクセルの分類を定義する。

enum SegmentationClass : UInt8

 

カメラフィードでは人物のみが識別されるため、 利用可能なピクセル分類は以下の二つ

  • ARFrame.SegmentationClass.person
  • ARFrame.SegmentationClass.none

 

cameraGrainIntensity

カメラグレインテクスチャで存在するグレイン(画像ノイズ)の量を指定する値。
0 〜 1 の範囲内で正規化され 0 はグレインを指定しない。

この値を cameraGrainTexture の depth コンポーネントに適用する時、Metal テクスチャに格納されている視覚的なイメージノイズデータのバリエーションの中から、強度レベルに一致するものを選択する。

var cameraGrainIntensity: Float { get }

 

cameraGrainTexture

ARKit で撮影しているビデオストリームの視覚特性に合わせた Metal テクスチャを生成する。
室内など暗い空間の場合、カメラ画像となる背景画像にノイズが走るため、仮想コンテンツにもそれに合わせたノイズをのせるためのテクスチャ。

var cameraGrainTexture: MTLTexture? { get }

 

ARCamera

exposureDuration

仮想コンテンツレンダリング時にモーションブラーを使用するための値。
カスタムレンダラーを使用し表示する場合は、この値を使用して仮想コンテンツへモーションブラーの適応量を指定する。

var exposureDuration: TimeInterval { get }

 

exposureOffset

カスタムレンダラーを使用するシーンで、シーンを明るくするため値。

var exposureOffset: Float { get }

 

Quick Look

ARQuickLookPreviewItem

AR クイックルック の見た目をカスタマイズするために使用するオブジェクト。
バックグラウンド時、共有シートで共有するコンテンツの指定、特定のモデルに対して拡大縮小を無効にするなどを制御する。

class ARQuickLookPreviewItem : NSObject

 

init(fileAt: URL)

ファイルの URL を使用し、新しい AR Quick Look プレビューを初期化する。

init(fileAt url: URL)

 

allowsContentScaling

ピンチジェスチャーで仮想コンテンツを拡大縮小可能か決めるブール値。

var allowsContentScaling: Bool { get set }

 

canonicalWebPageURL

ユーザーが共有シートを起動した時に共有する Web URL。
デフォルト値は nil。

共有シートを起動したときに Quick Look が USDZ ファイルを共有することを示す。

var canonicalWebPageURL: URL? { get set }

 

ディスプレイ(View)

ARView

ARView は割愛。 RealityKit を説明する際に紹介する。

 

ARSCNView

raycastQuery(from:allowing:alignment:)

ビュー上の点から発生するレイキャストクエリを作成する。
この関数を呼び出すと ARKit は引数のスクリーンスペースポイントから正の z 方向レイを飛ばし、現実環境に存在するかどうかを判断し3次元位置を返す。

func raycastQuery(from point: CGPoint, 
        allowing target: ARRaycastQuery.Target, 
        alignment: ARRaycastQuery.TargetAlignment) -> ARRaycastQuery?

 

rendersMotionBlur

モーションブラーをレンダリングするかどうかを決める。
ARSCNView の場合、SCNCamera のパラメーターを上書きする。

var rendersMotionBlur: Bool { get set }

 

rendersCameraGrain

SceneKit で仮想コンテンツに画像ノイズを適用するかどうかを決定する。
ARSCNView の場合、SCNCamera のパラメーターを上書きする。

var rendersCameraGrain: Bool { get set }

 

ARCoachingOverlayView

アプリを起動時に ARKit が平面を見つけるなど状態を知らせるコーチングオーバーレイを表示する UI を提供する。

別記事で記載。

 

ワールドトラッキング

ARWorldTrackingConfiguration

ARWorldTrackingConfiguration.PlaneDetection

初期化が追加

init(rawValue:)

 

automaticImageScaleEstimationEnabled

イメージトラッキングの際、トラッキングする画像の大きさを推定し設定するフラグ。

var automaticImageScaleEstimationEnabled: Bool { get set }

 

userFaceTrackingEnabled

ワールドトラッキングでフェイストラッキングを使用するか決めるフラグ。

var userFaceTrackingEnabled: Bool { get set }

 

supportsUserFaceTracking

ワールドトラッキングでフェイストラッキングをサポートするか決めるフラグ。

class var supportsUserFaceTracking: Bool { get }

 

wantsHDREnvironmentTextures

HDR の環境テクスチャを作成するするか決めるフラグ。

var wantsHDREnvironmentTextures: Bool { get set }

 

isCollaborationEnabled

Multiuser AR を有効/無効を決め、 ワールドデータを定期的に出力するか ARKit へ指示するフラグ。

var isCollaborationEnabled: Bool { get set }

 

ARPlaneAnchor

ARPlaneAnchor.Classification

このブログでは書き忘れたが iOS 11 からあるもの。
検出されたプレーンアンカーから、
現実世界の平面から分類プロパティから取得されたサーフェスのタイプと
その状態の両方を識別するもの。

今回、ドア、窓が追加された。

case door
case window

 

レイキャスト

ARRaycastQuery

現実世界のサーフェスで3次元空間の位置を調べるために使用する数学的なレイ。 3D ベクトルと開始位置を指定してレイキャストクエリを作成する。

ユーザーから Z 方向の外側に向かってキャストする(2D スクリーン位置とデフォルトベクトルを使用する)レイキャストクエリを作成する場合は、makeRaycastQuery(from:allowing:alignment:) か ARView、ARSCNView のメソッドを使用する。

 

init(origin:direction:allowing:alignment:)

新しいレイキャストクエリを作る。

init(origin: simd_float3, 
direction: simd_float3, 
allowing target: ARRaycastQuery.Target, 
alignment: ARRaycastQuery.TargetAlignment)

 

target

レイを発生させた時にターゲット(終点)となる平面タイプ。
平面、無限平面、推定平面のみ。

var target: ARRaycastQuery.Target { get }

 

ARRaycastQuery.Target

レイキャストを交差させることができる平面の種類。

enum Target : Int

 

指定できる enum の値は平面、平面ジオメトリ(推定平面)、無限平面

  • estimatedPlane
  • existingPlaneGeometry
  • existingPlaneInfinite

 

targetAlignment

重力方向に対してのターゲットの配置向き。
設定できるものは平面同様に、水平、垂直、その両方。

var targetAlignment: ARRaycastQuery.TargetAlignment { get }

 

ARRaycastQuery.TargetAlignment

重力方向に対してのターゲットの配置向きの設定の enum。
水平垂直、水平、垂直の設定。

  • any
  • horizontal
  • vertical

 

direction

3D 空間でレイの軌跡を表すベクトル。

var direction: simd_float3 { get }

 

origin

レイの開始位置を定義する 3D 座標。

var origin: simd_float3 { get }

 

ARTrackedRaycast

ARKit が連続して繰り返すレイキャストクエリ。 時間の経過とともに洗練された結果を返す。

 

update(_:)

連続して繰り返す必要がある場合、新しいクエリを提供する。
レイキャストクエリが失敗した場合、
ARKit は空の結果を更新ハンドラに渡し、クエリのレイの追跡を停止する。

func update(_ query: ARRaycastQuery)

 

stopTracking()

レイキャストクエリの繰り返しを停止する。

func stopTracking()

 

追跡したレイキャストは stopTracking() を呼び出して明示的に停止するまで継続的に更新されるが、
以下の場合レイキャストは自動的に停止する。

  • ARKit が sessionWasInterrupted(_:) を飛び出した時
  • セッション設定が変更された時
  • ARTrackedRaycast の割り当てが解除された時
  • update(_:) を使用して指定したクエリが失敗した時

 

ARRaycastResult

画面上の点を調べることによって見つけた現実世界の表面に関する情報。

class ARRaycastResult : NSObject

 

カスタムレンダラーを使用している場合は、スクリーンポイントを使用して実際の位置を以下の関数で見つけることができる。

  • ARFrame の raycastQuery(from:allowing:alignment:) 関数
  • ARSession の raycast(_:) 関数

 

追跡したレイキャスティングは、ARSession の trackedRaycast(_: updateHandler:) を呼び出す。

カスタムレンダラーを使わずに RealityKit、SceneKit を使用する場合は用意されている関数を使用する。 ARSCNView は raycastQuery(from:allowing:alignment:) 関数を使用して、スクリーンポイントから実際のサーフェスを検索できる。

取得できるパラメーターは既存のものと上記で紹介しているので省略。

var worldTransform: simd_float4x4
var anchor: ARAnchor?
var target: ARRaycastQuery.Target
enum ARRaycastQuery.Target
var targetAlignment: ARRaycastQuery.TargetAlignment
enum ARRaycastQuery.TargetAlignment

 

ARHitTestResult.ResultType

変更不明。

init(rawValue: UInt)

 

フェイストラッキング

ARFaceAnchor.BlendShapeLocation

変更不明。

init(rawValue: String)

 

ARFaceTrackingConfiguration

supportsWorldTracking

iOS デバイスがフェイストラッキングによるワールドトラッキングをサポートを示すフラグ。

ワールドトラッキングを有効にする前にこれを呼び出し、isWorldTrackingEnabled を使用しフェイストラッキング設定を始める。

class var supportsWorldTracking: Bool { get }

 

isWorldTrackingEnabled

フェイストラッキングによるワールドトラッキングを可能にするブール値。

iOS デバイスがフェイストラッキングによるワールドトラッキングをサポートしているかどうかを確認してから、この isWorldTrackingEnabled を呼び出す。

var isWorldTrackingEnabled: Bool { get set }

 

maximumNumberOfTrackedFaces

同時にフェイストラキングする顔の最大数。

デフォルト値は1。
特定のフレームでフェイストラッキングの数を制限するには、フェイストラッキングの最大数を設定する。

このプロパティを設定する前に supportedNumberOfTrackedFaces の値を確認する。

var maximumNumberOfTrackedFaces: Int { get set }

 

supportedNumberOfTrackedFaces

ARKit が同時にフェイストラッキングできる最大数。
現状では 3。

maximumNumberOfTrackedFaces を使用する場合は、この値を超えてはならない。

class var supportedNumberOfTrackedFaces: Int { get }

 

People(ボディトラッキング)

ARBodyTrackingConfiguration

3D 空間で人の動きのトラッキングのために使用するコンフィグレーション。

class ARBodyTrackingConfiguration : ARConfiguration

 

ARKit がバックカメラフィード内の人物を認識すると、 session(_: didAdd:) を呼び出し、 パッペティング(仮想キャラの操作)に使用する ARBodyAnchor を渡す。

ARConfiguration.FrameSemantics タイプ の bodyDetection はデフォルトで有効。 フレームの detectedBody を介して、検出されたボディの画面位置にアクセスできる。

また、平面検出と画像検出が有効になっているため、ボディアンカーを選択した表面または画像に配置することができる。

 

init()

新しいボディトラッキング設定を作成する。

init()

 

initialWorldMap

ARWorldMap を実行中の ARSession の状態をカプセル化する。
ARWorldMap と同じなので割愛。

多分、Multi peer 用。

var initialWorldMap: ARWorldMap? { get set }

 

automaticSkeletonScaleEstimationEnabled

トラッキングする人の身長を ARKit が推定するかどうかを決定するフラグ。

このプロパティを true に設定すると、   ARKit は人の体のアンカーの EstimatedScaleFactor の値を計算するように指示する。

ARKit は実世界の人物の位置を正確に推定するためにはその人物の身長を知っている必要があるが、このプロパティを有効にするとボディアンカーを割り当てる前に認識される人物の体格を自動で推定する。

var automaticSkeletonScaleEstimationEnabled: Bool { get set }

 

isAutoFocusEnabled

他のコンフィグレーションと同様に、カメラ画像をオートフォーカスを有効する。
iOS 11.3 からデフォルトで有効になっている。

var isAutoFocusEnabled: Bool { get set }

 

automaticImageScaleEstimationEnabled

上記のワールドトラッキングのものと同じ。

var automaticImageScaleEstimationEnabled: Bool { get set }

 

detectionImages

検出する画像の参照画像を設定する。
既存のワールドトラッキングのものと同じ。

var detectionImages: Set<ARReferenceImage> { get set }

 

maximumNumberOfTrackedImages

トラッキングする画像の最大数。
既存のワールドトラッキングのものと同じ。

var maximumNumberOfTrackedImages: Int { get set }

 

wantsHDREnvironmentTextures

HDR の環境テクスチャを作成するするか決めるフラグ。
ワールドトラッキングのものと同じ。

var wantsHDREnvironmentTextures: Bool { get set }

 

environmentTexturing

ARKit で環境テクスチャを生成するために使用する。
既存のワールドトラッキングのものと同じ。

var environmentTexturing: ARWorldTrackingConfiguration.EnvironmentTexturing { get set }

 

ARBodyAnchor

ARKit がカメラフィード内で検知した人物のピボットジョイントの 3D 空間での動きを追跡するオブジェクト。

class ARBodyAnchor : ARAnchor

 

ARBodyTrackingConfiguration を使用してセッションを実行することでモーションキャプチャを有効にし、
バックカメラフィード内の人物を認識すると ARBodyAnchor を使用してデリゲートのsession(_:didAdd :) を呼び出す。

ボディアンカーの変形位置はスケルトンの股関節を起点にマッピングされる。

また、フレームのアンカーリスト内で追跡している人体(ボディアンカー)にアクセスすることも可能。

 

skeleton

3D 空間でトラッキングされたボディのモーション情報を受け取る。

var skeleton: ARSkeleton3D { get }

 

estimatedScaleFactor

本体のデフォルトの高さと、実行時に ARKit が推定する高さを関連付ける。

automaticSkeletonScaleEstimationEnabled を true に設定した場合、 このプロパティを 0.0 〜 1.0 の値に設定する。

デフォルト値は 1.0。

var estimatedScaleFactor: CGFloat { get }

 

ARSkeleton3D

各ジョイントの 3D ローカル、およびモデル変換情報を追加することによってARSkeleton プロトコルを補完する。

class ARSkeleton3D : ARSkeleton

 

プロパティやメソッドはドキュメントの説明がないため割愛。

多分、ジョイントのローカルかモデルからの座標のプロパティとジョイント名から座標を取るメソッド。

var jointLocalTransforms: [simd_float4x4] { get }
var jointModelTransforms: [simd_float4x4] { get }
func localTransform(for: ARSkeleton.JointName) -> simd_float4x4?
func modelTransform(for: ARSkeleton.JointName) -> simd_float4x4?

 

ARSkeleton

ボディトラッキング対象のスケルトン用インターフェース。
ARKit はボディトラッキングの状態をジョイントの集まりとして動きを渡す。

class ARSkeleton : NSObject

 

definition

現在のボディの状態を定義するジョイントの構成。

var definition: ARSkeletonDefinition { get }

 

isJointTracked(_:)

ARKit が特定のインデックスのジョイントをトラッキングするかどうか伝える。

スケルトン定義内の 93 個すべてのジョイントをトラッキングしないため、
この機能を使用して特定のインデックスを使用してトラッキングするジョイントを決定する。

func isJointTracked(_ jointIndex: Int) -> Bool

 

ARSkeleton.JointName

トラッキングするジョイントの名前を定義するオブジェクト。

ARKit は名前付きジョイントのモーションを追跡し、その位置を使用して他の 85 の名前のないジョイントの位置を補間する。

struct JointName

 

新しいジョイント名を作成する。

init(rawValue: String)

 

設定されているものは、root を起点に頭、肩、足が設定されており、 左右肩を起点にそれぞれの手が設定されている。

static let root: ARSkeleton.JointName
static let head: ARSkeleton.JointName
static let leftFoot: ARSkeleton.JointName
static let leftHand: ARSkeleton.JointName
static let leftShoulder: ARSkeleton.JointName
static let rightFoot: ARSkeleton.JointName
static let rightHand: ARSkeleton.JointName
static let rightShoulder: ARSkeleton.JointName

 

ARSkeletonDefinition

名前付きジョイントの階層やそれらの相対位置の定義。

class ARSkeletonDefinition : NSObject

スケルトンは指定された階層で定義されているラベル付きジョイントのセットで構成され、このジョイントは他のジョイントの親となる。 スケルトンの定義の階層を識別するには parentIndices を使用する。

スケルトンをサーフェスに配置する場合、 ボディアンカーの原点は股関節にワールド位置が設定されるため、 ボディをサーフェス上に配置する場合、足は腰に対する現在のオフセットで計算する。

これは追跡されている人物が現在立っているか、しゃがんでいるかに関係なく機能する。

左足の関節インデックスを jointModelTransforms に渡すことで、体の原点からの足のオフセットを取得できる。

 

neutralBodySkeleton3D

ニュートラルポーズの 3D スケルトンで、高さは 1.8 メートルで T の形をしている。

このスケルトンは、他のすべてのスケルトンポーズを参照するために提供される。

var neutralBodySkeleton3D: ARSkeleton3D? { get }

 

defaultBody3D

3D で定義されたボディのデフォルトスケルトンの定義。

スケルトンのデフォルトの高さは 1.8 メートル。

class var defaultBody3D: ARSkeletonDefinition { get }

 

defaultBody2D

2D で定義されたボディのデフォルトのスケルトン定義。

多分 ARSkeletonDefinition は 3D と同じものが買えると予想されるため、自前で 2D へ当て込む。

class var defaultBody2D: ARSkeletonDefinition { get }

 

jointNames

固有のジョイント名のコレクション。

ジョイントインデックスをジョイント識別子に変換するには この配列を参照する。

var jointNames: [String] { get }

 

parentIndices

ドキュメントの記載なし。
多分親ジョイントのインデックス数。

@nonobjc var parentIndices: [Int] { get }

 

index(for:)

ドキュメントの記載なし。
多分、ジョイント名からスケルトンのインデックスを取得する。

@nonobjc func index(for jointName: ARSkeleton.JointName) -> Int

 

ARBody2D

バックカメラフィードで認識する人物のスクリーンスペースを表す。

class ARBody2D : NSObject

 

ARBody2D は ARBodyAnchor のパラメータと同じで、
ARBodyAnchor はスクリーンスペースの座標も持つ。

var skeleton: ARSkeleton2D { get }
class ARSkeleton2D
class ARSkeleton

 

イメージトラッキング

ARReferenceImage

resourceGroupName

このイメージのARリソースグループ名。

アセットカタログ内の AR リソースグループからこのイメージをロードした場合、このプロパティの値からリソースグループの名前を取得できる。

設定しいなければプロパティの値は nil を返す。

var resourceGroupName: String? { get }

 

validate(completionHandler:)

参照画像が有効かどうかを検証する。

画像トラッキングに適さない画像は無効であると見なす。
セッションの detectionImages 配列に渡す前に、ARKit が確実にトラッキングできるようプログラムで設定した参照画像に対してこの関数を呼び出すことができる。

Xcode のアセットカタログで参照画像を作成する場合は、自動的に検証を実行するためこのメソッドを使用する必要はない。

func validate(completionHandler: @escaping (Error?) -> Void)

 

ARImageAnchor

estimatedScaleFactor

上記 automaticImageScaleEstimationEnabled を指定した際に、トラッキングする画像の大きさの初期サイズと推論した現実的な物理サイズの間の要素を値として調べる時に使う。

デフォルト値は 1.0 で ARKit が現実世界で認識する画像が、参照画像で設定した physicalSize のパラメータと完全に一致することを意味する。

ARKit は自動的に画像アンカーの変換を補正を行い、この調整はイメージアンカーが現実世界のどこにあるのか ARKit が理解し修正する。

よって、参照画像で設定した physicalSize のパラメータと異なる物理的な画像サイズの場合、アンカーは拡大縮小され、これはその拡大縮小の値を表す。

var estimatedScaleFactor: CGFloat { get }

 

オブジェクトトラッキング

ARReferenceObject

resourceGroupName

イメージトラッキングと同様。

アセットカタログ内の AR リソースグループからこのオブジェクトをロードした場合、このプロパティの値からリソースグループの名前を取得できる。

設定していなければプロパティの値は nil を返す。

var resourceGroupName: String? { get }

 

ポジショナルトラッキング (主に VR 用)

ARPositionalTrackingConfiguration

空間内のデバイス位置を追跡する場合に使用するコンフィグレーション。

可能な限り低い解像度とフレームレートでカメラを動作させることで、
iOS デバイスの 6 DoF トラッキングを有効にし、カメラでの解析必要としないコンテンツ使用する。

要するに VR 用。

class ARPositionalTrackingConfiguration : ARConfiguration

 

init()

新しいポジショントラッキング用のコンフィグレーションを作成する。

init()

 

initialWorldMap

ワールドトラッキング同様にワールドマップを使用する。

 

planeDetection

ドキュメントに記載なし。
ARWorldTrackingConfiguration と同様なので、現実空間の平面認識を行うか否か。

var planeDetection: ARWorldTrackingConfiguration.PlaneDetection { get set }

 

マルチユーザー

ARSession.CollaborationData

ユーザーによって収集された現実環境に関する情報を保持するオブジェクト。

他のユーザーとのマルチユーザー AR エクスペリエンスを作成するには、ワールドトラッキンセッションでコラボレーションを有効し、
定期的に他のユーザーと共有する ARSession.CollaborationData を出力して各ユーザーと状態を同期させる。

class CollaborationData : NSObject

 

init(data:)

シリアライズされたコラボレーションデータから、コラボレーションデータオブジェクトを作成する。

別のユーザーからネットワーク経由でシリアライズされたコラボレーションデータを受信したら、それを使用して ARSession.CollaborationData オブジェクトを作成、update(with:) を呼び出してセッションを更新する。

init(data: Data)

 

data

シリアライズされたコラボレーションデータ。

セッションのワールドデータやアンカーに関する情報がシリアライズされたデータとなる。

var data: Data { get }

 

ARParticipantAnchor

マルチユーザー AR エクスペリエンスで別のユーザーを表すアンカー。

isCollaborationEnabled を true に設定すると、ARKit は現実環境で検出されたすべてのユーザーに対して session(_:didAdd:) からの ARParticipantAnchor をから各ユーザーのワールド座標を把握することができる。

class ARParticipantAnchor : ARAnchor

 

カスタムディスプレイ

ARMatteGenerator

ARKit がカメラフィード内で認識する現実世界から配置した仮想コンテンツで人と隠すために使用するマットテクスチャを作成するオブジェクト。
カスタムレンダラー用で ARView や ARSCNView で frameSemantics を設定し使用する。

カスタムレンダラーによる人物の遮蔽をサポートするためのマットジェネレータは、フレームの segmentationBuffer および EstimatedDepthData 内のアルファや深度情報を処理してマットおよび深度テクスチャが提供される。
これらのテクスチャを使用することで、アプリの仮想コンテンツの上に人を重ねることができる。

class ARMatteGenerator : NSObject

 

init(device:matteResolution:)

AR マットジェネレータを作成するイニシャライザ。

マットテクスチャをリアルタイムで作成するには、このオブジェクトを一度作成してフレームごとに再利用する。

init(device: MTLDevice, 
matteResolution: ARMatteGenerator.Resolution)

 

generateMatte(from:commandBuffer:)

キャプチャした画像のフル解像度または半分の解像度でアルファマットを生成し、初期化時に選択した解像度のアルファマットテクスチャを返す。

func generateMatte(from frame: ARFrame, 
     commandBuffer: MTLCommandBuffer) -> MTLTexture

 

generateDilatedDepth(from:commandBuffer:)

セグメンテーションステンシルの解像度で拡張された深度を生成し、
float32 型の単一チャンネルからなる拡張された深度テクスチャを返す。

カメライメージと仮想オブジェクトを合成する場合には、
この関数から提供される線形の深度情報を使用する。

func generateDilatedDepth(from frame: ARFrame, 
            commandBuffer: MTLCommandBuffer) -> MTLTexture

 

ARMatteGenerator.Resolution

マットテクスチャの解像度。

フレームごとのマットテクスチャを生成するため、カメラ画像の解像度をフルサイズか半分かを指定する。

enum Resolution : Int

 

パラメーター

  • full
  • half

 

以上、ARKit 3 の更新内容。

SceneKit の変更点 (Xcode 11 Beta 1)

今回も SceneKit のセッションがなく、ドキュメントの説明もないのでメソッドやプロパティ名から予想。
間違っていたらすみません。

ちなみに、Scene Editor の変更がそれなりにありそうなのだが NDA 的に紹介できないのでそのうち。

 

長いので最初にまとめ

以下、主な更新内容

  • エリアライトの追加
  • リフレクションプローブの追加
  • シーン全体のスクリーンスペースリフレクションの追加
  • カメラエフェクトの追加と調整
  • マテリアルでクリアコートのプロパティが追加

 

SCNScene

シーン全体での Screen Space Reflection が追加。
wantsScreenSpaceReflection で有効 / 無効、
MaximumDistance は有効距離、SampleCount はサンプリング回数、
Stride は多分レイトレーシングのステップ数で反射回数。

var wantsScreenSpaceReflection: Bool { get set }
var screenSpaceReflectionMaximumDistance: CGFloat { get set }
var screenSpaceReflectionSampleCount: Int { get set }
var screenSpaceReflectionStride: CGFloat { get set }

 

SCNView

以下のものが廃止され、macOS 10.15 から OpenGL での描画が使用できなくなる。

var openGLContext: NSOpenGLContext?
var pixelFormat: NSOpenGLPixelFormat?

 

macOS 10.15 で追加。
ウインドウがリサイズされた時に描画の変更を非同期で行うか否か。
現状でも非同期になっていると思われるのでデフォルトは true。

var drawableResizesAsynchronously: Bool { get set }

 

SCNNode

SCNHitTestOption で ignoreLightArea が追加された。
LightType で追加されたエリアライトで表示されるジオメトリをヒットテストの対象から外すものだと思われる。

static let ignoreLightArea: SCNHitTestOption

 

SCNSceneRenderer

以下、3つが追加。ドキュメント上は必須の設定 (Required)
多分でデフォルト値が設定されているため、開発者側ですることはないと思われる。

var currentViewport: CGRect { get }
var isTemporalAntialiasingEnabled: Bool { get set }
var usesReverseZ: Bool { get set }

 

currentViewport は現状のビューポートを取得するものだと想定される。 isTemporalAntialiasingEnabled リアルタイムでアンチエイリアス状態の変更を有効化するか設定するものだろうと思われる。(詳細不明)

また、delegate が weak だったのが unowned(unsafe) に変更された。

 

SCNHitTestResult

SCNHitTestResult で取得できる座標で SCNVector3 や SCNMatrix4 で設定されていたものが simd に変更されたものだと思われる。

var simdLocalCoordinates: simd_float3 { get }
var simdLocalNormal: simd_float3 { get }
var simdModelTransform: simd_float4x4 { get }
var simdWorldCoordinates: simd_float3 { get }
var simdWorldNormal: simd_float3 { get }

 

SCNLight

エリアライト

エリアライトが追加された。

LightType で area が選択可能になり、
areaExtents は有効範囲。
areaType で線と矩形と多分自前で設定できる平面の多角形を選択。
areaPolygonVertices は自前でエリアライトの平面を設定。
doubleSided はエリアライトの平面を両面表示にし、
drawsArea はエリアライトの線と矩形、ポリゴンを描画するか否か。

static let area: SCNLight.LightType { get set }
var areaExtents: simd_float3 { get set }
var areaType: SCNLightAreaType { get set }
var areaPolygonVertices: [NSValue]? { get set }
var doubleSided: Bool { get set }
var drawsArea: Bool { get set }

 

SCNLightAreaType

エリアライトでの形状設定。
線と矩形と多分自前で設定できる平面の多角形。

case line
case polygon
case rectangle

 

リフレクションプローブ

リフレクションプローブが追加された。
ライトプローブは周囲の光を画像に書き込み周りに反映するが、リフレクションプローブは周囲の鏡面反射のような状態を画像に書き込む。

ゲームエンジンなどでは光の反射は現実のようには処理できないため、背景などは反射対象になるが、隣接するジオメトリは反射の対象にはならない。

そのため、リアルタイムレイトレーシングを行う必要があるが、リフレクションプローブを使うことで擬似的に反射させることができる。

probeType でライトプローブかリフレクションプローブを選択し、
probeEnvironment でライトのパラメーター、
probeExtents、probeOffset は有効範囲とオフセット、
probeUpdateType はラディアンスマップを作成するかリアルタイムにするかで、
parallax はラディアンスマップでつくったキューブマップの視差ををどうするか設定するものだと思われる。

var probeType: SCNLightProbeType
var probeEnvironment: SCNMaterialProperty?
var probeExtents: simd_float3
var probeOffset: simd_float3
var probeUpdateType: SCNLightProbeUpdateType
var parallaxCenterOffset: simd_float3
var parallaxCorrectionEnabled: Bool
var parallaxExtentsFactor: simd_float3

 

SCNLightProbeType

ライトプローブでの設定追加。
どちらかが、既存のライトプローブでもう片方がリフレクションプローブ。
多分 radiance がリフレクション。

case irradiance
case radiance

 

SCNLightProbeUpdateType

以前はラディアンスマップを画像として事前に作成させていたが、今回からリアルタイムで計算し直すオプションが増えた模様。

case never
case realtime

 

SCNCamera

HDR でブルーム効果のパラメーターが追加され、多分、ブルーム効果が綺麗になると思われ。
IterationCount 減衰を繰り返す数で、
bloomIterationSpread 減衰繰り返しの際の強さ。

var bloomIterationCount: Int { get set }
var bloomIterationSpread: CGFloat { get set }

 

ポストエフェクトが追加された。
grain は画面の荒さ、
whiteBalance はカラーグレーディングでホワイトバランスの調整。

var grainIntensity: CGFloat { get set }
var grainIsColored: Bool { get set }
var grainScale: CGFloat { get set }
var whiteBalanceTemperature: CGFloat { get set }
var whiteBalanceTint: CGFloat { get set }

 

こちら詳細不明。
ビューポートサイズから投影している画面の座標を取得するのではと思われる。

func projectionTransform(withViewportSize viewportSize: CGSize) -> SCNMatrix4

 

SCNMaterial

車のボディのようなクリアコートのプロパティが追加された。

現状の表現では Meralness や Roughness の数値を上げると表面が完全に反射したり、完全にぼやけてしまう。

多分、表面に透明な塗装をすることで車のボディなどで見る色のついた上から鏡面反射が付加された現実に近い表示がされる。

var clearCoat: SCNMaterialProperty { get }
var clearCoatNormal: SCNMaterialProperty { get }
var clearCoatRoughness: SCNMaterialProperty { get }

 

SCNParticlePropertyController

inputOrigin が weak から unowned(unsafe) に変更。

 

SCNBufferStream

以下に UnsafeRawPointer 変更

func writeBytes(_ bytes: UnsafeRawPointer, count length: Int)
func writeBytes(_ bytes: UnsafeMutableRawPointer, count length: Int)

 

SCNTechnique

MTLLibrary の読み書きが追加された。

var library: MTLLibrary? { get set }

 

SceneKit Constants

多分、使用できる OpenGL のバージョンか何かを調べることができる。

 

var SCN_ENABLE_OPENGL: Int32 { get }

 

SCNLayer

macOS にあった SCNLayer クラスが 10.15 廃止された。

 

以上、見た目の変更に関するものがほとんどとなった。