Получить все ARAnchors сфокусированной камеры в ARKIT

Когда приложение запускается первым, на одной стене обнаруживается вертикальная поверхность, а не фокус камеры на вторую стену, во второй стене обнаруживается другая поверхность. Первая стена теперь больше не видна 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")
        }

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

Если вы хотите получить все сфокусированные узлы, соберите их в массив, удовлетворяющий заданному условию

Удачи!

Ключ к ответу находится в начале строки вашего if let заявление.

Давайте разберемся с этим:

Когда ты сказал let anchor = sceneView.session.currentFrame?.anchors.first, вы ссылаетесь на необязательный массив ARAnchorкоторый, естественно, может иметь более одного элемента.

Так как вы всегда звоните first Например, индекс [0], вы всегда получите 1-й 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

1-й хранить ARPlaneAnchor и его связанный SCNNodeи 2-й, чтобы предоставить уникальный идентификатор для каждой плоскости.

в 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()
}

Надеюсь, что оба из них будут указывать в правильном направлении...

Другие вопросы по тегам