こんにちは、スマートデバイス戦略開発グループの katayama です。
住まいカンパニーではSUUMOスコープ (SUUMOが提供するCardboardによるバーチャル物件内観のこと)を利用したVR (バーチャルリアリティ) 体験の提供を行っています。
SUUMOでは、アプリ / Webブラウザ のどちらからでも閲覧できるように、WebGLを利用して開発をしており、今回はこれを事例に、three.js を利用したVR体験の実装方法 (まずは全天球を表示してみるところまで) についてお話します。
SUUMOスコープとは
SUUMOスコープを使うと、VR (バーチャルリアリティ) 体験によって、マンションのモデルルーム等を家にいながらでも内見できるようになります。(※ 2016/02/23 (火) に第2弾をリリース)
360° VR体験の仕組み
まずは、360°の画像をグリグリ回す仕組みを説明します。
① 球体のオブジェクト(geometoryと呼びます)を作り、その中心にカメラを配置 ② RICOH THETA などで、撮ったパノラマ画像をテクスチャとして球体に貼り付ける

③ デバイスの傾きなどから、カメラの方向を求める
こうすることで、球体の内側から画像を見ているような形で、360°のVR体験を実現することができます。
Three.js で全天球を表示してみる
それでは、さっそく球体のオブジェクトを作り、360°画像を貼り付けてみましょう! WebGLを簡単に扱うために、Three.js というライブラリを使って作ってみます。
①まずは、htmlにThree.js をインポート
vrcanvas の箇所に、<canvas>要素で描画することにします、
[index.html] <!DOCTYPE html> <html lang="jp"> <head> <title>" VR contents</title> <meta charset="utf-8"> <meta id="viewport" name="viewport" content="width=device-width,user-scalable=no,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0"> <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent"> <meta name="apple-mobile-web-app-capable" content="yes"> </head> <body style="background:#000;"> <script src="js/three.min.js"></script> <script src="js/main.js"></script> </body> </html>
② シーンの作成とカメラの配置
[js/main.js] // シーンの作成 var scene = new THREE.Scene(); // カメラの作成 var camera = new THREE.PerspectiveCamera( 75, window.innerWidth/window.innerHeight, 0.1, 1000 ); // レンダラーの作成 var renderer = new THREE.WebGLRenderer(); renderer.setSize( window.innerWidth, window.innerHeight ); // body にcanvas要素として描画エリアを追加 document.body.appendChild( renderer.domElement ); [/js] <h3>③ 球体オブジェクトの作成と、360°画像のテクスチャ貼り付け</h3>
[js/main.js] // 球体の形状を作成 var geometry = new THREE.SphereGeometry(1, 100, 100); // 画像をテクスチャとして読み込み var texture = new THREE.ImageUtils.loadTexture("photo.jpg"); texture.minFilter = THREE.LinearFilter; texture.flipY = false; // テクスチャを使い、マテリアル(質感)を作成 var material = new THREE.MeshBasicMaterial({ side: THREE.DoubleSide, color: 0xFFFFFF, specular: 0xcccccc, shininess:50, ambient: 0xffffff, map:texture }); // 球体(形状)にマテリアル(質感)を貼り付けて物体を作成 var mesh = new THREE.Mesh(geometry, material); mesh.rotation.x += Math.PI; // 球体を回転させ、方向を調整 // シーンに物体を配置 scene.add( mesh );
④ 描画を行う
最後に、scene と camera を指定してレンダリングする。 併せて、球体が自動で回転する処理を加えてみます
[js/main.js] var render = function () { requestAnimationFrame( render ); mesh.rotation.y += 0.003; renderer.render(scene, camera); };
window.requestAnimationFrame() メソッドは、ブラウザに描画させたいアニメーションを指定し、次の再描画の前に、アニメーションを更新する指定した関数を呼び出すように要求します。このメソッドは再描画する前に呼び出されるコールバックメソッドを引数にひとつとります。 https://developer.mozilla.org/ja/docs/Web/API/Window/requestAnimationFrame
これで、以下のように360°画像を見ることができるようになりました! 歪みなく綺麗に見えていますね。
まとめると、以下の様なソースコードとなります。
[js/main.js] // シーンの作成 var scene = new THREE.Scene(); // カメラの作成 var camera = new THREE.PerspectiveCamera( 75, window.innerWidth/window.innerHeight, 0.1, 1000 ); // レンダラーの作成 var renderer = new THREE.WebGLRenderer(); renderer.setSize( window.innerWidth, window.innerHeight ); document.body.appendChild( renderer.domElement ); // body にcanvas要素として描画エリアを追加 // 球体の形状を作成 var geometry = new THREE.SphereGeometry(1, 100, 100); // 画像をテクスチャとして読み込み var texture = new THREE.ImageUtils.loadTexture("photo.jpg"); texture.minFilter = THREE.LinearFilter; texture.flipY = false; // テクスチャを使い、マテリアル(質感)を作成 var material = new THREE.MeshBasicMaterial({ side: THREE.DoubleSide, color: 0xFFFFFF, specular: 0xcccccc, shininess:50, ambient: 0xffffff, map:texture }); // 球体(形状)にマテリアル(質感)を貼り付けて物体を作成 var mesh = new THREE.Mesh(geometry, material); mesh.rotation.x += Math.PI; // 球体を回転させ、方向を調整 scene.add( mesh ); var render = function () { requestAnimationFrame( render ); mesh.rotation.y += 0.003; renderer.render(scene, camera); }; render();
次回は、デバイスの傾きに応じてカメラを回転させ、部屋全体を見れるようにしていき、 さらに2眼モード対応をしていきます。