Apple Engine

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

ARKit 2.0 のその先

今までの流れ。

 

ARKit 1.0 で6DoF のポジショントラッキングと水平の平面認識。


ARKit 1.5 で水平の平面認識と平面の詳細形状の認識、画像認識、顔と表情認識。


ARKit 2.0 で物体認識と物体の特徴点のスキャン、画像認識の強化、表情認識の強化、環境マップテクスチャの作成、近隣の特徴点を取得しそれを元に仮想空間の復元と共有。


という感じである。

 


2.0 の機能からすると環境マップはリアルさを求めた流れだが、物体や画像のトラッキングや仮想空間の復元は明らかにコミュニケーションツールとしての流れだろう。


現状、仮想空間の共有として最も楽な閲覧環境はメガネ的なデバイスだと思われるので、いくつかの問題が解決されれば Apple もこのタイプの商品を出すと思っている。


現実的な方法を考えると単体でメガネとして動くものではなく、Apple Watch のような iOS を母体としたものになるのだろう。  

そして、iPhone、Apple Watch や画像、物体認識がグラスのコントローラーやトリガーとして AR のインタラクションを起こす装置になると予想する。

 

Apple が ARKit で次に実装するだろうと思う機能は現実世界での遮蔽物の判定だろう。

現状のワールドマップのマッピングから深度情報を取得すれば、画像ベースで遮蔽物の判定はできるし、多分最終的には3Dのジオメトリ張りそうな感じはある。

 

もうひとつは、現実世界での物体のトラッキング。

現状のトラッキングは固定されたもので行うが、2.0 と画像認識のように動いても対応できるもの。

例えば、手の動きに合わせてトラッキングしアンカーを配置し追従する。

 

ARKit は直接的には関係無いのだが、この先eGPU の無線化もあるとは思っている。

もし、無線で eGPU が動作するようになるのなら、AR で事前に処理した映像を端末にかえすことができ、色々な用途に使用できる。

 

iOS 12 ではメジャーのアプリが標準でインストールされる。

これまでの AR は驚きを与えるものだったが、これからは生活を豊かにするためのツールとしてアプリの展開をしてゆくのだろう。


また、Apple は古くから 3DCG のモデリングツールをつくっていた Stuart Ferguson を招き入れている。

古くは LightWave 3D のモデラー、Modo の Luxology のファウンダー、Foundry に買収された後に技術責任者となっている人である。

https://www.linkedin.com/in/stuart-ferguson-34a5268/


簡素に扱えるなんらかのモデリングツールなのか、フォトグラメトリなのか、Xcode の Scene Editor が拡張されるか、どうなるかはわからないが面白いものが出てきそうな感じはある。


今後も Apple は AR を含めた 3DCG 分野に力を入れていくのだろう。

Geekbench からみる次期 Macbook Pro 13、15 inch のスペックを見てみる

13 inch のベンチマークも上がっていたため、13、15 両方調べてみた。

また、Bench の投稿数が少ないので内容は参考程度に。

 

噂の 13 inch のベンチマーク
https://browser.geekbench.com/v4/cpu/8868725

噂の 15 inch のベンチマーク
http://browser.geekbench.com/v4/cpu/8493093

 

スペックをまとめるとこんな感じ。

13 inch 15 inch
CPU Core i7-8559U Core i7-8750H
Core 4 6
Thead 8 12
メモリ 16G
(LPDDR3 2133MHz)
32G
(DDR4 2667MHz)
GPU Iris Plus Graphics 655 Radeon Pro 560

 

CPU

Multi Core の高い順で並べ替えている。

モデル Single Core Multi Core
iMac Pro (8 Core) 5008 30535
Macbook Pro 15-inch 2018? 4902 22316
iMac 27-inch
(i7-7700K)
5676 19329
Macbook Pro 13-inch 2018? 4448 16607
Macbook Pro 15-inch 2017
(i7-7920HQ)
4624 15551
iPhone X 4206 10128
Macbook Pro 13-inch 2017
(i7-7567U)
4606 9553
iPad Pro 10.5 inch 3909 9308

 

噂の 15inch をマルチコアベースで考えるとこんな感じ

  • 2017年の 15inch と比べて 1.43 倍速い
  • 現行の iMac 27inch フルスペックの約 1.15 倍速い
  • iMac Pro 8コアと比べて約 73 %ぐらいの速さ

 

噂の 13inch をマルチコアベースで考えるとこんな感じ

  • 2017年の 13inch と比べて 1.74 倍速い
  • 2017年の 15inch よりほんの少しだけ速い
  • 現行の iMac 27inch フルスペックと比べて約 85 %ぐらいの速さ
  • iMac Pro 8コアと比べて約 54 %ぐらいの速さ

 

OpenCL

OpenCL は統計としての情報がサイトにないので、本当に目安という感じで見て欲しい。

 

噂の 13 inch のベンチマーク
https://browser.geekbench.com/v4/compute/2572782

噂の 15 inch のベンチマーク
https://browser.geekbench.com/v4/compute/804002

 

高いスコアを取ってきているので、15-inch は 2017 の方が値が高くなっているが、もし発売されてベンチマークがいくつか出れば本当の値が出てきそう。
多分 iMac 27-inch (i7-7700K) と近いぐらいは出そうではある。

モデル GPU スコア
iMac Pro (8 Core) Vega 56 161056
iMac 27-inch
(i7-7700K)
Radeon RX 560 78992
Macbook Pro 15-inch 2017
(i7-7820HQ)
Radeon Pro 560 49100
Macbook Pro 15-inch 2018? Radeon Pro 560 41165
Macbook Pro 13-inch 2018? Iris Plus Graphics 655 36193
Macbook Pro 13-inch 2017
(i7-7567U)
Iris Graphics 650 32782

 

iOS の場合 OpenCL はプライベートフレームワークとなっており、ストアにあるものでは開発者が使用できないため Metal の集計。

