Постоянство данных AR в ARKit 1.0 в iOS - PullRequest
0 голосов
/ 12 октября 2018

ARKit 2.0 поддерживает постоянство данных AR с использованием карты мира.Я хочу добиться того же для следующих версий.Вот мой подход: размещение SCNNode после обнаружения вертикальной плоскости и добавление в нее локального массива.

Использование FireBase Realtime DB для хранения ARAnchor с уникальным идентификатором привязки.Затем я извлекаю ARAnchor из БД по нажатию кнопки перезагрузки.Найдите узел, соответствующий привязке с уникальным идентификатором, и добавьте его в качестве дочернего узла корневого узла сцены.Но это не работает, как ожидалось, как ARKit 2.0.Узел не размещает в точном месте, где он был последним.Ниже мой код:

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)
}

Любая помощь будет действительно оценена.

1 Ответ

0 голосов
/ 12 октября 2018

Это не очень хорошая идея.Нет доступа к World Map Data для разработчиков в ARKit 1.0 и ARKit 1.5 через инструменты Apple.Опции Persistence и Multiuser AR Experience доступны только в ARKit 2.0 для iOS 12 .

ARKit 2.0 содержит все необходимые классы, методыи свойства экземпляра для сохранения и получения точных данных карты мира.Он поддерживается не только приложениями в iOS 12, но и самой операционной системой.

Имеет ли смысл разрабатывать для iOS11 ?Вот список устройств, поддерживающих iOS12 (ARKit снижает совместимость с iPhone 6s и выше и iPad 2017 и выше):

enter image description here

Документация для разработчиков Apple о ARWorldMap классе.

Сохранение ARWorldMap в URL файла в iOS12 так просто:

func writeWorldMap(_ worldMap: ARWorldMap, to url: URL) throws {
    let data = try NSKeyedArchiver.archivedData(withRootObject: worldMap, requiringSecureCoding: true)
    try data.write(to: url)
}

Загрузка ARWorldMap изURL файла так же прост:

func loadWorldMap(from url: URL) throws -> ARWorldMap {
    let mapData = try Data(contentsOf: url)
    guard let worldMap = try NSKeyedUnarchiver.unarchivedObject(ofClass: ARWorldMap.self, from: mapData)
        else { throw ARError(.invalidWorldMap) }
    return worldMap
}
...