问题描述
我将3d对象放置在世界空间中。之后,我尝试随机移动相机。然后,现在我需要知道通过isNode
方法对象是否已位于视锥内部,该对象是否位于相机视图的中心,顶部或底部。
解决方法
解决方案
要实现此目的,您需要使用技巧。创建新的SCNCamera,使其成为pointOfView
默认摄像机的子级,并将其FoV
设置为大约10度。
然后在renderer(_:updateAtTime:)
实例方法内部使用isNode(:insideFrustumOf:)
方法。
这是工作代码:
import ARKit
class ViewController: UIViewController,ARSCNViewDelegate,SCNSceneRendererDelegate {
@IBOutlet var sceneView: ARSCNView!
@IBOutlet var label: UILabel!
let cameraNode = SCNNode()
let sphereNode = SCNNode()
let config = ARWorldTrackingConfiguration()
public func renderer(_ renderer: SCNSceneRenderer,updateAtTime time: TimeInterval) {
DispatchQueue.main.async {
if self.sceneView.isNode(self.sphereNode,insideFrustumOf: self.cameraNode) {
self.label.text = "In the center..."
} else {
self.label.text = "Out OF CENTER"
}
}
}
override func viewDidLoad() {
super.viewDidLoad()
sceneView.delegate = self
sceneView.allowsCameraControl = true
let scene = SCNScene()
sceneView.scene = scene
cameraNode.camera = SCNCamera()
cameraNode.camera?.fieldOfView = 10
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
self.sceneView.pointOfView!.addChildNode(self.cameraNode)
}
sphereNode.geometry = SCNSphere(radius: 0.05)
sphereNode.geometry?.firstMaterial?.diffuse.contents = UIColor.red
sphereNode.position.z = -1.0
sceneView.scene.rootNode.addChildNode(sphereNode)
sceneView.session.run(config)
}
}
此外,在此解决方案中,您可以为儿童相机开启orthographic projection
,而不是perspective
。当模型远离相机时,它会有所帮助。
cameraNode.camera?.usesOrthographicProjection = true
这是您的屏幕外观:
下一步
以相同的方式可以添加两个附加的SCNCameras,将它们放置在中央SCNCamera的上方和下方,并使用两个附加的isNode(:insideFrustumOf:)
实例方法测试对象。
对于不是黑客的解决方案,可以使用projectPoint:
API。
最好使用像素坐标,因为此方法使用实际摄像机的设置来确定对象在屏幕上的显示位置。
let projectedPoint = sceneView.projectPoint(self.sphereNode.worldPosition)
let xOffset = projectedPoint.x - screenCenter.x;
let yOffset = projectedPoint.y - screenCenter.y;
if xOffset * xOffset + yOffset * yOffset < R_squared {
// inside a disc of radius 'R' at the center of the screen
}
,
我用另一种方法解决了问题
let results = self.sceneView.hitTest(screenCenter!,options: [SCNHitTestOption.rootNode: parentnode])
其中parentnode
是目标节点的父节点,因为我有多个节点。