モデル スコア
iPad Pro 10.5 inch 29246
iPhone X 15233

 

まとめ

以前から Macbook Pro 13inch はスペック的に割高で買う候補にはならないと書いてきたが、 ある程度までのスペックを持ってきた。
もしこのスペックで現行のフルスペックの価格と同等になるのであれば妥当感はある。

15inch も iMac を超え、iMac Pro 8Core に近づく形となっており、
13、15inch ともに eGPU と組み合わせれば、わりとパワフルな環境ができるのではというところ。

とはいえ、フルスペックの Macbook Pro に、eGPU の Vega と BOX を買うと、多分価格的に iMac Pro 8Core に近くなるか超えてしまいそうな感はある。

iOS 12 SDK Bata 3 の ARKit 2 変更内容

Beta 版から記事を起こしているため今後変更される可能性あり。

物体認識のクラス ARReferenceObject で参照オブジェクトの情報をマージできるようになった。

それに伴いマージ失敗のエラーが追加されている。

 

追加

ARSessionObserver

ARError.Code

objectMergeFailed

Object Merge 失敗時のエラーコードを追加。

 

ARError

static var objectMergeFailed: ARError.Code { get }

Object Merge 失敗時のエラーを追加。

 

ARReferenceObject

func merging(_ object: ARReferenceObject) throws -> ARReferenceObject

 

ドキュメントで説明の記載なし。
以下、ARReferenceObject のヘッダーファイルから翻訳。

 

指定したオブジェクトをこの参照に合わせてマージ(結合)し、新しい参照オブジェクトを返す。

異なる条件で検出するため、同じオブジェクトを複数のスキャン情報から結合するために使用することができ、
対象のマージを成功させるには同じような特徴点を使用する(共有する)必要がある。

パラメーターの object は現在の参照オブジェクトへマージするための参照オブジェクト。マージに失敗した場合 throws から error が返される。

マージが成功しなかった場合は nil を返し、成功した場合は新しい参照オブジェクトを返す。

 

変更点不明

ARCamera.TrackingState

Modify と書かれているが変更点不明。

iOS 12 SDK Bata 3 の SceneKit、Scene Editor 変更内容

Beta 版から記事を起こしているため今後変更される可能性あり。

主に SCNSceneRenderer の delegate と、
SCNPhysicsContact の contactDelegate のプロパティ属性が「unowned(unsafe) 」から「weak」に変更された。

 

SCNSceneRendererDelegate

変更前
unowned(unsafe) var delegate: SCNSceneRendererDelegate? { get set }

 

変更後
weak var delegate: SCNSceneRendererDelegate? { get set }

 

SCNPhysicsContact

変更前
unowned(unsafe) var contactDelegate: SCNPhysicsContactDelegate? { get set }

 

変更後
weak var contactDelegate: SCNPhysicsContactDelegate? { get set }

 

その他

Beta 1 からの変更

Xcode でのライブラリ選択

Scene Editor で使用する Objects Library や Media Library の位置とショートカットが変更された。
左上部の Standard editor ボタンの横のボタンから選択する。

機能 旧ショートカット 新ショートカット
Objects Library Command + Option + Control + 3 Command + Shift + L
Media Library Command + Option + Control + 4 Command + Shift + M

 

Scene Editor

以下、変更

  • Xcode のアプリケーションメニュー、Editor にあった Display の項目の一部が、右下のアイコンから変更可能になり便利
  • 右下の Fly などのカメラ設定の変更が文字だけではなくアイコンがついた。
  • 右下に Storyboard のような Mac、iPhone、iPad、Apple Watch などの画面サイズのシミュレーションができるようになった
  • 右下のノードを選択時に表示されるマニピュレーターの座標系の中に、マニピュレーターのハンドルを移動のみと回転のみの選択ができるようになった
  • 左側の Scene Graph View の Filter で、文字列からさらにライト、カメラ、パーティクル、ジオメトリでフィルターできるボタンがついた
  • Scene Editor のシーンが表示されている部分で右クリックすると、アプリケーションメニューの Editor とほぼ同じメニューが表示されるようになった
  • 右下のもっとも右にあるボタンを押すと出る Secondary Editor の色が変更された
  • Scene Inspector の Procedural Sky の Adjustments のパラメーターが Scene Editor のシーンに正しく反映されるようになった
  • Scene Inspector の Environment の Look with background が消滅
  • Node Inspector でアニメーションがない状態で書き出せなくなった。以前は書きだせ必ず Xcode がクラッシュした
  • ジオメトリの初期のマテリアルが Blinn から Physically Based に変更された

 

まとめ

SceneKit 自体の機能追加はないが、Beta なのでバグはあるものの Xcode での便利さが増している。

Xcode 9 の Scene Editor、iOS 11 の Scene File の Procedual Sky のバグについて

Xcode 10 を触っていて気づいたのだが、Xcode 9 の Scene Editor、iOS 11 の Scene File では Procedual Sky で正しい表示がされないバグがある。

ちなみに Scene Editor での Procedual Sky の適応方法は、何らかのノードを選択後、Scene Inspector (Command + Option + 7) を押して、Background や Environment で Procedual Sky を選択する。

f:id:x67x6fx74x6f:20180703194346p:plain

 

問題点

問題点が2点ある

  • Xcode 9 の Scene Editor では Adjustments のパラメーターが適応されない
  • Xcode 9 の作成する Scene File の Adjustments のパラメーターが保存されるが、実行時適応されない

 

Xcode の Scene Editor 自体、SceneKit で作成されているため、Scene Editor で出ているバグはビルドした実際のアプリでも同様のバグが発生する。

ちなみに、Adjustments のパラメーターはトーンマップ用のパラメーター。

  

原因

Scene Editor で設定する Procedual Sky は Model I/O の MDLSkyCubeTexture を使用しており、MDLTexture のサブクラスとなっている。

テクスチャとして空をキューブマップとして描画するのだが、中身は MTLTexture なのでパラメーターを与えただけではテクスチャ内容の変更ができない模様。

