サイトトップ

Director Flash 書籍 業務内容 プロフィール

HTML5テクニカルノート

three.js入門 01: 3次元空間で立方体を回す


three.jsは、WebGLを使って3次元の表現ができる無償のJavaScriptライブラリです。本稿では、短いコードで3次元空間に立方体をつくって、回してみます。使ったプロパティやメソッドには、できるだけ公式ドキュメントへのリンクを加えました。

01 theree.jsライブラリを使う

ライブラリはthree.jsサイトのリンク[download]で、ZIPファイルがローカルに保存できます(図001)。buildフォルダの中に、開発用のthree.jsと公開用のthree.min.jsが納められていますので、用途に応じていずれかをお使いください。

図001■three.jsサイトの[download]のリンク

図001

CDNも公開されていますので、本稿ではこちらを使うことにします。


<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/84/three.min.js"></script>

02 シーンとカメラを定める

3次元空間であるシーンは、コンストラクタTHREE.Scene()でつくります。引数は要りません。シーンの中に3次元のオブジェクトや光源、それらを映しだすためのカメラが加えられます。カメラを定めるのはコンストラクタTHREE.PerspectiveCamera()です。引数はつぎの4つを渡します(図002)。


new THREE.PerspectiveCamera(視野角, 縦横比, 撮影開始距離, 撮影終了距離)

図002■カメラの設定

図002

視野角は画角とも呼ばれ、撮影する範囲の広がりのほか遠近法の強さにも影響します(「レンズと画角のちがいを知り、表現に活かす CG制作者のための画角講座」参照)。画面の縦横比は幅/高さです。そして、奥行きに対して撮影する範囲の始まりと終わりを与えます。シーンとカメラはつぎのように定め、カメラのz軸方向の位置はObject3D.positionプロパティで少し下げました(デフォルト値0)。なお、JavaScriptコードから<body>要素を参照することになるので、<script>要素は<body>の中に置いてください。


var width = window.innerWidth;
var height = window.innerHeight;

var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(30, width / height, 1, 1000);

camera.position.z = 100;

03 レンダラーで<canvas>要素をつくってページに加える

カメラの映したシーンを描くのがレンダラーです。コンストラクタTHREE.WebGLRenderer()<canvas>要素をつくります。引数は省きましょう。幅と高さはWebGLRenderer.setSize()メソッドで決めます(デフォルト値300×150ピクセル)。<canvas>要素はページに加えなければなりません。WebGLRenderer.domElementプロパティで参照できるので、<body>要素に差し込みました。これらの処理は関数(createRenderer())として定め、戻り値のレンダラーは変数に納めます(renderer)。


var renderer = createRenderer(width, height);

function createRenderer(width, height) {
	var renderer = new THREE.WebGLRenderer();
	renderer.setSize(width, height);
	document.body.appendChild(renderer.domElement);
	return renderer;
}

04 立方体をつくってシーンに加える

立体はMeshクラスのオブジェクトとしてつくります。メッシュには、かたちの幾何学情報となるジオメトリーと素材のマテリアルを与えなければなりません。直方体のジオメトリーをつくるのは、THREE.BoxGeometry()メソッドです。幅と高さと奥行きを引数に渡します。THREE.MeshNormalMaterial()でつくる素材は少し変わっていて、面の向きによって色が決まるのです。でき上がったジオメトリー(geometry)とマテリアル(material)のオブジェクトは、コンストラクタTHREE.Mesh()の引数にします。こうして関数(createCube())から返された立方体(cube)は、Object3D.add()メソッドでシーンに加えてください。


var side = Math.min(width, height) / 50;

var cube = createCube(side, side, side);

scene.add(cube);

function createCube(width, height, depth) {
	var geometry = new THREE.BoxGeometry(width, height, depth);
	var material = new THREE.MeshNormalMaterial();
	var cube = new THREE.Mesh(geometry, material);
	return cube;
}

カメラ(camera)で映したシーン(scene)の画像は、レンダラー(renderer)で<canvas>要素に描きます。そのために呼び出すのは、WebGLRenderer.render()メソッドです。引数にはシーンとカメラを渡します。これで、3次元空間に立方体が描かれます(図003)。ここまでのスクリプトは以下のコード001にまとめました。


renderer.render(scene, camera);

図003■3次元空間に立方体の正面が描かれた

図003

コード001■3次元空間に立方体を描く


var width = window.innerWidth;
var height = window.innerHeight;
var side = Math.min(width, height) / 50;
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(30, width / height, 1, 1000);
var renderer = createRenderer(width, height);
var cube = createCube(side, side, side);
camera.position.z = 100;
scene.add(cube);
function createRenderer(width, height) {
	var renderer = new THREE.WebGLRenderer();
	renderer.setSize(width, height);
	document.body.appendChild(renderer.domElement);
	return renderer;
}
function createCube(width, height, depth) {
	var geometry = new THREE.BoxGeometry(width, height, depth);
	var material = new THREE.MeshNormalMaterial();
	var cube = new THREE.Mesh(geometry, material);
	return cube;
}
renderer.render(scene, camera);

05 立方体をアニメーションで回す

3次元空間に立方体を描いたといっても、正面向きでは立体かどうかわかりません。オブジェクトはObject3D.rotationプロパティで軸を決めて回すことができます(角度はラジアン)。どうせならアニメーションで回しましょう。アニメーションの関数(update())を定めてwindow.requestAnimationFrame()メソッドに渡せば、画面が描き替わるたびに呼び出されてアニメーションとして動かせるのです(図004)。3次元空間を描きなおすWebGLRenderer.render()メソッドの呼び出しを忘れないようにしてください。スクリプトは以下のコード002にまとめ、サンプル001はjsdo.itに公開しました。


// renderer.render(scene, camera);
function update() {
	cube.rotation.x += 0.01;
	cube.rotation.y += 0.01;
	requestAnimationFrame(update);
	renderer.render(scene, camera);
}
update();

図004■3次元空間で立方体が回る

図004

コード002■3次元空間につくった立方体をアニメーションで回す


var width = window.innerWidth;
var height = window.innerHeight;
var side = Math.min(width, height) / 50;
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(30, width / height, 1, 1000);
var renderer = createRenderer(width, height);
var cube = createCube(side, side, side);
camera.position.z = 100;
scene.add(cube);
function createRenderer(width, height) {
	var renderer = new THREE.WebGLRenderer();
	renderer.setSize(width, height);
	document.body.appendChild(renderer.domElement);
	return renderer;
}
function createCube(width, height, depth) {
	var geometry = new THREE.BoxGeometry(width, height, depth);
	var material = new THREE.MeshNormalMaterial();
	var cube = new THREE.Mesh(geometry, material);
	return cube;
}
function update() {
	cube.rotation.x += 0.01;
	cube.rotation.y += 0.01;
	requestAnimationFrame(update);
	renderer.render(scene, camera);
}
update();

サンプル001■three.js r84: Rotating a cube


作成者: 野中文雄
作成日: 2017年4月19日


Copyright © 2001-2016 Fumio Nonaka.  All rights reserved.