Tutti Lab

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

Quadで円形プログレス

uGUIのImageは、fillAmountを使って簡単に円形のプログレスができるのですが、SpriteやQuadにはfillAmountに相当する機能がないようです。
こちらこちらに、Quadを使った円形プログレスの実現方法があるのですが、予め0→360度でα値を1→0とした画像を用意する必要があるようで、面倒だし汎用性がないな、と思いました。
そこで、角度(0~360度)を指定して円形プログレスをするための簡単なシェーダーコードを書いてみました。

f:id:tuti107:20170204193817p:plain

Shader "Tuti/Reticle"
{
  Properties
  {
    [NoScaleOffset] _MainTex("Texture", 2D) = "white" {}
    _Degree("Degree", Float) = 360.0
  }

  SubShader
  {
    Tags{ "Queue" = "Transparent" "IgnoreProjector" = "True" "RenderType" = "Transparent" }

    ZWrite On
    Blend SrcAlpha OneMinusSrcAlpha

    Pass
    {
      CGPROGRAM
      #pragma vertex vert
      #pragma fragment frag

      #include "UnityCG.cginc"

      #define PI 3.14159

      struct appdata
      {
        float4 vertex : POSITION;
        float2 uv : TEXCOORD0;
      };

      struct v2f
      {
        float2 uv : TEXCOORD0;
        float4 vertex : SV_POSITION;
      };

      sampler2D _MainTex;
      float _Degree;

      v2f vert (appdata v)
      {
        v2f o;
        o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
        o.uv = v.uv;
        return o;
      }
			
      half4 frag(v2f i) : SV_Target
      {
        half4 col = tex2D(_MainTex, i.uv);
        float xx = i.uv.x - 0.5;
        float yy = i.uv.y - 0.5;

        float deg = (atan2(yy, xx)) * 180.0 / PI;
        if (yy >= 0) {
          if (deg > _Degree) {
            col.a = 0.0;
          }
        }
        else {
          if (deg + 360.0 > _Degree) {
            col.a = 0.0;
          }
        }

        return col;
      }
      ENDCG
    }
  }
}

時計の12時の位置から時計回りにする場合は、z軸90度回転+Y軸で反転してください。
ちゃんとテストはやっていませんが、とりあえず動いているようです。

Oculus Touchをつかってみる

Oculus Touchが出荷され、約一月が経ちました。Oculus StoreにはOculus Touch対応コンテンツが多数並び、Oculus Touchの凄さを体験できるわけですが、一方で開発向きとなるとまだ情報が足りない状況のようです。
今回は、Oculus Touchの練習用に作成したコンテンツを取り上げ、開発のポイントを挙げていきたいと思います。
youtu.be
コンテンツは、今年大流行したアレを、Oculus Touchで体験する、というものです。

情報収取

Oculus Touchの技術情報については、以下が必読です。

準備

Oculus Touchにて「手やアバターを表示し、なにかをつかむコンテンツを作る」ためには、以下のインストールが必要です(詳細は上記情報収集をご参照)

  • Oculus Utilities for Unity 5(こちらからダウンロード可能)
  • Oculus Avatar SDK(同じくこちらからダウンロード可能)
  • Avater Grab Sample(こちらからダウンロード可能)、なおUnity 5.5でのみ動作(Unity 5.4ではクラッシュ)とのこと
  • その後適当なプロジェクトを作成し、上記ダウンロードしたパッケージ(OculusUtilities.unitypackage, OvrAvatar.unityPackage, AvatarGrabSample.unitypackage)をそれぞれインポートします

サンプル実行

Assets/Samples/Content/AvaterWithGrab をダブルクリックして、シーンをロードします。あとは、PlayerSettings→Other SettingsのVirtual Reality Supportedをチェックし、実行してみます。
f:id:tuti107:20161231102951p:plain
つかむ・離す・投げる、一通りのことができます。

つかめるものを追加

まずは、サンプルで「つかめるもの」がどのようになっているかを見てみます。
f:id:tuti107:20161231103341p:plain
ポイントは、Grabbableというスクリプトです。これはAvater Grab Sampleに含まれるスクリプトで、これを追加したオブジェクト(かつ、Collider, Rigidbodyも追加する必要あり)がつかめるようになります。
つかんだ時、離した時の振る舞いは、Grabbable#GrabBegin()、Grabbable#GrabEnd()メソッドにそれぞれ記述します。これらメソッドはvirtualメソッドですので、Grabbableクラスの子クラスを作ってこれらメソッドをオーバーライドすれば、任意のつかむ・離す際の処理を作成することができます。

Oculus Touchのバイブレーション

OVRHapticsClipを使用します。AudioClipを引数としてOVRHapticsClipを作成することで、そのAudioClipの音量に基づいた振動を作成できます。
作成したOVRHapticsClipを引数としてOVRHaptics.RightChannel.Mix()(=右側コントローラ、左側の場合はOVRHaptics.LeftChannel.Mix())を呼び出すことで、Oculus Touchが振動します。なお、振動させるためのメソッドにはMix()以外に幾つかあり、それぞれ挙動が異なります(詳細は情報収集で挙げたサイトを御覧ください)。
以下は、スタティックメソッドSE.PlaySE()を呼び出すと、効果音鳴動+振動するサンプルです。

