在ARKIT获得专注相机的所有ARAnchors

时间:2018-03-19 12:38:17

标签: ios arkit scnscene

  

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

varbinary

2 个答案:

答案 0 :(得分:4)

答案的线索在if let声明的开头。

让我们打破这个:

当你说let anchor = sceneView.session.currentFrame?.anchors.first时,你引用了一个ARAnchor的可选数组,它自然可以包含多个元素。

由于您始终致电first,例如index [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,其中显示了我们的内容:

enter image description here

因此,我们需要确定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()
}

希望这些都能指向正确的方向......

答案 1 :(得分:0)

为了使当前的节点处于观察点,您可以执行以下操作:

       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")
       }

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

祝你好运!