PhysX学习记录 七 冲突检测

时间:2023-01-25 00:15:50

原文地址:http://blog.csdn.net/heartrude/article/details/7790650


冲突碰撞是针对Shape的碰撞。Shape之间可能存在默认不碰撞检测的情况。相互碰撞检测方式如下图:

PhysX学习记录 七 冲突检测

Shape免冲突设置

只要设置ShapeDesc.shapeFlags |= NX_TRIGGER_ENABLE就可以使得该Shape免予冲突检测。

冲突检测优化

冲突检测是很耗性能的。每次的遍历是很难实现的。所以有一些性能上的优化。首先能够冲突检测的pair是在一定的距离内的。另外还要满足下面的冲突检测前的判断。

    (a->getActor()->isDynamic() || b->getActor()->isDynamic())
        && NxScene::getGroupCollisionFlag(a->getGroup(), b->getGroup())
        && (!(NxScene::getShapePairFlags(a,b) & NX_IGNORE_PAIR))

1.pair的两个actor必须有一个是dynamic的

2.Shape分组过滤器

可以手工把Shape分到组里面。系统维护了一个32*32的矩阵碰撞检测标志,也就是一共可用32个组。默认所有的Shape都在0组。如果两个组不碰撞,则不进行碰撞检测。下面函数可以修改矩阵标志位。
NxScene::setGroupCollisionFlag(CollisionGroup g1, CollisionGroup g2, bool enable);

3.Actor分组过滤器

Actor分组与Shape分组功能类似。不过Actor分组需要设置有效的碰撞标志位,而不能完全屏蔽碰撞。默认都在0组。如果希望默认能够冲突检测,就需要设置 0组合0组制件能够冲突碰撞。
    gScene->setActorGroupPairFlags(333,334, NX_NOTIFY_ON_START_TOUCH | NX_NOTIFY_ON_END_TOUCH);

标志位包括:NX_NOTIFY_ON_START_TOUCH, NX_NOTIFY_ON_END_TOUCH, NX_NOTIFY_ON_TOUCH.

4.Pair专门标志过滤器

可以只设置对应的两个actor或者shape的碰撞过滤。
    NxScene::setActorPairFlags(NxActor&, NxActor&, NxU32 flags);
    NxScene::setShapePairFlags(NxShape&, NxShape&, NxU32 flags);

5.Shape Conact过滤器

针对shape的128bit组、操作符、标志位判定过滤器。

6.专门的用户定义过滤器

设置了用户自定义过滤器后,其他的过滤器都失效了(2,3,4)。

CCD Continuous Collision Detection

这个我一开始是理解为连续冲突检测,就是一个simulate里面可以多次碰撞。看了文档后才发现原来是针对Discrete Collision Detection而来的。主要是针对高速移动actor的碰撞检测,如果使用discrete collision detect可能出现穿墙而过的情况而出现的一个算法。原理是就是DCD顾名思义就是离散冲突检测。检测只在各个step点上,所以可能导致穿墙。而CCD是step的路线框出一个矩形和另一个actor进行碰撞检测。所以可以避免穿墙的问题。
对于慢速移动、多碰撞物体模拟效果会步入DCD。比如在凹面上面滚动的球。

CCD有效的必要条件

1.NX_COUTINUOUS_CD设置为true,该设置可以在运行时修改: gPhysicsSDK->setParameter(NX_COUTINUOUS_CD, true)
或者NX_CF_INHERIT_SETTING标志位清除,NX_CF_CONTINUOUS_CD设置true

dynamic vs static
2.dynamic Actor对象必须有 CCD skeleton
3.dynamic Actor的线速度必须高于CCDMotionThreshold.默认是0
4.static Actor的shape必须是NxConvexMeshShape、NxTriangleMeshShape的组合

dynamic vs dyname
2.2个Actor至少包含一个设置了NX_SF_DYNAMIC_CCD的Shape
3.两个Actor必须包含CCD Skeleton
4.至少一个Actor的线速度必须超过CCDMotionThreshold
5.两个Actor的相对速度必须超过CCDMotionThreshold

ccd skeleton创建

这里记录一下ccd skeleton的创建相关内容。
主要是mesh的问题,上代码:
[cpp]  view plain copy
  1. NxCCDSkeleton* CreateCCDSkeleton (NxPhysicsSDK* pPhysxSDK, float size)  
  2. {  
[cpp]  view plain copy
  1. NxU32 triangles[3 * 12] = {   
  2.     0,1,3,  
  3.     0,3,2,  
  4.     3,7,6,  
  5.     3,6,2,  
  6.     1,5,7,  
  7.     1,7,3,  
  8.     4,6,7,  
  9.     4,7,5,  
  10.     1,0,4,  
  11.     5,1,4,  
  12.     4,0,2,  
  13.     4,2,6  
  14. };// 三角形定点序列。一个三角形3个点。这里写的是定点的index.对应后续的stm.points数组里面的定点序列。1就是stm.points[1]  
  15.   
  16.   
  17. NxVec3 points[8];  
  18.   
  19. //static mesh  
  20. points[0].set( size, -size, -size);  
  21. points[1].set( size, -size,  size);  
  22. points[2].set( size,  size, -size);  
  23. points[3].set( size,  size,  size);  
  24.   
  25. points[4].set(-size, -size, -size);  
  26. points[5].set(-size, -size,  size);  
  27. points[6].set(-size,  size, -size);  
  28. points[7].set(-size,  size,  size);  
  29.   
  30. NxSimpleTriangleMesh stm;  
  31. stm.numVertices = 8;  
  32. stm.numTriangles = 6*2;  
  33. stm.pointStrideBytes = sizeof(NxVec3);  
  34. stm.triangleStrideBytes = sizeof(NxU32)*3;  
  35.   
  36. stm.points = points;<span style="white-space:pre">              </span>// mesh的定点描述序列。  
  37. stm.triangles = triangles;<span style="white-space:pre">            </span>// 三角形定点序列  
  38. stm.flags |= NX_MF_FLIPNORMALS;  
  39. return pPhysxSDK->createCCDSkeleton(stm);  

由于 NxCCDSkeleton是一个Skeleton描述。所以不同的shape可以使用一个skeleton描述。不用每次创建shape都需要重新new新的
[cpp]  view plain copy
  1. NxCCDSkeleton。  
[cpp]  view plain copy
  1.   

杂记

速度并非高过某一值就必定发生穿墙。穿墙的速度是离散分布的。
比如29会碰撞,30穿墙,31碰撞,32穿墙。