three.js練習 boids

three.jsでboidsを試す

サンプル

gifアニメ

URL: https://hittaito.github.io/three-practice/day11/index.html
ソースコードこちら

注意

メモ書き&簡易実装なのできちんと知りたい方は参考の方を見てください。参考のp5.jsの劣化版移植みたいなもんなので

実装

参考1によるとboidsは結合、分離、整列の3つのルールを基に自身の移動先を決めている。 自身以外のposition, velocity情報が必要なため、テクスチャにposition, velocity情報を書き込みフラグメントシェーダで計算することにする。

基本的な処理

テクスチャのサイズに合わせてループを回す。最初に一定範囲内の判定を行い一定範囲内の時は結合、分離、整列の処理を行う。
今回は履歴を持たせるためy = 0の場合のみ。

 for (int x = 0; x < size.x; x++) {
      int y = 0;
      vec3 otherPos = texelFetch(uPosition, ivec2(x,y), 0).xyz;

      vec3 dir = otherPos - pos;
      float dist = length(dir);
      if (dist < 0.0001 || dist > radius) continue;

      /** 結合 */
      /** 分離 */
      /** 整列 */
    }
    /** 結合 後処理 */
    /** 整列 後処理 */
    vel += cohesDir + separation + align;
    pos += vel;

結合

自身から一定範囲内に存在する要素の中心に移動させる。単純に要素の中心を求め方向を求める。

      vec3 cohesion; // 要素のpositionを合計
      float nCohesion; // 一定範囲の要素数
      /** ループ処理内 */
      cohesion += otherPos;
      nCohesion++;

      /** ループ後処理*/
      vec3 cohesDir = vec3(0);
      if (nCohesion > 0.) {
          cohesion/= nCohesion;
          cohesDir = cohesion - pos;
      }

分離

近接した場合反対方向に移動させる。近接距離によって変化を入れてもいいかも

    vec3 separation

    / ** ループ処理内 */
    if (dist < uSeparate) {
        separation -= dir;
    }

整列

速度を周囲と合わせる動き。

      vec3 align;
      float nAlign;
      
      /** ループ処理内 */
      vec3 otherVel = texelFetch(uVelocity, ivec2(x,y), 0).xyz; // velocityテクスチャ
      align += otherVel;
      nAlign++;

     /** ループ処理後 */
    if (nAlign > 0.) {
      align /= nAlign;
    }

後はこれらを速度として合計し、positionを更新する。

参考

Boids|クリエイティブコーディングの教科書
three.js examples

感想等

簡易的な実装だが一応boidsとして動いているので動いたときは感動する(´;ω;`)
移動履歴をとっているのでこの作品( POOL)みたいにいい感じの作品を目指したい