我正在尝试检测相机何时面对放置在ARSKView中的物体。这是代码:
override func update(_ currentTime: TimeInterval) {
// Called before each frame is rendered
guard let sceneView = self.view as? ARSKView else {
return
}
if let currentFrame = sceneView.session.currentFrame {
//let cameraZ = currentFrame.camera.transform.columns.3.z
for anchor in currentFrame.anchors {
if let spriteNode = sceneView.node(for: anchor), spriteNode.name == "token", intersects(spriteNode) {
// token is within the camera view
let distance = simd_distance(anchor.transform.columns.3,
currentFrame.camera.transform.columns.3)
//print("DISTANCE BETWEEN CAMERA AND TOKEN: \(distance)")
if distance <= captureDistance {
// token is within the camera view and within capture distance
print("token is within the camera view and within capture distance")
}
}
}
}
}
问题在于,当对象直接位于相机的前面和后面时,intersects方法都返回true。如何更新此代码,使其仅检测spriteNode在当前相机取景器中的时间?顺便说一下,我正在使用SpriteKit,而不是SceneKit。
这是我用来实际创建锚点的代码:
self.captureDistance = captureDistance
guard let sceneView = self.view as? ARSKView else {
return
}
// Create anchor using the camera's current position
if sceneView.session.currentFrame != nil {
print("token dropped at \(distance) meters and bearing: \(bearing)")
// Add a new anchor to the session
let transform = getTransformGiven(bearing: bearing, distance: distance)
let anchor = ARAnchor(transform: transform)
sceneView.session.add(anchor: anchor)
}
func getTransformGiven(bearing: Float, distance: Float) -> matrix_float4x4 {
let origin = MatrixHelper.translate(x: 0, y: 0, z: Float(distance * -1))
let bearingTransform = MatrixHelper.rotateMatrixAroundY(degrees: bearing * -1, matrix: origin)
return bearingTransform
}
答案 0 :(得分:1)
我花了一段时间研究得出的结论是,试图获得currentFrame.camera
和anchor
之间的距离并不能简单地因为它返回相似的值而与anchor
是在摄像机的前面还是后面。我的意思是,假设我们的锚点位于x点,并且向前移动1米或向后移动1米,则距摄像机和锚点的距离仍为1米。
这样,经过一些试验,我相信我们需要查看以下variables
和functions
来帮助我们检测我们的SKNode
是否在镜头前:
(a)SpriteNode的zPosition
指向:
节点的z顺序(用于排序)。负数z是“插入”屏幕,正数z是“移出”屏幕
(b)open func intersects(_ node: SKNode) -> Bool
其中:
如果此节点的边界与边界相交,则返回true。 另一个节点的转换边界,否则为false。
因此,以下内容似乎可以完全满足您的需求:
override func update(_ currentTime: TimeInterval) {
//1. Get The Current ARSKView & Current Frame
guard let sceneView = self.view as? ARSKView, let currentFrame = sceneView.session.currentFrame else { return }
//3. Iterate Through Our Anchors & Check For Our Token Node
for anchor in currentFrame.anchors {
if let spriteNode = sceneView.node(for: anchor), spriteNode.name == "token"{
/*
If The ZPosition Of The SpriteNode Is Negative It Can Be Seen As Into The Screen Whereas Positive Is Out Of The Screen
However We Also Need To Know Whether The Actual Frostrum (SKScene) Intersects Our Object
If Our ZPosition Is Negative & The SKScene Doesnt Intersect Our Node Then We Can Assume It Isnt Visible
*/
if spriteNode.zPosition <= 0 && intersects(spriteNode){
print("Infront Of Camera")
}else{
print("Not InFront Of Camera")
}
}
}
}
希望有帮助...
答案 1 :(得分:1)
您也可以使用此功能检查相机的位置:-
- (void)session:(ARSession *)session didUpdateFrame:(ARFrame *)frame; {
simd_float4x4 transform = session.currentFrame.camera.transform;
SCNVector3 position = SCNVector3Make(transform.columns[3].x,
transform.columns[3].y,
transform.columns[3].z);
// Call any function to check the Position.
}
答案 2 :(得分:0)
我会给你一个线索。像这样检查ZPosition。
if let spriteNode = sceneView.node(for: anchor),
spriteNode.name == "token",
intersects(spriteNode) && spriteNode.zPosition < 0 {....}