Tutti Lab

元シリコンバレー在住のおっさん技術者、モバイルVRアプリ開発に挑戦中

Cardboardで360度立体視動画ビューワーを作る(1)

はじめに

これまで計6回にわたり、CardboardでVRゲームアプリを作るという内容で書いてきました。今回からは(数回にわたり)、360度立体視動画のビューワーアプリを開発していきたいと思います。このアプリ、娘とハッカソンに参加で書いた、メイカーフェアー向けアプリとして仕上げていくつもりです。なおこのアプリは「オリンピックを360度立体視動画で配信する」というコンセプトであり、単に指定したファイルのビューワーとして機能するだけでなく、360度立体視撮影カメラと連携し、カメラで撮影した映像をリアルタイムで本アプリへ配信・鑑賞できるようにする機能が必要となります。
今回はまず手始めに、360度立体視動画ファイル(ストリーミングではない)をCardboardで視聴するためのアプリを作ります。次回以降にて、360度立体視撮影カメラと連携したシステムへ仕上げていく予定です。

Movie Texture

360度立体視視聴可能なアプリの実現は、実はそれほど難しくありません。ムービーファイルを読み込み、適当な3Dオブジェクト(360度映像の場合は球)の面上でムービーを再生するだけ、です。ただ今回は「立体視」なので、ムービーには左右両方の映像が含まれています。例えばこんな感じです。これを左右それぞれに分割し、左目用は左目用の球の面に、右目用は右目用の球の面に、貼り付けることになります。最後に、左目用の3Dオブジェクトは左目側だけ、右目用の3Dオブジェクトは右目側だけで表示するように、カメラの設定を変更すれば完成!となります。
ただここで問題となるのが、どうやってムービーファイルを読み込んで3Dオブジェクトの面上で再生するか、という点です。UnityにはMovieTextureというAPIが用意されておりますが、残念ながらモバイル(Android/iOS)には現時点で未対応です。
幸いAsset Storeでは、これをモバイルで実現するためのアセットが公開されております。色々と先人の調査結果を参照したところ、Easy Movie Textureというアセットが良い、との情報に行き着きました。
本アセットは現在$55、無料のアセットではありませんが、非常に簡単に利用でき、かつ再生制御のためのAPIも充実していて、お買い得なアセットかと思います。
本アセットの機能は、以下の動画を見れば一目瞭然かと思います。
youtu.be

球の3Dオブジェクトを入手

次にテクスチャを貼り付ける球ですが、Unityの3D Object Sphereではうまくいきません。今回は球の外面ではなく、カメラを球の中心に設置・内面にテクスチャを貼り付けてムービーを再生して、まるでプラネタリウムを観るような感じを実現する必要があるのですが、Sphereは球の内側から見ると透過してしまいます(何らか内側から見えるようにする設定があるのかもしれませんが、私は知りません。。)。また詳細はわからないのですが、いろいろな解説ページを見る限り、球の3D形状も何でも良いわけではないようです。
そこで、こちらのサイトにて公開されている「sphere100.fbx」を活用させていただくことにしました。

球をシーン上に配置

あとは、これら用意したアセット群をシーンに配置していきます。
まずは、前回ご紹介した手順で、Cardboard SDKを取り込みます。ProjectのAssets上で、右クリック→Import Package→Custom Packageを選択、CardboardSDKForUnity.unitypackageをインポートします。インポートしたらAssets/Cardboard/Prefab/CardboardMain.prefabをHierarchyにドラッグ&ドロップします。なお、CardboardというオブジェクトがHierarchyにあるかと思います。こちらは削除してください。同様に、デフォルトでHierarchy上に配置されているMain Camera、Directional lightもいらないので削除してください。
次に右目用・左目用それぞれの球を作成します。まずはこれらをグルーピングするための空オブジェクトを生成(Hierarchyより右クリック→Create Empty)、名前をSpheresとします。そこにぶら下げる形で、上記でダウンロードしたsphere100.fbxを二つ追加します。sphere100.fbxをAssets配下の適当なフォルダに入れておけば、それをHierarchyのSphere上でドラッグ&ドロップするだけです。二つドラッグ&ドロップののち、名前をそれぞれ、Sphere100_L, Sphere100_Rとしてください。以上で、Hierarchyは以下のような感じになります。
f:id:tuti107:20160416113810p:plain
それぞれ、Position/Scaleを以下の通り設定してください。xはマイナス値となっていますが、これは(なぜか)こうしないとムービーが左右反転してしまうためです(現在のところ原因不明)。
f:id:tuti107:20160416120203p:plain

Easy Movie Textureの設定

