SceneKit:如何创建冻结的SCNNode副本以在后台队列上执行命中测试?

时间:2018-03-02 18:51:01

标签: scenekit ios11 hittest

现在我执行面部地标检测,然后在结果点上使用SCNSceneRenderer.hitTest(cgPt, options: [.rootNode: faceNode])来查找各种地标的3D位置。我的面部节点是ARFaceAnchor的孩子,并且ARSCNFaceGeometry。基本算法似乎工作得很好。但是,出于性能原因,我将特征检测和单个命中测试发送到后台队列,与同步执行所有操作相比,这似乎会导致准确性显着降低。

据推测,这是因为我使用给定的ARFrame来查找2D地标,但是当我异步执行命中测试时,我无法保证我的面部节点SCNNode处于相同的位置就像捕获帧时一样,它可能会移动一点点。 (使用ARFaceTrackingConfiguration跟踪/更新面部锚点。

有没有办法创建我可以传递的面部节点的“冻结”副本,以便异步执行命中测试而不会同时更改节点的位置?

根据我的理解,clone()copy()没有提供我正在寻找的内容。我尝试通过将新的SCNNode设置为原始的几何和位置来编写自己的frozenCopy()函数。但是,当我在创建时打印此节点的worldPosition与命中测试的时间时,它似乎已经改变,即使我实际上没有将它添加到场景层次结构......所以我不喜欢我认为它的行为与我的期望相符。我有这个想法吗?

任何想法都将非常感激。非常感谢!

extension SCNNode {
    func frozenCopy() -> SCNNode {
        // let scnCopy: SCNNode = self.copy() as! SCNNode
        // let scnCopy: SCNNode = self.clone()
        let scnCopy: SCNNode = SCNNode()
        scnCopy.geometry = self.geometry?.copy() as! SCNGeometry?
        scnCopy.transform = self.worldTransform

        // Setting more properties just in case...
        scnCopy.worldOrientation = self.worldOrientation
        scnCopy.worldPosition = self.worldPosition
        scnCopy.camera = self.camera?.copy() as! SCNCamera?
        scnCopy.light = self.light?.copy() as! SCNLight?
        scnCopy.pivot = self.pivot

        return scnCopy
    }
}

我考虑过的一个解决方案是尝试存储面部节点和相机变换以传递给自定义命中测试功能。如果可能的话,我想使用SceneKit API命中测试,因为我认为这比我自己编写的任何函数都要好。

0 个答案:

没有答案