方法" isNode(:insideFrustumOf :)"永远是真的

时间:2018-04-17 09:43:21

标签: ios swift scenekit arkit

我试图验证特定节点是否在场景的当前平截头体内。 因此,我使用Apple的方法isNode(_:insideFrustumOf:)。 我保存每次调用renderer(_:didAdd:for:)相应的节点,然后用isNode(_:insideFrustumOf :)测试。

但结果总是如此,这显然是错误的。

为什么我不能测试ARKit添加的节点?

更新: 问代码,如果有帮助的话,太棒了!

func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) {
    //...
        nodes.append(node)
    //...
}

nodes 是一个SCNNodes数组。

func renderer(_ renderer: SCNSceneRenderer, updateAtTime time: TimeInterval) {
        for node in nodes {
            let result = sceneView.isNode(node, insideFrustumOf: sceneView.pointOfView!)
            //...
        }
}

这里进行节点的评估。结果总是如此。

2 个答案:

答案 0 :(得分:1)

由于您尚未发布所有代码,因此难以提供“确定”答案。

说完这些,我为你创造了一个非常好的例子。

首先,我创建了一个[SCNNode]来存储添加到屏幕上的任何SCNNodes

 //Array To Store Any Added Nodes To The Scene Hierachy
 var nodesRendered = [SCNNode]()

然后我创建了3个不同的SCNNodes

/// Creates A Red, Blue & Green SCNNode
func createNodes(){

    //1. Create A Red Sphere
    let redNode = SCNNode()
    let redGeometry = SCNSphere(radius: 0.2)
    redGeometry.firstMaterial?.diffuse.contents = UIColor.red
    redNode.geometry = redGeometry
    redNode.position = SCNVector3(-1.5, 0, -1.5)
    redNode.name = "RedNode"

    //2. Create A Green Sphere
    let greenNode = SCNNode()
    let greenGeometry = SCNSphere(radius: 0.2)
    greenGeometry.firstMaterial?.diffuse.contents = UIColor.green
    greenNode.geometry = greenGeometry
    greenNode.position = SCNVector3(0, 0, -1.5)
    greenNode.name = "GreenNode"

    //3. Create A Blue Sphere
    let blueNode = SCNNode()
    let blueGeometry = SCNSphere(radius: 0.2)
    blueGeometry.firstMaterial?.diffuse.contents = UIColor.blue
    blueNode.geometry = blueGeometry
    blueNode.position = SCNVector3(1.5, 0, -1.5)
    blueNode.name = "BlueNode"

    //4. Add Them To The Hierachy
    augmentedRealityView.scene.rootNode.addChildNode(redNode)
    augmentedRealityView.scene.rootNode.addChildNode(greenNode)
    augmentedRealityView.scene.rootNode.addChildNode(blueNode)

    //5. Store A Reference To The Nodes
    nodesRendered.append(redNode)
    nodesRendered.append(blueNode)
    nodesRendered.append(greenNode)
}

完成此操作后,我创建了一个函数来确定这些是否位于相机的Frustrum中:

/// Detects If A Node Is In View Of The Camera
func detectNodeInFrustrumOfCamera(){

    guard let cameraPointOfView = self.augmentedRealityView.pointOfView else { return }

    for node in nodesRendered{

        if augmentedRealityView.isNode(node, insideFrustumOf: cameraPointOfView){

            print("\(node.name!) Is In View Of Camera")

        }else{

            print("\(node.name!) Is Not In View Of Camera")
        }
    }

}

最后在delegate回调中,我调用了这样的函数:

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

        detectNodeInFrustrumOfCamera()

  }

产生了如下结果:

RedNode不在相机视野中

BlueNode不在相机视野中

GreenNode在相机视野中

希望它指出你正确的方向......

答案 1 :(得分:0)

因此,我在进行ARKit项目时遇到了这个问题。对于ARKit自动添加的节点,函数isNode(node:, insideFrustumOf:)似乎总是返回true。

我的解决方法不是尝试跟踪ARKit添加的节点,而是使用透明材料创建一个新节点,该透明材料的“体积”与检测到的对象相同,然后创建引用并检查该节点是否在节点的内部视图。

添加以下变量:

    /// The object that was detected.
    var refObject: ARReferenceObject?

    /// The reference node for the detected object.
    var refNode: SCNNode?

    /// additional node which we'll use to check the POV against.
    var detectionNode: SCNNode?

实现委托函数didAdd

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


        if let objectAnchor = anchor as? ARObjectAnchor {

            guard let name = objectAnchor.referenceObject.name, name == "my_object" 
            else { return }
            print("detected object for the first time")


            // create geometry
            let cube = SCNBox(width: 0.1, height: 0.1, length: 0.1, chamferRadius: 0.0)

            // apply transparent material
            let material = SCNMaterial()
            material.transparency = 0.0
            cube.firstMaterial = material

            // add child node
            let detectionNode = SCNNode(geometry: cube)
            node.addChildNode(detectionNode)

            // store references
            self.detectionNode = detectionNode // this is the reference we really need
            self.refNode = node
            self.refObject = objectAnchor.referenceObject


        }
    }

最后实现此委托函数updateAtTime

public func renderer(_ renderer: SCNSceneRenderer, updateAtTime time: TimeInterval) {
        guard let node = self.detectionNode else { return }

        if let pointOfView = sceneView.pointOfView {
            let isVisible = sceneView.isNode(node, insideFrustumOf: pointOfView)
            print("Is node visible: \(isVisible)")
        }
}