サイトトップ

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

HTML5テクニカルノート

three.js入門 03: ジオメトリーを使う


「three.js入門」01「3次元空間で立方体を回す」と02「フォンマテリアルとライトを使う」は、よく使われる立方体でアニメーションをつくりました。基本的(primitive)な立体の形状はほかにもあります。かたちを決める幾何学的な情報がジオメトリーです。本稿は基本的なジオメトリーのいくつかをご紹介します。

01 立方体を回すサンプルコード

「three.js入門」01のコード002「3次元空間につくった立方体をアニメーションで回す」が短くてわかりやすいので、これを書き替えるかたちで進めます。その前に、少しだけ手直ししておきましょう。まず、three.jsのライブラリはr85が公開されたので、差し替えます。「Migration Guide」を見るかぎり、大きな変更はなさそうです。


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

つぎに、初期化のコードは関数(init())にして、DOMContentLoadedイベントのリスナーとして呼び出します(「three.js入門 02」03「JavaScriptコードを<head>要素に移す」参照)。そして最後に、変数と関数の名前です。立方体以外も試しますので、誤解されないように名前を変えました(meshとcreateMesh())。これから試すもととなる立方体を回すスクリプトは、以下のコード001のとおりです(図001)。jsdo.itにサンプル001として掲げました。


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);
var mesh;
function init() {
	scene = new THREE.Scene();
	camera = new THREE.PerspectiveCamera(30, width / height, 1, 1000);
	renderer = createRenderer(width, height);
	// cube = createCube(side, side, side);
	mesh = createMesh(side, side, side);
	camera.position.z = 100;
	// scene.add(cube);
	scene.add(mesh);
	update();
}

// function createCube(width, height, depth) {
function createMesh(width, height, depth) {
	var geometry = new THREE.BoxGeometry(width, height, depth);
	var material = new THREE.MeshNormalMaterial();
	// var cube = new THREE.Mesh(geometry, material);
	var mesh = new THREE.Mesh(geometry, material);
	// return cube;
	return mesh;
}
function update() {
	// cube.rotation.x += 0.01;
	mesh.rotation.x += 0.01;
	// cube.rotation.y += 0.01;
	mesh.rotation.y += 0.01;
	requestAnimationFrame(update);
	renderer.render(scene, camera);
}
// update();
window.addEventListener('DOMContentLoaded', init);

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

図001

コード001■3次元空間の立方体をアニメーションで回す


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

サンプル001■three.js r85: Rotating a cube with light

02 立体の基本的な幾何学要素

立体(メッシュ)の幾何学情報がジオメトリーです。その基本的な要素をたしかめましょう。つぎの3つです(図002)。

図002■立体の基本的な幾何学要素

図002

立体の表面をつくるポリゴンの数は変えられます。たとえば、直方体をつくるBoxGeometryのコンストラクタでは、第4から第6引数で各辺を何分割するかというセグメント数が与えられます(デフォルト値1)。平面のままかたちを変えないなら、細かく分ける意味はありません。曲面を表す場合には、数を増やすほど滑らかに見えます。


new BoxGeometry(幅, 高さ, 奥行き, 幅分割数, 高さ分割数, 奥行き分割数)

03 平面をつくる

直方体よりもさらに面の少ない平面をつくるのはPlaneGeometry()コンストラクタです。引数には幅と高さを渡します。


new THREE.PlaneGeometry(幅, 高さ)

前掲コード001の立体をつくる関数(createMesh())は、つぎのように書き替えます。受け取る引数はふたつですので、呼び出し側も引数の数を減らします。アニメーションはそのまま、3次元空間で平面が回ります(図003)。直したコード行数は少ないですからまとめて示すことはせず、jsdo.itに以下のサンプル002を掲げます。


function init() {

	mesh = createMesh(side, side);  // , side);

}

// function createMesh(width, height, depth) {
function createMesh(width, height) {
	// var geometry = new THREE.BoxGeometry(width, height, depth);
	var geometry = new THREE.PlaneGeometry(width, height);

}

