在ARkit2中跟踪多个图像并播放其视频

时间:2018-09-06 13:22:35

标签: swift augmented-reality arkit

下面是示例代码,跟踪单个图像,然后使用Apple的ARkit播放视频。 当前,视频在本地存储在设备上。 下面的代码仅跟踪单个图像并播放相应的视频。 如何修改它并让其跟踪多张图像并播放其视频?

 @IBOutlet var sceneView: ARSCNView!

// Create video player
let videoPlayer: AVPlayer = {
    // Load cat video from bundle
    guard let url = Bundle.main.url(forResource: "nyan-cat", withExtension: "mp4", subdirectory: "art.scnassets") else {
        print("Could not find video file")
        return AVPlayer()
    }

    let player = AVPlayer(url: url)

    NotificationCenter.default.addObserver(forName: NSNotification.Name.AVPlayerItemDidPlayToEndTime, object: nil, queue: nil) { notification in
        player.seek(to: CMTime.zero)
        player.play()
    }
    return player
}()

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

    // Show video overlayed to image
    if let imageAnchor = anchor as? ARImageAnchor {

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

        // Set AVPlayer as the plane's texture and play
        plane.firstMaterial?.diffuse.contents = self.videoPlayer
        self.videoPlayer.play()

        let playNode = SCNNode(geometry: plane)

        // Rotate the plane to match the anchor
        playNode.eulerAngles.x = -.pi / 2

        // Add plane node to parent
        node.addChildNode(playNode)
    }

    return node
}

2 个答案:

答案 0 :(得分:1)

如@SilentK所述,要跟踪多个ARImageAnchors,您需要设置要跟踪的最大图像数量,例如:

configuration.maximumNumberOfTrackedImages = 10

IOS12ARWorldTrackingConfiguration均可使用ARImageTrackingConfiguration的版本。

您还将知道,在将ARReferenceImage添加到Assets Bundle时,您必须为其分配一个name,例如:

enter image description here

现在,由于每个目标都包含一个唯一的名称,因此您可以轻松地使用它来加载不同的视频。因此,将每个视频命名为与imageTarget相同是最有意义的。

您要尝试执行的操作的示例可能如下所示:

//-------------------------
//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

    }

}

如果渲染了多个实例,则使用此方法进行无限循环播放会占用大量CPU:

 NotificationCenter.default.addObserver(forName: NSNotification.Name.AVPlayerItemDidPlayToEndTime, object: nil, queue: nil) { notification in
        player.seek(to: CMTime.zero)
        player.play()
    }

因此,您可能需要添加逻辑,一次仅播放一个视频,例如在VideoNode上执行SCNHitTest,这将触发它播放等。

希望有帮助...

答案 1 :(得分:0)

您必须在ARConfiguration上设置maximumNumberOfTrackedImages。

  

设置最大跟踪图像数量将限制   可以在给定帧中跟踪的图像。        如果可见的最大值超过最大值,则仅已被跟踪的图像将继续跟踪,直到跟踪丢失或其他   图像被删除。        默认值为1。

        configuration.maximumNumberOfTrackedImages = 2