2014年12月14日日曜日

Google CardboardSDK を使ってみた

CardboardSDK 発表!


先日、google が スマフォVR Cardboard 用に新たにSDKを発表しました。
https://www.google.com/get/cardboard/

今まではUnity+DiveSDKを使っていたのですが、
たまにすーっと左右に加速したままになるドリフトに悩まされていたので、
この機会に試してみる事にしました。

この記事は スマフォスロットイン系HMD Advent Calendar 2014 の14日目の記事です。

初日


まずは以下のサイトからダウンロードしてきました。
https://developers.google.com/cardboard/unity/download

サンプルを起動した所、なんか真っ暗で写りません・・・。
おかしいなぁと思って調べたら、以下の記述を発見しました。

> Requires Unity version 4.5+ and licenses for Unity Pro

え~?!Unity Pro が必要でした!
仕方が無いので、二画面の時の処理を呼ばないようにしたらなんとか表示されました。


えっと、これじゃ 駄目ですよね・・・初日はここでギブアップしました。

二日目


とりあえずサンプルを動作させる為に、unity pro版のtrial起動させてみました。
(ユニティちゃんディレクターズカップで使用する為のライセンスで、動画投稿もしたのですが、それは又別の機会に。)
その結果がこれ。


おぉ、なんかいいじゃないですか~、でもunity freeで作らないと公開できないし、
せっかくだからDiveで同じシーン見てみました。


こ、これは酷いですね。自分ちゃんと知らなかったのですが、
最近のVRHMDは広角レンズで強引に視野を広げる為、カメラで言う所の糸巻型に湾曲するんですね。
それを逆にソフトウェア側(shader?)で樽型に補正が必要だったとは・・・。
きっと Oculus Rift DK2 とか持ってる方はとっくに気が付いていたのだと思うのですが、
没入感の不足は画角の不足と勘違いしていたので、それに気が付けただけでも良しとします。

というわけで、CardboardSDKについては、結局 Unity Pro 買わないと使えない、
という事がわかっただけでした、それでは。

2014年11月14日金曜日

unity+diveでカメラの画角を変更する。

首の制御で失敗した~!


 最近クエリちゃん360VR(google play)をちょっと改良したのですが、
その際にカメラの方向を見るようにしました。
例によって以下のサイトからプログラム持ってきただけですがw
 http://www40.atwiki.jp/spellbound/pages/1408.html

で、最初強めに方向制御したら、人間とは思えない状態になってしまいました、グキッ。

こりゃあかん、って事で今は角度抑えめで微妙に入ってる状態です。
(制御良くわからんです、すみませぬ)

本題、diveのfov効いてなくね? 


前回、ハコスコに対応する為にDiveSDKのプログラム変更してましたが、
もともと参考にしたサイトが書いていた、fieldOfView(以下fov) を45に変更ってのは、
無効の様に見えました(実際右カメラに設定しても駄目だった。)

それで、DiveSDKのカメラのOpenDiveSenser.csを見た所、
独自のprojection変換行列が使われているようでした。(詳しくは以下)

http://docs.unity3d.com/ScriptReference/Camera-projectionMatrix.html

標準のパースペクティブカメラと違ってfovの値関係なさそうなので、
行列に入力される値を弄って画角かえます、具体的には以下の部分ですね。

cameraright.projectionMatrix = PerspectiveOffCenter((-zoom-correction)*(znear/0.1f), (zoom-correction)*(znear/0.1f), -zoom*(znear/0.1f)*aspectRatio, zoom*(znear/0.1f)*aspectRatio, znear, zfar);

後ろ二つのnearとfarは関係なさそうなので、テストで0.1fって値を4か所、右カメラだけ0.05fと小さくしてみました。
cameraright.projectionMatrix = PerspectiveOffCenter((-zoom-correction)*(znear/0.05f), (zoom-correction)*(znear/0.05f), -zoom*(znear/0.05f)*aspectRatio, zoom*(znear/0.05f)*aspectRatio, znear, zfar);


なんか右だけ広角っぽくなってますね!

なので、該当部分を以下みたいに書き換えてparamを0.1より増やせば望遠、減らせば広角になるのではないでしょうか?

