如何为Guendelman冲击传播对象进行排序?

时间:2012-06-02 00:25:39

标签: sorting 3d distance topology

这是关于在3D中形成地形树的问题。一点背景:我有一个物理引擎,我有身体和碰撞点和一些约束。这不是家庭作业,而是多线程的实验。

我需要以自下而上的方式对身体进行排序,其中包含属于图层的对象组,如本文档所示:参见" shock-propagation" http://www2.imm.dtu.dk/visiondag/VD05/graphical/slides/kenny.pdf

sorting tree

他用来描述如何迭代树的伪代码非常有意义:

shock-propagation(algorithm A)
compute contact graph
for each stack layer in bottom up order
     fixate bottom-most objects of layer
     apply algorithm A to layer
     un-fixate bottom-most objects of layer
next layer

我已经找到算法A(我的冲动代码)。 使用3D点列表进行树/图层排序(拓扑排序?)的伪代码是什么样的?

I.E。,我不知道在哪里停止/开始下一个"梯级"或"分支"。我想我可以通过y位置将其缩小,但这看起来很笨拙且容易出错。我是否会调查topographical sorting?我真的不知道如何在3D中进行此操作。我怎么会得到"边缘"对于拓扑排序,如果这样做的话?

我是否过度思考这个问题而我只是将点连接起来"通过找到点p1然后是最远的下一个点p2,其中p2.y> p1.y?我在这里看到一个问题,即使用纯距离p1与p0的距离可能大于p2,这会导致排序错误。

1 个答案:

答案 0 :(得分:1)

我自己刚刚解决了这个问题。

我在与本文链接的可下载源代码中找到了如何实现此目的的示例:

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);
                    }
                }
            }

}}}