Persist object orientations in ARKit ARWorldMap












0















I'm trying to persist a model in ARKit using the ARWorldMap. I can save and load the models, but the orientation I apply to the objects before I save is not persisted with the object.



What I'm currently doing



Objects are saved and loaded:



  /// - Tag: GetWorldMap
@objc func saveExperience(_ button: UIButton) {
sceneView.session.getCurrentWorldMap { worldMap, error in
guard let map = worldMap
else { self.showAlert(title: "Can't get current world map", message: error!.localizedDescription); return }

// Add a snapshot image indicating where the map was captured.
guard let snapshotAnchor = SnapshotAnchor(capturing: self.sceneView) else {
fatalError("Can't take snapshot")

}
map.anchors.append(snapshotAnchor)

do {
let data = try NSKeyedArchiver.archivedData(withRootObject: map, requiringSecureCoding: true)
try data.write(to: self.mapSaveURL, options: [.atomic])
DispatchQueue.main.async {
self.loadExperienceButton.isHidden = false
self.loadExperienceButton.isEnabled = true
}
} catch {
fatalError("Can't save map: (error.localizedDescription)")
}
}
}

/// - Tag: RunWithWorldMap
@objc func loadExperience(_ button: UIButton) {

/// - Tag: ReadWorldMap
let worldMap: ARWorldMap = {
guard let data = mapDataFromFile
else { fatalError("Map data should already be verified to exist before Load button is enabled.") }
do {
guard let worldMap = try NSKeyedUnarchiver.unarchivedObject(ofClass: ARWorldMap.self, from: data)
else { fatalError("No ARWorldMap in archive.") }
return worldMap
} catch {
fatalError("Can't unarchive ARWorldMap from file data: (error)")
}
}()

// Display the snapshot image stored in the world map to aid user in relocalizing.
if let snapshotData = worldMap.snapshotAnchor?.imageData,
let snapshot = UIImage(data: snapshotData) {
self.snapshotThumbnail.image = snapshot
} else {
print("No snapshot image in world map")
}
// Remove the snapshot anchor from the world map since we do not need it in the scene.
worldMap.anchors.removeAll(where: { $0 is SnapshotAnchor })

let configuration = self.defaultConfiguration // this app's standard world tracking settings
configuration.initialWorldMap = worldMap
sceneView.session.run(configuration, options: [.resetTracking, .removeExistingAnchors])

isRelocalizingMap = true
virtualObjectAnchor = nil
}


Rotation:



@objc func didRotate(_ gesture: UIRotationGestureRecognizer) {
sceneView.scene.rootNode.eulerAngles.y = objectRotation
gesture.rotation = 0
}


And then it's rendered:



  func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) {
guard anchor.name == virtualObjectAnchorName else {
return
}

// save the reference to the virtual object anchor when the anchor is added from relocalizing
if virtualObjectAnchor == nil {
virtualObjectAnchor = anchor
}
node.addChildNode(virtualObject)
}


How can I do this?



How can I go about doing this? I have tried multiple solutions, but the orientation is never kept. It loads the object at the correct position, but rotation and scaling is never kept, even if I apply it to the rootnode. The only option I can see is to also store the transform as a seperate data object, and load that and apply it. But seems like it should be possible to store this data with the object.










