Google PixcelのサイトがかっこよすぎたのでWeb上での3Dオブジェクトの扱い方に少しだけ触れてみた [three.js]

Google PixcelのサイトがかっこよすぎたのでWeb上での3Dオブジェクトの扱い方に少しだけ触れてみた

前置き

新型iPhoneの発表で賑わっていますね!僕はApple Watchを注文しました!はよ来い!!
その裏側でこっそりGoogleがPixcelの日本上陸を発表しました。

GoogleのWebサービスは使っているものの、端末はApple派な私は「ほーん?」程度にしか思っていなかったのですが、
エンジニアの端くれとして少しは情報見とくか・・・と思って公式ページにアクセスしてみました。
サムネイルから、とてもシンプルなページかと思いきや・・・


( ゚д゚)!!

なにこれ!!かっこよくない!?
え!こんなんできるのHTML5で?まじで?すごない!?

というWeb上の3D表現を全く知らない私はこのページのかっこよさに惚れ込んでしまったのでした。
そこで、今回はWeb上で3D表現を簡単にできる、three.jsを触ってみようと思います!

three.js

公式サイト

MITライセンスのオープンソースのライブラリ。Pixcelのサイトのソースを見てたらこれが使われている事がわかりました。
上に書いた公式のデモでもうめちゃめちゃすごい。なにこれ。
公式サイトトップにはいろんなthree.jsを使っているサイトやWebアプリのリンクがあるのでぜひ訪れてください。

入門 〜回転するキューブ〜

入門として公式サイトのドキュメントに回転するキューブを実際に作成する説明があります。
これをオレオレ日本語意訳(サボリ気味)をしながら作っていこうと思います。

はじめに

three.jsを使い始める前に、表示する場所が必要です。
このHTMLをローカルに作って、three.jsの入ったjsフォルダと一緒に置いといてください。

<!DOCTYPE html>
<html>
	<head>
		<meta charset=utf-8>
		<title>My first three.js app</title>
		<style>
			body { margin: 0; }
			canvas { width: 100%; height: 100% }
		</style>
	</head>
	<body>
		<script src="js/three.js"></script>
		<script>
			// ここに今から書くJSがはいるよ
		</script>
	</body>
</html>

シーンを作る

three.jsでいろんなものを描画するためには、シーン(scene) レンダラー(renderer) カメラ(camera) の3つが必要です。
カメラとシーンで3D表現をレンダーできます。

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 );

ここで何をしているか簡単に説明します。
まず最初にシーンを定義しているのはわかりますね。はい。

次に、カメラを定義しています。three.jsではいくつかカメラの種類がありますが、今回はPerspectiveCameraを使います。

  • 最初の引数(75)はField of Viewです。シーンの範囲を示しています。
  • 2つめの引数(window.innerWidth / window.innerHeight)はアスペクト比です。
    ほとんどの場合は表示する要素の幅を高さで割ったものを設定すれば大丈夫です。古い映像をワイドテレビで写したようなひしゃげた形にするためにはここを好きに変えてください。

  • 残りの2つの引数は近位および遠位のクリッピング面です。
    ここは私なりの理解ですが、ここに設定した近位よりも近くのオブジェクト、遠位よりも遠いオブジェクトは描画されないということだと思います。
    3Dゲームで動き回るときに、あまりに遠くのオブジェクトは描画されないですよね?あとゲームにもよりますがあまりにカメラに近いものは描画されなくなったりしますよね?そんなイメージだと思います。(少し適用)

次はレンダラーです。ここで魔法が起こります(日本語にするとダサい)。
WebGLをサポートしていない古いブラウザーのためにWebGLRendererを利用しています。

さらに、レンダラーを作成するときは、サイズを設定する必要があります。
描画したい範囲の幅と高さをつかってしまうのはいい考えです。(今回の場合はブラウザの幅と高さ)
もちろんここをwindow.innerWidth/2window.innerHeight/2にすると、小さくなりますよ。

もし描画サイズを変えずに、低解像度で描画したいのであれば、

setSize(window.innerWidth/2, window.innerHeight/2, false)

のように第3引数にfalseを渡してあげるといいです。
(内部的にはcanvas要素に100%の幅と高さが設定されます。)

最後に、レンダラーをHTMLに追加しています。
これはレンダラーがシーンを表示するためのcanvas要素となります。

「なんとなくわかった。OK。んで回転するキューブは?キューブはよ!!」
はいはい。次はキューブを作りましょう。

var geometry = new THREE.BoxGeometry( 1, 1, 1 );
var material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } );
var cube = new THREE.Mesh( geometry, material );
scene.add( cube );

camera.position.z = 5;

キューブを作るためにBoxGeometryを使います。
このオブジェクトは、頂点と、面をもったものになります。
骨組みみたいなイメージですかね?

骨組みみたいなのに加えて、色をぬるために素材を設定する必要があります。
いろいろありますが、今回はMeshBasicMaterialを使います。
今回は簡単にするために、緑色(0x00ff00)を設定しています。

そして、メッシュが必要になります。
メッシュは骨組みに素材を組み合わせて、シーンに追加できるオブジェクトを作ってくれるものだと思ってください。

最後にシーンに追加を行っていますね。初期値として、追加が行われた際はシーンの座標(0,0,0)に追加されます。
このままだと、カメラとキューブがめり込んじゃうので、カメラを少しだけずらしています。

シーンを描画する

いままで説明してきたソースコードを貼り付けてみても、何も起きないはずです。
実は今の時点では何も描画していません。描画するためには、render or animate loop(描画かアニメーションループ)が必要です。

function animate() {
requestAnimationFrame( animate );
renderer.render( scene, camera );
}
animate();

これでスクリーンがリフレッシュされるたびに、シーンを毎回書き直すループが作られました。
単純にインターバルを設定せずに、requestAnimationFrameを使う理由としては、ユーザの端末に無駄な負荷をかけないように、他のサイトを見ているときなどに動作を制限することにあります。

キューブにアニメーションを追加する

ここまでやってきたあなたの画面には、おもしろない緑色の四角が描画されているでしょう。
回転させてもう少し面白くしましょう。

cube.rotation.x += 0.01;
cube.rotation.y += 0.01;

この処理が毎フレーム(60分の1秒ごと)に実行されて、キューブにすてきなアニメーションを与えます。
基本的に移動や変化といったアニメーションはこのループを通して処理されます。
もちろんここで他の関数を呼んだりして、100行では済まないアニメーション関数を実行してください。

結果

おめでとうございます!あなたの最初のthree.jsのアプリができました!
すべてのコードは以下から確認してください。そしていろいろいじってみて理解してください。

まとめ

以上でthree.jsの入門が終わりました。
いつもはドキュメントは飛ばし飛ばし読むので、ガッツリ訳しながら読むと疲れますね!
作成したものは下に埋め込んでますので、「Result」ってボタンをクリックして確認してみてください!回転するキューブが見れるはずです!

では!