THETA S で全天球映像を配信するまで(2) UVマッピングを作ってみました


こんにちは、インフォコム技術企画室のがねこです。

来る2016年2月16日、17日に行われる、WebRTC Conference Japan 2016RICOH THETA S を使ったリアルタイム全天球配信のデモを展示する予定です。今回はTHETA S から取得できるライブ映像を、WebGLの球面上に貼り付ける準備をやってみます。

前回は映像の形式について調べました。全天球映像として表示するには、これをWebGLの3D空間内の、球面に貼り付けなくてはなりません。2つの円のそれぞれを、半球に貼り付けます。(前回記載した通り、実際に欲しい領域は楕円になります)

貼り付ける方法はUVマッピングと呼ばれる方法と、シェーダーと呼ばれる方法があるようです。今回はUVマッピングと呼ばれる方法を利用しています。

おおざっぱに言うと、UVマッピングでは次の図のように平面の座標と立体上の座標を対応させるようです。今回は楕円形を半球に対応させていきます。

theta_uv_map.png

このUVマッピングを実現するまでは、遠い道のりでした。

凹みさんによるUnityでのマッピング

VRやスマートホームなどの実験を積極的に公開している 凹みさんが、Unityを使ってTHETA S の映像を3D空間にマッピングする方法を公開していました。

発売前に RICOH THETA S のライブビューを Unity でリアルタイムに全天球で見るやつ作ってみた

このマッピング用のデータを使う許可をtwitter上でお願いしたところ、快く了承いただいたので利用させていただきました。

Blenderでの読み込み、微調整

3DモデリングのBlenderというツールがあります。これを用いてUnityのマッピングデータを読み込み、調整しました。

(1) Unityからモデルの読み込み

Unityのプロジェクトから、.fbxファイルを読み込みます。

theta_blender_fbx.png

theta_blender_fbx2.png

(2) 180度を越える重なり部分を除去

凹さんの元の方法では水平方向の180度を越える部分は半透明にして重なり合わせているようです。これを今回はぶっつりと切り落とします。

theta_blender_overwrap.png

theta_blender_remove_overwrap.png

theta_blender_no_overwrap.png

その結果、下図のように半球と元の映像の楕円部分が対応することになります。

theta_blender_mode_uv.png

(3) 2つの半球を調整

ここからは微妙なマウスさばきで半球の映像の位置関係を調整します。チームメンバーの一人にやってもらいましたが、職人芸の世界です。

theta_blender_modify_uv_1.png

反対側も同じく調整します。

theta_blender_modify_uv_2.png

Three.js(WebGLライブラリ)用にエクスポート

作ったマッピングを、WebGLライブラリであるThree.js用にエクスポートします。そのためにはThree.jsに含まれるアドオンが必要です。こちらの記事を参考にしながら、Three.jsのio_mesh_threejs ディレクトリを、Blender アドオン用ディレクトリの配下にコピーしました。

theta_blender_export_1.png

反対側もエクスポートします。

theta_blender_export_2.png

Three.jsでの読み込み

ようやくWebの世界まで来ました。WebGLのライブラリであるThree.jsで、先ほどエクスポートしたjsonファイルを読み込みます。

var loader = new THREE.JSONLoader(true); // init the loader util

loader.load('uv/half_sphere_1.json', function(geometry1, materials1) {
  // create a new material
  var material1 = new THREE.MeshPhongMaterial({
      map: videoTexture, // specify and load the texture
      color: 0xffffff,
      specular: 0xcccccc,
      shininess: 50,
      ambient: 0xffffff,
      overdraw: true
  });

  // create a mesh with models geometry and material
  var mesh1 = new THREE.Mesh(
      geometry1,
      material1
  );

  //  mesh1.rotation.y = -Math.PI/5;
  mesh1.scale.set(0.1, 0.1, 0.1);
  mesh1.position.set(0, 0, 0).normalize();
  scene.add(mesh1);
});

loader.load('uv/half_sphere_2.json', function(geometry2, materials2) {
  // create a new material
  var material2 = new THREE.MeshPhongMaterial({
      map: videoTexture, // specify and load the texture
      color: 0xffffff,
      specular: 0xcccccc,
      shininess: 50,
      ambient: 0xffffff,
      overdraw: true
  });

  // create a mesh with models geometry and material
  var mesh2 = new THREE.Mesh(
      geometry2,
      material2
  );

  //  mesh2.rotation.y = -Math.PI/5;
  mesh2.scale.set(0.1, 0.1, 0.1);
  mesh2.position.set(0, 0, 0).normalize();
  scene.add(mesh2);
});

ライブラリの公開

今回調べた内容を私たちのデモから切り離し、自由にお使いいただける形でgithubに公開しています。ご興味のある方は、ぜひお試しください。

参考

他にもTHETA Sの映像をWebGLで表示する方法が公開されています。一部ではとてもホットな話題になっています。

UVマッピング方式

THETA S のUSBライブストリーミングをブラウザで球面マップする

THETAのDualfisheye動画をThree.jsで表示してみた

シェーダー方式

https://github.com/gtk2k/gtk2k.github.io/tree/master/aframe_theta_s_live_preview