在计算convex和Triangle Mesh的碰撞中由于最终碰撞的级别会被分解为convex-triangle之间的碰撞检测,因此如果一个convex同时和Triangle Mesh中的多个Triangle发生接触的时候会导致一些 接触点是不正确的(对于单个Convex-triangle是正确的对于convex-mesh却是不正确的)如图:
为了方便我画了2d的模式,蓝色和红色各代表一个三角形,绿色是一个凸多面体,在这一时刻绿色和红色会计算出那个蓝色箭头的法向量,而绿色和蓝色三角行会计算出灰色的法向量,红色的那个最近点对是在红色三角形的面上而,蓝色的是在蓝色三角形的一条边界上而这条边界是和红色共享的(图中表示的就是红蓝的交点),这样的边称为inner edge,在上图情况下这个在inner edge上的接触点应该被消除。
在看一张图:
同样这次接触点也存在inner edge 上但是这一次是正确的接触点应该被保留!,那么为什么会出现第一张图这样错误的接触点呢,关键在于convex在和蓝色三角形进行碰撞测试的时候并不知道红色三角形的存在,也就是说该最近点对只是对于蓝色三角形单独而言的,如果将红色三角形考虑在内,那么由于这条inner edge也包含于红色三角形,因此如果红色三角形的最近点并不在这个edge上,那么对于整体而言这个edge上的点均不是最近点,因此都应该被排除。
因此最终算法如下,首先定义一个avoid集合代表那些feature(顶点,边)应该会被排除,收集完所有接触点之后,分2个pass进行,第一遍扫描每一个三角形上的接触点,对于三角形的任一个顶点,如果没有出现在该三角形的最近点对中那么加入avoid集合,对于任意一条边如果没有出现在该三角形的最近点对中那么加入avoid集合,对于面而言永远不需要加入avoid集合(这是由凸面体的性质决定的),
第2个pass重新扫描所有接触点如果它不再avoid集合中那么作为正常接触点输出,否则抛弃。
使用这种方法 在我的测试中暂时还没有出现过任何由于inner edge导致的法向错误:如图
不过在测试中发现由于目前使用每帧增加一个的接触点缓存,这会导致物速度很大撞击时由于地面的反作用很大并且而且作用在一个点上,产生反转的角速度,因此有必要设计一个一次产生多个接触点的方法,不过我已经想好怎么做了,就暂且加入Todo list把,后面还要把concave和convex的cast完成,柔体vs刚体的碰撞算法,以及最近大致看了下的使用Cycled coordinate decent 方法计算IK的系统需要做