はじめに
@shu223さんの記事を参考に、
補足という形にはなりますが、調べた範囲でまとめたいと思います。
また、NDAがありますので、スクショは貼りません。
ARKit2
今回発表されたARKit2では、大きく6つのアップデートがありました。
Improved face tracking
舌判定の追加。何に使うんでしょうね(白目)
Image detaction and tracking
画像の検出とトラッキング。これは1.5からの内容ですね。
3D object detection
3D物体の検出
オブジェクトに画像など重ねて貼り付けたりする事ができます。
Persistent experiences
継続。一度オブジェクトを配置して、移動させたりしても、次からまた同じ状態からスタートできる
Shared experiences
AR空間の共有。同時に複数人で同じAR空間を見る事ができます。発表された内容では対戦ゲームができます。(現地でやりましたがかなり楽しいです)
今回はこのShared experiencesで主に使われる、ARWorldMapについて調べてみました
ARWorldMap
ARKitは、現実空間におけるユーザーのデバイスの位置を特定するために使用するすべての空間マッピング情報が含まれています。
また、マッピングのデータなど確認する事ができます。
//世界地図に記録された空間マッピングデータの粗い表現。
var rawFeaturePoints: ARPointCloud
精度は分かりませんが、点群データを取得できればARだけでなく、深度推定などにも応用できそうですね。
このWorldMapをキャプチャするには、あらかじめ空間を認識しておく必要があるみたく、今どのくらい取得するのに適した状態かステータスを確認する事ができます
ARFrame.WorldMappingStatus
ARKitのフレームがどの程度マッピングを行なっているかの状態
取得方法
func session(_ session: ARSession, didUpdate frame: ARFrame) {
// frame.worldMappingStatus
}
WorldMappingStatus
notAvailable
WorldMapがまだ利用できない状態
セッションはカメラから見えるデバイスの周りの現実空間のない内部マップ、またシーンを持っていません。
このときに呼び出すと、エラーが発生してしまうので、利用させないような工夫が必要です。
limited
WorldTrackingを行うには、現在のデバイス位置の周辺の領域をまだ十分にマッピングしていない状態。
一応この状態でも保存はできますが、読み込み時に位置がずれたりする場合があります。
この状態で保存するのは好ましくないので、もう少し認識させる必要があります。
extending
WorldTrackingは現在のデバイスの位置をマッピングしている状態。
デバイスの位置とそこから見えるシーンをマッピングするためのデータを取得できる状態です。
この状態から保存をしても問題なく利用できるとのことです。
mapped
この状態であれば問題なくマッピングが高品質な状態で保存できるはずです。
ここから新たに別のデバイスやセッションで読み込みを行うことで、保存したWorldMapのような
位置や状態が再度読み込めれるはずです。
では早速WorldMapの取得方法を見てみましょう
getCurrentWorldMap(completionHandler:)
実行中のARSessionからWorldTrackingセッションの空間マッピング状態とアンカーのセットをカプセル化したオブジェクトを取得します
取得に失敗した際はnilが返ってきます。安心ですね。
このオブジェクトには、
ARKitがデバイスを移動する物理空間(ARKitがデバイスの位置と向きを決定するために使用する)と、
セッションに追加されたオブジェクト(検出された実際の機能や配置された仮想コンテンツ)の情報が入っています。
再読み込み
if let unarchived = try? NSKeyedUnarchiver.unarchivedObject(of: ARWorldMap.classForKeyedUnarchiver(), from: data),
let worldMap = unarchived as? ARWorldMap {
// Run the session with the received world map.
let configuration = ARWorldTrackingConfiguration()
configuration.planeDetection = .horizontal
// 読み込んだWorldMapをセット
configuration.initialWorldMap = worldMap
sceneView.session.run(configuration, options: [.resetTracking, .removeExistingAnchors])
}
サンプルでは、NSKeyedUnarchiverを使用して保存・読み込みを行なっています。
読み込みの前に、
1.ワールドマップを共有する前に、送信デバイス上のローカルの空間を認識させておく
2.受信側と送信側のデバイスを隣接さセルこと(両方が同じ環境のビューになるようになります)
最後に
こちらの内容は公開されておりますが、変更がある可能性があります。
また、間違いなどありましたらコメントをよろしくお願いします。