Box2d将地面摩擦力设置为最大值-无滑动。

4

我有一个在边缘形状上的方盒子。现在我对方盒子施加冲量,让它跳起来。但是当它落在地面上时,就不应该再动了。所以我将方盒子的恢复系数设置为0,并将边缘形状和方盒子的摩擦力系数设置为1。但它仍然会在地面上滑动。如何防止任何滑动?


Box2D并不是为速度而设计的,也不是为精确度而设计的。摩擦和恢复力并不能百分之百地工作,你不应该期望它们能够完美运作。当恢复力都为零时,通常会有一点点弹跳,当摩擦力都为1时,通常会有一点点滑动。然而,它不应该“轻易滑动”,因此可能在您的设置中仍然缺少某些东西。 - iforce2d
我已将摩擦力改为100,它按照需要工作。但我不知道最大值是多少,这样我就可以设置最大值,并确保即使力很大,它也永远不会滑动。我应该从numeric limits(c ++)设置浮点最大值吗? - Narek
1
我认为最大值应该是1,但就像我说的那样,它根本不准确。如果你可以通过调整数字得到想要的结果,当然可以将它们更改为任何你需要的值。 - iforce2d
1个回答

1
正如您所发现的那样,您可以通过增加摩擦力来防止滑动。
至于您可以将摩擦力设置为的最大值,没有文档记录摩擦力值的最大值。话虽如此,最大摩擦力值存在一些限制。
在“VaryingFriction”测试中,将std::numeric_limits<float>::infinity()作为第一个摩擦力值尝试,结果是无限摩擦力方块碰到的第一个平台消失了。哎呀!这不是我想要的结果。
查看Box2D 2.3.2 C++源代码的评论,发现以下与摩擦力有关的变量:
- b2Fixturem_friction成员变量。 - b2Contactm_friction成员变量。 - b2ContactVelocityConstraintfriction成员变量。

这些被定义为float32类型的实例,而float32本身是float类型的一种单精度浮点类型。这给我们提供了一个最大的上限,即以下内容可以给我们提供的(不会溢出):

std::numeric_limits<float>::max()
< p > b2Contact m_friction 成员变量实质上是取夹具摩擦力的乘积的平方根的结果:

std::sqrtf(m_fixtureA->m_friction * m_fixtureB->m_friction)

因此,任何给定夹具的m_friction值都需要低于浮点数最大值的平方根,以避免在此乘积中潜在的溢出。也就是说,我们可以从以下公式得到任何b2Fixture摩擦设置的更现实的上限:
std::sqrtf(std::numeric_limits<float>::max())

如果不考虑的friction成员变量,这可能就足够好了;但是在b2ContactSolver::SolveVelocityConstraints()中,它会被另一个浮点数normalImpulse乘以。因此,float-max的平方根可能仍然过高,无法确保完全避免任何潜在的溢出风险。
而溢出可能意味着使用无穷大的摩擦力:糟糕!尽管由于使用过高的摩擦值而导致物体消失可能是一个错误,但除非修复库的源代码,否则我们仍然会受到仍存在风险的最大浮点值的平方根作为上限的限制。顺便说一下,我已经提交了一个issue,并提供了一种我发现的解决方法。
作为一个经验法则,我会增加fixture的摩擦力,直到没有更多的滑动,然后就保持不变。
另一方面,还有其他防止滑动的方法(除了增加摩擦力),比如这些...
  1. 更改物体的类型。如果在与地面碰撞后将物体设置为静态,它就不会再物理上移动,直到你将其改回动态。
  2. 当盒子与地面碰撞时创建一个关节,将盒子与地面绑定。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接