1

パーティクル システムの物理更新機能が正しくないようです。すべてのパーティクルがマウスに引き寄せられるようにしています。

パーティクルはマウス ポインタに向かって移動し、非常に近くまで移動します。近くにいるとスピードが速すぎて、ポインタから遠く離れて二度と戻ってこない.

更新機能は次のとおりです。

void updateParticle(particle& p,double time){
    const double G=0.000000000066726;
    const double POINTERMASS=1000000000000;

    double squareDistance=pow(p.coords.x-pointerDevice.x,2)+pow(p.coords.y-pointerDevice.y,2)+pow(p.coords.z-pointerDevice.z,2);
    if(squareDistance<0.001)
        squareDistance=0.001;//to fix the possible division by zero

    coords_3d_f accelerationVector={p.coords.x-pointerDevice.x,p.coords.y-pointerDevice.y,p.coords.z-pointerDevice.z};

    accelerationVector=vector_scalar_multiplication(vector_unit(accelerationVector),((G*POINTERMASS)/squareDistance));
    accelerationVector=vector_scalar_multiplication(accelerationVector,time);

    p.velocity=vector_addition(p.velocity,accelerationVector);

    p.coords.x-=p.velocity.x*time;
    p.coords.y-=p.velocity.y*time;
    p.coords.z-=p.velocity.z*time;
}

squareDistance が一定の場合、プログラムは問題ないように見えますが、間違っていることはわかっています。

それで、私は何を間違っていますか?

4

4 に答える 4

4

力は距離の 2 乗に反比例するため、距離が 0 に近づくと、力 (および加速度) は無限大に近づきます。つまり、粒子が非常に近づくと、粒子も非常に速くなります。

物理的に正確にしたい場合は、ポインター オブジェクトのサイズを有限にして、粒子が跳ね返るようにします。

正確である必要がない場合は、パーティクルが非常に接近しているときに力を減少させることができます。

于 2012-07-18T14:04:00.860 に答える
1

それは非常に簡単です: 粒子がマウス ポインターと接触すると、 ゼロで除算することは違法であるため、粒子に対して未定義の動作が発生しますsquareDistance0((G*POINTERMASS)/squareDistance)

これはあなたにとってよりうまくいくかもしれません:

if (squareDistance >= 1.0) // 1.0 is the zero tolerance for your context of pixel distances
{
    // proceed normally
    accelerationVector=vector_scalar_multiplication(vector_unit(accelerationVector),((G*POINTERMASS)/squareDistance));
    accelerationVector=vector_scalar_multiplication(accelerationVector,time);
}
else
{
    // no acceleration
    accelerationVector=/*{0, 0}*/;
}
于 2012-07-18T14:03:09.540 に答える
0

運動方程式のシミュレーションには、有限間隔での関数の積分が含まれるため、関数を近似することしかできません。これにより、システムが不安定になります。簡単で迅速な解決策は、固定ステップのverlet 統合を使用することです。

void integrate(particle& p, double t2, const particle& mouse)
{
  // universal gravitational constant
  const double G = 0.000000000066726;

  // artificial drag
  // set it to 1.0 to not have any drag
  // set it to 0.0 to not have any momentum
  const double drag = 0.99;

  // get direction and distance between the particle and the mouse
  dvec3 dir = p.pos - mouse.pos;
  double dist2 = dot(dir, dir);
  double dist = sqrt(dist2);
  dir /= dist;

  // calculate relative acceleration vector
  dvec3 a = -dir * G * (p.mass + mouse.mass) / dist2;

  // verlet integration
  dvec3 tmp = p.pos;
  p.pos += (p.pos - p.prev_pos) * drag + a * t2;
  p.prev_pos = tmp;
}

void update(particle& p, double elapsed, const particle& mouse, double& accumulator)
{
  // fixed timestep (arbitrary)
  const double timestep = 1.0 / 120.0;
  const double timestep2 = timestep * timestep;

  // "accumulate" time
  accumulator += elapsed;

  // "consume" time
  while(accumulator > timestep)
  {
    // perform integration
    integrate(p, timestep2, mouse);
    accumulator -= timestep;
  }
}

注:わかりやすくするために、 GLM 数学ライブラリを使用します。

于 2012-07-18T15:15:16.480 に答える
0

パーティクルがマウス ポインタに非常に近づくと、パーティクルは非常に高速になります。この速度に を掛けるとtime、パーティクルは非常に遠くにジャンプします。

最大速度を設定することで、これを修正することができます。

于 2012-07-18T14:14:47.993 に答える