3d 找到修复边碰撞中错误碰撞法线的方法

3d 找到修复边碰撞中错误碰撞法线的方法,3d,geometry,physics,collision,bullet,3d,Geometry,Physics,Collision,Bullet,主要问题是,Bullet 2(具体来说是2.82,也许Bullet 3也没有检查)处理边缘碰撞的过程非常糟糕,生成了扭曲的反应法线 测试用例1:一个小的btBoxShape,定位(0,9,0),垂直对齐,落在另一个盒子(同样由btBoxShape制成)的表面上,并对齐。法线计算正确,碰撞仅发生在Y(垂直)轴上。长方体在OY轴上轻微反弹,并保持围绕其居中 测试用例2:一个小盒子(0,9,0)垂直对齐,(同上)落在另一个盒子的表面上(这次由btbvhttrianglemeshshape制成,由两个

主要问题是,Bullet 2(具体来说是2.82,也许Bullet 3也没有检查)处理边缘碰撞的过程非常糟糕,生成了扭曲的反应法线

测试用例1:一个小的
btBoxShape
,定位(0,9,0),垂直对齐,落在另一个盒子(同样由
btBoxShape
制成)的表面上,并对齐。法线计算正确,碰撞仅发生在Y(垂直)轴上。长方体在OY轴上轻微反弹,并保持围绕其居中

测试用例2:一个小盒子(0,9,0)垂直对齐,(同上)落在另一个盒子的表面上(这次由
btbvhttrianglemeshshape
制成,由两个共面三角形制成),也合并在一起。法线计算不正确,碰撞发生在所有轴上。长方体反弹到一侧,有时(取决于特定的碰撞坐标)非常明显

即使对法线进行硬编码并在此基础上重新计算碰撞点(请参见下文),也无济于事

//newNormal was set to hard-coded value of (0,-1,0) before
cp.m_normalWorldOnB = colObj0Wrap -> getWorldTransform().getBasis() * newNormal;
cp.m_positionWorldOnB = cp.m_positionWorldOnA - cp.m_normalWorldOnB * cp.m_distance1;
cp.m_localPointB = colObj0Wrap -> getWorldTransform().invXform( cp.m_positionWorldOnB 
注意:尽管正确设置了tri信息并验证代码是否正常执行,但使用btAdjustInternalEdgeContacts在任何可见方式下都没有帮助。虽然它确实可以工作,并对模拟的可靠性进行了一些小的改进(尽管CPU成本相当高),但它仍然不能解决这个特定的问题

问题是:如何修正案例2的行为以匹配案例1。任何关于如何避免这种情况的建议(欢迎使用代码乱码),或者为什么它不能按应有的方式工作的建议都是受欢迎的

进一步参考:


发生问题的原因是两个对象之间发生了多次碰撞-spheretri碰撞也是如此。碰撞检测器不仅检测到三面碰撞,从而结束曲面三角形的迭代(如预期),而且它还继续遍历BVH(如预期),导致与相邻三角形的边发生另一次碰撞。这可以通过多种方式进行复制,例如,将对象抛向trimesh边附近(但仍在网格的内部!),将对象抛向内部三边(边)附近,但不对称地(对称下落将导致边力抵消)。即使曲面在该点非常平坦,对象也会飞到一边(有时会飞得很厉害)

我想到的唯一通用解决方案,不需要彻底重写Bullet 2代码,就是过滤碰撞对象的流形,例如在
gContactStartedCallback
中,查找所有曲面碰撞,并删除与该曲面相邻的所有边的所有边碰撞。观察给定trimesh流形上的
numContacts>=2
,通常是一种方法;这种情况不应该经常发生,检查流形上的几个点并不是CPU密集型的

根据联系人的距离删除联系人在这里也很有用,尽管这对于生产代码IMO来说太粗糙/特定于上下文的修复方法。不过,我仍在寻找一种更简单、更高效的解决方案

另外,一个部分解决方法(如论坛讨论中所述)是更改timestep值;对于三角形网格和以合理速度移动的任何对象,默认设置失败。对于“常规速度”,需要最大1/300的固定时间步长,对于“高速”1/600或更低,YMMV。请注意,它大大增加了CPU负载,只会减少问题,在许多情况下根本无法解决问题


相关问题已发布在Bullet的问题跟踪器上。

谢谢+1如果除了bug跟踪器之外,还附加一些(官方?)教程的链接,那就更好了。具体来说,我想解决的是:一个B刚体在非常接近B刚体的2上滑动。不幸的是,目前最好的答案(使用ray)是黑客。对于随机碎片来说,这太昂贵和乏味了。我想修复的方法应该包括或
ContactAddedCallback
。但是,它可能只适用于解决单个
btBvhTriangleMeshShape
@cppneunizer中的正常冲突。在这种情况下,我能给您的唯一建议是手动过滤冲突,实际上是使用回调(正如我提到的,
btinternaledgeutability
在我的情况下效果不太好)。在我的应用程序中,在
ContactAddedCallback
中,我添加了(除其他外)对过滤方法的调用,-如果无法使用自定义过滤代码重新编译Bullet,则使用类似的方法是IMVHO的最佳解决方案。只需检查两个联系人是否都是您想要检测的联系人,如果是,请删除它们(或其中一个)。嗯,听起来不错。如果你决定把这个片段作为胶囊问题的解决方案,我也会在那里投票。感谢