using UnityEngine;

public class SE : MonoBehaviour {

  public AudioSource audioSource;
  public OVRHapticsClip hapticClip;

  private static SE thisObj;

  void Start () {
    thisObj = this;
    hapticClip = new OVRHapticsClip(audioSource.clip);
  }
	
  public static void PlaySE() {
    if (thisObj != null) {
      thisObj.audioSource.Play();
      OVRHaptics.RightChannel.Mix(thisObj.hapticClip);
      OVRHaptics.LeftChannel.Mix(thisObj.hapticClip);
    }
  }
}

No Oculus Rift App ID has been provided

エディタで実行すると、問題なく実行できますが、上記のエラーがでます。Oculusサイトにて、アプリを登録してIDを取得することで、本エラーを回避できるようです(私がつくったコンテンツをエディタ上で実行する上では特に問題がなかったため、試していません)。詳細は、上記「情報収集」で挙げたサイトを御覧ください。

PP◯Pっぽい素材

終わりに

Oculus Touchは本当にすごいです。CG空間に触る、というユーザ体験は先行していたHTC Viveをも超えるものでは、と個人的には思います。

VR Trip around the world

私が開発したVRゲーム「VR Trip around the world」が、幸運にもVRゲームコンテストMSI VR JAMのファイナリストに残りました。

プレーヤーは、指定された場所で写真を撮影すべく広大なVRの世界を飛び回ります。VR世界の移動、となると最も懸念の課題が「VR酔い」です。本作では、遠くへ移動する際「巨人」になって世界を見渡し、次に行く場所を探します。「巨人」になって世界を見渡し、怪しそうな場所を探して、「元の姿」に戻り、細かな場所を探索する、という新たなVRにおける移動手段についても提案しています。
www.youtube.com

本アプリはOculus CV1専用であり、こちらから無料でダウンロードできます。
ぜひプレイいただき、気に入って頂けた方は、こちらより投票を頂けると幸いです(2016年12月28日迄)。

Vuforia for Unityを使って(擬似)ハンドトラッキング

前回、Viforia for Unityの機能を活用し、Google Cardboardでポジショントラッキングを実現する方法について記載しました。同様に、Vuforia for Unityを使うことで(擬似)ハンドトラッキングも可能です。
Vuforiaでは直接「手」を認識することはできません。しかし、手にマーカーを貼り付ける、マーカーを貼り付けたふだを持つなど、マーカ認識を通じて手の位置を認識する、ということは比較的容易に実現できます。
先日とあるVRイベント向けに開発した「Santa Claus Job Simulator」というサンタのお仕事を体験するアプリにて、この擬似ハンドトラッキングを実装してみましたので、本実装技術についてご紹介したいと思います。
www.youtube.com

ARCameraの設定

Google CardboardにてVuforia for Unityを利用した(マーカ認識による)ハンドトラッキングをする際のポイントは「VRのヘッドトラッキングを考慮した上で、Vuforiaで認識した「手」を「手の位置」に表示すること」です。
Vuforia for Unityはデフォルトでは「はじめに発見した認識対象の座標を固定し、認識対象との位置関係に応じてCameraの位置を変える」という設定になっています。VuforiaがImage Targetに指定された認識対象を発見した際、Image Targetの座標・回転が変化するのではなく、ARCamera(Main Cameraを子として含む)の座標・回転を変化させることで、相対的にImage Targetが動いているように見せます。
VRでなければ、特段問題は生じませんが、VR(Player SettingsにてVirtual Reality SupportedがON)の場合、ヘッドトラッキングによりデバイスの回転によりMain Cameraを回転させます。このため、上記のデフォルト設定では、ヘッドトラッキングの回転設定とVuforiaの回転設定が競合してしまい、ちょっと都合が悪いです。

そこで、

  • ARCameraのVuforia BehaviorコンポーネントのWorld Center Modeをデフォルトの「FIRST TARGET」から「CAMERA」に変更します。これで、認識対象物が発見された際の固定される座標はMain Cameraとなり、代わりにImage Targetの座標が変わります。
  • また、もう一点、Image TargetはMain Cameraの子とします。これは上記の通り、認識対象の位置はMain Cameraが固定であることを前提としていますから、ヘッドトラッキングによるMain Cameraの回転変化に関わらず、Image TargetからはMain Cemeraが固定に見えるようにするためです。

f:id:tuti107:20161221234833p:plain

また、Image Targetと「手」の位置関係にも工夫が必要です。Santa Claus Job Simulatorでは、マーカ付きの看板を手に持ってもらい、そのマーカを認識することで手を表示するようにしています。
f:id:tuti107:20161221233051p:plain

このためImage Target認識時に表示される手の位置・回転は、看板に貼り付けられたマーカからの相対位置・回転を設定する必要があります。
f:id:tuti107:20161221233148p:plain

高速化が不可欠

