[iOS] Google VR SDK の代替案としての MetalScope


この記事は、iOS で 360° のパノラマ写真・動画を表示する手段として Google VR SDK for iOS を利用する際の問題点と、その代替案としての MetalScope を紹介するものです。

MetalScope: Metal-backed 360° panorama view for iOS
https://github.com/ejeinc/MetalScope

ちなみに MetalScope のメンテナは僕です。ダイレクトマーケティング。

Google VR SDK for iOS の気になるところ

現在公開されている iOS 向け 360° 動画ビュワーの実装としては、Google VR SDK for iOS が最も有名だと思います。その他にもサードパーティのライブラリがいくつか見つかりますが、Cardboard 用のステレオ表示でレンズの歪み補正ができるのは上記の Google の SDK 以外にはほとんどありません。

この Google 謹製の SDK は、ビューを追加するだけで 360° パノラマ写真・動画をネイティブアプリに簡単に埋め込むことができてとても良い感じなのですが、実際に使ってみると気になる点もあります(そのいくつかは v1.10 以降のアップデートで大幅に改善されました 🎉)。

  • Objective-C の API が Swift 向けに最適化されていない
  • 視点の回転をリセットできず、また初期値の指定ができない
  • ドラッグで視点を回転できるものの、指を離した後に(iOS 特有の)減速アニメーションがなく止まる
  • AVPlayer が隠蔽されているため動画の細かなコントロールに難あり(v1.10v1.20 で改善されました)
  • 動画再生の挙動が不安定である(v1.20 で改善されました)
  • ステレオ表示時の UI をカスタマイズできない(すごく… Android です…)
  • Bitcode 未対応(v1.10 で改善されました)
  • オープンソースではない(CocoaPods 必須、バグ修正が困難 etc…)

MetalScope

MetalScopeGoogle VR SDK for iOS を置き換えることを目的に、SceneKitMetal をベースに開発した iOS 向けの 360° パノラマ描画フレームワークです。

Pros & Cons

Pros

  • Swift 3
  • 視点回転のリセットが可能(アニメーション付き)
  • AVPlayer を直接操作可能(MetalScope は出力を受け取るだけ)
  • ステレオ表示時の UI を自由にカスタマイズ可能
  • SceneKit との互換性(オリジナルの SCNScene を簡単に表示可能)
  • オープンソース

Cons

  • Metal 必須(OpenGL ES とは非互換)
  • iOS 9.0+
  • Objective-C 非サポート
  • Cardboard QR コードの読み取りに未対応
  • パノラマ表示の最大化とステレオ表示への遷移は手動

使い方

PanoramaView

Google の SDK にある GVRPanoramaViewGVRVideoView に相当するのが PanoramaView です。

guard let device = MTLCreateSystemDefaultDevice() else {
    fatalError("MetalScope requires Metal 🤘")
}

let panoramaView = PanoramaView(frame: ..., device: device)

// パノラマ画像(平面視)を読み込む
let panoramaImage = UIImage(...)
panoramaView.load(panoramaImage, format: .mono)

// パノラマ動画(立体視)を読み込む
let videoURL = URL(...)
let player = AVPlayer(url: videoURL)
panoramaView.load(player, format: .stereoOverUnder)
player.play()

// 好きな SCNScene を読み込む
panoramaView.scene = ...

// ダブルタップで回転リセット
let recognizer = UITapGestureRecognizer(
  target: panoramaView,
  action: #selector(PanoramaView.setNeedsResetRotation))
recognizer.numberOfTapsRequired = 2
panoramaView.addGestureRecognizer(recognizer)

60 FPS の動画はこちら

StereoView + StereoViewController

MetalScope では、ビュー構造の明瞭さを重視して PanoramaView とは別に StereoView がステレオ表示用のビュークラスとして用意されています。UIViewController のサブクラスである StereoViewController を使うと interface orientation などの管理を一任することができます。

let stereoViewController = StereoViewController(device: ...)

// メディアを読み込むか
stereoViewController.load(image, format: .stereoOverUnder)

// SCNScene を PanoramaView から引き継ぎ
stereoViewController.scene = panoramaView.scene

// 必要に応じてステレオの歪み補正の値を調整可能
stereoViewController.stereoParameters = StereoParameters(
  screenModel: .default,
  viewerModel: .cardboardMay2015)

present(stereoViewController, animated: true, completion: nil)

おわりに

MetalScope は、もともと弊社アプリ「VR CRUISE」用に開発した独自実装の 360° 動画プレイヤーを整備・改修して公開したものです(当時は Google VR SDK の iOS 版がまだ公開されていませんでした)。今は Google の SDK も公開され、リリース当初にあった問題点もかなり修正されましたが、一方で気になる点もまだあります。もし必要環境に Metal を許容できる場合には、MetalScope も試してみて下さい 😉