update() 関数があり、これが呼ばれるとテクスチャの再生成し MDLSkyCubeTexture として生成するのだと思われる。

 

このような流れで MDLSkyCubeTexture を使用するのだが、
どうやら Scene Editor や SceneKit では update() 関数が呼ばれていない可能性がある。

 

MDLSkyCubeTexture について

6面のキューブマップテクスチャが生成され、背景画像が作成される。
キューブマップの背景に関しては過去記事を参照。

appleengine.hatenablog.com

 

内部的には幅 64、高さ 384 の画像のテクスチャとなっている模様。
(もしかしたら Mipmap で1番小さい画像を取得している可能性あり)

 

パラメーター

Scene Editor で設定できるのものが全てのパラメーターとなっている

 

シミュレーションパラメーター

パラメーター名 説明
turbidity Float 空のかすみや曇り具合
sunElevation Float 太陽の位置
upperAtmosphereScattering Float 空の色に影響を与える値
groundAlbedo Float 空の透明度に影響を与える値
groundColor CGColor? 擬似的な地面の色
horizonElevation Float 地面の色をレンダリングする際に下の中心を基準にした角度 (単位はラジアン)

 

トーンマップパラメーター

パラメーター名 説明
gamma Float 適用するガンマ補正値
exposure Float 適用する露出補正値
brightness Float 明るさを強調させるための値
contrast Float コントラストを強調させるための値
saturation Float 彩度を強調させるための値
highDynamicRangeCompression vector_float2 テクスチャの色の輝度の圧縮曲線を決める2つのパラメータ(Photoshop のトーンカーブのようなもの)

 

Xcode 10 のシーンエディターの値を使い、Xcode 9 で MDLSkyCubeTexture を表示してみる

以下、Xcode 10 でのパラメーター。
Unity のデフォルトのような背景になる。

パラメーター名
turbidity 1.0
sunElevation 0.778
upperAtmosphereScattering 0.4
groundAlbedo 0.33
groundColor #383838 (0.22,0.22,0.22,1.0)
horizonElevation 0
gamma 0.05
saturation -2

 

コード

コードで書いてみる。

SCNScene の background に設定するため、SCNScene の初期化の後に以下を書く。

// MDLSkyCubeTexture の初期化
let skyTexture = MDLSkyCubeTexture(
    name: "sky", 
    channelEncoding: .uInt8,
    textureDimensions: vector_int2(1024, 1024),
    turbidity: 1.0,
    sunElevation: 0.778,
    sunAzimuth: 0,
    upperAtmosphereScattering: 0.4,
    groundAlbedo: 0.33
)

let groundColor = UIColor(red: 0.22, green: 0.22, blue: 0.22, alpha: 1.0)
skyTexture.groundColor = groundColor.cgColor

skyTexture.gamma = 0.05
skyTexture.exposure = 0
skyTexture.brightness = 0
skyTexture.contrast = 0
skyTexture.saturation = -2

skyTexture.update()

scene.background.contents = skyTexture
scene.lightingEnvironment.contents = skyTexture

 

MDLSkyCubeTexture の初期化には名前と channelEncoding、textureDimensions の値がある。

channelEncoding はピクセルフォーマット。
SceneKit での Metal は bgra8Unorm なので uInt8 を設定している。

textureDimensions はキューブマップ各1面の大きさ。
基本的には正方形を指定する形になると思われる。

 

表示結果

このような感じになる。

f:id:x67x6fx74x6f:20180703194758p:plain

 

update() 関数を呼ばないとこんな感じ。

f:id:x67x6fx74x6f:20180703194838p:plain

ARKit 2 の環境マッピング AREnvironmentProbeAnchor を試してみる

Beta 版から記事を起こしているため今後変更される可能性あり。

ARKit 2 で環境マップテクスチャの作成ができるようになった。

通常は AREnvironmentProbeAnchor から環境マッピングのテクスチャを作成するのだが、SceneKit の場合は設定をするとデフォルトでオンになるため、1行書くだけで実装できる。

 

Xcode 10 Beta で Xcode 9 と同様に「Augmented Reality App」でプロジェクトを作成。

viewWillAppear の ARWorldTrackingConfiguration に設定を追加するだけ。

let configuration = ARWorldTrackingConfiguration()
configuration.environmentTexturing = .automatic

 

あとは、Physically Based のマテリアルに Metalness の Float Value を 1、Roughness を Float Value を 0 に適応したアンカーやジオメトリを置くと環境マッピングされたマテリアルの反射を試すことができる。

 

automatic の AREnvironmentProbeAnchor 振る舞い

environmentTexturing を automatic で設置される AREnvironmentProbeAnchor は、 ドキュメントには書かれていないため詳細は不明だが、試したところ、 AREnvironmentProbeAnchor の変化があった時の端末の位置と向きを取る。

起動し端末を立てたままそのままでしばらくすると、位置は XYZ 軸で約 0 の、回転は Y軸が約 -90、extent は XYZ 軸で無限大を取る。

また、6面のキューブマップの1面の画像は 256 x 256 で構成されている模様。
(iPhone 6s で試しているため他の端末では解像度が異なるかも?)

負荷的には iPhone 6s で 60fps 切ったり切らなかったり。

 

AREnvironmentProbeAnchor を取得する

ARSessionDelegate の func session(_ session: ARSession, didUpdate anchors: [ARAnchor]) を使用し、 ARAnchor の配列から AREnvironmentProbeAnchor を調べて、そのアンカーの environmentTexture から MTLTexture を取得する。

environmentTexture はすぐに生成されないのであるか無いか確認する必要があり。
また、MTLTextureType が CubeMap なので、そのまま CIImage などに変更できないので注意。

 

サンプル

environmentTexturing を automatic にして Metalic な球体を 0.5m 上に置いたサンプルを作成してみた。

github.com

 

まとめ

