見出し画像

【フリーのJSライブラリ、LiquidFunでサイエンス vol.3】異星の海を見てみよう~世界の重力と粒子の密度を変えてみる〔コード編〕~

あまり身近でなかった「液体」のシミュレート画像を見る機会が増えてきました。

液体のふるまいをシミュレートする手法のひとつが「粒子法」ですが、この分野でのフリーソフトはまだ少なく、アマチュアがちょっと試してみるのが難しいのが悩みです。

「LiquidFun(リキッド・ファン)」はGoogle社が提供する、粒子法によるシミュレートが可能な数少ないフリーソフトで、JavaScriptという言語で表記することで、アマチュアでも手軽に操る事ができます。

今回は、以下の記事でトライした現象のコードをご紹介します。

本記事では実装コードをご紹介していますが、様々な理由により、この説明通りにいかない場合がしばしばあります。申し訳ありませんが、自己責任・自己解決でお進めくださるよう、お願いいたします。

(再掲)LiquidFunの入手先とベースとなるプログラム


この記事では、LiquidFunのJavascript版をダウンロードして、このサンプルプログラムを修正する、というアプローチでコードを実装します。

同梱されているC言語のソースを使ったり、他のグラフィックスライブラリと連携させる事も可能な様ですが、上記が結果を得る最もシンプルな方法です。

以下の記事にもありますが、前準備を簡単に再掲します。


LiquidFunの入手先

LiquidFunは、以下のサイトで無料公開されています。

上記ページの下の方に、ダウンロード用のリンクがあります。

ここから、liquidfun-1.1.0.zip をクリックしてZIPファイルをダウンロードします。


ダウンロードしたZIPファイルを解凍すると、以下のフォルダが展開されます。

上記のフォルダの内、一番下にある、liquidfun というフォルダを開きます。

上記の一番上にある Box2D というサブフォルダを開きます。


その中に、lfjs というサブフォルダがあります。

この lfjs をどこか適当なところにコピーしてください。
これだけでインストールは終わりです。

他にある多数のファイルは、Cでコンパイルしてより高速化をめざす場合のソースコードなどです。Javascript のコードしか利用しない場合は他は不要です。

改変するファイル

lfjsフォルダに入っている、INDEX.html というHTMLファイルをダブルクリックしてみてください。

index.html がブラウザ上でWEBページとして開かれ、以下の画面が表示されます。ここから様々なサンプルプログラムを実行できます。

今回は、一番上にある、Dam Break(水中崩壊)を修正して使います。(修正結果は、この画面から確認します)

Dam Break はこんなデモです。

メニューを選択


長方形の水塊が現れます


ただちに崩れ・・・


バッシャーンとしぶきが上がります

このWEBページはスタンドアロンで参照するページとなります。

このデモのファイルの在処は以下となります。

lfjsフォルダの中にある testbed フォルダを開きます。

その中にある、tests フォルダを開きます。

ここにプログラム本体である、testDamBreak.js があります。

これをメモ帳などで編集します。

バックアップは取っておきましょう。

修正したプログラム


以下が、修正したプログラムです。コメントアウトした部分が、改変部です。

function TestDamBreak() {
//-----★カメラ★------
  camera.position.x = 4;//def2
  camera.position.y = 2;//def2
  camera.position.z = 4;//def3
  var bodyDef = new b2BodyDef();

//-----★重力★------
  world.SetGravity(new b2Vec2(0, -1.4));//def(0,-10)|地上-10、タイタン-1.4

  var ground = world.CreateBody(bodyDef);

  var chainShape = new b2ChainShape();
//-----★底の形★------

  chainShape.vertices.push(new b2Vec2(0, 0));
  chainShape.vertices.push(new b2Vec2(4, 0));

//傾斜
  chainShape.vertices.push(new b2Vec2(6, 1.3));
  chainShape.vertices.push(new b2Vec2(6.5, 1.3));
  chainShape.vertices.push(new b2Vec2(6.5, 0));

  chainShape.vertices.push(new b2Vec2(8, 0));
  chainShape.vertices.push(new b2Vec2(8, 4));
  chainShape.vertices.push(new b2Vec2(0, 4));

  chainShape.CreateLoop();
  ground.CreateFixtureFromShape(chainShape, 0);

  var psd = new b2ParticleSystemDef();
  psd.radius = 0.022;//半径 def:0.025
  psd.dampingStrength = 0.2;//減衰率 def:0.2


 psd.density = 0.45;//def1か|水1、メタン0.42
 psd.viscousStrength=0.3;//粘性 def:無し


  var particleSystem = world.CreateParticleSystem(psd);

  var shape = new b2PolygonShape;

//-----★粒子団の形★------
  shape.SetAsBoxXYCenterAngle(1, 0.8, new b2Vec2(1.5, 1), 0);


  var pd = new b2ParticleGroupDef();
  pd.shape = shape;

//-----★粒子団の色を追加★------
  pd.color.Set(0, 0, 255, 255);//◆粒子の色:R・G・B・濃さ
 
  var particleSystem = world.CreateParticleSystem(psd);
  var group = particleSystem.CreateParticleGroup(pd);


}

