LoginSignup
0

More than 1 year has passed since last update.

ProcessingでSnowParticleの作成

Posted at

この記事はProcessing Advent Calendar 2021の24日目の記事です。

はじめに

blenderで作成している雪だるまくんに最適な雪を見つけたくて作成しました。

実装したソースコードはいかにあります。
GitHub

データの管理

データはJavaのCollectionであるArrayListを使い管理しています。
ArrayListは可変長配列を扱うことが可能なデータ構造で動的に値を追加したり削除が可能なため使おうと思いました。

SnowParticle

早速SnowParticleを制作します。

SnowParticleは大きく分けて2つのクラスによって実装されています。

SnowParticle

SnowParticle自体に関わるクラスでParticleの位置や速度、加わっている力、質量、マテリアルなどの要素を定義しています。そのため1つ1つのParticleに速度や大きさなどに異なるパラメーターを割り当てが行えます。

コンストラクター

SnowParticleのコンストラクターを見ていきます。

SnowParticle(PVector initPosition, float initMass, float particleMax){
    position = initPosition.copy();
    velocity = new PVector(0.0, 0.0, 0.0);
    acceleration = new PVector(0.0, 0.0, 0.0);
    mass = initMass;
    particleCounter = particleMax;
  }

particleCounter変数は生成Particleの最大個数を動的に変化させることができます。大きければ大きいほどParticleの生成個数は増えます(その分重くなります)。
位置ベクトルがcopyで呼び出されているのは名前空間汚染を避けるためです。

addForce

力を加えるメソッドで加速度ベクトルを求めます。
力は重力や風力などで加え方によってParticleの動きを大きく変化させます。

void addForce(PVector force){
  PVector calcForce = PVector.div(force, mass);
  acceleration.add(calcForce);
}

update

値の更新を行います。
particleCounterは1ずつ減らしていきParticleの削除を行うかどうかの判定を行うための準備しています。

void update(){
  // 速度ベクトルに加速度ベクトルを加算
  velocity.add(acceleration);
  // 位置ベクトルに速度ベクトルを加算
  position.add(velocity);
  // 加速度ベクトルを0にリセットする。
  acceleration.mult(0.0);
  // Particleの個数をカウントする。
  particleCounter -= 1.0;
}

render

Particle自体の描画を行うためのメソッドです。
ここでParticleの大きさや色を決定します。

void render(){
  float size = mass;
  // stroke(200, 200, 200);
  fill(240, 240, 250);
  pushMatrix();
  translate(position.x, position.y, position.z);
  ellipse(0, 0, size, size);
  popMatrix();
}

isCheckEdge

このメソッドはできる限りParticleが画面外に出ないようするためです。
x軸のみ定義されています。できる限り画面表示したいので特定の領域に達すると跳ね返り反対方向に飛んでいきます。

void isCheckEdge(){
  float positionMaxX = 100;
  if(position.x < 0.0){
    position.x = 0.0;
    velocity.x *= -1.0;
  } else if(position.x > width) {
    position.x = width + positionMaxX;
    velocity.x *= -1.0;
  }
}

isRemove

Particleの削除を行うかどうかの結果のみ返します。
削除自体はもう1つのクラスであるSnowParticleSystemで制御します。

boolean isRemove(){
  if(particleCounter < 0.0){
    return true;
  } else {
    return false;
  }
}

SnowParticleSystem

SnowParticleクラス自体を追加や配列からの削除、メソッドの呼び出しなど重要な制御をします。

コンストラクター

SnowParticleクラスをArrayListで定義しています。
windは風力の定義で今後外部からコントロールできるようコンストラクターで初期化をしています。

ArrayList<SnowParticle> particles;
PVector wind;
boolean flag;
SnowParticleSystem(){
  particles = new ArrayList<SnowParticle>();
  wind = new PVector(0.01, 0.0);
  // 今は気にしなくて良いです。
  flag = false;
}

addParticleSystem

ArrayListSnowParticleクラスを追加します。この際Particleの位置ベクトルや質量などの値も生成しています。

void addParticleSystem(){
  // particleMaxは適切でないので移動する予定です
  float particleMax = 500;
  PVector position = new PVector(random(-width * 0.5, width), -height * 0.1);
  float mass = random(1.0, 5.0);
  particles.add(new SnowParticle(position, mass, particleMax));
  }

updateParticleSystem

ArrayListにあるSnowParticleクラス自体と定義メソッドの制御をしています。

void updateParticleSystem(){
  for(int count = particles.size() - 1; count >= 0; count--){
    SnowParticle particle = particles.get(count);
    float mass = particle.mass;
    // 重力の定義 Particleの質量をかける。
    PVector gravity = new PVector(0.0, 0.01 * mass);
    // 風力を追加
    particle.addForce(wind);
    // 重力を追加
    particle.addForce(gravity);
    // 値の更新
    particle.update();
    // Particleの描画
    particle.render();
    // Particleが画面外かどうかの判定
    particle.isCheckEdge();

    // 削除するかどうかの判定
    // trueならば削除
    if(particle.isRemove()){
      // ArrayListのremoveメソッド
      particles.remove(count);
    }
  }
}

つまずいたところ

2Dで実装したあと3D実装する予定でしたがカクカクしてしまい、問題を解消中です。

今後の予定

  • コンストラクターで制御できるパラメーターを増やす。
  • blenderやGLSLと組み合わせる。
  • 吹雪感を出す。
  • データ構造やアルゴリズムの深い知識
  • 3Dで実装すると同時にフレームレートが落ちてしまう問題を解消する。

参考文献

  • The Nature of Code: Simulating Natural Systems with Processing
  • プログラミングコンテスト攻略のためのアルゴリズムとデータ構造
  • 世界で闘うプログラミング力を鍛える本~コーディング面接189問とその解法~

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0