かなり簡単に現実空間のものを反射するマテリアルができることがわかると思う。
より精度を高めたい場合は、environmentTexturing を manual にして、自前で AREnvironmentProbeAnchor をいくつか置くと良いと思われる。

ARKit 2.0 の更新内容 (iOS 12 Bata 2)

NDA の問題でスクリーンショットなどセッション資料のものを使用している。
また、Beta 版から記事を起こしているため今後変更される可能性あり。

遅くなってしまったが iOS 12 Bata の ARKit 2.0 更新内容を見てゆく。

Bata 2 の内容だが 1.0 の Beta の際は Configuration 関連の名称が変更したぐらいなので、 今回も機能的には GM までほぼ変更はないと思われる。

 

増えた機能

  • 環境マップテクスチャの作成
  • 物体認識と物体のトラッキング
  • 物体認識用の物体のスキャニング
  • 画像認識と画像のトラッキング
  • 現実世界から得た特徴点からのワールドマップの作成と復元(他の端末との空間共有などに使用)
  • 顔認識での舌の動きの取得

 

f:id:x67x6fx74x6f:20180622194719p:plain

f:id:x67x6fx74x6f:20180622194733p:plain

 

ワールドマップによるワールドトラッキングについて

WWWDC のセッションやドキュメントでは以下の2つを想定している。

  • Multiuser AR experiences
  • Persistent AR experiences

Multiuser は空間と仮想オブジェクトであるアンカーを他の端末に渡し仮想空間を共有、 Persistent は空間と仮想オブジェクトであるアンカーを保存し、再開した際に復元する。

 

物体認識用の物体のスキャニング

ARKit 自体には簡単にスキャンする UI 等がないため、地道に実装することになる。

特徴点のスキャンが完了したら .arobject のファイルとして保存し、
物体認識時に参照用のオブジェクトとして使う。

Apple のサンプルファイルでスキャンできるため、こちらを使用して振る舞いを確かめるとよいかと。

Scanning and Detecting 3D Objects | Apple Developer Documentation

 

ちなみに、スキャンはマシンパワーを使いまくるので基本的には物体のスキャニングは開発者側が事前に行なっておいた方がよいと思われる。
また、ある程度正確な特徴点のスキャンが行わないと物体認識時に上手く行かない場合があるので注意。

画像認識同様に真っ白で物体のコントラスト差がなく特徴点が認識しづらいものや、透明なもの、鏡面の物質などは物体のスキャンに向いていない。

 

既存機能の変更点

機能的な変更は特にないが、移動や回転などで使用している vector_float3 や matrix_float4x4 などが Accelerate Framework の simd で設定するものに変更されている。

 

増えたクラス

  • AREnvironmentProbeAnchor
  • ARWorldMap
  • ARReferenceObject
  • ARObjectAnchor
  • ARObjectScanningConfiguration
  • ARImageTrackingConfiguration

 

以下、変更を見てゆく。
今回あまりコードに触れていないので、翻訳が間違っていたらごめんなさい。

 

ARSession

ARSession

追加

func getCurrentWorldMap(completionHandler: @escaping (ARWorldMap?, Error?) -> Void)

ARWorldMap でワールドトラッキングの際、セッションの空間のマッピング状態とアンカーのセットをカプセル化したオブジェクトとして返す。

このメソッドを使用してセッションのワールドマップを保存した後、 initialWorldMap プロパティに割り当て、run(_: options:) を使用すると同じ空間認識とアンカーを別のセッションで開始する。

ARWorldTrackingConfiguration で Configuration を設定しないと即 completionHandler が返るので注意。

 

createReferenceObject(transform:center:extent:completionHandler:)

セッションでワールド空間の指定した領域から参照オブジェクト (3D オブジェクトの物体認識検出用オブジェクト) を作成する。

抽出する領域のローカル座標の原点と方向を設定する transform、
抽出する領域のバウンディングボックスの中心を定義する center、
抽出する領域の幅、高さ、深さを中心点としたローカル座標の範囲 extent を設定する。

completionHandler では、参照オブジェクトとなるワールドマップの指定された領域を表す ARReferenceObject を渡す referenceObject、エラー時の説明する ARError を渡す error がある。

 

注意点

このメソッドは参照オブジェクトのスキャンを可能にする ARObjectScanningConfiguration が設定されているセッション内で動作し、設定されていない場合は即 completionHandler が返る。

参照オブジェクトはスキャンした状態を元に原点が設定される。参照オブジェクトの原点を抽出した後で調整するには、applyingTransform メソッドを使用する。
例えば、スキャンした現実のフィギュアの頭の上に吹き出しを出したい時など、原点を頭の上に設定しておくと吹き出しを出す高さを考慮ても済む。

 

変更

setWorldOrigin(relativeTransform:)

引数が matrix_float4x4 から simd_float4x4 に変更。

 

ARSessionObserver

ARError.Code

追加

エラー用 enunm

名前 コード
fileIOFailed 500
insufficientFeatures 400
invalidConfiguration 303
invalidReferenceObject 301
invalidWorldMap 302
microphoneUnauthorized 104

 

ARError

追加

エラードメインと上記のエラーコード取得用

  • errorDomain: String
  • fileIOFailed: ARError.Code
  • insufficientFeatures: ARError.Code
  • invalidConfiguration: ARError.Code
  • invalidReferenceObject: ARError.Code
  • invalidWorldMap: ARError.Code
  • microphoneUnauthorized: ARError.Code

 

ARSCNView

追加

func unprojectPoint(_ point: CGPoint, ontoPlane planeTransform: simd_float4x4) -> simd_float3?

ARKit によって指定した 2D ビューの点から投影されたレイが、
指定した平面と交差するワールド空間の 3D ポイントを返し、レイが平面と交差しない場合 nil を返す。

point は平面上に投影する 2D ビュー空間の点。 planeTransform は3D ワールド空間での平面の位置と方向を指定する変換行列で、 この変換が定義するローカル座標空間の XZ 平面となる。

 

