PhysX 3.2中的刚体模拟: TolerancesScale

在创建PhysX 3.2的PhysX SDK对象和PxScene对象的时候,我们会发现,跟PhysX 2.8时候相比,有一个多出来的参数特别醒目:

PX_INLINE physx::PxPhysics* PxCreatePhysics(
	physx::PxU32 version,
	physx::PxFoundation& foundation,
	const physx::PxTolerancesScale& scale,
	bool trackOutstandingAllocations = false,
	physx::PxProfileZoneManager* profileZoneManager = NULL);

PX_INLINE PxSceneDesc::PxSceneDesc(const PxTolerancesScale& scale):


这个参数就是上面加粗的参数,PxTolerancesScale scale。这个参数干什么用的呢?

我们还是看看它的定义吧:

 

class PxTolerancesScale
{
public: 

	/** brief
	The approximate size of objects in the simulation. 
	*/

	PxReal	length;


	/** brief
	The approximate mass of a length * length * length block.
	*/
	PxReal	mass;

	/** brief
	The typical magnitude of velocities of objects in simulation. This is used to estimate 
	*/
	PxReal	speed;


	/**
	\brief constructor sets to default 
	*/
	PX_INLINE PxTolerancesScale();

	/**
	\brief Returns true if the descriptor is valid.
	\return true if the current settings are valid (returns always true).
	*/
	PX_INLINE bool isValid() const;

};

 

从字面意思看,是SDK在模拟的时候,这个变量定义了容忍的各种变量数值的级别。但是要搞清楚这个问题,我们需要对刚体模拟的一些最基本的东西进行一番梳理:

首先,在物理世界中,有一个默认的加速度,施加给场景中的所有物体,这么说可能觉得弯弯绕的难听死了,呵呵,但是如果说是重力,那么大家就都明白了。在场景中的所有物体,都会受到重力的影响,而重力是多少呢?常用的是9.8?

没错,常用的是9.8,或者粗略一点,10,但是单位系统呢,哦,是m/s^2。

 

好的,暂且放下重力,再说下一个,看起来不太相关的东西,就是物体的大小。我们的编辑器中,都会有根据引擎设计的初衷而与生俱来就有的某个单位系统,这个单位系统,可以跟标准的国际单位制一致,也可以是按照一定比例的缩放,比如有的引擎是3个长度单位对应国际单位制中的1米,有的是10,有的是64,不一而足。

不一样的单位系统,就决定了创建出来的物体的大小就是完全不一样的,同样是一米大小的问题,对应到相应的引擎中,可以是3个长度单位,可以是10,也可以是64。

 

了解了这些,我们还要看看刚体的碰撞过程,当SDK检测到两个物体有重叠的空间之时(也就是有碰撞的时候),会如何来处理这检测到的碰撞呢?是所有的碰撞都义无反顾的生成弹开的力呢,还是为了更快的进入稳定状态,当物体之间的碰撞非常轻微的时候,直接忽略呢?PhysX SDK选择的是后者,并且通过PxSceneDesc::bounceThresholdVelocity定义什么样的相对速度,算是“非常轻微”。这个bounceThresholdVelocity,与scale相关。

还有根据碰撞点计算摩擦力的时候,如何合并相邻的碰撞点一起计算摩擦力的控制参数PxSceneDesc::contactCorrelationDistance,也与scale相关。

 

除了上面说到的这些,还有物体的质量、前面的文章中讲过的contactOffset和restOffset等,都会影响到模拟的表现。

 

---------------------------------------------------------------------------

上面的这些东西,虽然啰嗦,但是如果理解不透彻的话,会对如何合理的使用PxTolerancesSacle依然是一头雾水。我们创建的物理世界的时候,可以使用我们自己的单位系统,但是要让我们自己的单位系统创建出来的东西能够正常工作,最起码看起来是正常的,那么就需要合理的设置PxTolerancesScale中的参数,并且合理搭配其他能影响模拟表现的变量。具体来说:

Scale.length: 会影响PxSceneDesc::sweepEpsilonDistance的精度,两个Shape之间碰撞的判断精度(contact offset即两个shape嵌入深度,以及PxSceneDesc::contactCorrelationDistance)。
Scale.speed: 会影响对物体是否进入睡眠状态(sleep)的判断精度,以及碰撞是否足以导致反弹的判断精度(PxSceneDesc::bounceThresholdVelocity)。
Scale.mass: 暂时未使用,但是以后可能会使用。

 

如果以一个实例来说明使用的话,比如在某个引擎中,n个长度单位对应1m,那么,可以做这样的尝试:

scene.gravity.y = -9.8f*n;

Scale.speed = scene.gravity.y;

Scale.length = n;

同时,可以按照一定的百分比,比如2%或者3%来定义contactOffset和restOffse的大小,当然,restOffset取正还是取负,需要看游戏的设计需求了。

*这只是一个通用的实例,不一定适合所有的情况,但是如果发现在使用自己的单位系统后,即便是最普通的刚体模拟,也有奇怪或则不稳定的表现,那么就需要怀疑上面提到的这些变量的设置是否合适,并且逐一进行检查,找出原因。到现在为止,已经发现过因为contactOffset、restOffset或者gravity设置不合适,出现刚体抖动的问题了。

 

 

posted @ 2013-06-12 18:35  爱生活,爱编程  阅读(1093)  评论(0编辑  收藏  举报