ARKit 2.0 has AR data persistence using World Map. I want to achieve the same for below versions. Here's my approach: placing SCNNode after detecting vertical plane and adding to it local array.
Using FireBase Realtime DB
to store ARAnchor with unique anchor ID.
Next I'm retrieving ARAnchor from DB on tap of reload button. Find node corresponding to anchor with unique ID and adding it as child of scene root node. But this doesn't work as expected like ARKit 2.0. Node doesn't place at exact location it was last. Below is my code:
guard let node = self.selectedNode else { return }
guard let data = try? NSKeyedArchiver.archivedData(withRootObject: node.anchor!, requiringSecureCoding: false) else { print("Could not archeive" )
return
}
let string = data.base64EncodedString()
self.saveData(dataString: string, forKey: node.name!)
func saveData(dataString : String, forKey : String) {
db.collection("roomdecorateDB").document(forKey).setData([
"anchor": dataString]) { err in
if let err = err {
print("Error writing document: \(err)")
} else {
print("Document successfully written!")
}
}
}
func reloadData() {
guard let cloudAnchor = try? NSKeyedUnarchiver.unarchivedObject(ofClass: ARAnchor.self, from: data) else { return print("Could not decode") }
print("world map \(cloudAnchor!)")
// Run the session with the received world map.
let configuration = self.standardConfiguration
self.sceneView.session.run(configuration, options: [.resetTracking, .removeExistingAnchors])
self.sceneView.session.add(anchor: cloudAnchor!)
// document id is the name of node, we can find node from node array and place to scene view
guard let node = self.nodeArray.first(where: {$0.name == document.documentID})else {continue}
node.position = SCNVector3((cloudAnchor?.transform.columns.3.x)!, (cloudAnchor?.transform.columns.3.y)!, (cloudAnchor?.transform.columns.3.z)!)
self.sceneView.scene.rootNode.addChildNode(node)
}
Any help would be really appreaciated.