share|improve this question



























    0















    I'm trying to persist a model in ARKit using the ARWorldMap. I can save and load the models, but the orientation I apply to the objects before I save is not persisted with the object.



    What I'm currently doing



    Objects are saved and loaded:



      /// - Tag: GetWorldMap
    @objc func saveExperience(_ button: UIButton) {
    sceneView.session.getCurrentWorldMap { worldMap, error in
    guard let map = worldMap
    else { self.showAlert(title: "Can't get current world map", message: error!.localizedDescription); return }

    // Add a snapshot image indicating where the map was captured.
    guard let snapshotAnchor = SnapshotAnchor(capturing: self.sceneView) else {
    fatalError("Can't take snapshot")

    }
    map.anchors.append(snapshotAnchor)

    do {
    let data = try NSKeyedArchiver.archivedData(withRootObject: map, requiringSecureCoding: true)
    try data.write(to: self.mapSaveURL, options: [.atomic])
    DispatchQueue.main.async {
    self.loadExperienceButton.isHidden = false
    self.loadExperienceButton.isEnabled = true
    }
    } catch {
    fatalError("Can't save map: (error.localizedDescription)")
    }
    }
    }

    /// - Tag: RunWithWorldMap
    @objc func loadExperience(_ button: UIButton) {

    /// - Tag: ReadWorldMap
    let worldMap: ARWorldMap = {
    guard let data = mapDataFromFile
    else { fatalError("Map data should already be verified to exist before Load button is enabled.") }
    do {
    guard let worldMap = try NSKeyedUnarchiver.unarchivedObject(ofClass: ARWorldMap.self, from: data)
    else { fatalError("No ARWorldMap in archive.") }
    return worldMap
    } catch {
    fatalError("Can't unarchive ARWorldMap from file data: (error)")
    }
    }()

    // Display the snapshot image stored in the world map to aid user in relocalizing.
    if let snapshotData = worldMap.snapshotAnchor?.imageData,
    let snapshot = UIImage(data: snapshotData) {
    self.snapshotThumbnail.image = snapshot
    } else {
    print("No snapshot image in world map")
    }
    // Remove the snapshot anchor from the world map since we do not need it in the scene.
    worldMap.anchors.removeAll(where: { $0 is SnapshotAnchor })

    let configuration = self.defaultConfiguration // this app's standard world tracking settings
    configuration.initialWorldMap = worldMap
    sceneView.session.run(configuration, options: [.resetTracking, .removeExistingAnchors])

    isRelocalizingMap = true
    virtualObjectAnchor = nil
    }


    Rotation:



    @objc func didRotate(_ gesture: UIRotationGestureRecognizer) {
    sceneView.scene.rootNode.eulerAngles.y = objectRotation
    gesture.rotation = 0
    }


    And then it's rendered:



      func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) {
    guard anchor.name == virtualObjectAnchorName else {
    return
    }

    // save the reference to the virtual object anchor when the anchor is added from relocalizing
    if virtualObjectAnchor == nil {
    virtualObjectAnchor = anchor
    }
    node.addChildNode(virtualObject)
    }


    How can I do this?



    How can I go about doing this? I have tried multiple solutions, but the orientation is never kept. It loads the object at the correct position, but rotation and scaling is never kept, even if I apply it to the rootnode. The only option I can see is to also store the transform as a seperate data object, and load that and apply it. But seems like it should be possible to store this data with the object.










    share|improve this question

























      0












      0








      0


      1






      I'm trying to persist a model in ARKit using the ARWorldMap. I can save and load the models, but the orientation I apply to the objects before I save is not persisted with the object.



      What I'm currently doing



      Objects are saved and loaded:



        /// - Tag: GetWorldMap
      @objc func saveExperience(_ button: UIButton) {
      sceneView.session.getCurrentWorldMap { worldMap, error in
      guard let map = worldMap
      else { self.showAlert(title: "Can't get current world map", message: error!.localizedDescription); return }

      // Add a snapshot image indicating where the map was captured.
      guard let snapshotAnchor = SnapshotAnchor(capturing: self.sceneView) else {
      fatalError("Can't take snapshot")

      }
      map.anchors.append(snapshotAnchor)

      do {
      let data = try NSKeyedArchiver.archivedData(withRootObject: map, requiringSecureCoding: true)
      try data.write(to: self.mapSaveURL, options: [.atomic])
      DispatchQueue.main.async {
      self.loadExperienceButton.isHidden = false
      self.loadExperienceButton.isEnabled = true
      }
      } catch {
      fatalError("Can't save map: (error.localizedDescription)")
      }
      }
      }

      /// - Tag: RunWithWorldMap
      @objc func loadExperience(_ button: UIButton) {

      /// - Tag: ReadWorldMap
      let worldMap: ARWorldMap = {
      guard let data = mapDataFromFile
      else { fatalError("Map data should already be verified to exist before Load button is enabled.") }
      do {
      guard let worldMap = try NSKeyedUnarchiver.unarchivedObject(ofClass: ARWorldMap.self, from: data)
      else { fatalError("No ARWorldMap in archive.") }
      return worldMap
      } catch {
      fatalError("Can't unarchive ARWorldMap from file data: (error)")
      }
      }()

      // Display the snapshot image stored in the world map to aid user in relocalizing.
      if let snapshotData = worldMap.snapshotAnchor?.imageData,
      let snapshot = UIImage(data: snapshotData) {
      self.snapshotThumbnail.image = snapshot
      } else {
      print("No snapshot image in world map")
      }
      // Remove the snapshot anchor from the world map since we do not need it in the scene.
      worldMap.anchors.removeAll(where: { $0 is SnapshotAnchor })

      let configuration = self.defaultConfiguration // this app's standard world tracking settings
      configuration.initialWorldMap = worldMap
      sceneView.session.run(configuration, options: [.resetTracking, .removeExistingAnchors])

      isRelocalizingMap = true
      virtualObjectAnchor = nil
      }


      Rotation:



      @objc func didRotate(_ gesture: UIRotationGestureRecognizer) {
      sceneView.scene.rootNode.eulerAngles.y = objectRotation
      gesture.rotation = 0
      }


      And then it's rendered:



        func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) {
      guard anchor.name == virtualObjectAnchorName else {
      return
      }

      // save the reference to the virtual object anchor when the anchor is added from relocalizing
      if virtualObjectAnchor == nil {
      virtualObjectAnchor = anchor
      }
      node.addChildNode(virtualObject)
      }


      How can I do this?



      How can I go about doing this? I have tried multiple solutions, but the orientation is never kept. It loads the object at the correct position, but rotation and scaling is never kept, even if I apply it to the rootnode. The only option I can see is to also store the transform as a seperate data object, and load that and apply it. But seems like it should be possible to store this data with the object.










      share|improve this question














      I'm trying to persist a model in ARKit using the ARWorldMap. I can save and load the models, but the orientation I apply to the objects before I save is not persisted with the object.



      What I'm currently doing



      Objects are saved and loaded:



        /// - Tag: GetWorldMap
      @objc func saveExperience(_ button: UIButton) {
      sceneView.session.getCurrentWorldMap { worldMap, error in
      guard let map = worldMap
      else { self.showAlert(title: "Can't get current world map", message: error!.localizedDescription); return }

      // Add a snapshot image indicating where the map was captured.
      guard let snapshotAnchor = SnapshotAnchor(capturing: self.sceneView) else {
      fatalError("Can't take snapshot")

      }
      map.anchors.append(snapshotAnchor)

      do {
      let data = try NSKeyedArchiver.archivedData(withRootObject: map, requiringSecureCoding: true)
      try data.write(to: self.mapSaveURL, options: [.atomic])
      DispatchQueue.main.async {
      self.loadExperienceButton.isHidden = false
      self.loadExperienceButton.isEnabled = true
      }
      } catch {
      fatalError("Can't save map: (error.localizedDescription)")
      }
      }
      }

      /// - Tag: RunWithWorldMap
      @objc func loadExperience(_ button: UIButton) {

      /// - Tag: ReadWorldMap
      let worldMap: ARWorldMap = {
      guard let data = mapDataFromFile
      else { fatalError("Map data should already be verified to exist before Load button is enabled.") }
      do {
      guard let worldMap = try NSKeyedUnarchiver.unarchivedObject(ofClass: ARWorldMap.self, from: data)
      else { fatalError("No ARWorldMap in archive.") }
      return worldMap
      } catch {
      fatalError("Can't unarchive ARWorldMap from file data: (error)")
      }
      }()

      // Display the snapshot image stored in the world map to aid user in relocalizing.
      if let snapshotData = worldMap.snapshotAnchor?.imageData,
      let snapshot = UIImage(data: snapshotData) {
      self.snapshotThumbnail.image = snapshot
      } else {
      print("No snapshot image in world map")
      }
      // Remove the snapshot anchor from the world map since we do not need it in the scene.
      worldMap.anchors.removeAll(where: { $0 is SnapshotAnchor })

      let configuration = self.defaultConfiguration // this app's standard world tracking settings
      configuration.initialWorldMap = worldMap
      sceneView.session.run(configuration, options: [.resetTracking, .removeExistingAnchors])

      isRelocalizingMap = true
      virtualObjectAnchor = nil
      }


      Rotation:



      @objc func didRotate(_ gesture: UIRotationGestureRecognizer) {
      sceneView.scene.rootNode.eulerAngles.y = objectRotation
      gesture.rotation = 0
      }


      And then it's rendered:



        func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) {
      guard anchor.name == virtualObjectAnchorName else {
      return
      }

      // save the reference to the virtual object anchor when the anchor is added from relocalizing
      if virtualObjectAnchor == nil {
      virtualObjectAnchor = anchor
      }
      node.addChildNode(virtualObject)
      }


      How can I do this?



      How can I go about doing this? I have tried multiple solutions, but the orientation is never kept. It loads the object at the correct position, but rotation and scaling is never kept, even if I apply it to the rootnode. The only option I can see is to also store the transform as a seperate data object, and load that and apply it. But seems like it should be possible to store this data with the object.







      ios swift scenekit arkit arworldmap






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked Nov 20 '18 at 21:09









      eivindmleivindml

      3091723




      3091723
























          0






          active

          oldest

          votes











          Your Answer






          StackExchange.ifUsing("editor", function () {
          StackExchange.using("externalEditor", function () {
          StackExchange.using("snippets", function () {
          StackExchange.snippets.init();
          });
          });
          }, "code-snippets");

          StackExchange.ready(function() {
          var channelOptions = {
          tags: "".split(" "),
          id: "1"
          };
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function() {
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled) {
          StackExchange.using("snippets", function() {
          createEditor();
          });
          }
          else {
          createEditor();
          }
          });

          function createEditor() {
          StackExchange.prepareEditor({
          heartbeatType: 'answer',
          autoActivateHeartbeat: false,
          convertImagesToLinks: true,
          noModals: true,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: 10,
          bindNavPrevention: true,
          postfix: "",
          imageUploader: {
          brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
          contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
          allowUrls: true
          },
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          });


          }
          });














          draft saved

          draft discarded


















          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53401578%2fpersist-object-orientations-in-arkit-arworldmap%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown

























          0






          active

          oldest

          votes








          0






          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes
















          draft saved

          draft discarded




















































          Thanks for contributing an answer to Stack Overflow!


          • Please be sure to answer the question. Provide details and share your research!

          But avoid



          • Asking for help, clarification, or responding to other answers.

          • Making statements based on opinion; back them up with references or personal experience.


          To learn more, see our tips on writing great answers.




          draft saved


          draft discarded














          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53401578%2fpersist-object-orientations-in-arkit-arworldmap%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown





















































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown

































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown







          Popular posts from this blog

          "Incorrect syntax near the keyword 'ON'. (on update cascade, on delete cascade,)

          Alcedinidae

          Origin of the phrase “under your belt”?