ARWorldTrackingConfiguration

追加

var initialWorldMap: ARWorldMap?

getCurrentWorldMap を使用してセッションのワールドマップを保存した後、その構成のワールドマップを復元する際に使用する。

ARKit が記録されたワールドマップを現在の環境と合わない場合、
セッションは初期状態の ARCamera.TrackingState.Reason.relocalizing 状態になる。
たとえば、ワールドマップが記録された場所とはまったく異なる場所にいる場合などで合わなくなる。

 

var maximumNumberOfTrackedImages: Int

同時にトラッキングできる検出画像の最大数。
0 より大きい値に設定すると、画像トラッキングが可能になる。
以前のものとは異なり、空間を移動しても連続してトラッキングされる。

画像検出は、ARKit が最初にカメラビューで検出したときの画像の位置と向きを報告し、その後はまれな更新しか行われない。

ARWorldTrackingConfiguration では少数の画像しか同時にトラッキングできない。
さらに多くの画像をトラッキングしたい場合は ARImageTrackingConfiguration の方を使用する。

 

class var isObjectDetectionSupported: Bool { get }

3D オブジェクトの検出をサポートしているか示すフラグを取得する。
オブジェクト検出を有効にするには、detectObjects プロパティに ARReferenceObject インスタンスを指定する。

 

var detectionObjects: Set { get set }

現実環境で物体認識から検出する 3D オブジェクトのセット。
このプロパティを使用して、設定している 3D オブジェクトを選択、 ユーザーの現実環境で指定したオブジェクト検索し、ARObjectAnchor として AR で使用できるようにする。

画像認識と同じように Xcode のアセットカタログで参照オブジェクトの .arobject ファイルを設定してこの命令で設定する。

 

var environmentTexturing: ARWorldTrackingConfiguration.EnvironmentTexturing { get set }

環境マップテクスチャを生成するために使用する。

シーン内の特定のポイントからのすべての方向のビューを示すキューブマップテクスチャを生成し、Physically Based Rendering を使用したリアルっぽいマテリアルの反射や照明を実現する。

ARWorldTrackingConfiguration.EnvironmentTexturing のプロパティを none から変更すると使用でき、
manual を設定すると AREnvironmentProbeAnchor を作成してセッションに追加することで任意の場所から環境マップテクスチャを作成、
automatic では ARKitはAREnvironmentProbeAnchor オブジェクトを自動的に作成し配置する。

いずれの場合も、セッションがカメラの画像を収集すると自動的に環境マップテクスチャを生成する。

session(_:didUpdate :) などのデリゲートメソッドを使用して、テクスチャがいつ利用可能かを調べ、アンカーのenvironmentTexture プロパティからアクセスをする。

ARSCNView と automaticUpdatesLighting オプションを使用してARコンテンツを表示すると、SceneKit はAREnvironmentProbeAnchor テクスチャマップを自動的に取得しシーンを照らす。

 

ARWorldTrackingConfiguration.EnvironmentTexturing

ワールドトラッキングARセッションで環境テクスチャを生成するオプション。

 

追加

オプション名 説明
none 環境マップテクスチャを生成しない
manual セッションで追加するプローブアンカーに対してのみ環境マップテクスチャを生成する
automatic 環境マップテクスチャをいつ、どこで生成するか自動的に決定する

 

AREnvironmentProbeAnchor

ワールドトラッキングで環境照明情報である環境プローブアンカーのオブジェクト。 これを元に環境マップテクスチャが生成される。

セッションでこのテクスチャマップ生成を有効にするには、上記の environmentTexturing プロパティを設定する必要がある。

  

追加

init(transform: simd_float4x4, extent: simd_float3)
init(name: String, transform: simd_float4x4, extent: simd_float3)

新しい環境プローブアンカーを作成する

name はアンカーの識別用、
transform はこのアンカーを空間に配置するためのワールド座標、
extent は視差補正が考慮されたリフレクションのテクスチャ(Parallax-Corrected Cubemap)を投影するときに使用するアンカーの位置周辺の領域。

 

var environmentTexture: MTLTexture?

プローブアンカーの位置からすべての方向のビューを表すキューブマップテクスチャ。

 

var extent: simd_float3

init で設定しているものと同じもので、
視差補正が考慮されたリフレクションのテクスチャ(Parallax-Corrected Cubemap)を投影するときに使用するアンカーの位置周辺の領域.

マテリアルが反射するオブジェクトをレンダリングするには、アンカーの位置を中心とするプロキシジオメトリに環境マップテクスチャを投影し、投影テクスチャからサンプリングする必要がある。 テクスチャがグローバルライティングとして使用されることを示す無限の範囲、またはテクスチャがシーンの特定の領域におけるローカルライティングの条件を示す有限の範囲を設定する。

 

ARWorldMap

空間マッピングをしたワールドマップのセッション状態は、ユーザがデバイスを移動する物理的な空間と、 セッションに追加された ARAnchor オブジェクトのアンカーの集まりを持つ。

ワールドマップを保存し、それらを使って新しいセッションを開始することで、複数ユーザーで空間を共有する Multiuser AR experiences と保存した空間を復元する Persistent AR experiences を使用することができる。

 

追加

var anchors: [ARAnchor]

ワールドマップに記録されたアンカーの集まり。

この配列は、ワールドマップキャプチャ時のセッション内のサブクラスを含む ARAnchor オブジェクトのスナップショット。
ワールドマップを作成すると、その環境で静的であると見なされるすべてのアンカーが自動的に格納される。 そのため、ARTrackable に適合しているものは省かれてしまうので注意。

ワールドマップを作成後、マップを保存または共有する前にこの配列からアンカーを追加・削除したりすることが可能。 ワールドマップの共有や復元時に不必要なアンカーの削除などができる。

 

var center: simd_float3

