人气 170

[游戏程序] 关于椭球碰撞检测的思考 [复制链接]

九艺网 2017-3-10 17:01:04

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?注册

x
如有转载, 请注明出处:
http://www.azure.com.cn/
近日突然变得的比较清闲,这样我就可以仔细想想以前没有想清楚的问题。
椭球碰撞是现今比较高效的一种方法。看了老外的一篇论文,, 发现老外说一个事情非常罗嗦, 最前面还把线性代数的知识讲了一遍, 看完了才发现是大学课本上的知识. 便马上跳过了.
实际碰撞中, 将椭球包裹住角色, 能产生比较好的吻合.这样碰撞效果更加的精确了.
这里我所思考的范围还不涉及碰撞后的滑动, 那是我下一步要思考的 .
这里我主要总结下, 椭球碰撞的几个要点:
1. 椭球的表示:
这里说的椭球都是正椭球, 是没有倾斜的那种(如果考虑倾斜的就超级复杂了  ), 用三个半径 X, Y, Z, 和一个中心点坐标P来表示.如下图:

                               
登录/注册后可看大图

在这个图里, 三个半径分别是 X=3, Y=7, Z=3
2. 计算椭球下一次位置
只有发生移动才能发生碰撞, 当然只用把椭球的中心坐标P改变位移即可.
P' = P + v
3. 根据新中心坐标P', 把待碰撞检测的三角形变换到椭球空间中来(重点)
假设待碰撞检测的三角形三个顶点为a, b, c. 在那个论文中, 作者大肆炫耀他的数学知识, 总是把一个非常简单的问题解释的又臭又长. 说了半天线性代数中基础基的问题, 赚取了不少的稿费.  
其实这个椭球空间的转换再简单不过了.
我们假设转换后的顶点为a', b', c'
那么有
a' = CBM * (a - P')
b' = CBM * (b - P')
c' = CBM * (c - P')
其中CBM是一个转换矩阵
[ 1/X 0 0]
[ 0 1/Y 0]
[ 0 0 1/Z]
还记得吗, X,Y,Z是上图椭球的三个半径.
这样转换后, 椭球就变成了一个处在原点, 半径为1的正球了(想不过来,仔细想想  )
待检测的三角形(a' b' c')就被变换到原点附近, 这样就只用判断其与这个半径为1正球的关系就可以知道是否发生碰撞了.  
4. 开始碰撞检测了
I. 首先粗略排除绝对不可能相交的.
通过变换后三点(a' b' c')形成一个平面 Plane, 首先判断此平面到原点的距离, 如果大于1则绝对不可能与此待检测的三角形发生碰撞, 在这里你可以直接从你的检测函数中退出了. 当距离小于或者等于1, 再跳到步骤II.
II. 判断是否有任意一点在单位球内.
这也是个快速剔除的方法, 如果a' b' c' 任意一点到原点的距离小于1, 则发生碰撞了, 如果都不小于1, 则我们需要转到第III步, 进行次昂贵的相交测试运算.
III. 边与单位球的相交检测
对于三角形 a' b' c' , 它有三条边a'b', b'c', c'a', 那么我们检测原点到三条边的距离, 如果有任意一条小于1, 则发生了碰撞, 如果非常遗憾的都不小于1的话, 我们就进入最昂贵的第四步的碰撞检测.
IV. 最后一步
在前面第一步, 我们已经计算出来了a'b'c' 组成的平面Plane, 这里第一步首先计算出从原点作垂线到Plane的垂足的坐标. 然后判断此坐标是否在a'b'c'组成的三角形内. 如果在内, 则碰撞发生, 如果不在内, 则无碰撞发生.

5. 是否应该移动到下个位置呢.
我们可以把3,4步集成到一个函数 bool collide(vec3 newpos)中, 如果我们把P'传进去发生碰撞了, 那么我们第2步的坐标改变则不可以发生, 如果不考虑滑动的话, 则不改变位移,停在原地算了.如果没有发生碰撞, 则我们可以大大方方改变原来椭球的中心坐标了, 也就是物体可以向前移动了.当然如果移动速度过快, 会发生穿墙的问题. 这个问题暂时还没有想到如何解决, 如果哪位想到了, 也可以告诉我. 谢谢.
总结:
以上的讲解, 并未提供详细的代码, 关于如何求到面的距离, 到直线的距离, 也不在这里的讨论范围内, 这些算法网上非常多, 在那篇老外的论文中, 后面也提供了相关的代码, 大家可以去看看.
[此贴子已经被作者于2007-5-8 22:08:46编辑过]

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

QQ|手机版|小黑屋|九艺游戏动画论坛 ( 津ICP备2022000452号-1 )

GMT+8, 2024-4-20 00:07 , Processed in 0.116745 second(s), 23 queries .

Powered by Discuz! X3.4  © 2001-2017 Discuz Team.