swift - 如何在没有 ARHitTest 的情况下将 AR 对象放置在平面上?
问题描述
我正在做一个 AR 项目并尝试将一个对象添加到水平面。我的目的是让用户在他们的环境中搜索对象,一旦检测到水平面,对象就会出现在平面的中心点上。这是代码:
func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) {
if anchor is ARPlaneAnchor {
guard let planeAnchor = anchor as? ARPlaneAnchor else { return }
let plane = SCNPlane(width: CGFloat(planeAnchor.extent.x), height: CGFloat(planeAnchor.extent.z))
let planeNode = SCNNode()
planeNode.position = SCNVector3(x: planeAnchor.center.x, y: 0, z: planeAnchor.center.z)
planeNode.geometry = plane
print("Plane Node: \(planeNode.position)")
planeNode.transform = SCNMatrix4MakeRotation(-Float.pi / 2, 1, 0, 0)
node.addChildNode(planeNode)
let chestScene = SCNScene(named: "art.scnassets/empty_treasure_chest copy.scn")
guard let chestNode = chestScene?.rootNode.childNode(withName: "chest", recursively: true) else { return }
sceneView.scene.rootNode.addChildNode(chestNode)
chestNode.position = planeNode.position
print("Chest Node: \(chestNode.position)")
sceneView.scene.rootNode.enumerateChildNodes { (node, _) in
if node.name == "chest_lid_top_wood" {
print("found top")
top = node
top.physicsBody = SCNPhysicsBody(type: .static, shape: SCNPhysicsShape(node: top, options: nil))
} else if node.name == "chest_bottom_wood" {
print("found bottom")
bottom = node
bottom.physicsBody = SCNPhysicsBody(type: .static, shape: SCNPhysicsShape(node: bottom, options: nil))
}
}
} else {
return
}
}
该应用程序将正确检测平面,但对象不会直接放置在平面上,通常它会在世界原点位置抬离平面。更令人困惑的是,我有显示 planeNode 和 chestNode 位置的打印语句,尽管我将 chestNode 的位置分配给 planeNode 位置,但这些值最终是不同的。我了解大多数人使用 ARHitTest 来放置 AR 对象,但这样做会阻碍我试图实现的用户体验。
有什么建议么?提前致谢!
干杯!
解决方案
根据我的经验,ARKit 在worldPosition
计算节点之前将委托方法称为“提前”。它仍然是[0, 0, 0]
,这就是为什么您的对象出现在世界原点的原因。
有两种解决方法:
您可以将您的添加chestNode
为孩子node
而不是场景的rootNode
. 但是,这会导致每次ARKit
更新平面时节点都会移动,因为这会更新node
. 这通常是你想要的。
另一种方法是等待至少 1 帧,然后chestNode
通过将节点的实际位置包装在类似的东西中来更新您的位置
DispatchQueue.main.asyncAfter(deadline: .now() + 0.05) { [weak sceneView] in
sceneView?.scene.rootNode.addChildNode(chestNode)
chestNode.position = planeNode.position
}
推荐阅读
- r - t.test 在第三列上的特定代码之后的两列之间
- sql - 如何在spark上做一个sql连接?
- scala - 在scala中将字符串日期(不带分隔符)转换为日期格式
- html - 我的导航栏粘在页面的右边缘,当它在滚动时粘在顶部
- php - 如何以小时、天、周、月、年 PHP 的形式获取分钟
- php - 我怎样才能改变css的特性?
- python - Python Selenium rel=nofollow 链接
- python - 如何在 QScintilla 中实现基于缩进的代码折叠?
- wpf - XAML 属性编辑器中的 WPF Enum Flags Dependency 属性
- java - 表达式中的优先级,包括 java 中的括号和 int 类型转换