Как я могу обнаружить несколько изображений в AR? - PullRequest
0 голосов
/ 23 апреля 2019

Я создаю это приложение для живой газеты с ARKit, которое преобразует изображения из газеты в видео. Я могу обнаружить одно изображение и воспроизвести на нем видео, но когда я пытаюсь сделать это на двух изображениях и воспроизводить соответствующее видео на этих изображенияхя получаю сообщение об ошибке типа Attempted to add a SKNode which already has a parent

Я пытался проверить отслеживаемые изображения и сравнить их с эталонными изображениями, но я думаю, что с моей логикой что-то не так.

Это мой ViewDidAppear() метод

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)

    // Create a session configuration
    let configuration = ARImageTrackingConfiguration()

    if  let trackedImages = ARReferenceImage.referenceImages(inGroupNamed: "NewsPaperImages", bundle: Bundle.main) {

        configuration.trackingImages = trackedImages
        configuration.maximumNumberOfTrackedImages = 20



    }

    // Run the view's session
    sceneView.session.run(configuration)
}

func renderer(_ renderer: SCNSceneRenderer, nodeFor anchor: ARAnchor) -> SCNNode? {
    let node = SCNNode()

    if let imageAnchor = anchor as? ARImageAnchor {

        if(imageAnchor.referenceImage == UIImage(named: "Image2_River")) {
            self.videoNode = SKVideoNode(fileNamed: "riverBeauty.mp4")
        }

        print("Yes it is an image")
        self.videoNode.play()

        let videoScene = SKScene(size: CGSize(width: 480, height: 360))

        videoNode.position = CGPoint(x: videoScene.size.width/2, y: videoScene.size.height/2)
        videoNode.yScale = -1.0
        videoScene.addChild(videoNode)

        let plane = SCNPlane(width: imageAnchor.referenceImage.physicalSize.width, height: imageAnchor.referenceImage.physicalSize.height)


        plane.firstMaterial?.diffuse.contents = videoScene

        let planeNode = SCNNode(geometry: plane)
        planeNode.eulerAngles.x = -.pi/2

        node.addChildNode(planeNode)

        }
    return node

}

должно воспроизводиться видео на каждом обнаруженном изображении, но вместо этого происходит сбой.

1 Ответ

0 голосов
/ 27 апреля 2019

Глядя на ваш код и исходя из того, что вы сказали, я думаю, что вам нужно изменить свою логику, чтобы создать видео-узел, используя вместо этого свойство name вашего ARReferenceImage.

Когда вы создаете ARReferenceImage либо статически (в пределах ARResourceBundle), либо динамически, вы можете присвоить ему имя, например:

enter image description here

Затем вы можете использовать имена, чтобы добавить логику, чтобы назначить различное видео каждому обнаруженному referenceImage.

И чтобы сохранить ваш код DRY, вы можете создать функцию многократного использования для создания вашего видео узла.

Как простой пример может выглядеть примерно так:

  //-------------------------
  //MARK: - ARSCNViewDelegate
  //-------------------------

  extension ViewController: ARSCNViewDelegate{

    func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) {

      //1. Check We Have Detected An ARImageAnchor
      guard let validAnchor = anchor as? ARImageAnchor else { return }

      //2. Create A Video Player Node For Each Detected Target
      node.addChildNode(createdVideoPlayerNodeFor(validAnchor.referenceImage))

    }


    /// Creates An SCNNode With An AVPlayer Rendered Onto An SCNPlane
    ///
    /// - Parameter target: ARReferenceImage
    /// - Returns: SCNNode
    func createdVideoPlayerNodeFor(_ target: ARReferenceImage) -> SCNNode{

      //1. Create An SCNNode To Hold Our VideoPlayer
      let videoPlayerNode = SCNNode()

      //2. Create An SCNPlane & An AVPlayer
      let videoPlayerGeometry = SCNPlane(width: target.physicalSize.width, height: target.physicalSize.height)
      var videoPlayer = AVPlayer()

      //3. If We Have A Valid Name & A Valid Video URL The Instanciate The AVPlayer
      if let targetName = target.name,
        let validURL = Bundle.main.url(forResource: targetName, withExtension: "mp4", subdirectory: "/art.scnassets") {
        videoPlayer = AVPlayer(url: validURL)
        videoPlayer.play()
      }

      //4. Assign The AVPlayer & The Geometry To The Video Player
      videoPlayerGeometry.firstMaterial?.diffuse.contents = videoPlayer
      videoPlayerNode.geometry = videoPlayerGeometry

      //5. Rotate It
      videoPlayerNode.eulerAngles.x = -.pi / 2

      return videoPlayerNode

    }

  }

Как вы можете видеть, я решил использовать AVPlayer в качестве моего видеоконтента, хотя вы можете продолжать использовать вашу видеосцену, если пожелаете.

Надеюсь, это направит вас в правильном направлении ...

...