ワールドマップがセッションで記録された際のワールド座標の原点に対するマッピングデータの中心点。
extent のプロパティとともにワールドマップに記録されたデータの bounding box を定義する。

 

var extent: simd_float3

ワールドマップがセッションで記録された際のワールド座標原点に対する空間マッピングデータの大きさ(広さ)。
center のプロパティとともにワールドマップに記録されたデータの bounding box を定義する。

 

var rawFeaturePoints: ARPointCloud

ARFrame の rawFeaturePoints と同様に、ワールドマップに記録された空間マッピングデータの特徴点を表す。

セッション中にカメラの視野にあった実世界のオブジェクトの大まかな輪郭をポイントクラウドで視覚化し表示するため、 ワールドマップの記録をデバッグや、サイズを調べて空間取得の品質を調べることができる。

ソフトウェアリリース間で未処理の特徴点の数や配置などの安定は保証されないらしいので注意。 多分、OS やアプリが同じバーションで使用することが望まれるということだと思われる。

 

ARReferenceObject

現実世界で認識させる 3D のオブジェクト

物体検出により、セッションが設定されている 3D オブジェクトを認識したときに、トリガーとして任意の AR コンテンツのインタラクションを起こすことができる。 たとえば、美術館の彫刻を検出して仮想キュレーターを提供したり、ボードゲームの人物を検出したり、ゲームの視覚効果をつくり出すことができる。

 

追加

init(archiveURL url: URL) throws

指定されたファイルの URL から参照オブジェクトをロードする。

url はロードする参照オブジェクトを含むローカルファイルの URL。
throws から NSError オブジェクトへのポインタである error が返され、nil の場合エラーをチェックする。

参照オブジェクトを返し、ワールドトラッキングでの検出で使用するには、detectObjects に追加する。

 

class func referenceObjects(inGroupNamed: String, bundle: Bundle?) -> Set?

Xcodeプロジェクトのアセットカタログにあるすべての参照オブジェクトを指定した AR リソースグループへ読み込む。

name は Xcode プロジェクトのアセットカタログにある AR リソースグループ名、
bundle アセットカタログのリソースを読み込むバンドル。アプリのメインバンドルを使用する場合は nil。

init と同様にワールドトラッキングで使用するには detectObjects に追加する。

 

var name: String?

参照オブジェクト用の名前。

Xcodeアセットカタログから参照オブジェクトをロードする際に必要な名前です。 extractReferenceObject を使用してセッションで記録したオブジェクトに名前を割り当てることもできる。

 

var center: simd_float3
var extent: simd_float3

参照オブジェクトの空間マッピングデータの中心点と大きさ

extent と center プロパティは、ローカル座標で参照オブジェクトに記録されたデータのバウンディングボックスを定義する。 extractReferenceObject(transform:center:extent :)を呼び出すときに、transform パラメータを使用してその座標系を定義し、 applyTransform(_ :)を使用して別の参照オブジェクトを作成して座標を変更することもできる。

 

var scale: simd_float3

参照オブジェクトが定義するローカル座標空間での倍率。

extent にこの scale を掛ければ、オブジェクトの物理サイズがメートル単位になる。(らしい? 翻訳あっているか不安)

 

func export(to: URL, previewImage: UIImage?)

指定されたファイル URL でオブジェクトをバイナリファイルとして書き出す。

url は参照オブジェクトデータを書き込む URL、
previewImage は参照オブジェクトのファイル(.arobject)に埋め込まれるサムネイルイメージ。

ARKit 自体はファイルのサムネールを使用することはないが、Xcode、Finder、QuickLook などで視覚的にわかりやすいようにするため設定する。

通常のファイル操作と同様に、成功した場合は true。false の場合は、error パラメータがくる。

 

class let archiveExtension: String

書き出す ARReferenceObject インスタンスのファイルの拡張子。
export(to:previewImage :)メソッドで書き出す際、この拡張子を使用する。

 

func applyingTransform(simd_float4x4) -> ARReferenceObject

参照オブジェクトにここで指定した座標変換を適用すると新しい参照オブジェクトを返す。
transform は参照オブジェクトのローカル座標空間の変換行列で変換された参照オブジェクトが返る。

 

var rawFeaturePoints: ARPointCloud

ARFrame や ARWorldMap と同様なため割愛。

 

ARObjectAnchor

追加

var referenceObject: ARReferenceObject

オブジェクトアンカーによって参照され検出されたオブジェクト。
セッションの構成時に detectObjects 配列で指定した ARReferenceObject オブジェクト。

 

ARObjectScanningConfiguration

背面カメラから現実空間の物体を 3D オブジェクトとしてスキャンするための構成の設定。

こちらを使用してセッションを実行すると、オブジェクトスキャンに必要なデータの収集が可能になる。
この構成のセッションでオブジェクトをスキャンした後、createReferenceObject を呼び出し、セッションの内部空間マッピングデータの領域をスキャン。それを参照オブジェクトを使用することができる。

 

Apple 先生からのありがたき警告文

ARObjectScanningConfiguration は開発のシナリオでのみ使用される。
再現性の高い空間マッピングはパフォーマンスとエネルギーコストが高く、参照オブジェクトのスキャンに必要のない ARKit 機能を無効する必要があるため。
エンドユーザー側での AR は、ARWorldTrackingConfiguration を使用すべし。

 

追加

init()

新しいオブジェクトスキャン構成(コンフィグレーション)の初期化。
AR セッションでこの構成を使用するには、ARSession の run(_: options:) メソッドに渡す。

 

var planeDetection: ARWorldTrackingConfiguration.PlaneDetection { get set }

カメラでキャプチャされたイメージの平面をセッションが自動的に検出するかどうかとその方法を指定する。

デフォルトでは平面検出はオフ。 水平または垂直の平面検出を有効にすると、セッションでは ARPlaneAnchor オブジェクトが追加され、キャプチャされたビデオ画像の解析によって平面に見える領域が検出されると、ARSessionDelegate、ARSCNViewDelegate、または ARSKViewDelegateオブジェクトに通知される。
オブジェクトスキャンセッションでは、検出された平面を使用して、スキャンされたオブジェクトの原点(アンカーポイント)がその範囲に比例する場所を特定するのに役立つ。

 

