TECHブログ


パノラマ画像と3Dモデルを組み合わせた道案内コンテンツ

はじめに

360度パノラマ画像を用いたコンテンツは、このTECHブログでもよく取り上げている題材です。ただ、これまでのパノラマコンテンツは、球体の中心から向きを変えながら見ることはできても移動はできません。パノラマ間を移動するにしても、パノラマの表示を切り替えているだけで瞬間移動をしているようになってしまいます。今回は、簡易な3Dモデルと組み合わせることでその問題を少しでも解消し、実際に移動しているような感覚を持てるような道案内コンテンツを目指します。
また、PCだけでなくスマートホンやタブレットなどのモバイル端末でも操作できるようにします。

開発環境

  • Unity2020.3.x
  • Visual Studio 2019

事前準備

  • 動作確認用にApache等でローカル環境にWebサーバを立てておく
  • UnityはWebGL用にビルドできる設定にしておく
  • 360度パノラマ画像の用意
    今回は以前の記事、WebGLで閲覧可能な道案内コンテンツ作成およびモバイル対応と同じ素材を使用
    神田駅東口から弊社の事務所までを撮影したものです
  • マップに合った3Dモデルの用意
    PLATEAU(プラトー)から、テクスチャ無しの軽いモデルを使用
    パノラマ画像の撮影箇所に相当する区域のデータをダウンロード

実装

パノラマ画像と3Dモデルの組み合わせ

3Dモデルは国土交通省の主導するPLATEAUを利用します。
PLATEAUは都市の3Dマップを正確な縮尺で提供してくれています。テクスチャ有りのデータもあるのでそれだけで道案内素材として完結もできますが、テクスチャの写真内に映りこんでいる看板や著作物の扱いが難しい(PLATEAU Policy)ため、テクスチャ無しのデータを選択します。
また、スマートホン等のモバイルデバイスでも動作させたいため、今回はなるべく3Dモデルのデータが軽くなるようにテクスチャ無しでローポリゴンのモデルを利用します。地面のモデルはポリゴン数が多いためUnityのPlaneで代替します。

シーンに配置した3Dモデルに合わせて、パノラマ画像をテクスチャとして適用させた球オブジェクトを配置します。
この時、パノラマ画像と3Dモデルがぴったりと重なるように、球の位置と向きを調整します。

3Dモデルの役割は、現在のパノラマから次のパノラマへの間の空間の補完です。パノラマ間を瞬間移動しただけではわからなかった、どのくらいの距離をどちらの方向に移動しているのかといった感覚が、3Dモデルがあるおかげでわかるようになります。

Hotspotの配置

Hotspot(パノラマ上に配置されたアイコン、テキストやボタン等)を、3Dモデル上とパノラマ内部と配置します。

  • パノラマ内
    次のパノラマへ移動するためのボタン
    目的地である弊社事務所の方向を示すアイコン、交差点や道路名などを説明するテキストを配置
  • 3Dモデル上
    移道中の目印となる建物や店を配置

カメラ操作

PCの場合はマウスを使って操作しますが、スマートホンなどのタッチパネルによる操作の場合も考えます。
また、機種によってはPCでもタッチスクリーン対応の場合もあるため、入力がマウス操作でもタッチ操作どちらであっても動作できるようにしておきます。

/// <summary>
/// タッチ情報
/// UnityEngine.TouchPhaseを元に情報追加
/// </summary>
public enum InputPhase
{
    None,
    Began,
    Moved,
    Stationary,
    Ended,
    Canceled,
    Pinched
}

タッチ入力の状態は、Unity標準のUnityEngine.TouchPhaseがあります。
マウス操作でも同様に状態を判断するために、このTouchPhaseにPinchedを追加してInputPhaseとして定義しておきます。

/// <summary>
/// タッチ情報を取得
/// </summary>
/// <returns>タッチ情報</returns>
public static InputPhase GetPhase()
{
  // タッチ操作がある場合
  // タッチ入力が指2本の場合            
  if (Input.touchCount == 2)
  {
      return InputPhase.Pinched;
  }
   // タッチ入力が指1本の場合 
  else if (Input.touchCount == 1 &&
          !isPinched)
  {
      // UnityEngine.TouchPhaseを取得してindexを取得
      return (InputPhase)((int)Input.touches[0].phase);
  }
  // タッチを離した場合
  // タッチ操作がない場合
  else if (Input.touchCount == 0)
  {
      isPinched = false;

      // マウス操作の場合
      if (Input.GetMouseButtonDown(0))
      {
          prePosition = Input.mousePosition;

          return InputPhase.Began;
      }
      else if (Input.GetMouseButton(0))
      {
          return InputPhase.Moved;
      }
      else if (Input.GetMouseButtonUp(0))
      {
          return InputPhase.Ended;
      }
      else if (Input.GetAxis("Mouse ScrollWheel") != 0)
      {
          return InputPhase.Pinched;
      }
  }
}

入力がInputPhaseで定義したどの状態であるのかを判断して、カメラの動作を制御します。
指一本でのタッチ入力またはマウスの左クリックしたBeganの状態がドラッグ操作開始、ドラッグ中の状態がMovedになります。
このドラッグ操作時にカメラの回転を制御します。
指2本でのピンチ入力またはマウスホイール操作でPinchedの状態になり、カメラのズームイン/アウトを制御します。
また、ピンチ入力中はisPinchedをTrueにして、他の入力を受け付けないようにしておきます。

ミニマップによる確認と移動

ミニマップを設けることで現在位置を俯瞰的に確認ができるようになります。パノラマ内のカメラ向きと連動させれば、進行方向の確認もできます。
また、マップ内のパノラマ位置に配置したアイコンをクリックすることで、指定したパノラマへ直接移動ができるようにします。

デモ

以上の内容で作成したWebGLコンテンツになります。
PC、モバイル端末どちらでも動作します。(古い機種だと動作が不安定になる可能性があります)
画像・3Dモデルのデータが大きいため無線の場合はWi-Fi環境必須になります。

※新しいタブで開きます

WebGLコンテンツデモ

カメラ操作方法
  • カメラの回転
    マウス操作のドラッグ、タッチ操作のドラッグ
  • ズームイン/アウト
    マウス操作のホイール回転、タッチ操作のピンチイン/アウト

まとめ

360度パノラマは、全周囲の様子を確認ができるので現実の一場面の中に入り込んだような没入感も得られますが、あくまでその場に立ち止まった状態に限ったもので、隣り合う空間のパノラマ画像へと移動するという感覚は得られませんでした。今回3Dモデルと組み合わせることで、パノラマ画像だけではできなかった道を移動しながら目的地に向かっているという感覚の表現が可能になりました。
また、使用しているパノラマ画像数はそれほど多くないですし、3Dモデルもポリゴン数の少ないの簡易的なものを使用しています。道中の様子をもっと詳細に表現したいのであれば、GoogleMapのストリートビューように大量のパノラマ画像や、ポリゴン数の多い精細な3Dモデルが必要となってきますが、道案内という目的に限れば簡単な素材だけでも十分であると感じました。