魚の群れ(3D)

Tinkercadを使って魚のモデルを作成し、それを群れにして泳がせるコンテンツをつくってみました。
fishschool
マウスをドラッグすることで視点をかえることもできます。
体を動かしながら魚群が動く様子は見ているだけでも面白いと思います。
プログラムも短く記述できたと思いますが、それよりも自分で描いた魚のモデルがお気に入りです。

PShape[] fishShape;
PShape riverBottom;
float thetaV, thetaH;

class Fish {
  PVector pos;
  PVector move;
  int index = (int)random(8);
  int tick = (int)random(10);
  
  Fish(float x, float y, float z, float dx, float dz){
    pos = new PVector(x, y, z);
    move = new PVector(dx, 0, dz);
  }
  
  void paint(){
    pushMatrix();
    scale(3);
    translate(pos.x, pos.y, pos.z);
    rotateY(atan2(move.x, move.z));
    shape(fishShape[index]);
    popMatrix();    
  }

  void move(){
    if (++tick % 5 == 0) {
      index = (index + 1) % 8;
    }
    pos.add(move);
    if(pos.x < -500 || pos.x > 500){
      move.x *= -1;
    }
    if(pos.z < -500 || pos.z > 500){
      move.z *= -1;
    }
  }
}

ArrayList<Fish> fish = new ArrayList<Fish>();

void setup(){
  size(600, 600, P3D);
  riverBottom = loadShape("riverbottom.obj");
  PShape N = loadShape("fish-N.obj");
  PShape L1 = loadShape("fish-L1.obj");
  PShape L2 = loadShape("fish-L2.obj");
  PShape R1 = loadShape("fish-R1.obj");
  PShape R2 = loadShape("fish-R2.obj");
  fishShape = new PShape[]{N, L1, L2, L1, N, R1, R2, R1};

  for(int j = 0 ; j < 5 ; j++){
    float x = random(-200, 200);
    float y = random(-200, -40);
    float z = random(-200, 200);
    float mx = random(-2, 2), mz = random(-2, 2);
    int num = (int)random(5, 10);
    for(int i = 0 ; i < num ; i++){
      float dx = random(-80, 80);
      float dy = random(-30, 30);
      float dz = random(-80, 80);
      fish.add(new Fish(x+dx, y+dy, z+dz, mx, mz));
    }  
  }
}

void draw(){
  background(100, 100, 255);
  translate(width/2, height/2);
  float tx = cos(radians(thetaH))*1000;
  float tz = sin(radians(thetaH))*1000;
  float ty = atan(radians(thetaV))*1000;
  camera(0, -400, 0, tx, ty, tz, 0, 1, 0);
  lights();
  pushMatrix();
  scale(10);
  shape(riverBottom);
  popMatrix();
  for (Fish f : fish) {
    f.move();
    f.paint();
  }    
}

void mouseDragged(){
  thetaH -= (pmouseX - mouseX);
  thetaV -= (pmouseY - mouseY);
}

p5jsに変換してホームページに張り付けようとしたのですが、3Dモデルの色の指定がProcessingとp5jsでは異なるため、思いのほか苦労しています。以下にZIPファイルを置きました。是非ダウンロードして試してみてください。

魚の群れ ダウンロード