three.js BufferGeometry入門 Part1

three.jsのBufferGeometryクラスの使い方を解説していく。three.js r84を使用。
この記事で使うプログラムはこちら

GeometryとBufferGeometry

three.jsにはGeometryというジオメトリを表すクラスと、このGeometryクラスを継承してより具体的なジオメトリを表すBoxGeometrySphereGeometryなどがある。シンプルなシーンの作成ならこれらを使うが、BufferGeometryクラスを使うとより複雑な処理を書くことができる。具体的にどんなことができるかは公式Examplesのwebgl/advancedの項目を見るのが手っ取り早い。

素のwebglの知識が全くない状態だとBufferGeometryの使いどころとか感覚がつかめないと思う。まずはwgld.orgの「ブラウザの準備」〜「インデックスバッファによる描画」あたりまで読んでおくと良い。BufferGeometryを使う分には素のwebglが書ける状態にまで持っていく必要はない。テキストを読んでなるほどと思えればおk。この記事は上記の記事を読んだ前提で話を進める。

BufferGeometryで4角形を作る

今のwebglでは点、線、3角形しか作ることができない。4角形を作るには3角形を2つ用意する必要がある。

main01.js

// シーンの作成
var scene = new THREE.Scene();
// カメラの作成
var camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.set(0, 0, 10);
// レンダラーの作成
var renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setClearColor(0x00142b);
document.getElementById("CanvasContainer").appendChild(renderer.domElement);
// ジオメトリの作成
var geometry = new THREE.BufferGeometry();
var numPoints = 6; // ジオメトリを構成する点の数
// 頂点の設定
var positions = new THREE.Float32BufferAttribute(numPoints * 3, 3);
// 一枚目の三角形
positions.setXYZ(0, -1.0, 1.0, 0);
positions.setXYZ(1, -1.0, -1.0, 0);
positions.setXYZ(2, 1.0, -1.0, 0);
// 二枚目の三角形
positions.setXYZ(3, 1.0, -1.0, 0);
positions.setXYZ(4, 1.0, 1.0, 0);
positions.setXYZ(5, -1.0, 1.0, 0);
// position attributeを追加
geometry.addAttribute("position", positions);
// マテリアルの作成
var material = new THREE.MeshBasicMaterial({color: 0xffffff});
// メッシュの作成
var mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);
// 描画開始
render();
function render() {
renderer.render(scene, camera);
requestAnimationFrame(render);
}

BufferGeometryはBufferAttributeクラスで作成したattributeをaddAttribute()で追加するという形で使う。THREE.Float32BufferAttributeとかはBufferAttributeクラスを各TypedArrayで作成しやすくした便利クラス。使い方はソース読むのがわかりやすい。
https://github.com/mrdoob/three.js/blob/master/src/core/BufferAttribute.js

function Float32BufferAttribute( array, itemSize ) {
BufferAttribute.call( this, new Float32Array( array ), itemSize );
}

ここの引数にあるarrayは配列そのものであったり配列の要素数のことだったりする。上のプログラムでは要素数を渡している。

// 頂点の設定
var positions = new THREE.Float32BufferAttribute(numPoints * 3, 3);

numPoints * 3としているのは1個の頂点には(x, y, z)の3つの値があるから頂点数 * (x, y, z)という意味。itemSizeは追加したいattributeがいくつの数値の集合で意味をなすのかを表す。position attributeは(x, y, z)の3つで1つの頂点を表すのでitemSizeが3。ちなみにcolor attributeは(r, g, b)のつもりならitemSizeは3で、(r, g, b, a)なら4になる。こんな感じに1次元配列でattributeを扱うのでBufferAttributeのsetXYZ()メソッドとかは直感的に配列にアクセスしてx, y, zを設定できるように内部でうまいことitemSize使ってる。

setXYZ: function ( index, x, y, z ) {
index *= this.itemSize;
this.array[ index + 0 ] = x;
this.array[ index + 1 ] = y;
this.array[ index + 2 ] = z;
return this;
},

threejs公式Exampleのこれはキューブ状に点をバラバラに配置して3角形を大量に描画している。positionの他にcolor attributeとnormal attributeも設定している。

Part1は終了。次回はインデックスバッファを使って4つの頂点で4角形を作る解説をする。

次回 : three.js BufferGeometry入門 Part2