図003■3次元空間で平面が回る

図003

サンプル002■three.js r85: Rotating a plane

04 正二十面体をつくる

面の多い立体としては、正二十面体がIcosahedronGeometry()コンストラクタでつくれます。引数は中心から頂点までの半径です。


new THREE.IcosahedronGeometry(半径)

前掲のコードをつぎのように書き替えれば、3次元空間につくられた正二十面体が回ります(図003)。以下のサンプル003がjsdo.itに掲げたコードです。面の数がもう少し少ない正八面体のOctahedronGeometryや球面のSphereGeometryも、基本的に同じようにつくれます。これらも、それぞれサンプル004と005としてjsdo.itに加えました。球面も厳密にはポリゴンの三角形で組み立てられます。


function init() {

	mesh = createMesh(side);  // , side);

}

// function createMesh(width, height) {
function createMesh(radius) {
	// var geometry = new THREE.PlaneGeometry(width, height);
	var geometry = new THREE.IcosahedronGeometry(radius);

}

図004■3次元空間で正二十面体が回る

図004

サンプル003■three.js r85: Rotating a icosahedron

05 立方体の頂点座標を動かす

基本的なジオメトリーでつくった立体であっても、頂点の座標はあとから変えられます。前掲コード001の立方体で試してみましょう。立体のMesh.geometryプロパティでGeometryオブジェクトが参照できます。そして、頂点座標のオブジェクトを納める配列がGeometry.verticesです。配列から取り出したオブジェクトのxyz座標を、つぎの関数(randomizeVertices())でランダムな位置にずらします。すると、立方体のかたちが歪むのです(図005)。


function init() {

	mesh = createMesh(side, side, side);
	randomizeVertices(mesh.geometry.vertices);

}

function randomizeVertices(vertices) {
	var range = side / 2;
	var length = vertices.length;
	for (var i = 0; i < length; i++) {
		var vertex = vertices[i];
		vertex.x += -range / 2 + Math.random() * range;
		vertex.y += -range / 2 + Math.random() * range;
		vertex.z += -range / 2 + Math.random() * range;
	}
}

図005■立方体の頂点座標がランダムにずれて歪んだ

図005

コード002■3次元空間で頂点の歪んだ立方体が回る


var width = window.innerWidth;
var height = window.innerHeight;
var side = Math.min(width, height) / 50;
var scene;
var camera;
var renderer;
var mesh;
function init() {
	scene = new THREE.Scene();
	camera = new THREE.PerspectiveCamera(30, width / height, 1, 1000);
	renderer = createRenderer(width, height);
	mesh = createMesh(side, side, side);
	randomizeVertices(mesh.geometry.vertices);
	camera.position.z = 100;
	scene.add(mesh);
	update();
}
function createRenderer(width, height) {
	var renderer = new THREE.WebGLRenderer();
	renderer.setSize(width, height);
	document.body.appendChild(renderer.domElement);
	return renderer;
}
function createMesh(width, height, depth) {
	var geometry = new THREE.BoxGeometry(width, height, depth);
	var material = new THREE.MeshNormalMaterial();
	var mesh = new THREE.Mesh(geometry, material);
	return mesh;
}
function randomizeVertices(vertices) {
	var range = side / 2;
	var length = vertices.length;
	for (var i = 0; i < length; i++) {
		var vertex = vertices[i];
		vertex.x += -range / 2 + Math.random() * range;
		vertex.y += -range / 2 + Math.random() * range;
		vertex.z += -range / 2 + Math.random() * range;
	}
}
function update() {
	mesh.rotation.x += 0.01;
	mesh.rotation.y += 0.01;
	requestAnimationFrame(update);
	renderer.render(scene, camera);
}
window.addEventListener('DOMContentLoaded', init);

サンプル006■three.js r85: Rotating a cube with vertices randomized


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


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