Persist object orientations in ARKit ARWorldMap
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
add a comment |
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
add a comment |
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
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
ios swift scenekit arkit arworldmap
asked Nov 20 '18 at 21:09
eivindmleivindml
3091723
3091723
add a comment |
add a comment |
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
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
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.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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