float param=0.1f;
cameraleft.projectionMatrix = PerspectiveOffCenter(
(-zoom+correction)*(znear/param), (zoom+correction)*(znear/param),
-zoom*(znear/param)*aspectRatio, zoom*(znear/param)*aspectRatio,
znear, zfar);
cameraright.projectionMatrix = PerspectiveOffCenter(
(-zoom-correction)*(znear/param), (zoom-correction)*(znear/param),
-zoom*(znear/param)*aspectRatio, zoom*(znear/param)*aspectRatio,
znear, zfar);

fovと違って値から絵が予想できないのですが、何度かテストすれば最適な画角が得られそうです。
cardboardとハコスコ両方でdiveつかったり、タオバイザーのレンズを広角に変更したりする場合は試してみてください!

"Query-Chan model" by Pocket Queries, Inc. is licensed under a Creative Commons Attribution 4.0 International License(CC-BY).

2014年11月7日金曜日

cardboardやタオバイザー用にunity+diveで作った物をハコスコ対応にする。

はじめに

先日、クエリちゃん360VR(google play)というのを、cardboard用にunity+diveで作成しました。

ほとんど以下のスライドを見ながらサンプルを少しいじっただけです。
http://www.slideshare.net/NobuhikoSasaki/ss-38173018

あ、カメラを回す部分は以下のサイトを参考にしました。
http://greety.sakura.ne.jp/redo/2014/09/durovis-dive-sdkcardboard.html

更に、以下のサイトの最後を参考に、ハコスコにも対応しました。
http://warapuri.tumblr.com/post/98800390873/spherical-image-cam-unity

ハコスコ対応

ハコスコ対応だけハマったので詳しく書きます。
入力を制御してる適当なクラスの上の方に変数を追加します。


  public bool doubleCameraFlag = true;


更にupdate関数で以下の様に書いていました。
先ほどのサイトに書いてる事だけだと絵が潰れるので、aspect比も変更しています。
(本当は座標も補正した方が良さそうです、ハコスコの時ちょっと近いwww)


  // タッチ情報を取得する
  TouchPhase touchPhase = TouchPhase.Ended;
  if (Input.touchCount > 0)
  {
   touchPhase = Input.GetTouch (0).phase;
  }
  // タッチ直後?
  if ((touchPhase == TouchPhase.Began) ||
      // マウスが押された瞬間?
      (Input.GetMouseButtonDown(0)))
  {
   doubleCameraFlag ^= true;
   GameObject diveCamera = GameObject.Find("Dive_Camera");
   if (doubleCameraFlag == true)
   {
    // 左カメラ復活
    diveCamera.GetComponent<OpenDiveSensor>().cameraleft.enabled = true;
    // 右カメラを元に戻す
    //diveCamera.GetComponent<OpenDiveSensor>().cameraright.fieldOfView = 85.0F;
    diveCamera.GetComponent<OpenDiveSensor>().cameraright.rect =
     new Rect(0.5F, 0.0F, 0.5F, 1.0F);
   }
   else
   {
    // 左カメラ停止
    diveCamera.GetComponent<OpenDiveSensor>().cameraleft.enabled = false;
    // 右カメラ補正
    //diveCamera.GetComponent<OpenDiveSensor>().cameraright.fieldOfView = 45.0F;
    diveCamera.GetComponent<OpenDiveSensor>().cameraright.rect =
     new Rect(0.0F, 0.0F, 1.0F, 1.0F);
   }
   // アスペクト比も変更
   if (doubleCameraFlag == true)
   {
    diveCamera.GetComponent<OpenDiveSensor>().aspectRatio=
        (Screen.height*2.0f)/Screen.width;
   }
   else
   {
    diveCamera.GetComponent<OpenDiveSensor>().aspectRatio=
        (Screen.height*1.0f)/Screen.width;
   }
  }

で、このプログラム外部からDive_Cameraを制御しているのですが、
何故かDive_Cameraのupdate関数ではUnityEngine.TouchPhaseが使えませんでした。
またいつかエラーになる原因を調べたいです・・・。