16
16

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

ARKitで動き出すポスターを作る

Posted at

ポスターやカードをカメラで写すとARが浮かび上がってくるタイプのARが流行っています。手軽でできて分かりやすいARです。この機能をARKitで実装する方法を紹介していきます。

以下みたいなイメージ。

gif.gif
https://www.youtube.com/watch?v=mg-RDMab6VQ

[Swift/ARKit2] 動くポスターを1時間でつくろうという記事の実装部分の解説です。

ポスター画像と再生用の動画を用意する

 画像マーカーとなるポスター画像ファイルと、マーカーを読み取った際に再生する動画ファイルを用意しましょう。それぞれjpgファイルとmp4ファイルだと間違いないと思います。また、2Dのポスターが突然動き出すように表現するためには、それぞれ縦横比を統一した方が良いでしょう。

ポスター画像をARImageResourceに登録する

 ARKitで作るAR名刺と同じ容量で、ポスターが画像をARImageResourceに登録しましょう。

ポスター動画をプロジェクトに追加する

 ポスター動画(例ではmovie.mp4というファイル)をXcodeのプロジェクトに対してドラッグアンドドロップします。

画像を読み取ったら反応するようにする

まずはsceneViewをARSCNViewDelegateに準拠させます。また、AR Resourcesの画像をtrackingImagesとしてARImageTrackingConfigurationにセットしときます。

override func viewDidLoad() {
    super.viewDidLoad()
        
    sceneView.delegate = self
}

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    
    let configuration = ARImageTrackingConfiguration()
    
    if let trackedImages = ARReferenceImage.referenceImages(inGroupNamed: "AR Resources", bundle: Bundle.main) {
        configuration.trackingImages = trackedImages
    }
    sceneView.session.run(configuration)
}

 以下のようにrenderer(didAdd node:)のメソッドを書き、ARImageAnchorの発見を検知します。

extension ViewController: ARSCNViewDelegate {
    func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) {
        guard let imageAnchor = anchor as? ARImageAnchor else {
            return
        }
    }
}

SKVideoNodeとSKSceneで動画のシーンを作成する

 次にARKit(正確にはSceneKit)で動画を再生する方法を解説します。動画自体は2Dなので、今回SpriteKitを使って動画を再生します。SpriteKitで作られたSKSceneをSceneKitで再生していきます。

 予め用意してXcodeにドラッグアンドドロップしていたmovie.mp4を呼び出して動画を再生します。

guard let imageAnchor = anchor as? ARImageAnchor else {
    return
}
guard let fileUrlString = Bundle.main.path(forResource: "movie", ofType: "mp4") else {
    return
}
let videoItem = AVPlayerItem(url: URL(fileURLWithPath: fileUrlString))
let player = AVPlayer(playerItem: videoItem)
player.play()

次に、SKSceneを作成し、その中にSKVideoNodeを追加します。

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

let videoNode = SKVideoNode(avPlayer: player)
videoNode.position = CGPoint(x: size.width / 2, y: size.height / 2)
videoNode.yScale = -1.0

videoScene.addChild(videoNode)

SCNPlaneのマテリアルとして動画のシーンをセットする

 最後にポスターと同じサイズの平面のジオメトリを持つSCNNodeを作成し、そのマテリアルとして、動画を再生するSKSceneを渡すことで、動画を再生する平面のノードを作ることができます。最後にその平面をImageAnchorの位置にあるnodeに追加して完成です。

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 = -Float.pi / 2
node.addChildNode(planeNode)

画像検知後の一連のコードは以下です。

extension ViewController: ARSCNViewDelegate {
    func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) {
        guard let imageAnchor = anchor as? ARImageAnchor,
            let fileUrlString = Bundle.main.path(forResource: "black", ofType: "mp4") else {
                return
        }
        let videoItem = AVPlayerItem(url: URL(fileURLWithPath: fileUrlString))
        let player = AVPlayer(playerItem: videoItem)
        player.play()
        
        let size = CGSize(width: 480, height: 360)
        let videoScene = SKScene(size: size)
        
        let videoNode = SKVideoNode(avPlayer: player)
        videoNode.position = CGPoint(x: size.width / 2, y: 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 = -Float.pi / 2
        node.addChildNode(planeNode)
    }
}

以上です。特定のポスター画像を発見すると、その位置に動画を再生することができました。

gif

(動画はイメージ Using ARKit To Display Video In Augmented Realityから引用)

関連記事

https://qiita.com/IZUMIRU/items/3c36f7730aff5e6305c5
https://medium.com/quick-code/using-arkit-to-display-video-in-augmented-reality-3a2e4c1418ad

16
16
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
16
16

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?