我试图验证特定节点是否在场景的当前平截头体内。 因此,我使用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!)
//...
}
}
这里进行节点的评估。结果总是如此。
答案 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)")
}
}