【问题标题】:Contact graph接触图
【发布时间】:2009-06-13 22:21:15
【问题描述】:

对于我正在构建的物理引擎,我需要在前一帧快速确定两个刚体是否接触。我希望它尽可能快,所以也许你们可以提供一些想法?

这是我到目前为止所得到的。 (而且效果还不错,但整件事让我想知道如何改进它。)

    // I thought using a struct would be a good idea with only two values?
    struct Contact 
    {
        public readonly PhyRigidBody Body1;
        public readonly PhyRigidBody Body2;

        public Contact(PhyRigidBody body1, PhyRigidBody body2)
        {
            Body1 = body1;
            Body2 = body2;
        }
    }

    class ContactComparer : IEqualityComparer<Contact>
    {
        public bool Equals(Contact x, Contact y)
        {
            // It just have to be the two same bodies, nevermind the order.
            return (x.Body1 == y.Body1 && x.Body2 == y.Body2) || (x.Body1 == y.Body2 && x.Body2 == y.Body1);
        }

        public int GetHashCode(Contact obj)
        {
            // There has got to be a better way than this?
            return RuntimeHelpers.GetHashCode(obj.Body1) + RuntimeHelpers.GetHashCode(obj.Body2);
        }
    }

    // Hold all contacts in one big HashSet.
    private HashSet<Contact> _contactGraph = new HashSet<Contact>(new ContactComparer());



    // To query for contacts I do this
    Contact contactKey = new Contact(body1, body2);
    bool prevFrameContact = _contactGraph.Remove(contactKey);
    // ... and then I re-insert it later, if there is still contact.

【问题讨论】:

    标签: c# optimization


    【解决方案1】:

    您可以改为使用 Dictionary&lt;PhyRigidBody, HashSet&lt;PhyRigidBody&gt;&gt; 将给定的身体映射到与之接触的一组其他身体(这意味着您将每个“联系人”保持两次,因为每个身体都包含在其他)。这将完全避免 Contact 结构,以及有点可疑的 Equals 方法。我不确定这是否是一种改进,但值得考虑。

    【讨论】:

    • 如何提取扩展或类级方法,PhyRigidBody 的“联系人” - 即 bool contacted = somePhyRigidBody.Contact(anotherObject)。更好的是,如果您以后想要实现非刚性物理,您应该考虑将 Contact() 方法作为接口的一部分,以便您轻松扩展您的库。
    • 我认为您在这里混合了两个不同的问题:如何确定联系人确实应该放在可以被覆盖的地方(如接口等)。但是这家伙问的是如何存储前一帧的联系人数据,据说是计算之后。
    • 感谢您的想法。想我会为每个 PhyRigidBody 添加一个“HashSet 联系人”。仍然需要保留两次联系人,除非我在查询联系人时简单地检查两个机构。
    【解决方案2】:

    我对此感到困惑:

    // It just have to be the two same bodies, nevermind the order.
    return (x.Body1 == y.Body1 && x.Body2 == y.Body2) || (x.Body1 == y.Body2 && x.Body2 == y.Body1);
    

    但总的来说,我不明白这一点。有多少具尸体?身体是否移动,所以它们的接触经常改变?你能把它们放到空间网格中吗?您需要多久知道一次接触是什么?

    如果不知道更多关于这个问题的信息,很难说太多,尽管我的直觉是,把所有东西都包裹在哈希码和数据结构中会花费你大量的时间。

    【讨论】:

    • 在每一帧,我必须能够确定两个物体是否在前一帧接触。在每一帧,我都需要多对身体的信息。场景中可能有很多尸体(数千),但其中很大一部分可能是静止的或睡觉的。我需要能够查询任意两个身体上的前帧联系人。
    • 基本上它是一个稀疏的布尔矩阵。您可以有一个由 body1 索引的一维数组,每个项目都包含一个 body2 数字列表。这基本上是一个哈希设置。另一方面,如果您的查询序列是高度可预测或连续的,您可以利用这一点。
    猜你喜欢
    • 1970-01-01
    • 2012-06-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-26
    • 2018-06-12
    相关资源
    最近更新 更多