LoginSignup
21
17

More than 5 years have passed since last update.

three.jsで線が伸びるアニメーション

Last updated at Posted at 2015-07-18

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/

21
17
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
21
17