gpt4 book ai didi

ios - swift : ARKit Save ARPlaneAnchor for next session

转载 作者:搜寻专家 更新时间:2023-10-31 21:59:05 25 4
gpt4 key购买 nike

ARKit 很新,我在 swift 方面也很新……所以我遇到了一些麻烦……

我想保存在 session 期间检测到的 ARPlaneAnchor 并在我重新启动我的应用程序时重新加载它们。我的手机总是在同一个地方,我想扫描房间一次。每次启动应用程序时,都会想起我在房间里找到的 Anchor。

我尝试了几种解决方案:

解决方案1:使用以下方法保存 ARPlaneAnchor:NSKeyedArchiver.archiveRootObject(plane, toFile: filePath)

我遇到了这个错误:

Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[ARPlaneAnchor encodeWithCoder:]: unrecognized selector sent to instance

我想也许我不能在本地保存这种数据

解决方案 2: 存储 ARPlaneAnchor 的数据,然后在我启动应用程序时实例化它们。数据主要是 float 的。我可以轻松创建 ARAnchor,我可以将它们转换为 ARPlaneAnchor,但我无法修改 ARPlaneAnchor 的“center”和“extend”参数> 因为他们只有 getter 而没有 setter。所以我无法创建好的 anchor 。

我愿意接受任何解决方案。我想我需要存储 ARAnchor 对象,但现在我找不到不崩溃的方法!因此,如果有人可以帮助我,我将不胜感激。

最佳答案

首先...如果您的应用仅限于设备永久安装并且用户永远无法移动或旋转设备的情况,那么使用 ARKit 在相机画面上显示叠加内容有点像“用大炮”之类的情况。您也可以在开发时确定您的 3D 引擎需要什么样的相机投影,使用“哑”相机供稿,并在顶部运行您的 3D 引擎,而不需要 iOS 11 或支持 ARKit 的设备。

因此,在您致力于具体的解决方案和解决方法之前,您可能需要更多地考虑您的用例或技术堆栈。


至于你更具体的问题...

ARPlaneAnchor 完全是一个只读类,因为它的用例完全是只读的。它存在的唯一目的是为 ARKit 提供一种方法来为您提供有关检测到的平面的信息。但是,一旦您获得了这些信息,您就可以随心所欲地使用它。从那时起,您不再需要在等式中保留 ARPlaneAnchor

也许您对平面检测(和基于 SceneKit 的显示)的典型用例感到困惑:

  1. 开启平面检测
  2. 回复renderer(_:didAdd:for:)接收 ARPlaneAnchor 对象
  3. 在该方法中,返回与平面 anchor 关联的虚拟内容
  4. ARSCNView 自动为您定位该内容,使其跟随飞机的位置

但是,如果您的飞机相对于相机的位置是静止的,则您不需要所有这些。

如果放置需要持续管理,您只需要 ARKit 来处理场景中的内容放置,就像实时平面检测的情况一样(ARKit 改进了它对平面位置和范围的估计并相应地更新 anchor )。如果您提前完成了所有飞机查找工作,您将不会收到更新,因此您不需要 ARKit 来管理更新。

相反,您的步骤可以看起来更像这样:

  1. 知道飞机在哪里(世界空间中的位置)。
  2. 将虚拟内容的位置设置为飞机的位置。
  3. 直接将内容添加到场景中。

换句话说,您的“解决方案 2”是朝着正确方向迈出的一步,但还不够。您想要归档的不是 ARPlaneAnchor 实例本身,而是它包含的信息 — 然后在取消归档时,您不需要重新创建 ARPlaneAnchor 实例,您只需需要使用该信息。

因此,如果您使用“实时”平面检测来放置内容:

func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) {
guard let planeAnchor = anchor as? ARPlaneAnchor else { return }
let extent = planeAnchor.extent
let center = planeAnchor.center
// planeAnchor.transform not used, because ARSCNView automatically applies it
// to the container node, and we make a child of the container node

let plane = SCNPlane(width: CGFloat(extent.x), height: CGFloat(extent.z))
let planeNode = SCNNode(geometry: plane)
planeNode.eulerAngles.x = .pi / 2
planeNode.simdPosition = center
node.addChildNode(planeNode)
}

然后你可以为静态内容放置做这样的事情:

struct PlaneInfo { // something to save and restore ARPlaneAnchor data
let transform: float4x4
let center: float3
let extent: float3
}
func makePlane(from planeInfo: PlaneInfo) { // call this when you place content
let extent = planeInfo.extent
let center = float4(planeInfo.center, 1) * planeInfo.transform
// we're positioning content in world space, so center is now
// an offset relative to transform

let plane = SCNPlane(width: CGFloat(extent.x), height: CGFloat(extent.z))
let planeNode = SCNNode(geometry: plane)
planeNode.eulerAngles.x = .pi / 2
planeNode.simdPosition = center.xyz
view.scene.rootNode.addChildNode(planeNode)
}

// convenience vector-width conversions used above
extension float4 {
init(_ xyz: float3, _ w: Float) {
self.init(xyz.x, xyz.y, xyz.z, 1)
}
var xyz: float3 {
return float3(self.x, self.y, self.z)
}
}

关于ios - swift : ARKit Save ARPlaneAnchor for next session,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45306688/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com