var isAutoFocusEnabled: Bool { get set }

デバイスカメラのオートフォーカス有効にするか決める。
オートフォーカスはデフォルトで有効。

 

ARHitTestResult

変更

var worldTransform: simd_float4x4 { get }
var localTransform: simd_float4x4 { get }

共に、返り値を matrix_float4x4 から simd_float4x4 に変更

 

ARAnchor

変更

  • init(transform: simd_float4x4)
  • var transform: simd_float4x4 { get }

引数を matrix_float4x4 から simd_float4x4 に変更

 

追加

init(name: String, transform: simd_float4x4)

新規のアンカーオブジェクトで名前をつけて初期化できるようになったもの

 

var name: String? { get }

アンカー識別用の名前。

 

ARFrame

追加

var worldMappingStatus: ARFrame.WorldMappingStatus

このフレームのワールドマップを生成状態、または再生成などのステータスを提示する。

すべてのワールドトラッキングセッションは、ユーザー環境でデバイスの位置を決定するために使用する内部のワールドマップを構築する。   その内部状態のスナップショットを ARWorldMap オブジェクトとして保存し、後で保存したセッションを再開したり、デバイス間で共有してすることができる。

セッション中にいつでも getCurrentWorldMap (completionHandler:) を呼び出すことができるが、
このプロパティを使用して、セッションが現在有用な ARWorldMap を生成するのに十分なデータを持っているかどうかを判断したり、
ユーザーへ空間のマッピングの作業を促す。

 

ARFrame.WorldMappingStatus

指定したフレームで表示されている領域のマッピング状態を表す値。

名称 状態
notAvailable ワールドマップがない状態
limited 周辺の領域はまだ完全にマッピングされていない
extending 訪れた区域をマップしたが、周囲でマッピングさせていない場所がある
mapped 可視領域を適切にマッピングしている

 

追加

ARFrame.WorldMappingStatus.notAvailable

セッションの currentFrame の worldMappingStatus が notAvailable である場合、 デバイス周囲の現実世界の空間の内部マップにもカメラにも見えるシーンがない。 この時点で getCurrentWorldMap(completionHandler :)を呼び出すとエラーが発生する。

このステータスは新しいセッションの開始直後に発生する。 ワールドマップを保存または共有するにはユーザーが周囲の探索し、 アプリ側でセッションの状態を調べて mapped や extending に変更されるまで待つ。

 

ARFrame.WorldMappingStatus.limited

セッションの currentFrame の worldMappingStatus が limited である場合、 デバイス周囲の現実空間もカメラから見えるシーンもまだ完全にマッピングされていない。

現時点で、getCurrentWorldMap(completionHandler :)を呼び出してワールドマップを保存することは可能だが、 得られる ARWorldMap は、デバイスの位置付近の現実空間での再現にはあまり役に立たない。

より高品質の世ワールドマップを作成するには、ユーザーが周囲の探索し、セッションのステータスが mapped や ARFrame.WorldMappingStatus.extendingに変更するまで待つ。

 

ARFrame.WorldMappingStatus.extending

セッションの currentFrame の worldMappingStatus が extending である場合、 デバイスが最近通過した現実空間の高精度な内部マップを生成したが、 デバイスの周囲の領域をマップするためのデータを収集している。

この状態は保存されたワールドマップの再生成の質は中から高。

  • currentFrameのステータスがARFrame.WorldMappingStatus.extendingである間にgetCurrentWorldMap(completionHandler :)を呼び出してワールドマップを保存します。
  • ARWorldMapから新しいセッション(後でまたは別のデバイス)を実行すると、新しいセッションを実行するデバイスは、セッションを保存したデバイスが訪問した位置と向きを通過します。

現時点でワールドマップの保存または共有は適切な結果が得られる可能性があるが、 ユーザーがより多くの環境を探索して mapped のセッションにステータスが変わるまで待つと、 より高品質なワールドマップが再現できる可能性がある。

 

ARFrame.WorldMappingStatus.mapped

セッションの currentFrame の worldMappingStatus が mapped の場合、 デバイスの現在の位置やカメラから見えるシーンの現実空間で高精度な内部マップを生成されたことを表す。 この状態は、保存されたワールドマップで再生成する際に最高の信頼性を表す。

  • currentFrame のステータスが mapped である間に getCurrentWorldMap を呼び出してワールドマップを保存する。
  • その ARWorldMap から新しいセッションや別のデバイスで実行すると、新しいセッションを実行するデバイスは、ワールドマップが保存されたときと同じような現実の位置や向きを復元する。

 

ARCamera

追加

func unprojectPoint(_ point: CGPoint, ontoPlane planeTransform: simd_float4x4, orientation: UIInterfaceOrientation, viewportSize: CGSize) -> simd_float3?

ドキュメント上での説明なし。

ARSCNView の func unprojectPoint(_ point: CGPoint, ontoPlane planeTransform: simd_float4x4) -> simd_float3? に端末の傾きと画面の大きさをつけたものだと思われる。

 

変更

  • var eulerAngles: simd_float3 { get }

返り値を vector_float3 から simd_float3 に変更

 

  • var intrinsics: simd_float3x3 { get }

返り値を matrix_float3x3 から simd_float3x3 に変更

 

  • var transform: simd_float4x4 { get }
  • var projectionMatrix: simd_float4x4 { get }
  • func projectionMatrix(for orientation: UIInterfaceOrientation, viewportSize: CGSize, zNear: CGFloat, zFar: CGFloat) -> simd_float4x4
  • func viewMatrix(for: UIInterfaceOrientation) -> simd_float4x4

返り値を matrix_float4x4 から simd_float4x4 に変更

 

  • func projectPoint(_ point: simd_float3, orientation: UIInterfaceOrientation, viewportSize: CGSize) -> CGPoint

