Определите, находится ли SKNode перед камерой (ARKit Spritekit) - PullRequest
0 голосов
/ 16 октября 2018

Я пытаюсь определить, когда камера направлена ​​на мой объект, который я поместил в 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
    }

Ответы [ 3 ]

0 голосов
/ 20 октября 2018

Я провел некоторое время, глядя на это, и пришел к выводу, что попытка получить расстояние между currentFrame.camera и anchor не работает просто потому, что возвращает одинаковые значения независимо от того, anchor перед или позади камеры.Под этим я подразумеваю, что если мы предположим, что наш якорь находится в точке x, и мы движемся вперед на 1 метр или назад на 1 метр, расстояние от камеры и якоря все еще составляет 1 метр.

Таким образом, после некоторых экспериментовЯ считаю, что нам нужно взглянуть на следующие variables и functions, чтобы помочь нам определить, находится ли наш SKNode перед камерой:

(a) zPosition SpriteNode, который относится к:

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")
            }

        }
    }
}

Надеюсь, это поможет ...

0 голосов
/ 22 октября 2018

Вы также можете использовать эту функцию для проверки положения камеры: -

- (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.
 }
0 голосов
/ 19 октября 2018

Я бы дал вам подсказку.Проверьте ZPosition следующим образом.

    if let spriteNode = sceneView.node(for: anchor), 
       spriteNode.name == "token", 
       intersects(spriteNode) && spriteNode.zPosition < 0 {....}
...