我正在使用ARReferenceImages在ARKit中玩,当一个引用图像被识别时,我尝试添加一个SCNNode,然后不管是否在其他地方识别相同的引用映像,都保留该节点的位置。
我可以正确地添加我的SCNode,但是如果我移动我的标记,它会再次捡起它,并将我放置的节点移动到标记的位置。
我要添加的代码如下:
func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) {
guard let imageAnchor = anchor as? ARImageAnchor else { return }
let referenceImage = imageAnchor.referenceImage
print("MAPNODE IS NIL = \(self.mapNode == nil)")
updateQueue.async {
if self.mapNode == nil {
// Create a plane to visualize the initial position of the detected image.
let plane = SCNPlane(width: 1.2912,
height: 1.2912)
let planeNode = SCNNode(geometry: plane)
planeNode.opacity = 1
/*
`SCNPlane` is vertically oriented in its local coordinate space, but
`ARImageAnchor` assumes the image is horizontal in its local space, so
rotate the plane to match.
*/
planeNode.eulerAngles.x = -.pi / 2
self.mapNode = planeNode
/*
Image anchors are not tracked after initial detection, so create an
animation that limits the duration for which the plane visualization appears.
*/
// Add the plane visualization to the scene.
node.addChildNode(planeNode)
}
}
}在这里读取文档experience#2958517声明
应用最佳做法 这个示例应用程序简单地可视化了ARKit在用户环境中检测每个参考图像的位置,但是您的应用程序可以做得更多。按照下面的提示设计AR经验,很好地使用图像检测。 使用检测到的图像来设置AR场景的参考框架。与其要求用户选择虚拟内容的位置,或者在用户的环境中任意放置内容,不如使用检测到的图像来锚定虚拟场景。您甚至可以使用多个检测到的图像。例如,零售商店的应用程序可以通过识别放置在店门两侧的海报,然后在海报之间直接计算字符的位置,从而使虚拟角色从商店的前门出现。 备注 使用ARSession setWorldOrigin(relativeTransform:)方法重新定义世界坐标系,以便您可以将所有锚点和其他内容相对于您选择的参考点放置。 设计您的AR体验使用检测到的图像作为虚拟内容的起点。ARKit不跟踪每个检测到的图像的位置或方向的变化。如果试图放置与检测到的图像相关联的虚拟内容,则该内容可能会出现不正确的位置。相反,使用检测到的图像作为启动动态场景的参考框架。例如,你的应用程序可能识别科幻电影的戏剧海报,然后虚拟宇宙飞船出现在海报上并在环境中飞行。
所以我试着把我的世界变换设置为等同于我的形象锚的转换。
self.session.setWorldOrigin(relativeTransform: imageAnchor.transform)然而,我的mapNode在它移动的地方遵循imageAnchor。我还没有实现renderer update方法,所以我不知道为什么这个方法会继续前进。
我假设setWorldOrigin方法不断地更新到imageAnchor.transform,而不仅仅是那个时刻,这很奇怪,因为该代码只被调用一次。有什么想法吗?
发布于 2018-03-24 02:07:56
如果要在mapNode的位置添加ARImageAnchor,可以在转换ARImageAnchor时设置mapNode的位置,并将其添加到场景中,但如果这有意义,则不链接到参考图像。
这样做是可以的:
func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) {
//1. If Out Target Image Has Been Detected Than Get The Corresponding Anchor
guard let currentImageAnchor = anchor as? ARImageAnchor else { return }
//2. An ImageAnchor Is Only Added Once For Each Identified Target
print("Anchor ID = \(currentImageAnchor.identifier)")
//3. Add An SCNNode At The Position Of The Identified ImageTarget
let nodeHolder = SCNNode()
let nodeGeometry = SCNBox(width: 0.02, height: 0.02, length: 0.02, chamferRadius: 0)
nodeGeometry.firstMaterial?.diffuse.contents = UIColor.cyan
nodeHolder.geometry = nodeGeometry
nodeHolder.position = SCNVector3(currentImageAnchor.transform.columns.3.x,
currentImageAnchor.transform.columns.3.y,
currentImageAnchor.transform.columns.3.z)
augmentedRealityView?.scene.rootNode.addChildNode(nodeHolder)
}在问题的另一部分中,您似乎暗示要检测同一图像的多次出现。我可能错了,但我认为唯一的方法是删除引用映像的相应ARImageAnchor,这可以这样做(在最后一个代码片段的末尾添加它):
augmentedRealitySession.remove(anchor: currentImageAnchor)这里的问题是,一旦ARImageAnchor被删除,每当再次检测到它时,您都必须处理是否应该添加内容,这是很棘手的,因为ARImageAnchor.identifier对于referenceImage来说总是一样的,而不管它是否被删除,然后重新添加,因此很难存储在dictionary中等等。因此,根据您的需要,您需要找到一种方法来确定是否存在该位置的内容,以及是否重新添加它等等。
关于setWorldOrigin的问题的最后一部分看起来有点奇怪,就像您说的那样,但是也许您可以添加一个Bool来防止它可能发生变化,例如:
var hasSetWorldOrigin = false然后,在此基础上,您可以确保只设置一次,例如:
func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) {
//1. If Out Target Image Has Been Detected Than Get The Corresponding Anchor
guard let currentImageAnchor = anchor as? ARImageAnchor else { return }
//2. If We Havent Set The World Origin Set It Based On The ImageAnchorTranform
if !hasSetWorldOrigin{
self.augmentedRealitySession.setWorldOrigin(relativeTransform: currentImageAnchor.transform)
hasSetWorldOrigin = true
//3. Create Two Nodes To Add To The Scene And Distribute Them
let nodeHolderA = SCNNode()
let nodeGeometryA = SCNBox(width: 0.04, height: 0.04, length: 0.04, chamferRadius: 0)
nodeGeometryA.firstMaterial?.diffuse.contents = UIColor.green
nodeHolderA.geometry = nodeGeometryA
let nodeHolderB = SCNNode()
let nodeGeometryB = SCNBox(width: 0.04, height: 0.04, length: 0.04, chamferRadius: 0)
nodeGeometryB.firstMaterial?.diffuse.contents = UIColor.red
nodeHolderB.geometry = nodeGeometryB
if let cameraTransform = augmentedRealitySession.currentFrame?.camera.transform{
nodeHolderA.simdPosition = float3(cameraTransform.columns.3.x,
cameraTransform.columns.3.y,
cameraTransform.columns.3.z)
nodeHolderB.simdPosition = float3(cameraTransform.columns.3.x + 0.2,
cameraTransform.columns.3.y,
cameraTransform.columns.3.z)
}
augmentedRealityView?.scene.rootNode.addChildNode(nodeHolderA)
augmentedRealityView?.scene.rootNode.addChildNode(nodeHolderB)
}
}希望我的回答能为你提供一个有用的起点,假设我已经正确地解释了你的问题,
https://stackoverflow.com/questions/49458193
复制相似问题