[iOS 11][ARKit] 近所の駐車場で、大型ディスプレイでビデオを見る!
1 はじめに
うちの近所の駐車場には、縦3m、横5mの大型ディスプレイは、ありません・・・
そこで、ARKitで、その気になれるサンプルアプリを作成して見ました。
これは、ARKitでシーン上に1つのキューブを表示して、そのテクスチャーに動画を貼ったものです。
今回は、このようなアプリの作成方法について紹介させて頂きます。
2 SKVideoNode
SKVideoNodeは、SpriteKitで使用するノードの一つであり、名前からも想像できるとおり、ビデオの再生ができます。
Documentation > SpriteKit > SKVideoNode
残念ながら、SKVideoNodeは、SpriteKit(2D)のシーン(SKScene)にしか追加できませんが、SceneKit(3D)のノードの表面を表現するSCNMaterialには、テクスチャーのようにSKSceneを適用することができます。
従って、AVPlayer -> SKVideoNode(2D) -> SKScene(2D) -> SCNMaterial(3D)という順に適用すれば、SceneKit(3D)のノードのテクスチャーとして動画を使用できることになります。
3 動画テクスチャーとして適用したキューブ
先の適用順でSCNNodeを生成するコードは、下記のようになります。
func createVideoNode(size:CGFloat, videoUrl: URL) -> SCNNode { // AVPlayerを生成する let avPlayer = AVPlayer(url: videoUrl) // SKSceneを生成する let skScene = SKScene(size: CGSize(width: 1000, height: 1000)) // あまりサイズが小さいと、ビデオの解像度が落ちる // AVPlayerからSKVideoNodeの生成する let skNode = SKVideoNode(avPlayer: avPlayer) // シーンと同じサイズとし、中央に配置する skNode.position = CGPoint(x: skScene.size.width / 2.0, y: skScene.size.height / 2.0) skNode.size = skScene.size skNode.yScale = -1.0 // 座標系を上下逆にする skNode.play() // 再生開始 // SKSceneに、SKVideoNodeを追加する skScene.addChild(skNode) // SCNBoxノードを生成して、マテリアルにSKSeceを適用する let node = SCNNode() node.geometry = SCNBox(width: size, height: size, length: size, chamferRadius: 0) let material = SCNMaterial() material.diffuse.contents = skScene node.geometry?.materials = [material] node.scale = SCNVector3(1.7, 1, 1) // サイズは横長 return node }
そして、このノードを生成して、シーンに追加する要領です。
// ビデオのURL let videoUrl = Bundle.main.url(forResource: "video", withExtension: "mp4")! // ビデオ動画をテクスチャーとして適用した縦3mのキューブの生成 let videoNode = createVideoNode(size: 3.0, videoUrl: videoUrl) // 位置は、カメラの前方5m videoNode.position = SCNVector3(0, 0, -5.0) // シーンに追加する sceneView.scene.rootNode.addChildNode(videoNode)
4 動画のループ再生
動画をエンドレスに再生したい場合、AVPlayerの機能でループ再生するだけです。
//ループ再生 avPlayer.actionAtItemEnd = AVPlayerActionAtItemEnd.none; NotificationCenter.default.addObserver(self, selector: #selector(ViewController.didPlayToEnd), name: NSNotification.Name("AVPlayerItemDidPlayToEndTimeNotification"), object: avPlayer.currentItem)
再生が終了した時点で、最初までシークする
@objc func didPlayToEnd(notification: NSNotification) { let item: AVPlayerItem = notification.object as! AVPlayerItem item.seek(to: kCMTimeZero, completionHandler: nil) }
5 最後に
動画がテクスチャーとして利用できると、また、色々楽しそうなものが作れそうです。
ほんと、ARKitは凄いと思います。
コードは、下記に置きました。参考になれば幸いです。
[GitHub] https://github.com/furuya02/ARKitVideoSample
※動画は、ATTRIBUTION LICENSE 3.0 で公開されている、Mikah氏のものを利用させて頂きました。 http://mazwai.com/#/grid/videos/14
6 参考リンク
Introducing ARKit
Apple Developer > Documentation > ARKit
WWDC2017 Session 602 Introducing ARKit: Augmented Reality for iOS
ARKit by Example — Part 3: Adding geometry and physics fun
[iOS 11] はじめてのARKit #WWDC2017
[iOS 11][ARKit] 距離の計測について #WWDC2017
[iOS 11][ARKit] 平面の検出について #WWDC2017
[iOS 11][ARKit] 物理衝突を実装して、キューブを落として見る #WWDC2017
[iOS 11][ARKit] 空間に3Dテキストを表示してみる #WWDC2017
[iOS 11] ARKitでソファー設置からあの子の身長測定まで色々やってみた