HTML5テクニカルノート
three.js入門 03: ジオメトリーを使う
- ID: FN1704012
- Technique: HTML5 / JavaScript
- Library: three.js r85
「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■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)。
- 頂点(vertex): 3次元空間の座標。頂点同士を直線で結び合うことによって立体がかたちづくられる。
- 辺(edge): ふたつの頂点を結ぶ直線。辺によって立体のかたちが決まる。
- 面(face): 3つの辺でつくられる表面の最小単位。ポリゴンともよばれる。
図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次元空間で平面が回る
サンプル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次元空間で正二十面体が回る
サンプル003■three.js r85: Rotating a icosahedron
-
サンプル004■three.js r85: Rotating a octahedron
-
サンプル005■three.js r85: Rotating a sphere
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■立方体の頂点座標がランダムにずれて歪んだ
コード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.