はじめに
はじめまして、drama(@1901drama)です!
ARを勉強するにあたり日本語ドキュメントが少なくて苦戦したので、
誰かの助けになれば...と思い、Qiitaデビューしました。少しでもARが普及すると嬉しいです。
※記載間違い等あれば教えてください。
ARkit 2.0の発表
もう5ヶ月程前ですが、2018/9にARKit2.0(iOS12)がリリースされましたね。
https://www.moguravr.com/arkit-2-0/
~追加された機能達~
・ARのマルチプレイが可能に
・ARオブジェクトの再利用が可能に
・イメージ認識やトラッキングサポートが拡大
・AR向けフォーマット「USDZ」に対応 など
つまり、AR体験を
・他人と同時に見れる(共有出来る)
・過去の情報を再現出来る
・専用アプリ以外(safariや他のデバイス)でも見れる ということに。
以前unityでARをやってたときよりも、めちゃくちゃ出来ることが増えていて驚きです。
これはもう電脳コイルのようなAR時代も近いのではないか!!? と思い ARを始めました。
今回はAR開発を初めて 一つ目に作ったものを紹介します。
出来たもの
グラフィティーアートをどこでも出来れば楽しそう!という考えから、ARでラクガキするSNSを作りました。
3Dオブジェクトを置いたり描いたり、つくったものを共有/評価 出来ます。
GRAF その1 pic.twitter.com/iePHYO43D3
— drama (@1901drama) 2019年2月13日
・置いたり、書いたり
・共有したり、評価したり、上書きしたりGRAF その2 pic.twitter.com/vJk1tVdYmN
— drama (@1901drama) 2019年2月13日
手こずった点は山ほどある...のですが、 一先ず、このアプリの肝であるAR共有機能についてのみ解説します。GRAF その3 pic.twitter.com/CEC5LkmKWG
— drama (@1901drama) 2019年2月13日
ARの共有方法
ARKitのARWorldMapを使っています。
https://developer.apple.com/documentation/arkit/arworldmap
ARWorldMapには、物理的な空間情報と空間の特徴点を記録したARanchorが含まれています。
ざっくりいうと、ARworldMap≒取得した空間内の位置情報群 と思って頂ければいいです。
このARWorldMapを利用し下図のような形で、空間情報の共有を実装しました。
・作成ユーザーを識別する為に、Authenticationを利用。
・空間情報(ARWorldMap)とオブジェクトの情報はサイズが大きいのでCloudStorageを利用。
・その他の情報は、Firestoreを利用。
※図のRealtime DBは、Firestoreに変更しました。
【処理の順番】
1.空間に置いたり描いたりしたオブジェクトと、空間情報(ARWorldMap)を紐づけて表示させます。
//空間にオブジェクトを置く時の処理
//SCNodeを作成し名前をつける。(細かい設定等は省略します)
let testNode= SCNNode()
testNode.name = "testNode"
//アンカーにSCNNodeと同じ名前をつけて、タッチした場所(空間)に追加する。
let Anchor = ARAnchor(name: "testNode", transform: hitTestResult.worldTransform)
sceneView.session.add(anchor: Anchor)
self.testNodes.append(testNode)
//空間にanchorが追加された時の処理
func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) {
//anchorと同じ名前のSCNNodeを空間に追加する。
for testNode in testNodes{
if anchor.name == testNode.name {
sceneView.scene.rootNode.addChildNode(testNode)
}
}
}
2.空間情報(ARworldMap)と 置いたり描いたりしたオブジェクトの情報を アーカイブし、共有したい人がアップロードします。
//Apple公式
func writeWorldMap(_ worldMap: ARWorldMap, to url: URL) throws {
let data = try NSKeyedArchiver.archivedData(withRootObject: worldMap, requiringSecureCoding: true) try data.write(to: url)
}
//①ARachor(ARworldMap)を取得→②ARachor(ARworldMap)をアーカイブ(シリアライズ)してdata化 →③dataをURLにアップロードの流れ
//アプリ内に記載したコード
func dataExport(){
//AR_DATA(ARworldMap) Export
self.sceneView.session.getCurrentWorldMap { (worldMap, error) in
guard let worldMap = worldMap else { print("Error getting current world map."); return }
do {
self.ar_data = try NSKeyedArchiver.archivedData(withRootObject: worldMap, requiringSecureCoding: true)
} catch let error as NSError { print("failed to write: \(error)")}
}
//OBJECT_DATA(オブジェクト) Export
let objectData = self.testNodes
do {
self.object_data = try NSKeyedArchiver.archivedData(withRootObject: objectData, requiringSecureCoding: true)
} catch let error as NSError { print("failed to write: \(error)") }
}
//この後 FirebaseのFirestoreにアップロードしてます。
3.最後に、共有されたい人がインポートすることで、空間を再現します。
//Apple公式
func loadWorldMap(from url: URL) -> ARWorldMap throws {
let mapData = try Data(contentsOf: mapURL) guard let worldMap = try NSKeyedUnarchiver.unarchivedObject(of: ARWorldMap.classForKeyedUnarchiver(), from: mapData) as? ARWorldMap else { throw ARError.invalidWorldMap } return worldMap
}
//④dataをURLからダウンロード→⑤dataをアンアーカイブ(デシリアライズ)してARachor(ARworldMap)化→⑥現在の環境にARachor(ARworldMap)を反映
//アプリ内に記載したコード
//この前に FirebaseのFirestoreからダウンロードしてます。(downloadsPath_AR_DATA,downloadsPath_OBJECT_DATA)
func dataImport(){
//OBJECT_DATA(オブジェクト) Import
let unarchievedOBJECT_DATA = try? NSKeyedUnarchiver.unarchiveObject(with:Data(contentsOf:downloadsPath_OBJECT_DATA))
guard let downloadtestNodes:[SCNNode] = unarchievedOBJECT_DATA as? [SCNNode] else { return }
for testNode in downloadtestNodes {
self.testNodes.append(testNode)
}
//AR_DATA(ARworldMap) Import
let unarchievedAR_DATA = try? NSKeyedUnarchiver.unarchiveObject(with:Data(contentsOf:downloadsPath_AR_DATA))
guard let newWorldMap = unarchievedAR_DATA as? ARWorldMap else {return}
//downloadしたARWorldMapを反映
self.configuration.initialWorldMap = newWorldMap
self.sceneView.session.run(self.configuration)
}
まとめ
AR開発は成果物が空間に目に見えて現れるのが面白いです。
普段はディレクションやサービス設計がメインなので、アプリ開発自体も楽しいです。
ここまで読んで頂きありがとうございました!
※今回のアプリは、ちゃんとしたキャラクターが完成すればリリースする予定です。