順に解説します。

なお、デモプログラムは、Box2Dという2次元物理エンジン(シミュレートアプリ)を組み合わせた形を取っており、プログラムの大半は、Box2Dに関する内容です。

ご注意

プログラム中の数値が、現実世界での、時間や距離とどう関係するか、一切確認できていません。(プログラムの1が現実世界の1mとか、実行時の経過時間1秒が現実世界の1分とか)

現段階ではすべて、相対的な評価(より高くなるとか、より時間がかかるなど)しか得られない点をご了承ください。

カメラの設定

後述する器の形が入る様、カメラの位置を変えます。

//-----★カメラ★------
  camera.position.x = 4;//def2
  camera.position.y = 2;//def2
  camera.position.z = 4;//def3

重力の設定

重力は、物理系 world の子関数 SetGravity(2次元ベクトル) で設定します。2次元ベクトルは、b2Vec2(右方向、上方向)という関数で指定しますので、コードは、以下の様に記述します。

SetGravity( b2Vec2(右方向、上方向)) 

デフォルトは、おそらくですが(0,-10)のようですので、タイタンでは、この1/7の(0,-10)で設定します。(2つ目がマイナスなので下向きに重力が働いている事を示します)

//-----★重力★------
  world.SetGravity(new b2Vec2(0, -1.4));//def(0,-10)|地上-10、タイタン-1.4

重力の設定は以上です。

器の形

器は、デモでは chainShape という折れ線のオブジェクトで定義されていて、このオブジェクトに頂点を vertices.push(追加するベクトル) という子関数で追加してきます。

具体的には以下コードで記述します。

chainShape.vertices.push(new b2Vec2(x座標, y座標));

この中身を修正します。

浜辺を模した傾斜部のある形にしました。また、横に長くしました。

var chainShape = new b2ChainShape();
//-----★底の形★------

  chainShape.vertices.push(new b2Vec2(0, 0));
  chainShape.vertices.push(new b2Vec2(4, 0));

//傾斜
  chainShape.vertices.push(new b2Vec2(6, 1.3));
  chainShape.vertices.push(new b2Vec2(6.5, 1.3));
  chainShape.vertices.push(new b2Vec2(6.5, 0));

  chainShape.vertices.push(new b2Vec2(8, 0));
  chainShape.vertices.push(new b2Vec2(8, 4));
  chainShape.vertices.push(new b2Vec2(0, 4));

  chainShape.CreateLoop();


粒子の密度など

タイタンの海はメタンで、密度が水の0.45程度でした。

粒子系のオブジェクトは、psd ですが、このアブジェクトの属性で、密度は指定できます。(ただしLiquidFunで指定できるのは1つの値のみです)

密度は、density という属性で指定できます。

デフォルトでは1の様なので、仮にこれを水とみて、0.45を代入しました。

また、他の属性として、粒子半径 radius、減衰率(くずれ易さ?)dampingStrength、粘性 viscousStrength なども指定できます。

これらについての知識を持ち合わせていないのですが、”波っぽく”見える値を試行錯誤で選びました。(この3つは、あまり物理的な妥当性はありません)

psd.radius = 0.022;//半径 def:0.025
  psd.dampingStrength = 0.2;//減衰率 def:0.2


 psd.density = 0.45;//def1か|水1、メタン0.42
 psd.viscousStrength=0.3;//粘性 def:無し


粒子団(水塊)の色と形

デモでは、粒子団(水塊)は、 pd というオブジェクトで与えられています。

粒子団の形を少し変え、大きな塊をやや高い所から落とす様にしました。
粒子団の形は、SetAsBoxXYCenterAngle(幅、高さ、中心ベクトル という子関数で与えます。

また、若干見た目に気を遣って、粒子団の色を設定しています。粒子団の色は、color.Set(赤、緑、青、濃さ) という子関数で与えます。

//-----★粒子団の形★------
  shape.SetAsBoxXYCenterAngle(1, 0.8, new b2Vec2(1.5, 1), 0);
・・・
pd.shape = shape;
・・・
//-----★粒子団の色を追加★------
  pd.color.Set(0, 0, 255, 255);//◆粒子の色:R・G・B・濃さ


以上で、プログラムの改変ができました。

比較となる地上でのシミュレートは、重力の値を(0,-10)に、粒子密度を1にすると確認できます。

プログラムの実行

デモ起動画面 index.html  から実行してみましょう。 



初期状態は、この様な形になります。


地上でのパラメータ

重力と粒子密度を地上での値とした場合は、以下の様になるはずです。




タイタンでのパラメータ

タイタンでは非常にゆっくりと水塊が崩れます。

しぶきも高く舞い・・・

浜辺を波がより遠くまで駆け上がります。

右端の潮だまりは、地上での場合より深くなっています。

すべてがスローモーションの様にすすみました。
現実世界でも、低重力の異星ではこういった波の立ち方をするのでしょうか。



この記事が気に入ったらサポートをしてみませんか?