読者です 読者をやめる 読者になる 読者になる

リクルート住まいカンパニー Tech Blog

ITのちからで暮らしをよくしたい、エンジニア・デザイナーが発信するTech情報メディア

three.jsを利用したVR体験の実現 ②

f:id:recruit-sumai:20170309105217j:plain

こんにちは、スマートデバイス戦略開発グループの katayama です。

前回は、「three.jsを利用したVR体験の実現 ① 全天球を表示してみる」で、RICHO THETA S などの360°カメラで撮影した全天球の画像を表示させ、自動で回転するところまでお話しました。

今回はその続きで、デバイスの向きに合わせてカメラを回転させる処理と、 Oculus Rift / Cardboard のように2眼の効果をつける処理についてお話します。

具体的には左図の様なものが、右図のように2眼になるイメージです! f:id:recruit-sumai:20170322182635p:plain

 

デバイスの回転の取得方法

スマホには様々なセンサーが搭載されており、デバイスがどちらの方向を向いているかも、センサーから取得することができます。ブラウザにはその向きを簡単に取得できるAPIが用意されています。

それが、deviceorientation event になり、

window.addEventListener("deviceorientation", function(event){
    console.log('alpha : %f', event.alpha);
    console.log('beta : %f', event.beta);
    console.log('gamma : %f', event.gamma);
});

というように取得することが可能です。 f:id:recruit-sumai:20170322182701p:plain

画像 ) デバイスの向きのイベント |  Microsoft Developer Network (https://msdn.microsoft.com/ja-jp/library/dn433240(v=vs.85).aspx) より

 

このalpha, beta, gamma の数字から、WebGLでのカメラがどこを向けばよいかを計算する必要があります。 この計算は、実際やってみると結構厄介なものです。

 

……が、この計算をやってくれるライブラリが、Three.js のプロジェクトにはあります。 (自分は、独自に実装を終えた後に気づいたので、嬉しいような悲しいような。という気持ちでしたが。。) (https://github.com/mrdoob/three.js/blob/master/examples/js/controls/DeviceOrientationControls.js)

とても便利なので、これを利用して回転を加えていこうと思います。

 

デバイスの回転に併せてカメラを回転させる

やることは超簡単!!DeviceOrientationControls.jsを読み込んだら 以下の様にコントロールに追加する

var controls = new THREE.DeviceOrientationControls( camera, true );
controls.connect();

あとは、render() の部分で、controls.update() を呼ぶだけです。

var render = function () {
 requestAnimationFrame( render );
 controls.update();
 renderer.render(scene, camera);
};

めちゃくちゃ簡単ですね。これで、デバイスの向けた方向に併せてカメラが回転し、部屋をグルグル見渡す体験が可能です。

 

2眼のエフェクトを加える (CardboardEffect.js)

最後に、Oculus Rift のように、2眼モードにするエフェクトを加えてみます。 SUUMOで実装した際は、OculusRiftEffect.js というものがあったのですが、現在 three.js のgithub上から何故かなくなっていて、新しくCardboardEffect.js というものがあったので、こちらで解説します!

// rendererにCardboardEffectをかける
var effect = new THREE.CardboardEffect(renderer);

var render = function () {
 requestAnimationFrame( render );
 controls.update();

 // rendererのrenderメソッドではなく、effect の renderメソッドを呼ぶ
 effect.render(scene, camera);
};

render();

たったこれだけで、2眼モードにすることが可能です! 結果はこんな感じになりました f:id:recruit-sumai:20170322182725j:plain  

以上です。簡単でしたね!最後にソースコードのまとめを貼っておきます。

まとめのソースコード

[main.js]
// シーンの作成
var scene = new THREE.Scene();
// カメラの作成
var camera = new THREE.PerspectiveCamera( 75, window.innerWidth/window.innerHeight, 0.1, 1000 );

var controls = new THREE.DeviceOrientationControls( camera, true );
controls.connect();

// レンダラーの作成
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 );

// rendererにCardboardEffectをかける
var effect = new THREE.CardboardEffect(renderer);

var render = function () {
    requestAnimationFrame( render );
    controls.update();

    // rendererのrenderメソッドではなく、effect の renderメソッドを呼ぶ
    effect.render(scene, camera);
};

render();

three.js は便利でしたね! 色々なエフェクトが簡単に扱えるので、是非やってみてください!