three.jsで線が伸びてくアニメーションをつくるときに少しクセがあったのでメモ。
まずは通常の"伸びない"線の描き方。
var scene, line;
function drawNormalLine(){
var geometry = new THREE.Geometry();
geometry.vertices.push(new THREE.Vector3(-100,0,0));
geometry.vertices.push(new THREE.Vector3(100,0,0));
var material = new THREE.LineBasicMaterial({color: 0x00FFFF, linewidth: 2});
line = new THREE.Line(geometry, material);
scene.add(line);
}
これで、
line.geometry.vertices.push(new THREE.Vector3(200,0,0));
line.geometry.verticesNeedUpdate = true;
とか、やっていけば線が伸びるんだろうと思ったら伸びない。
解決するにあたり参考になったのは、このポスト↓
http://stackoverflow.com/questions/31399856/drawing-a-line-with-three-js-dynamically/31411794#31411794
ポイントは、
var geometry = new THREE.Geometry();
ではなく、
var geometry = new THREE.BufferGeometry();
を使うこと。
基本的に、geometryの頂点数(verticesの数)を動的に増やしていくことはできないんだそう。
なので、最初にある程度、頂点を配列にどばっと入れておいて、その内いくつ目までの頂点を使うかを指定する。
function drawDynamicLine(){
//---最大頂点数をあらかじめ指定する必要がある。ここでは30
var maxpoints = 30;
//---BufferGeometryを使うのがポイント
var geometry = new THREE.BufferGeometry();
//---頂点の場所を格納していくarrayを用意。各頂点(x,y,z)の3つの数字があるので3倍する
var positions = new Float32Array(maxpoints * 3);
geometry.addAttribute('position', new THREE.BufferAttribute(positions, 3));
//---配列に頂点の座標をいれてく。ひとまずmaxpointsで設定した頂点数の内、2頂点分
var array = geometry.attributes.position.array;
array[0] = -100; //x1
array[1] = 0; //y1
array[2] = 0; //z1
array[3] = 100; //x2
array[4] = 0; //y2
array[5] = 0; //z2
//---BufferGeometryクラスの.addGroup 引数は( start, count, indexOffset )
//---とりあえず用意した頂点のうち0番から2番まで結ぶ
geometry.addGroup(0, 2, 0);
//---あとは、通常と同じ
var material = new THREE.LineBasicMaterial({ color: 0x990000, linewidth : 5});
line = new THREE.Line(geometry, material);
scene.add(line);
}
で、"伸ばせる"線の最初の部分が描ける。
用意した頂点(maxpointsで指定した数)のいくつ目までを使って線を描くかを決めるのは↓の数。
line.geometry.drawcalls[0].count
アップデート: .geometry.drawcallsが廃止された。
用意した頂点(maxpointsで指定した数)のいくつ目までを使って線を描くは、
line.geometry.setDrawRange( start, count );
で更新する。
なので、これ以降、
index = 3; //---新たに加える頂点のindex (ここでは、最大30)
var array = geometry.attributes.position.array;
array[index*3] = newX; //---新たに加える頂点のx座標
array[index*3+1] = newY; //---新たに加える頂点のy座標
array[index*3+2] = newZ; //---新たに加える頂点のz座標
とかで、頂点座標を配列に加えてから、
line.geometry.setDrawRange(0, 3);
ってやると、0番目から3番目の頂点までを含む線が描ける。
なので、線が伸びるアニメーションをつくりたいときは、最初にスタート地点からゴール地点までの頂点を全部登録しておいて、drawcalls[0].countの数を .setDrawRange(0, 3)の数を、animation関数の中で増やしていけば、伸びていくはず。
http://jsfiddle.net/yuyuyuyoyoyo/0zurstzw/9/