欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

有关求Unity的求解器与迭代器

程序员文章站 2022-04-22 19:02:31
...

在PhysX3.2中,刚体模拟相对于2.8.x时代,多了两个概念:contactOffset和restOffset。这两个变量加入的初衷是为了让SDK能够更好的控制相互靠的很近的物体,尽快将他们稳定下来。我们来看看文档对这两个变量的描述:

  1. /**
  2. \brief Sets the contact offset.
  3. Shapes whose distance is less than the sum of their contactOffset values will generate contacts. The contact offset must be positive and
  4. greater than the rest offset. Having a contactOffset greater than than the restOffset allows the collision detection system to
  5. predictively enforce the contact constraint even when the objects are slightly separated. This prevents jitter that would occur
  6. if the constraint were enforced only when shapes were within the rest distance.
  7. <b>Default:</b> 0.02f * PxTolerancesScale::length
  8. <b>Sleeping:</b> Does <b>NOT</b> wake the associated actor up automatically.
  9. \param[in] contactOffset <b>Range:</b> (maximum(0,restOffset),inf)
  10. @see getContactOffset PxTolerancesScale setRestOffset
  11. */
  12. virtual void setContactOffset(PxReal contactOffset) = 0;
  13. /**
  14. \brief Sets the rest offset.
  15. Two shapes will come to rest at a distance equal to the sum of their restOffset values. If the restOffset is 0, they should converge to touching
  16. exactly. Having a restOffset greater than zero is useful to have objects slide smoothly, so that they do not get hung up on irregularities of
  17. each others' surfaces.
  18. <b>Default:</b> 0.0f
  19. <b>Sleeping:</b> Does <b>NOT</b> wake the associated actor up automatically.
  20. \param[in] restOffset <b>Range:</b> (-inf,contactOffset)
  21. @see getRestOffset setContactOffset
  22. */
  23. virtual void setRestOffset(PxReal restOffset) = 0;


从上面的说明可能比较委婉,但是我们可以粗俗一点的理解,contactOffset的作用相当于是把物体的碰撞形体变得肥了那么一点点,这样SDK可以更早以及更持续的获取两个物体之间的碰撞信息;而restOffset的作用则是允许两个物体的嵌入深度,只要嵌入的不够深,那么SDK不会用力把物体分开。

并且从值域我们可以看到,restOffset是可以为负数的,这时意味着允许嵌入的范围是从物体的边缘往里允许嵌入;那么,如果设置为正数的话,就是往外了 -- 如果把两个restOffset都是正的Box摞起来,他们之间会有空隙存在的,呵呵。

 

如果有PhysX 2.8的使用经验的话,那么你一定知道PhysX 2.8中的skinWidth,也就是Shape允许被穿透的厚度。这个参数的配置,在PhysX3.2中,就相当于是contactOffset=0,同时restOffset=-skinWidth。

 

从这两者的用途看,也许restOffset能够让两个物体更快的进入稳定状态的作用更加直观一些,因为他明确的定义了不超出某个范围,SDK就不会加力来把两个物体分开。相对来讲,contactOffset就不是那么容易理解了:为什么扩大了碰撞范围、更早更持续的感知到物体之间的碰撞,反而能够帮助物体更快的稳定下来呢?这一点跟PhysX SDK对物体的碰撞状态管理有关。想想这种状态:两个物体靠得非常近,这一帧稍微嵌入一点点,下一帧就刚刚分开,接下来又是持续的这样分分合合,这在一堆物体堆积在一起的时候是常见的情形。这样的情况下,如果没有contactOffset做一点提前预判的话,那么碰撞点的生成就是不连续的,SDK就需要生成很多TOUCH_FOUND、TOUCH_LOST这样的事件,不仅开发者处理起来麻烦,SDK管理起来也觉得不轻松。于是,就有了把碰撞形体变得肥胖一点,预判一下,这样可以更持续的获得碰撞的事件,并且由于只是在contactOffset的范围内,因此SDK虽然会生成碰撞信息,但是不会实际加力把这两个物体分开,于是,当他们满足Sleeping的条件后,就会分别进入Sleeping状态,碰撞点也就不会再生成了。

 

也许这么说,还是觉得比较空洞,不是那么好理解,那么,我们就做一个实验来看着两个到底是怎么工作的吧。

请把下面的代码加入到PhysX SDK的某个Sample中,让他们可以被执行到就可以:

 

  1. const PxVec3 pos = getCamera().getPos();
  2. PxVec3 dir = getCamera().getViewDir();
  3. PxVec3 oriPos = pos + dir*20;
  4. PxVec3 initVel (0.0f);
  5. PxVec3 halfExts (1.0f);
  6. PxReal contactOffset = 0.1f;
  7. PxReal restOffset = -0.01f;
  8. PxRigidDynamic* pActor0 = createSphere(PxVec3(oriPos.x - halfExts.x-contactOffset, oriPos.y, oriPos.z), halfExts.x, &initVel, mManagedMaterials[MATERIAL_RED], mDefaultDensity);
  9. pActor0->setActorFlag(PxActorFlag::eDISABLE_GRAVITY, true);
  10. PxShape* shape0[1];
  11. pActor0->getShapes(shape0, 1);
  12. shape0[0]->setContactOffset(contactOffset);
  13. shape0[0]->setRestOffset(restOffset);
  14. PxRigidDynamic* pActor1 = createSphere(PxVec3(oriPos.x+halfExts.x, oriPos.y, oriPos.z), halfExts.x, &initVel, mManagedMaterials[MATERIAL_RED], mDefaultDensity);
  15. pActor1->setActorFlag(PxActorFlag::eDISABLE_GRAVITY, true);
  16. pActor1->getShapes(shape0, 1);
  17. shape0[0]->setContactOffset(contactOffset);
  18. shape0[0]->setRestOffset(restOffset);


执行前,请打开PVD,这样,可以连接到PVD来观察碰撞点的生成情况。

同时,在这里,我也附加了两张图来说明这段代码的运行情况:

上面的代码,我们创建两个球,他们之间的最近距离刚好是一个contactOffset,这样他们看起来是不相交的,但是根据contactOffset和restOffset的工作方式,他们之间会产生碰撞点,并且不会移动,因为SDK不会尝试把他们分开,正如下面的图中我们看到的:

有关求Unity的求解器与迭代器

 

由于取消了重力,他们俩就会呆在那里,等待睡眠,然后碰撞事件就可以结束了,如这张图中我们看到的状态:

有关求Unity的求解器与迭代器

 

通过这个例程,对这两个概念的理解应该容易多了吧有关求Unity的求解器与迭代器

当然,如果还觉得不够深刻,那么,就请修改上面的代码吧,多尝试几种情况,理解就会更深,也能够更合适的根据自己的场景,选择合适的参数来设置给contactOffset和restOffset。

相关标签: 转载