この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
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でソファー設置からあの子の身長測定まで色々やってみた