WebGLのアドベントカレンダー8日目です。
Three.jsを使って、旗をはためかせるアニメーションの作り方を説明します。物理的に正しい動きというより、PlaneGeometryとSin波を使い簡単なコードでそれっぽいものを目指します。以前このPCサイトで使っていたものです。
#やりかた
まずPlaneGeometryのMeshを用意します。
//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.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.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さんです。おねがいします!