跟踪多个图像并在 ARkit2 中播放它们的视频
Tracking multiple images and play their videos in ARkit2
我有下面的示例代码,跟踪单个图像然后使用 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
}
您必须在 ARConfiguration 上设置 maximumNumberOfTrackedImages。
Setting the maximum number of tracked images will limit the number of
images that can be tracked in a given frame.
If more than the maximum is visible, only the images already being tracked will continue to track until tracking is lost or another
image is removed.
Default value is one.
configuration.maximumNumberOfTrackedImages = 2
正如@SilentK 所说,为了跟踪多个 ARImageAnchors
,您需要设置要跟踪的最大图像数,例如:
configuration.maximumNumberOfTrackedImages = 10
从 IOS12
开始,ARWorldTrackingConfiguration
和 ARImageTrackingConfiguration
都可用。
正如您所知,当您将 ARReferenceImage
添加到 Assets Bundle
时,您必须为其分配一个 name
,例如:
现在由于每个目标都包含一个唯一的名称,您可以轻松地使用它来加载您的不同视频。因此,将每个视频命名为与您的 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,这将触发它播放等
希望对您有所帮助...
我有下面的示例代码,跟踪单个图像然后使用 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
}
您必须在 ARConfiguration 上设置 maximumNumberOfTrackedImages。
Setting the maximum number of tracked images will limit the number of images that can be tracked in a given frame. If more than the maximum is visible, only the images already being tracked will continue to track until tracking is lost or another image is removed. Default value is one.
configuration.maximumNumberOfTrackedImages = 2
正如@SilentK 所说,为了跟踪多个 ARImageAnchors
,您需要设置要跟踪的最大图像数,例如:
configuration.maximumNumberOfTrackedImages = 10
从 IOS12
开始,ARWorldTrackingConfiguration
和 ARImageTrackingConfiguration
都可用。
正如您所知,当您将 ARReferenceImage
添加到 Assets Bundle
时,您必须为其分配一个 name
,例如:
现在由于每个目标都包含一个唯一的名称,您可以轻松地使用它来加载您的不同视频。因此,将每个视频命名为与您的 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,这将触发它播放等
希望对您有所帮助...