Vuforiaをハンドトラッキングに活用する上でもう一つ重要な点は、可能な限り処理の高速化を図ることです。
VR表示しながら、同時にマーカ認識するという処理は、モバイル端末にとって非常にヘビーなものとなります。
このため、Edit->Project Settings->Qualityにて処理をFastestとして描画・表示負荷を下げる等、できるだけ処理を軽くし、Vuforiaの認識処理にリソースを回してあげる必要があります。
描画負荷が高い場合等、Vuforiaの認識処理のための余裕がない場合、認識の品質は明らかに低下し、すぐに認識対象を見失ってしまいます。こうなると心地よりハンドトラッキングとは程遠くなってしまいます。

最後に

今回は、Google Cardboard向けに(擬似)ハンドトラッキング処理を実装した当方が開発したゲームを例に、Vuforiaによる(擬似)ハンドトラッキングを実装する方法について説明をしました。
モバイル向けにはVuforiaを活用したハンドトラッキング・ポジショントラッキングをどんどん活用したい、と思っていますが、最新のモバイルVRヘッドセットであるDaydream ViewではVuforiaが使えません。Google Cardboardのようにスマホカメラの位置に穴を開けるわけにはいきませんので。。
何らか他の方法を検討する必要があるな、と考えております。

UNIBOOK7で、ThetaSによる360度立体視映像配信について書かせていただきました

知人に紹介いただいたことがきっかけで、UNIBOOK7の「第8章 ThetaSを使った360度立体視映像配信」を書かせていただきました。
f:id:tuti107:20161221221355j:plain
半年ほど前、ThetaSを2台使った360度立体視の撮影・配信についてブログにかきましたが、その当時は、私の知識不足&当時作成していたアプリの要求仕様に合わない、ということから中途半端となっていた、撮影と配信、そして配信映像を視聴するためのモバイルアプリの作り方について記載しております。
本書には、その他多数の著名クリエイターが執筆した読み応えのある内容満載です。購入いただけると幸いです!

www.unity-bu.com

Oculus Touch + Daydream View

Oculus TouchとDaydream View、それにPixelが一気に届きました。週末はいじり倒します!
f:id:tuti107:20161208224808j:plain

Vuforiaの認識精度を上げるには

はじめに

前回、Vuforia for UnityのExtended Tracking機能を利用してGoogle Cardboardでポジショントラッキングということで記事を書いたところ、ブログ始めて以来の反響、非常に驚きました。モバイルVRでもポジショントラッキングをやりたい、というニーズは高いのかもしれません。
前回の記事では、結局十分な精度を実現できず、自分が動かなくても、プルプルとポジションが動いてしまう状態のままで公開をしましたが、その後、精度を上げる方法について調べましたので、これをご紹介しようと思います。

理想的なイメージとは?

Vuforiaは、イメージの特徴点を比較することで、イメージを認識します。特徴点の詳細については割愛しますが、Vuforiaの場合、この特徴点は「イメージを白黒化した上で、尖った部分
(三角形や長方形の角のような箇所)」に多く現れるようです(詳細はこちら)。
理想的なイメージは、
- コントラストがはっきりしている。コントラストが低いと「尖り」が分かりづらくなるため
- ごちゃごちゃしている。シンプルだと特徴点が少なくなってしまう
- 規則性がない。詳細は分かりませんが、特徴点を比較する上で、規則的な配列の特徴点は、認識率を悪化させるのだと思われます
もの、となります。

f:id:tuti107:20161201161146j:plain f:id:tuti107:20161201161155j:plain

前回は、Vuforiaがサンプルとして提供している「stones」というイメージを利用しており、上記の条件は満たしております。

印刷品質・サイズ

次に疑われるのは、印刷したイメージの印刷品質・サイズです(詳細はこちら)。
印刷したイメージのサイズがあまりにも小さすぎると、カメラより入力した画像から十分な特徴点を抽出できず、認識を失敗したり・精度が不安定となります。サイズについては、端末ー印刷物間の距離(m)<印刷物のイメージの幅✖️10以下、とするのが良いようです。前回私は幅30cmでイメージを印刷したので、距離は3m以内、ということになります。私はせいぜい2m程度の距離で試したため、印刷サイズの問題ではないようです。
印刷品質については、「コントラストはっきり」「テカらない」、かつ「印刷物に折り目などがない」ものである必要があります。
私は前回、ペラッペラの再生紙に、印刷品質「普通」で印刷したため、コントラストが低く、紙がよれてしまい一部部屋の光をかなり反射している、という最悪の状況になっていました。
そこで、ためしにイメージをディスプレイに表示し、試してみたところ、品質はかなり安定しました。早速こちらの紙を注文しました!

終わりに

前回品質が低かった理由は、単に印刷物が粗末だったためでした。ディスプレイ表示によるポジショントラッキングは、ゲーム等の開発に十分耐えうる品質(Oculus RiftやHTC Viveと比べればかなり低いですが)です。
ちなみに、名刺サイズの用紙に認識用イメージをプリントし、手の甲に貼り付ければ、簡易ハンドトラッキング(ハンドポジショントラッキングというのが正確)も可能な旨、確認しました。これらを駆使すれば、モバイルVRでも、Oculus RiftやHTC Viveの様な没入感のあるアプリを開発することもできそうですね。