方法“isNode(:insideFrustumOf :)”始终为true

问题描述 投票:0回答:2

我正在尝试验证特定节点是否在场景的当前平截头体内。因此我使用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!)
            //...
        }
}

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

ios swift scenekit arkit
2个回答
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()

  }

产生的结果如下:

红色节点不是鉴于相机

BlueNode不是在相机的视图

GreenNode是鉴于照相机

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


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)")
        }
}
© www.soinside.com 2019 - 2024. All rights reserved.