在 ARKit ARWorldMap 中保持对象方向
Persist object orientations in ARKit ARWorldMap
我正在尝试使用 ARWorldMap 在 ARKit 中保留一个模型。我可以保存和加载模型,但我在保存之前应用到对象的方向不会与对象一起保留。
我目前在做什么
保存和加载对象:
/// - 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: { [=10=] 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
}
旋转:
@objc func didRotate(_ gesture: UIRotationGestureRecognizer) {
sceneView.scene.rootNode.eulerAngles.y = objectRotation
gesture.rotation = 0
}
然后渲染:
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)
}
我该怎么做?
我该怎么做呢?我尝试了多种解决方案,但从未保持方向。它在正确的位置加载对象,但旋转和缩放永远不会保留,即使我将它应用于根节点。我能看到的唯一选择是将转换存储为单独的数据对象,然后加载并应用它。但似乎应该可以将此数据与对象一起存储。
Apple Documentation for ARWorldMap
表明 ARWorldMap
class 的属性是:
当您存档世界地图时,这些是唯一保存的信息。在 session 期间添加到锚点的任何有关节点的信息(例如更改节点比例和方向)在存档期间不会与世界地图一起保存。
我记得看过 WWDC session,他们演示了一款名为 SwiftShot 的多人 AR 游戏,玩家可以用球击中不同的 objects。他们提供了源代码,我注意到他们使用了一个名为 BoardAnchor
的自定义 ARAnchor
subclass,他们用来在锚 class 中存储附加信息,例如游戏板。
参见:SwiftShot: Creating a Game for Augmented Reality.
您可以使用相同的方法来存储,例如,节点的比例和方向,这样当您取消存档世界地图并重新定位时,您可以使用 ARSCNViewDelegate
的 renderer(_:didAdd:for:)
根据存储在自定义 ARAnchor
.
中的信息调整节点大小和缩放
我正在尝试使用 ARWorldMap 在 ARKit 中保留一个模型。我可以保存和加载模型,但我在保存之前应用到对象的方向不会与对象一起保留。
我目前在做什么
保存和加载对象:
/// - 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: { [=10=] 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
}
旋转:
@objc func didRotate(_ gesture: UIRotationGestureRecognizer) {
sceneView.scene.rootNode.eulerAngles.y = objectRotation
gesture.rotation = 0
}
然后渲染:
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)
}
我该怎么做?
我该怎么做呢?我尝试了多种解决方案,但从未保持方向。它在正确的位置加载对象,但旋转和缩放永远不会保留,即使我将它应用于根节点。我能看到的唯一选择是将转换存储为单独的数据对象,然后加载并应用它。但似乎应该可以将此数据与对象一起存储。
Apple Documentation for ARWorldMap
表明 ARWorldMap
class 的属性是:
当您存档世界地图时,这些是唯一保存的信息。在 session 期间添加到锚点的任何有关节点的信息(例如更改节点比例和方向)在存档期间不会与世界地图一起保存。
我记得看过 WWDC session,他们演示了一款名为 SwiftShot 的多人 AR 游戏,玩家可以用球击中不同的 objects。他们提供了源代码,我注意到他们使用了一个名为 BoardAnchor
的自定义 ARAnchor
subclass,他们用来在锚 class 中存储附加信息,例如游戏板。
参见:SwiftShot: Creating a Game for Augmented Reality.
您可以使用相同的方法来存储,例如,节点的比例和方向,这样当您取消存档世界地图并重新定位时,您可以使用 ARSCNViewDelegate
的 renderer(_:didAdd:for:)
根据存储在自定义 ARAnchor
.