如何确定SceneKit中哪个childNode最靠近屏幕中心?

时间:2019-06-08 17:26:32

标签: arrays swift scenekit child-nodes

我在场景中放置了一堆标记,作为3D世界中固定节点位置的childNodes。当我四处移动电话时,我需要确定哪个标记节点最接近2D屏幕中心,因此我可以获得对应于该节点的文本描述并显示它。

现在,在渲染循环中,我只是在forEach循环中确定了每个节点到屏幕中心的距离,并确定该距离是否小于150,如果是,则获取该节点的标题和副本。但是,这不能解决我的问题,因为可能有多个满足该条件的节点。我需要比较所有节点到中心的距离,并得到最接近的一个节点

func renderer(_ renderer: SCNSceneRenderer, willRenderScene scene: SCNScene, atTime time: TimeInterval){

    scene.rootNode.childNodes.filter{ $0.name != nil }.forEach{ node in

        guard let pointOfView = sceneView.pointOfView else { return }
        let isVisible = sceneView.isNode(node, insideFrustumOf: pointOfView)
        if isVisible {

            let nodePos = sceneView.projectPoint(node.position)
            let nodeScreenPos = CGPoint(x: CGFloat(nodePos.x), y: CGFloat(nodePos.y))
            let distance = CGPointDistance(from: nodeScreenPos, to: view.center)

            if distance < 150.0 {
                print("display description of: \(node.name!)")
                guard let title = ar360Experience?.threeSixtyHotspot?[Int(node.name!)!].title else { return }
                guard let copy = ar360Experience?.threeSixtyHotspot?[Int(node.name!)!].copy else { return }
                titleLabel.text = title
                copyLabel.text = copy

                cardView.isHidden = false

            }else {
                cardView.isHidden = true
            }
        }

    }
}

1 个答案:

答案 0 :(得分:0)

有多种方法可以做到这一点。就像迭代所有节点以找到它们的距离一样。但是就像您说的那样,这样效率很低。

您可以做的就是使用GKQuadTree ... https://developer.apple.com/documentation/gameplaykit/gkquadtree

将节点数据存储为其他格式。

这是GameplayKit,可让您更快地迭代数据集,以便找到距离中心最近的节点。

通过将区域分成四个(因此为四边形)部分并将节点存储到其中也存储该部分的rect的那些部分之一中来工作。然后将这四个部分中的每一个都细分为四个,依此类推。

因此,当您要求最接近给定点的节点时,它可以快速消除大多数节点。