2016年7月27日水曜日

Three.jsでメタボールをつくる

Googleで「メタボール」を検索すると、n 次元の有機的なオブジェクトという説明が見つかる。この説明だといまひとつピンとこないので、自分なりに調べてみた結果、球体などの曲線で形成される立体を融合した立体というものらしい。このメタボールをThree.js(r79)でつくる。

Three.jsではメタボールをマーチングキューブという方法で描画する。Three.jsのサンプル集にマーチングキューブ法によるメタボールのデモ(webgl_marchingcubes.html)があるので、これを参考にする。

MarchingCubes.jsの読み込み


ダウンロードしたファイルを解凍し、three.js-master\examples\js\MarchingCubes.jsを
適当なフォルダにコピーする。ここではjs_r79というフォルダにコピー。それをhtmlから読み込む。


キューブマップの準備


今回はメタボールのテクスチャにキューブマップを使用するのでその準備をする。キューブマップについてはThree.jsでキューブマップを使うを参照。

// キューブマップ用のテクスチャ作成
var cubeTexture = new THREE.CubeTextureLoader()
    .setPath( 'sunflower/' )
    .load( [ 'sunflower_er_left.png', 'sunflower_er_right.png', 'sunflower_er_up.png', 'sunflower_er_down.png', 'sunflower_er_front.png', 'sunflower_er_back.png' ] );
cubeTexture.format = THREE.RGBFormat;

// シーンの作成
var scene = new THREE.Scene();
// シーンの背景テクスチャを設定
scene.background = cubeTexture;

// マテリアル作成
// 環境マップ(envmap)に作成したテクスチャ(cubeTexture)を設定
var material = new THREE.MeshStandardMaterial( { color: 0xdddddd, envMap: cubeTexture, roughness: 0.1, metalness: 0.5, transparent: true, opacity: 0.7 } );

MarchingCubesインスタンスの作成


MarchingCubesインスタンスを作成し、シーンに追加する。

// MarchingCubesインスタンスの作成
// 第1引数はresolutionで、値を大きくするほど滑らかな描画になる
var effect = new THREE.MarchingCubes( 64, material, true, true );
effect.position.set( 0, 0, 0 );
effect.scale.set( 1000, 1000, 1000 );

// シーンに追加
scene.add( effect );

メタボールの作成


以下のような関数を作成し、その中でMarchingCubes.addBallにより球体を作成する。この関数をレンダリングループで呼ぶ。

// Three.jsサンプル集にあるwebgl_marchingcubes.htmlのupdateCubesの一部を省いてほぼそのまま使用
// object: 作成したMarchingCubesインスタンス
// time: 経過時間の差分
// numblobs: 作成する球体の数
function updateCubes( object, time, numblobs) {

 object.reset();

 var i, ballx, bally, ballz, subtract, strength;

 subtract = 100;
 strength = 1.2 / ( ( Math.sqrt( numblobs ) - 1 ) / 4 + 1 );

 for ( i = 0; i < numblobs; i ++ ) {

  ballx = Math.sin( i + 1.26 * time * ( 1.03 + 0.5 * Math.cos( 0.21 * i ) ) ) * 0.27 + 0.5;
  bally = Math.abs( Math.cos( i + 1.12 * time * Math.cos( 1.22 + 0.1424 * i ) ) ) * 0.77;
  ballz = Math.cos( i + 1.32 * time * 0.1 * Math.sin( ( 0.92 + 0.53 * i ) ) ) * 0.27 + 0.5;

  object.addBall( ballx, bally, ballz, strength, subtract );
 }
}

結果


以上をもとに作成したメタボールがこちら。




0 件のコメント:

コメントを投稿