時間tで、各粒子について、次のようになります。
P position
V speed
粒子A(i)とA(j)の間の情報のN *(N-1)/2配列(i <j)。完全なN*(N-1)グリッドの代わりに、対称性を使用して上三角行列を評価します。
MAT[i][j] = { dx, dy, dz, sx, sy, sz }.
これは、粒子jに関して、粒子jの距離がdx、dy、dzの3つの成分で構成されていることを意味します。デルタビーはdtで乗算され、sx、sy、szです。
インスタントt+dtに移動するには、速度に基づいてすべてのパーティクルの位置を暫定的に更新します
px[i] += dx[i] // px,py,pz make up vector P; dx,dy,dz is vector V premultiplied by dt
py[i] += dy[i] // Which means that we could use "particle 0" as a fixed origin
pz[i] += dz[i] // except you can't collide with the origin, since it's virtual
次に、N *(N-1)/ 2配列全体をチェックし、粒子のカップルごとの新しい相対距離を暫定的に計算します。
dx1 = dx + sx
dy1 = dy + sy
dz1 = dz + sz
DN = dx1*dx1+dy1*dy1+dz1*dz1 # This is the new distance
DN <D ^ 2で、粒子の直径がDの場合、ちょうど過去のdtで衝突が発生しています。
次に、これが発生した場所を正確に計算します。つまり、衝突の正確なd'tを計算します。これは、古い距離の2乗D2(dx * dx + dy * dy + dz * dz)と新しいDNから実行できます。
d't = [(SQRT(D2)-D)/(SQRT(D2)-SQRT(DN))]*dt
(時間dtで距離SQRT(D2)-SQRT(DN)をカバーする速度で、SQRT(D2)からDまでの距離を短縮するために必要な時間)。これにより、パーティクルiの参照フレームから見たパーティクルjが「オーバーシュート」していないという仮説が立てられます。
これはより多額の計算ですが、衝突が発生した場合にのみ必要になります。
d'tとd"t= dt-d'tがわかれば、dx * d't / dtなどを使用してPiとPjの位置計算を繰り返し、粒子iとjの正確な位置Pを瞬時に取得できます。衝突の;あなたは速度を更新し、それから残りのd "tのためにそれを統合し、時間dtの終わりに位置を取得します。
ここで停止した場合、このメソッドは3粒子の衝突が発生した場合に機能しなくなり、2粒子の衝突のみを処理することに注意してください。
したがって、計算を実行する代わりに、パーティクル(i、j)のd'tで衝突が発生したことをマークし、実行の最後に、衝突が発生した最小のd'tとその間のd'tを保存します。
つまり、粒子25と110をチェックし、0.7dtで衝突を見つけたとします。次に、0.3dtで110と139の間に衝突が見つかります。0.3dtより前の衝突はありません。
衝突更新フェーズに入り、110と139を「衝突」させ、それらの位置と速度を更新します。次に、(i、110)と(i、139)ごとに2 *(N-2)の計算を繰り返します。
おそらくまだ粒子25との衝突がありますが、現在は0.5 dtであり、おそらく、0.9dtで139から80の間の衝突があることがわかります。0.5 dtが新しい最小値であるため、25から110の間で衝突計算を繰り返し、衝突ごとにアルゴリズムでわずかな「速度低下」が発生することを繰り返します。
このように実装された場合、現在の唯一のリスクは「ゴースト衝突」のリスクです。つまり、粒子は時間t-dtでターゲットからD>直径にあり、時間tで反対側のD>直径にあります。
これを回避するには、dtを選択する必要があります。これにより、特定のdtで粒子が自身の直径の半分を超えて移動することはありません。実際には、最速のパーティクルの速度に基づいて適応型dtを使用する場合があります。ゴースト視線衝突はまだ可能です。さらなる改良は、任意の2つの粒子間の最も近い距離に基づいてdtを減らすことです。
このように、衝突の近くでアルゴリズムがかなり遅くなるのは事実ですが、衝突が起こりそうにないときは非常に速くなります。2つの粒子間の最小距離(ループ中にほとんどコストをかけずに計算)が、最速の粒子(これもほとんどコストをかけずに見つける)が50 dts未満でカバーできない場合、それは4900です。すぐそこに%速度が上がります。
とにかく、衝突のない一般的なケースでは、5つの合計(実際には配列のインデックス付けのために34のようになります)、3つの積、およびすべてのパーティクルカップルに対していくつかの割り当てを行いました。粒子の更新自体を考慮に入れるために(k、k)のカップルを含めると、これまでのところコストの適切な概算が得られます。
この方法には、O(M ^ 3)ではなく、粒子の数に応じてスケーリングされるO(N ^ 2)であるという利点があります。
最新のプロセッサ上のCプログラムは、数万のオーダーの多数の粒子をリアルタイムで管理できると期待しています。
PS:これは実際にはNicolas Repiquetのアプローチと非常によく似ており、複数の衝突の4D付近で速度を落とす必要があります。