前提・実現したいこと
ARKitでARのオブジェクトを生成して、保存 => アプリ再起動後に生成していたARのオブジェクトを表示させたいのですが表示されません。
以下コードはタッチした場所に球体を表示し、savebuttonを押した後再起動し、loadbuttonを押すと元々表示していた位置に球体が表示されるコードです。問題点として、平面にオブジェクトを置いた時しか対応していません。hittestのtypeをexistingPlaneUsingExtentからfeaturePointにしても上手く動作しません。hittestで取得できる値がCGPointのためx,yの2値しか扱えないからでしょうか。
ARオブジェクトを表示、アプリの再起動後、ARオブジェクトを元の位置に復元したいです。平面の時だけではなく。
ご教授よろしくお願いします。
該当のソースコード
import UIKit import SceneKit import ARKit class ViewController: UIViewController, ARSCNViewDelegate { @IBOutlet var sceneView: ARSCNView! var worldMapURL: URL = { do { return try FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true).appendingPathComponent("worldMapURL") } catch { fatalError("No such file") } }() @IBAction func saveButtonPressed(_ sender: Any) { sceneView.session.getCurrentWorldMap { worldMap, error in guard let map = worldMap else { return } guard let data = try? NSKeyedArchiver.archivedData(withRootObject: map, requiringSecureCoding: true) else { return } guard ((try? data.write(to: self.worldMapURL)) != nil) else { return } } } @IBAction func loadButtonPressed(_ sender: Any) { var data: Data? = nil do { try data = Data(contentsOf: self.worldMapURL) } catch { return } guard let worldMap = try? NSKeyedUnarchiver.unarchivedObject(ofClass: ARWorldMap.self, from: data!) else { return } let configuration = ARWorldTrackingConfiguration() configuration.planeDetection = .horizontal configuration.initialWorldMap = worldMap sceneView.session.run(configuration, options: [.resetTracking, .removeExistingAnchors]) } override func viewDidLoad() { super.viewDidLoad() sceneView.delegate = self //ARSCNViewデリゲートの指定 sceneView.scene = SCNScene() //シーンの作成 sceneView.debugOptions = [ARSCNDebugOptions.showFeaturePoints] //特徴点の表示 sceneView.autoenablesDefaultLighting = true //光源の有効化 //https://note.com/npaka/n/n77e2d49bfea5 let configuration = ARWorldTrackingConfiguration() //コンフィギュレーションの生成 configuration.planeDetection = .horizontal sceneView.session.run(configuration) } override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) { guard let touch = touches.first else {return} // スクリーン座標に変換する let touchPos = touch.location(in: sceneView) // タップされた位置のARアンカーを探す let hitTest = sceneView.hitTest(touchPos, types:.existingPlaneUsingExtent) if !hitTest.isEmpty { // タップした箇所が取得できていればanchorを追加 let anchor = ARAnchor(transform: hitTest.first!.worldTransform) sceneView.session.add(anchor: anchor) } } func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode,for anchor: ARAnchor) { guard !(anchor is ARPlaneAnchor) else { return } let sphereNode = SCNNode() sphereNode.geometry = SCNSphere(radius: 0.05) sphereNode.position.y += Float(0.05) //let scene = SCNScene(named: "art.scnassets/ship.scn") // シーンからノードを検索 //let rabbitNode = (scene?.rootNode.childNode(withName: "ship",recursively: false))! // 検出面の子要素にする node.addChildNode(sphereNode) } }
あなたの回答
tips
プレビュー