2016年3月13日日曜日

Unity5 ThetaSの画像をSkyboxで動的にアニメーション

ThetaSの映像を動的アニメーションで表示したい


360度カメラThetaSで撮影した映像をUnityに取り込んで表示したいです。

要件

要件は次の通りです。
  1. 1人称視点でカメラの向きに応じた角度の映像を見れる。
  2. プログラムから映像の再生をコントロールできる(再生、停止、x倍速再生など)。
1.の要件だけであれば「360度カメラthetaで撮った写真をunityで使う」のやり方で実現できます(このブログエントリでは、Blenderで円球を作っていますが、通常のSphereでもこだわりを捨てれば問題ないと思います。)。
しかし、1.のやり方では、通常の再生のみで2.の再生をコントロールすることができません。現状、MovieTextureでは動画の再生コントロールには対応していないからです。

方針

  • 動画の各フレームを静止画に変換し、静止画のテクスチャを高速で切り替えることでアニメーションを実現する。
  • Sphereマテリアルではなく、Skyboxにアニメーションを投影する。
現状、MovieTextureによる動画の再生コントロールができないようです。そこで、ThetaSで撮影した360度動画の各フレームを静止画として出力して、高速で切り替えることによって上記の要件を実現します。静止画を割り当てたテスクチャを切り替えはプログラムからコントロールするため再生速度などの変更も可能と言えるでしょう。

また今回は、ThetaSで撮影した素材をSkyboxに割り当てます。他のオブジェクトを設置しやすくなるからです。(夜空のThetaS映像をSkyboxで投影し、UFOなどのオブジェクトが動いていたら素敵です。)

早速 作ってみましょう。

Theta Sの360度動画を静止画群に変換

Adobe PremiereとAdobe Media Encoderで動画の各フレームをJPEG画像に変換しました。
ThetaS動画を出力した静止画群

画像群をUnityに取り込み

作成した360度画像群をUnityに取り込みます。一つのディレクトリにまとめてます。
画像群を取り込み

取り込み後はテクスチャをCubeMapとして設定します。すべての画像を選んで、[Unity4,Unity5]thetaとかで撮った全球画像をSkyboxに指定する方法を適応します。すべての画像がCubeMap Typeとして設定されるまでしばらく時間がかかるかと思います。
取り込んだ全ての画像をCubemapテクスチャにする

Skyboxの作成とMain Cameraへアタッチ

  1. 新規マテリアルを作成し、Shaderを「Skybox/Cubemap」にします。
  2. HierarchyでMain Cameraを選択し、InspectorのAdd Componentボタンを押します。
  3. Rendering→Skyboxを選び、Skyboxコンポーネントを追加します。
  4. Custom Skyboxに1.で作成したSkyboxをドラッグし、設定します。
Skyboxを作成し、Main Cameraに登録

スクリプトの作成

Skyboxの設定はUnityEditor上で設定することが多いと思います。しかし、C#(もしくはJavaScript)のコード上からSkyboxのテクスチャを設定します。再生コントロールをするためです。
次の手続きの実装を行います。
  • 作成したコードはMain Cameraにアタッチする。
  • Startメソッドで、AssetDatabaseを使ってテクスチャを読み込み、リストに追加する。
  • UpdateメソッドでSkyboxのテクスチャを適切に切り替える。
まずは次のコードを書いてみました。Updateでは毎回フレームを切り替えています。テクスチャが繰り返し一定速度で再生されるはずです。(フレームレートは入力元の映像とおなじになるとは限らないです。)


// SkyboxRunner.cs
using UnityEngine;
using UnityEditor;
using System.Collections;
using System.Collections.Generic;

public class SkyboxRunner : MonoBehaviour {

    Skybox skybox;
    List skyboxTextures = new List();
    int index = 0;

    void Start () {
        // アタッチしたスカイボクスを取得
        skybox = GetComponent();

        // AssetDatabaseからテクスチャをロード
        var guids = AssetDatabase.FindAssets("t:Texture", new string[] { "Assets/SkyboxTex/nightsky1" });
        foreach (string guid in guids) {
            Texture texture = AssetDatabase.LoadAssetAtPath(AssetDatabase.GUIDToAssetPath(guid));
            skyboxTextures.Add(texture);
        }
    }
 
    void Update () {        
        // スカイボックスのテクスチャを切り替える
        skybox.material.SetTexture("_Tex", skyboxTextures[index]);
        index++;
        if (index >= skyboxTextures.Count) {
            index = 0;
        }
    }

}

ここでは、一定速度での繰り返し再生であるため、通常の再生と変わりません。Updateメソッドの内容を変更すれば、フレーム更新を自在に操ることができます。


まとめ

Theta Sで撮影した映像をUnityの3D空間に投影し、再生コントロールもしたかったのですが、MovieTextureなどでは実現できなかったため、各フレームを静止画に書き出してアニメーションすることで実現しました。
(もっといいほうがあればいいのですが、、、)