如何将 ARPlaneAnchor 放置在与 ARImageAnchor 相同的位置

How to put an ARPlaneAnchor at the same location as an ARImageAnchor

我正在尝试将 ARImageAnchor 放置在与 ARPlaneAnchor 相同的位置,但它不起作用。这是我认为问题所在的 renderer 函数的开始:

func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) {
        guard let imageAnchor = anchor as? ARImageAnchor else { return }
        guard let planeAnchor = anchor as? ARPlaneAnchor else { return }
        ...
}

当我注释掉与 planeAnchor 有关的所有内容时,它工作正常,但是一旦我尝试将它们放在同一位置,它仍然可以编译,但它不会检测到参考图像。有人以前见过这样的问题吗?谢谢!

更新:将 sceneView 作为我的 ARSCNView,我使用此代码:

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {

    print("got here")
    guard let touchLocation = touches.first?.location(in: sceneView),
        let hitTest = sceneView?.hitTest(touchLocation, options: nil),
        //let detectedPlane = planes[planeAnchor],
        let nodeTapped = hitTest.first?.node,
        let nodeName = nodeTapped.name else { return }
    print("got here 2")

    print(nodeName)

}

但 "got here 2" 从未打印出来,当我点击平面时没有任何反应。我应该尝试什么?

进一步查看后我认为这不可能。

如果您将 ARWorldTrackingConfiguration 设置为检测飞机,例如:

  configuration.planeDetection = .horizontal

然后在委托方法中添加这个调试日志:

func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) {

    print(anchor.classForCoder)

}

您会看到,当您检测到目标图像时,它将记录 ARImageAnchor 而如果检测到水平面,它将记录:ARPlaneAnchor.

这就是你的保护声明没有执行的原因:

 guard let planeAnchor = anchor as? ARPlaneAnchor else { return }

只是因为不能同时有两个anchor...

存在 ARPlaneAnchorARImageAnchor

根据您上次的回复更新,这将使您获得这些属性:

   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. Get The Targets Name
    let name = currentImageAnchor.referenceImage.name!

    //3. Get The Targets Width & Height
    let width = currentImageAnchor.referenceImage.physicalSize.width
    let height = currentImageAnchor.referenceImage.physicalSize.height

    //4. Log The Reference Images Information
    print("""
    Image Name = \(name)
    Image Width = \(width)
    Image Height = \(height)
    """) 
}

我还是不明白为什么你还需要一个 PlaneAnchor,你可以用它来显示模型等:)

如果你想在那个锚点添加一些东西,那么试试这个:

  /// Generates An SCNPlane On The Detected Image At The Size Of The Target
///
/// - Parameters:
///   - node: SCNNode
///   - width: CGFloat
///   - height: CGFloat
func generateModel(_ node: SCNNode, width: CGFloat, height: CGFloat){

    let nodeToAdd = SCNNode()
    let planeGeometry = SCNPlane(width: width, height: height)
    planeGeometry.firstMaterial?.diffuse.contents = UIColor.red
    nodeToAdd.geometry = planeGeometry
    nodeToAdd.transform = SCNMatrix4MakeRotation(-Float.pi / 2, 1, 0, 0)
    node.addChildNode(nodeToAdd)
}

并在委托方法中调用:

 generateModel(node, width: width, height: height)

我认为这就是您要实现的目标。

更新: 要在添加的节点上进行 hitTest,只需使用 touchesBegan,例如

   override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {

    guard let touch = touches.first?.location(in: self.augmentedRealityView),
    let hitTest = self.augmentedRealityView?.hitTest(touch, options: nil),
    let nodeTapped = hitTest.first?.node,
    let nodeName = nodeTapped.name else { return }

    print(nodeName)

}

更新: 如果放置在 ImageAnchor 上的对象看起来摇摇欲坠,可能是您在 ARAssets Bundle 中错误地设置了 referenceImage 大小: