WebGL
three.js
WebGLDay 8

PlaneGeometryをSin波で、はためかせる

More than 3 years have passed since last update.

WebGLのアドベントカレンダー8日目です。

Three.jsを使って、旗をはためかせるアニメーションの作り方を説明します。物理的に正しい動きというより、PlaneGeometryとSin波を使い簡単なコードでそれっぽいものを目指します。以前このPCサイトで使っていたものです。

hoge.jpg

やりかた

まずPlaneGeometryのMeshを用意します。

plane_junbi
//hoge.jpgをテクスチャにしたSEGX,SEGYに分割されたPlaneを作る。
var texture = THREE.ImageUtils.loadTexture('hoge.jpg');
var geometry = new THREE.PlaneGeometry(1300, 1228, SEGX, SEGY);
var material = new THREE.MeshLambertMaterial({map:texture});
plane = new THREE.Mesh(geometry, material);
scene.add(plane); 

このPlaneのverticesを毎フレームをsin波で動かします。z方向のみ波うたたせます。

plane_ugokasu
plane.geometry.verticesNeedUpdate=true;//これを忘れずに書く
for (var i=0;i<SEGX+1;i++) {
    for (var j=0;j<SEGY+1;j++) {
        //(i,j)のvertexを得る
        var index = j * (SEGX + 1) + i % (SEGX + 1);
        var vertex = plane.geometry.vertices[index];
        //時間経過と頂点の位置によって波を作る
        var amp=100;//振幅
        vertex.z = amp * Math.sin( -i/2 + time*15 );
    }           
}

ポイントはgeometry.verticesNeedUpdate=trueにすることと、Planeの各Vertixの参照のしかたです。
amp=100とかi/2,time*15とかの数値は適当に変更してみてください。

こんな感じにできました。 細かなコードはこちらを参照してください。iOS8とかでも動きます。

Perlinノイズも使ってみる

Sin波だけだと、ちょっと退屈な動きなのでperlinノイズhttps://github.com/josephg/noisejs で変化を付けてみます。perlinノイズは、連続的でゆるやかな乱数が得られます。

先ほどsin波の振幅amp=100としていた部分に、perlinノイズも加え、以下のように変更しました。

perlin_kuwaeru
//perlin.jsを使用
var amp = 50 + 300 * noise.perlin3(i/20+time/5,j/70,time);
vertex.z = amp * Math.sin( -i/2 + time*15 );

perlinノイズnoise.perlin3(x,y,z)は、よくわかってないですがx,y,zをちょっとかえたら、戻り値もちょっとかわるみたいなイメージです。

結果、こんな感じになりました。 sinだけのものより変化がつきました。

おわりに

以上、擬似的に旗っぽいものを作りました。そもそもzしか変えてないので、物理的におかしく、生地がのびてるわけですが、それっぽくも見える気もます。
実際に私が使ったときは、生地がのびないような処理を入れたりしました、パラメータをかえるだけでも、もっとよくなったりするかもしれません。

あすは@Rinforzando_960さんです。おねがいします!