私は自分でこれに取り組みました。
このペーパーにリンクされているダウンロード可能なソース コードで、これを実現する方法の例を見つけました。
http://www-cs-students.stanford.edu/~eparker/files/PhysicsEngine/
具体的には、221 行目から始まる WorldState.cs ファイルです。
しかし、すべての静的オブジェクトに -1 のレベルを割り当て、他の各オブジェクトに異なるデフォルト レベルの -2 を割り当てるという考え方です。次に、レベル -1 のボディとの衝突ごとに、衝突したボディをリストに追加し、そのレベルを 0 に設定します。
その後、while ループ while(list.Count > 0) を使用して、衝突するボディをチェックし、レベルを body.level + 1 に設定します。
その後、まだデフォルト レベル (前に -2 と言いました) を持つシミュレーション内の各ボディに対して、そのレベルを最高レベルに設定します。
さらに細かい点がいくつかありますが、例のコードを見ると、これまで以上にうまく説明できます。
それが役に立てば幸い!
Evan Parker のコードからの関連コード。【スタンフォード】
{{{
// topological sort (bfs)
// TODO check this
int max_level = -1;
while (queue.Count > 0)
{
RigidBody a = queue.Dequeue() as RigidBody;
//Console.Out.WriteLine("considering collisions with '{0}'", a.Name);
if (a.level > max_level) max_level = a.level;
foreach (CollisionPair cp in a.collisions)
{
RigidBody b = (cp.body[0] == a ? cp.body[1] : cp.body[0]);
//Console.Out.WriteLine("considering collision between '{0}' and '{1}'", a.Name, b.Name);
if (!b.levelSet)
{
b.level = a.level + 1;
b.levelSet = true;
queue.Enqueue(b);
//Console.Out.WriteLine("found body '{0}' in level {1}", b.Name, b.level);
}
}
}
int num_levels = max_level + 1;
//Console.WriteLine("num_levels = {0}", num_levels);
ArrayList[] bodiesAtLevel = new ArrayList[num_levels];
ArrayList[] collisionsAtLevel = new ArrayList[num_levels];
for (int i = 0; i < num_levels; i++)
{
bodiesAtLevel[i] = new ArrayList();
collisionsAtLevel[i] = new ArrayList();
}
for (int i = 0; i < bodies.GetNumBodies(); i++)
{
RigidBody a = bodies.GetBody(i);
if (!a.levelSet || a.level < 0) continue; // either a static body or no contacts
// add a to a's level
bodiesAtLevel[a.level].Add(a);
// add collisions involving a to a's level
foreach (CollisionPair cp in a.collisions)
{
RigidBody b = (cp.body[0] == a ? cp.body[1] : cp.body[0]);
if (b.level <= a.level) // contact with object at or below the same level as a
{
// make sure not to add duplicate collisions
bool found = false;
foreach (CollisionPair cp2 in collisionsAtLevel[a.level])
if (cp == cp2) found = true;
if (!found) collisionsAtLevel[a.level].Add(cp);
}
}
}
for (int step = 0; step < num_contact_steps; step++)
{
for (int level = 0; level < num_levels; level++)
{
// process all contacts
foreach (CollisionPair cp in collisionsAtLevel[level])
{
cp.ResolveContact(dt, (num_contact_steps - step - 1) * -1.0f/num_contact_steps);
}
}
}
}}}