引数を vector_float3 から simd_float3 に変更

 

ARFaceAnchor

TrueDepth カメラを使用した顔認識

 

追加

leftEyeTransform: simd_float4x4

顔の左目の位置と向きを示す変換行列。

顔のアンカーに対しての眼球の中心の位置を示す。 +Z 軸は、眼球の中心から瞳孔の方向に向いている。 回転は眼球の向きを示し、X 軸の回転は瞳孔の上下で、Z軸は回転しない。

 

var rightEyeTransform: simd_float4x4

顔の右目の位置と向きを示す変換行列。
左目と同じなので割愛。

 

var lookAtPoint: simd_float3

視線の方向を推定する。

このベクトルは leftEyeTransform と rightEyeTransform 行列から抽象化して、 ユーザの目がどこに集中しているかを推定する。

  • ユーザーが左を見ている場合、ベクトルは正の X 軸成分を持ちます。
  • ユーザーが近くのオブジェクトに集中している場合はベクトルの長さは短くなる。
  • ユーザーが離れたオブジェクトに集中している場合はベクトルの長さは長くなる。

 

BlendShapeLocation

追加

static let tongueOut: ARFaceAnchor.BlendShapeLocation

舌の伸展を表す係数

0.0 の値は舌が完全に口の中にあることを示し、
1.0 の値は舌が口から遠くにあることを示す。

ちなみに、今回は使用できないが iOS 11 の復元ファイルのアニ文字に、上下左右など舌の動きのブレンドシェイプが用意されている。

 

ARDirectionalLightEstimate

変更

var primaryLightDirection: simd_float3 { get }

返り値を vector_float3 から simd_float3 に変更

 

ARImageTrackingConfiguration

追加

init()

イメージトラッキング設定の初期化をする。
セッションでこの設定を使用するには、ARSession の run(_:options :) メソッドに渡す。

 

var trackingImages: Set { get set }

現実世界で検出やトラッキングするイメージのセット

Xcode のアセットカタログや ARReferenceImageクラスを使用して設定した 2D 画像を現実世界で検索し、ARImageAnchor として AR で使用する。

 

var maximumNumberOfTrackedImages: Int { get set }

ARWorldTrackingConfiguration のものと同様にトラッキングできる画像の最大数。

 

var isAutoFocusEnabled: Bool { get set }

他の isAutoFocusEnabled 同様、オートフォーカスの使用するかの設定。

 

 

まとめ

ワールドマップの保存、共有や画像やオブジェクトのトラッキングができるようになり、AR として必要な機能はある程度揃った。
もうそろそろ AR グラスなどのハードを出してくれる頃合いだと思っている。

 

 

変更不明なやつ。

  • ARSession > init(rawValue:)
  • ARSession > ARSession > ARSessionObserver > ARError.Code > unsupportedConfiguration
  • ARSession > ARSession > ARSessionObserver > ARError.Code > sensorUnavailable
  • ARSession > ARSession > ARSessionObserver > ARError.Code > sensorFailed
  • ARSession > ARSession > ARSessionObserver > ARError.Code > worldTrackingFailed
  • ARSession > ARSession > ARSessionObserver > ARError.Code > cameraUnauthorized
  • ARSession > ARSession > ARSessionObserver > ARError.Code > invalidReferenceImage
  • ARSession > ARSession > ARSessionObserver > ARError > var errorCode: Int
  • ARSession > ARSession > ARSessionObserver > ARError > var errorUserInfo: [String : Any]
  • ARSession > ARSession > ARSessionObserver > ARError > var localizedDescription: String
  • ARSession > ARSession > ARSessionObserver > ARError > static var cameraUnauthorized: ARError.Code
  • ARSession > ARSession > ARSessionObserver > ARError > static var errorDomain: String
  • ARSession > ARSession > ARSessionObserver > ARError > static var invalidReferenceImage: ARError.Code
  • ARSession > ARSession > ARSessionObserver > ARError > static var sensorFailed: ARError.Code
  • ARSession > ARSession > ARSessionObserver > ARError > static var sensorUnavailable: ARError.Code
  • ARSession > ARSession > ARSessionObserver > ARError > static var unsupportedConfiguration: ARError.Code
  • ARSession > ARSession > ARSessionObserver > ARError > static var worldTrackingFailed: ARError.Code
  • ARSession > ARSession > ARSessionObserver > ARError > static func != (lhs: ARError, rhs: ARError) -> Bool
  • ARConfiguration.WorldAlignment.gravity
  • ARConfiguration.WorldAlignment.gravityAndHeading
  • ARConfiguration.WorldAlignment.camera
  • ARSCNView > ARSCNDebugOptions > init()
  • ARPlaneGeometry > var vertices: [vector_float3]
  • ARPlaneGeometry > var textureCoordinates: [vector_float2]
  • ARPlaneGeometry > var triangleCount: Int
  • ARPlaneGeometry > var triangleIndices: [Int16]
  • ARPlaneGeometry > var boundaryVertices: [vector_float3]
  • ARHitTestResult > ARHitTestResult.ResultType > init(rawValue: UInt)
  • ARPointCloud > var points: [vector_float3] { get }
  • ARPointCloud > var identifiers: [UInt64] { get }
  • ARCamera > TrackingState > notAvailable
  • ARCamera > TrackingState > limited(ARCamera.TrackingState.Reason)
  • ARCamera > TrackingState > ARCamera.TrackingState.Reason
  • ARCamera > TrackingState > normal
  • ARFaceAnchor > ARFaceGeometry > var vertices: [vector_float3]
  • ARFaceAnchor > ARFaceGeometry > var textureCoordinates: [vector_float2]
  • ARFaceAnchor > ARFaceGeometry > var triangleIndices: [Int16]
  • ARFaceAnchor > ARFaceGeometry > BlendShapeLocation > init(rawValue: String)