Bakulog

獏の夢日記的な何か。

MOVERIO BT-300をUnityとかXamarinで触る

デベロッパーズガイドに詳細載ってないけど出来そうなことをやったら出来ました、という報告です。

もくじ

  1. MOVERIO BT-300とは
  2. Android StudioはMOVERIOの開発に使えないの?
  3. Unityで3D(サイドバイサイド)を試す
  4. Xamarin (VS) で作ったアプリを配置してみる
  5. その他注意点とか

1. MOVERIO BT-300とは

いわゆるスマートグラスです。情報は公式ページにのってますが、スマートグラスやHMDに類する中では小型軽量なのが特長です。

https://twitter.com/baku_dreameater/status/804294589867692032

はい。MOVERIO BT-300を予約で買いました。

そこで、開発者目線で軽く触った内容を共有しておきます。

具体的な視点としては、Android Studio以外の2大MOVERIO開発環境であるUnityXamarinでふつうにMOVERIOにさわれるね、という話を紹介していきます。

  • Unityでやったこと
    • サイドバイサイド(3D対応)を適当に試した結果を紹介します。
    • UnityからMOVERIO BT-300の固有APIを叩く話は本記事では扱いません。
  • Xamarinでやったこと
    • Xamarinでは「MOVERIO BT-300の固有APIC#から使えるぞ!やったー!」というのをやってみます。
  • その他
    • Unityいじってた3D対応の注意点をひとつ発見したので、それを紹介します。

2. Android StudioはMOVERIOの開発に使えないの?

使えます。全く問題なく使えます。

というか、公式の技術者向け情報から拾えるデベロッパーズガイドにはAndroid Studioを使う場合の手順が載っています。つまりデファクトスタンダードです。

こんな記事を書いておいてアレですが、導入の手筋としては大人しくAndroid Studioを使ってガイド通りに進め、サンプルプロジェクトの動作を見ておくことをオススメします。

3. Unityでサイドバイサイド(3D対応)を試す

ここからが本題です。本節に対応したサンプルパッケージはこちらから。「文章は読まん!」という人はパッケージ中の「Moverio3dSample/Scenes/Main.scene」を開き、何かを感じ取ってください。

サンプルはEthanとグルグル動くブロックを表示させてますが、本記事ではユニティちゃんを表示した例で説明していきます。イメージとしては以下のような画面を作ればOKです。

screenshot_2016-12-03-12-30-48

ここからは具体的な説明に進みます。

MOVERIO BT-300では左目、右目用の画像を繋げたものを用意し、3Dモードに入ることで3Dに対応します。具体的には次のような処理がされてます。

  1. アプリはMOVERIOに1280x720で画像を渡す
  2. MOVERIOは受け取った1280x720の画像を横方向に2倍引き延ばして2540x720の画像にする
  3. 大きくした画像を左半分と右半分にわけて表示する

この処理で画像がどう変化するか体感したければ、MOVERIOホーム画面で3Dモードに入ってみるのをオススメします1

ともかく、この仕様を踏まえるとUnity側から渡すべき画像の中身は以下のようになります。

  • 1280x720画像で、左半分は左目にうつす画像、右半分は右目にうつす画像にする
  • 画像は切断後に引き延ばし処理されることを考えて、あらかじめ画像を横方向0.5倍にスケールしておく

上の画像ではユニティちゃんが細くなってますが、これは引き延ばしを想定して横方向に縮めているためです。2倍引き延ばすと普通のユニティちゃんに戻り、MOVERIO装着時に見えるイメージはコチラの方になります。

screenshot_unitychan_2x

逆に、引き延ばしを忘れて等倍映像のユニティちゃんをヨコに並べると太ったユニティちゃんが出てきてしまうので気を付けましょう。

ここまでは主に仕様の話でした。実装のことも軽く触れておくと、サンプルのケースでは以下のような方針でやっています。

  1. 目に相当するカメラをふたつ用意し、目カメラのレンダー先(Target Texture)をデフォルトではなくRender Textureに設定
  2. Render TextureMaterialに載せてPlaneに投影し、視聴用スクリーン的なものを用意
  3. Mainのカメラには視聴用スクリーンがうつるようにする

画像のスケール処理はRender Textureの解像度を変えたりPlaneScaleを調整することで良い感じにしています。多分ほかにも手はあるので、効率良さそうなのを思いついたら試してみてください。

いっぽう、この手ではデメリットとしてGUIのレイヤー制御がうまくいかないことも分かります。上のやり方ではGUIをメインのカメラにだけ表示しているのですが、この場合次のような問題が生じます。

  • 片目にしか映らない
  • GUIが横にグニョーンと拡大されてしまう

GUIが延びてしまっている参考として、さきほどの画面の右目部分だけ抜き出したのがコチラです。

screenshot_unitychan_2x_right

これらの問題を解決する手としてはメニュー相当のオブジェクトも3D空間中に作り込んでしまうとか、あるいはMOVERIOの固有APIを叩いてメニュー表示時だけ2D化、主画面は3D、というような切り替えをサポートする必要があるでしょう。

ただしMOVERIOは3Dモードのカーソル挙動がちょっとアレなので(これについては本記事の末尾に記載)、見た目の問題だけ解決してもダメだったりします。

(2016/12/5追記) : ひとつ書き忘れていたので追記ですが、UnityでMoverio用にアプリを作る際には「Player Settings」でPortraitを無効化してください。これを忘れていると、首を大きくかしげたときにUnityがPortraitモードへ遷移しようとしてしまい(さらにMoverioがそれを邪魔して?)、UIがグチャグチャになります。

