見出し画像

【LiquidFunでサイエンス】固液混相を簡単にシミュレートしてみよう

液体が、波打ったり、しぶきを上げる様子をシミュレートできるフリーのJSライブラリ、「LiquiFun(リキッドファン)」についての記事です。
 「LiquiFun」は本来はゲーム用途であり、2次元、基本粒子の性質(密度や半径)は1種類だけ、という制約はあり、また、現時点ではCDNという形態で配信されていないために、GAS(google Apps Script)に組み込んで使う事も困難です。
それでも「LiquiFun」は粒子法というシミュレート手法を使っている、数少ないフリーウェアであり、かつ、JavaScriptというアマチュアでも比較的平易に扱えるプログラムで操作できる利点もあり、これを日常の用途に役立てられないか?という事を探っていく記事です。
「LiquiFun」の導入については、こちらをご覧下さい。スタンドアロンでの作動方法のご紹介ですが、いつかGASに組み込めればいいなと思っています。


Box2Dで扱う固体要素を登場させる事で、固液混相は簡単に実現できる

LiquidFunは、Box2Dという、2次元物理シミュレーションライブラリをベースにしています。

ここで扱える固体の物体をLiquidFunの中に登場させられれば、ぐっと実用性が高まりそうです。
 
これを試したのが、以下の記事です。

シミュレートの様子を示したものを1つ再掲しましょう。



今回は、このシミュレートをするためのコードについてご説明します。


Box2Dのコードを一から書き下すのは難しい・・・サンプルから、Box2Dで扱う物体を引用する

固体要素を組み込むには、本家Box2Dのコードをそのまま記述します。

とはいえ、このBox2Dは、物体の記述の仕方にひとクセあり、全く初学のアマチュアが一からコードを書くのは容易ではありません。

そこで、LiquidFunを導入した時に一緒に保存される、サンプルコードから、使えそうなものを引用します。

サンプルコードは、「testbed」フォルダ下の「tests」という子フォルダに数多く入っています。



ファイル名から、何を行っているのか何となく分かりますが、実際に作動させるには、トップページから選べるファイル(たとえば、testDamBreak.js など)の中身を、そっくり書き換えてしまうのが簡単です。

実際には、元のファイルの控え(testDamBreakのコピー.jsなど)を取ったあと、試したいファイルの方を、testDamBreak.js に改名してやります。

すると、トップページで、DamBreak を選べばこれを試す事ができます。

確認後は元の状態にもどしておきましょう。

さて、使えそうなサンプルを見つけたら、その中身を引用します。今回は、
小さなボックスを山に積む「testPyramid.js」から引用し、「testDamBreak.js」に埋め込むする事にしました。


「testDamBreak.js」に、「testPyramid.js」の中身を埋め込んだコード(多少修正)


以下が、そのコードです。

function TestDamBreak() {
  camera.position.y = 2;
  camera.position.z = 3;
  var bodyDef = new b2BodyDef();
  var ground = world.CreateBody(bodyDef);

  var chainShape = new b2ChainShape();
  chainShape.vertices.push(new b2Vec2(-2, 0));
  chainShape.vertices.push(new b2Vec2(2, 0));
  chainShape.vertices.push(new b2Vec2(2, 4));
  chainShape.vertices.push(new b2Vec2(-2, 4));

//------★★箱の山 testPyramid.js を引用★★------

  var x = new b2Vec2(0, 0.2);
  var y = new b2Vec2();
  var dx = new b2Vec2(0.025, 0.125);
  var dy = new b2Vec2(0.0125, 0);


  for (var i = 0; i < 4; i++) {
    y = new b2Vec2(x.x, x.y);
    for (var j = i; j < 4; j++) {
      var bodyDef = new b2BodyDef();
      bodyDef.type = b2_dynamicBody;
      bodyDef.position = y;
      bodyDef.friction=0.1;//◆箱の摩擦

      var box = new b2PolygonShape();
      box.SetAsBoxXY(0.05, 0.05);
      bodyDef.shape = box;
      var body = world.CreateBody(bodyDef);

      body.CreateFixtureFromShape(box, 0.5);//◆箱の密度

      b2Vec2.Add(y, y, dy);
    }
    b2Vec2.Add(x, x, dx);

  }

//-----↑↑★★箱の山 testPyramid.js を引用★★↑↑------


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

  var shape = new b2PolygonShape;
  shape.SetAsBoxXYCenterAngle(0.8, 1, new b2Vec2(-1.2, 1.01), 0);

  var psd = new b2ParticleSystemDef();
  psd.radius = 0.017;//◆粒子系の半径
  psd.dampingStrength = 0.2;

//-----★粒子系の密度を追加★------
  psd.density = 1;//◆粒子の密度

  var particleSystem = world.CreateParticleSystem(psd);

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

//-----★粒子団の色を追加★------
  pd.color.Set(0, 0, 255, 255);//◆粒子の色:R・G・B・濃さ

 
  var group = particleSystem.CreateParticleGroup(pd);
}


//------★★箱の山 testPyramid.js を引用★★-----
・・・ここが引用部・・・
//-----↑↑★★箱の山 testPyramid.js を引用★★↑↑-----

中段で、上記の部分が、引用した部分です。

なお、固体要素は、液体要素より先に書いておく必要があります。

Box2Dは、コードに表した順に逐次動き出す仕様なので、液体を先に記載すると、固体を描画している途中でもう、液体が崩れ始めてしまいます。


次の記事から、その内容を簡単にご説明していきます。


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