2

当应用程序首先启动时,在一面墙上检测到垂直表面,而不是相机聚焦到第二面墙上,在第二面墙上检测到另一个表面。现在 ARCamera 看不到第一面墙,但这段代码为我提供了第一面墙的锚点。但我需要第二面墙的锚点,它现在在相机中可见/聚焦。

if let anchor = sceneView.session.currentFrame?.anchors.first {
    let node = sceneView.node(for: anchor)
    addNode(position: SCNVector3Zero, anchorNode: node)
} else {
    debugPrint("anchor node is nil")
}
4

2 回答 2

6

答案的线索在你if let陈述的开头。

让我们分解一下:

当您说 时let anchor = sceneView.session.currentFrame?.anchors.first,您是在引用一个可选数组ARAnchor,它自然可以有多个元素。

由于您总是调用first例如索引 [0],因此您将始终获得ARAnchor添加到数组中的第一个。

由于您现在有 2 个锚点,因此您自然需要最后一个(最新的)元素。因此,您可以尝试以下方法:

if let anchor = sceneView.session.currentFrame?.anchors.last {

    let node = sceneView.node(for: anchor)
    addNode(position: SCNVector3Zero, anchorNode: node)

     } else {

        debugPrint("anchor node is nil")
}

更新: 由于另一位发帖者对这个问题的解释不同,他们认为问题是如何检测 ARPlaneAnchor 是否在视野中?让我们以另一种方式处理它。

首先,我们需要考虑到 ARCamera 有一个 Frostrum,其中显示了我们的内容:

在此处输入图像描述

因此,我们需要确定 ARPlaneAnchor 是否为inViewOfFrostrum.

首先,我们将创建 2 个变量:

var planesDetected = [ARPlaneAnchor: SCNNode]()
var planeID: Int = 0

第一个用于存储ARPlaneAnchor及其关联SCNNode的 ,第二个用于为每个平面提供唯一的 ID。

在中ARSCNViewDelegate我们可以可视化一个 ARPlaneAnchor,然后存储它的信息,例如:

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

    //1. Get The Current ARPlaneAnchor
    guard let anchor = anchor as? ARPlaneAnchor else { return }

    //2. Create An SCNode & Geometry To Visualize The Plane
    let planeNode = SCNNode()
    let planeGeometry = SCNPlane(width: CGFloat(anchor.extent.x), height: CGFloat(anchor.extent.z))
    planeGeometry.firstMaterial?.diffuse.contents = UIColor.cyan
    planeNode.geometry = planeGeometry

    //3. Set The Position Based On The Anchors Extent & Rotate It
    planeNode.position = SCNVector3(anchor.center.x, anchor.center.y, anchor.center.z)
    planeNode.eulerAngles.x = -.pi / 2

    //4. Add The PlaneNode To The Node & Give It  A Unique ID
    node.addChildNode(planeNode)
    planeNode.name = String(planeID)

    //5. Store The Anchor & Node
    planesDetected[anchor] = planeNode

    //6. Increment The Plane ID
    planeID += 1

}

现在我们已经存储了检测到的平面,我们当然需要确定其中是否有任何一个在 ARCamera 的视图中,例如:

/// Detects If An Object Is In View Of The Camera Frostrum
func detectPlaneInFrostrumOfCamera(){

    //1. Get The Current Point Of View
    if let currentPointOfView = augmentedRealityView.pointOfView{

        //2. Loop Through All The Detected Planes
        for anchorKey in planesDetected{

            let anchor = anchorKey.value

            if augmentedRealityView.isNode(anchor, insideFrustumOf: currentPointOfView){

               print("ARPlaneAnchor With ID \(anchor.name!) Is In View")

            }else{

                 print("ARPlaneAnchor With ID \(anchor.name!) Is Not In View")
            }

        }

    }
}

最后我们需要访问这个函数,我们可以用下面的delegate方法来做,例如renderer(_ renderer: SCNSceneRenderer, updateAtTime time: TimeInterval)

func renderer(_ renderer: SCNSceneRenderer, updateAtTime time: TimeInterval) {

        detectPlaneInFrostrumOfCamera()
}

希望这两个都指向正确的方向......

于 2018-03-19T23:47:36.260 回答
2

为了获取当前处于视图中的节点,您可以执行以下操作:

       var targettedAnchorNode: SCNNode?
       if let anchors = sceneView.session.currentFrame?.anchors {
           for anchor in anchors {

               if let anchorNode = sceneView.node(for: anchor), let pointOfView = sceneView.pointOfView, sceneView.isNode(anchorNode, insideFrustumOf: pointOfView) {
                   targettedAnchorNode = anchorNode
                   break
               }
           }

           if let targettedAnchorNode = targettedAnchorNode {
               addNode(position: SCNVector3Zero, anchorNode: targettedAnchorNode)
           } else {
               debugPrint("Targetted node not found")
           }

       } else {
           debugPrint("Anchors not found")
       }

如果您想获取所有焦点节点,请将它们收集到满足指定条件的数组中

祝你好运!

于 2018-03-20T06:16:08.943 回答