disable_portlait

5. Xamarin (VS) で作ったアプリを配置してみる

前の節ではUnityを使い、MOVERIOの3D対応が使えるらしいことを確認できました。

XamarinでもUIレイアウトに配慮すれば当然同じようなことが出来ますが、こちらでは別の重要案件としてMOVERIO BT-300の固有ライブラリ(BT300Ctrl.jar)が使えるか試してみましょう。

ここからはVS2017RCを使った例を示します。たぶんVS2015Xamarin Studioを使っていても大筋は変わらないと思います。

まずはプロジェクトの新規作成をし、jarのラッパーをビルドするところまで一気にやります。クロスプラットフォームとか贅沢は言わずにおとなしくAndroid向けアプリとして作っていきましょう。

  1. メインのアプリプロジェクトとして、単一画面プロジェクトを新規作成
  2. 1で作ったソリューションに対して追加プロジェクトを作成し、種類はバインドライブラリプロジェクトにする
  3. メインプロジェクトの参照ライブラリとして、2で作ったバインドライブラリプロジェクトを追加
  4. 2作ったバインドライブラリプロジェクトにはJarsフォルダがあるので、ここに公式からダウンロードしてきたBT300Ctrl.jarを追加。
  5. 4で追加したBT300Ctrl.jarについて、プロパティでビルドアクションがInputJarになっているのを確認
  6. とりあえずビルド。

ここまでやると、バインドライブラリプロジェクトが勝手にBT300Ctrl.jarのラッパーを作ってくれるので、以降はメインのプロジェクトのみをいじり、MOVERIOのAPIはラッパー越しに叩けばOKとなります。

bt300_xamarin_vs

あとはそれっぽくUIを作ってメインコードにそれっぽくハンドラを書けば動きます。

using Android.OS;
using Android.App;
using Android.Widget;
using System.Threading.Tasks;
using Com.Epson.Moverio.Btcontrol;

namespace MoverioBt300BasicSample
{
    [Activity(Label = "MoverioBt300BasicSample", MainLauncher = true, Icon = "@drawable/icon")]
    public class MainActivity : Activity
    {
        DisplayControl _displayControl;

        protected override void OnCreate(Bundle bundle)
        {
            base.OnCreate(bundle);

            // Set our view from the "main" layout resource
            SetContentView(Resource.Layout.Main);


            //Initialize handlers those using MOVERIO API
            _displayControl = new DisplayControl(ApplicationContext);

            var button2DMode = FindViewById<Button>(Resource.Id.button2DMode);
            var button3DMode = FindViewById<Button>(Resource.Id.button3DMode);
            var buttonMute3sec = FindViewById<Button>(Resource.Id.buttonMute3Sec);
            var checkBoxShowToast = FindViewById<CheckBox>(Resource.Id.checkBoxShowToast);
            var seekBarIntensity = FindViewById<SeekBar>(Resource.Id.seekBarIntensity);


            button2DMode.Click += (_, __) => _displayControl.SetMode(DisplayControl.DisplayMode2d, checkBoxShowToast.Checked);
            button3DMode.Click += (_, __) => _displayControl.SetMode(DisplayControl.DisplayMode3d, checkBoxShowToast.Checked);

            buttonMute3sec.Click += (_, __) => Task.Run(async () =>             
            {
                _displayControl.SetMute(true);
                await Task.Delay(3000);
                _displayControl.SetMute(false);
            });

            seekBarIntensity.ProgressChanged += (_, e) => _displayControl.SetBacklight(e.Progress);            
        }
    }
}

using Com.Epson.Moverio.Btcontrol;とあるのがラッパーによって使えるようになったAPI名前空間です。 上記コード中のDisplayControlクラスが実際に使っているクラスで、必要ならもう一つのラップクラスであるSensorも利用できます。 今回は「とりあえず公式サンプルと同じことをやろう」ということでセンサーは使っていません。

手元でささっと試したい人向けにソースをGitHubに上げてますが、再頒布になってしまうのを防ぐため、BT300Ctrl.jarは含めていません。ライブラリは公式から取得してください。

5. その他注意点とか

Unityの節でもほんの少しだけ触れましたが、現状のMOVERIO BT-300は3Dモード時のカーソル移動に若干問題というかクセがあります。

その内容ですが、3Dモード時はカーソルが左目ウィンドウか右目ウィンドウのいずれか一方にしか現れません。落書きで描くと以下のようなイメージです。

screenshot_unitychan_3dmode_prob

直感的な解釈ですが、MOVERIOは3Dモードになると左+右ディスプレイをデュアルモニタ的に認識するので、カーソルが全体の中でひとつしか存在しないよ、ということになるみたいです。

この解釈でいくと、逆に2D表示はディスプレイの複製だと思っておけば分かりやすいです。

それで、この3Dモード時のカーソル動作は動きとしては納得できるんですが、UXとして使いやすいかと言われるとちょっとアレですね…。

対策としてはコントローラのメインボタンを押したら2Dに戻す、とかそういった操作をサポートしてカーソル操作への足がかりを作った方が親切なのかもしれません。

今回は以上です。次回に記事化するとしたら、今度はセンサーを使う例も紹介したいと思います。


  1. これをやるとホーム画面がヒジョーーーに視認しづらくなります。そもそもホーム画面で3Dモードに入れてしまうのはバグに見えるんですが、果たしてバグだとしたら直るのでしょうか…?