碰撞检测阶段总结

最近调整碰撞检测,总结出以下:
(1).球和棱碰撞,碰撞法向量不是与棱相接的两个平面的法向量的和的单位向量,而是碰撞点到球心的向量。法向量要先求出,然后才能算碰撞点,法向量可以通过表示棱的向量 和 棱上一点到球心向量 的向量三重积求出。
球和点碰撞法向量好找,就是半径向量。
即:面和棱、点碰撞,碰撞法向量为那个面在碰撞点的切平面的法向量

(2)碰撞检测树可以改进成多种节点相结合的,让它们都实现一个接口ICollisionTreeNode,抽象出来method和property,分割时估算一下顶点线性相关程度,然后再选择子节点类型。

BTW:
发现最基础的问题比如几何体求交,别人都不怎么重视。也许是他们足够NB,不需要注意。一个球和三角形求交,还不是最精确的(边的求交不是直线和二次曲面求交那种,这种一个球和一条线段只能求出一个点),竟然被我弄了好几天才弄出来(+优化)。以后加上任意形状刚体那估计更不好说。
由于建碰撞树时的近似处理,当分割较BT的网格时,一个大的三角形组将会 分不成 多个小三角形组,造成递归至堆栈溢出。所以应该狠一下,精确处理。



至此,球和Tri-mesh的碰撞检测&处理就彻底OK了。接下来是Tri-mesh和Tri-mesh的……另外,最好实现OBB树。
当然,与平面有关的就比较简单,不提了。
球和Tri-mesh碰撞包括:
  球和静态物体的碰撞
  球和任意刚体的碰撞

留图


附:
球和三角形相交检测,以下过程按顺序执行,一旦相交就return,停止和这个三角形继续检测:
(1).判断球心与三角面垂直且过三边的平面的位置关系,如果被包围,那么直接判断球心到三角面所在平面距离是否<=半径
(2).根据(1)的结果,如果球心在哪条边外,那么试着和那条线段求交
(3).判断球心到三角形某顶点距离<=r

球和线段求交:
(1).计算线段包围球,检查求和这个包围球是否相交(好像可以省略判断,速度差不多)
(2).若相交,用一开始提到的向量三重积计算出法向量,用投影长算距离,算碰撞位置。
(3).判断距离是否小于半径 且 碰撞位置在线段包围球内

代码
(注:Intersect是包围球的一个方法,包围球有字段vCentre,dRange,
%为向量积运算符,&为两点距离运算符,^为两点距离平方运算符)
ExpandedBlockStart.gifContractedBlock.gif        /**//// <summary>
InBlock.gif        
/// 判断线段是否和包围球相交
ExpandedBlockEnd.gif        
/// </summary>

None.gif        public bool Intersect(Vector vStart, Vector vEnd, out double dist, out Vector n, out Vector pos)
ExpandedBlockStart.gifContractedBlock.gif        
dot.gif{
InBlock.gif            Vector v 
= 0.5 * (vStart + vEnd);
InBlock.gif            
double r = 0.5 * (vStart & vEnd);
InBlock.gif
InBlock.gif            
if ((v & vCentre) <= (r + dRange))
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                Vector v1 
= (vCentre - vEnd);
InBlock.gif                Vector v2 
= (vStart - vEnd);
InBlock.gif
InBlock.gif                n 
= (v2 % v1 % v2).UnitVector;
InBlock.gif                dist 
= v1 * n;
InBlock.gif                pos 
= vCentre - dist * n;
InBlock.gif
InBlock.gif                
return (dist <= dRange) && ((pos ^ v) < r * r);
ExpandedSubBlockEnd.gif            }

InBlock.gif            dist 
= 0;
InBlock.gif            n 
= new Vector();
InBlock.gif            pos 
= new Vector();
InBlock.gif            
return false;
ExpandedBlockEnd.gif        }

转载于:https://www.cnblogs.com/Yuri/archive/2007/07/13/814847.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值