找到一种在边缘碰撞中修复错误碰撞法线的方法

时间:2014-11-07 16:25:18

标签: 3d geometry physics collision bullet

主要的问题是子弹2(2.82,具体 - 也许是子弹3,还没有检查过)处理边缘碰撞,产生偏差的反应法线。

测试案例1:一个小的btBoxShape,位于(0,9,0),垂直对齐,落在另一个盒子(由btBoxShape制成)脸上,是煤制的。正常计算正常,碰撞仅发生在Y(垂直)轴上。盒子在OY轴上稍微反弹并保持在它周围的中心位置。

case1

测试案例2:一个小盒子,位于(0,9,0)垂直对齐,(同上)落在另一个盒子的脸上,(这次是由btBvhTriangleMeshShape由2个共面三角形组成),也是煤炭签名。法线计算不正确,碰撞发生在所有轴上。盒子弹跳到侧面,有时(取决于具体的碰撞坐标)非常明显。

case2

即使对正常进行硬编码并根据它重新计算碰撞点(见下文)也无济于事。

//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 
尽管正确设置了三个信息并且验证代码 正在执行,但使用btAdjustInternalEdgeContacts的NB无论以任何可见方式都没有帮助。虽然 工作并且对模拟的可靠性进行了一些小的改进(虽然CPU成本相当高),但它仍然无法解决这一特定问题。

问题是:如何修复案例2的行为以匹配案例1。任何建议如何避免这种情况(代码kludges欢迎),或为什么这不起作用的方式是受欢迎的。

进一步参考:

https://github.com/bulletphysics/bullet3/issues/92

http://www.bulletphysics.org/Bullet/phpBB3/viewtopic.php?f=9&t=8113

https://bullet.googlecode.com/files/GDC10_Coumans_Erwin_Contact.pdf

https://code.google.com/p/bullet/issues/detail?id=27

http://www.bulletphysics.org/Bullet/phpBB3/viewtopic.php?f=9&t=4603

1 个答案:

答案 0 :(得分:1)

问题发生的原因是两个对象之间发生了多个碰撞 - 球体< - >三次碰撞也是如此。碰撞检测器不仅检测到三面碰撞,结束表面三角形的迭代(如预期的那样),而且还保持遍历BVH(也是预期的那种),导致与相邻三角形的另一次碰撞&# 39;边缘。这可以以许多方式再现,例如,通过将一个物体扔到三角形边缘附近(但仍然在网格的内侧部分!),通过在内部三边形(边缘)附近投掷一个物体但不对称(对称下降将导致边缘)部队取消)。即使表面在那一点上完全平坦,物体也会飞到一边(有时是狂野的)。

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

根据距离移除联系人也可以在这里创造奇迹,尽管在生产代码IMO中使用的修复程序太粗糙/特定于上下文。我仍然在寻找一种更简单,更有效的解决方案。

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

相关问题已发布在子弹问题跟踪器here上。