次に、上記でご紹介したEasy Movie Textureをインポートし、各種設定を行っていきます。
まずは、球の内側に貼り付けるテクスチャのマテリアルを用意します。利用するマテリアルはAssets/EasyMovieTexture/VideoMaterial.matなのですが、左右別個に必要となるため、VideoMaterial.matをコピーし、二つ複製、それぞれ名前をVideoMaterial_L.mat, VideoMaterial_R.matとします。なお複製ですが、Command+C→Command+V(WindowsならCtrl)、ではありません。Command+C→Command+Dで複製できます。
f:id:tuti107:20160416114051p:plain
これらマテリアルを作成したら、それぞれのTiling, Offsetの値を変更します。それぞれ、VideoMaterial_Lは、Tiling=(1, 0.5), Offset=(0, 0)、VideoMaterial_Rは、Tiling=(1, 0.5), Offset=(0, 0.5)とします。これは、上記で説明した通り、ムービーには左右両眼用のものが縦に並んで配置されており(左目用が上、右目用が下)、右目用の球・左目用の球にそれぞれ分離して貼り付ける必要があります。そこで、Tiling(1を全部とした時、縦・横それぞれどこまでテクスチャとして扱うか)を、(1,0.5)として、横方向は全部・縦方向はムービーの縦方向サイズの半分だけ使用、Offset(どの位置からテクスチャとして扱うか)を、左目用は(0,0)=左上、右目用は(0,0.5)=左側・縦方向は中央の位置、として、右目・左目それぞれの部分のみテクスチャとして利用する、としています。
f:id:tuti107:20160416115342p:plainf:id:tuti107:20160416115347p:plain
また、いずれもShaderをUnlit/Textureに変更してください。これで、このマテリアルが設定された面は照明の影響を受けなくなります。これらマテリアルの設定が終わりましたら、VideoMaterial_Lを、shere100_LのMaterialsへ、VideoMaterial_Rを、sphere100_RのMaterialsへそれぞれドラッグ&ドロップしてください。これで、これらそれぞれの球にそれぞれのマテリアルが設定されます。
f:id:tuti107:20160416120215p:plain
合わせて、sphere100_L, sphere100_RにそれぞれレイヤーEYE_L, EYE_Rを割り当てます。レイヤーは、インスペクター右上のLayerをクリックすることで、変更(追加)できます。まずLayer→Add Layerより、EYE_L, EYE_Rを追加します。
f:id:tuti107:20160416121335p:plain
その後再びLayerをクリックすると、EYE_L, EYE_Rを選択できるようになります。これら設定は、後述の「左目からは左目用の球を、右目からは右目用の球のみ見えるようにする」ために利用します。
最後に、Media Player Ctrlの設定を行います。Hirarchyにて右クリック→Create Emptyで空オブジェクトを作成、名前を「Player」としたのち、インスペクターよりAdd Componentを押下→Media Player Ctrlを追加してください(これがEasy Movie Textureの本体です)。このMedia Player Ctrl、どのオブジェクトに貼り付けてもいいのですが(例えばCardboardMain)、とりあえずこのような形としました。
f:id:tuti107:20160416125109p:plain

  • Str File Nameには、再生するムービーファイルの名前を設定します。ストリーミング形式(例えばhttp://www.test.com/test.mp4)も指定できるようですが、まだ試せていません。今回は、360度立体視動画のムービーファイルを用意し、これをAssets/StreamingAssets配下に格納、本ファイルのファイル名を設定しております(BSDance.mp4)。ムービーファイルはAssets/StreamingAssetsに置くようにしてください。なお、YouTubeのストリーミング動画をmp4に変換する方法についてはここでは触れません。
  • Target Materialには、再生したムービーを貼り付ける3Dオブジェクトを設定します。今回は、左右両眼用の球sphere100_L, sphere100_Rを設定します(Sizeを2とすることで二つ設定が可能です)。
  • B Full Screenはフルスクリーンビデオ再生の際にチェックします。今回は使用しません。
  • BSupport Rockchipは、特定のチップ搭載の端末時の問題解決用、とのことです。今回は使用しません(本チップ搭載の端末を持っていません)。
  • ScaleValueとobjResizeは、Game Objectのリサイズに利用します。今回は使用しません。
  • B Loopをチェックすると、ムービー再生完了時、自動的にループ再生します
  • B Auto playをチェックすると、Media Player Ctrlを設定したGameObjectがアクティブになった際に、自動的にムービー再生を開始します。

なお、iOS端末の場合、Unityのバージョンに合わせて、パッチを当てる必要があります。Unity 5以降なら、Assets/EasyMovieTexture/Unity5_Patch_IOS、Unity4.6.3以降なら、Assets/EasyMovieTexture/Unity463_Patch_IOS、をそれぞれダブルクリックし、必要なパッチをインポートしてください。

Cardboardの設定

最後に、Cardboardの設定を行います。右目・左目用それぞれのカメラのToggle Culling Maskを設定し、それぞれのカメラからそれぞれの目用の球のみ見えるようにします。
f:id:tuti107:20160416131945p:plainf:id:tuti107:20160416131948p:plain
ここで注意が必要なのが、Culling Maskではなく、Toggle Culling Maskだということです。その名の通りトグルした値の設定します。上記はMain Camera Leftの設定ですが、Toggle Culling Maskには右目用レイヤーのEYE_Rを設定します。すると、Main Camera Leftは設定されたEYE_R「以外」のレイヤーを表示するようになります(よって左目用の球は、EYE_Lレイヤーに設定されているので、見えます)。同様に、Main Camera RightのToggle Culling MaskにはEYE_Lを設定します。
以上で全ての設定が完了です。前回ご説明の通り、File→Build SettingsよりiOSまたはAndroidを選択後、Player Settingにて、Bundle IdentifierとDefault Orientationを設定し、Buildしてください。なお、iOSの場合は、XCodeにてBitcode=No, Security Frameworkの追加が必要な点、ご注意ください。
f:id:tuti107:20160416133222j:plain

まとめ

今回は、360度立体視動画ビューワーを作る、ということで、EasyMovieTextureを活用し、ファイル指定した360度立体視動画の再生が可能なアプリを作成するところまで進めました。1行もコードを書くことなくこれだけの機能が実現できるのは、まさにUnity, Asset Storeのおかげです。
次回は、本アプリでストリーミング動画再生にチャレンジする予定です。