凸多边形碰撞检测的分离轴算法(SAT)
2021/12/4 17:46:57
本文主要是介绍凸多边形碰撞检测的分离轴算法(SAT),对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
碰撞检测可分为 Broad Phase (粗略检测)与 Narrow Phase (精细检测) 两个阶段。粗略检测阶段可直接比较两个物体的AABB包围框是否碰撞以节省计算量和时间。在精细检测中,SAT(Separating Axis Theorem,分离轴定理)碰撞检测算法直观且高效,它的原理清晰易懂,即若两个物体没有发生碰撞,则总会存在一条直线,能将两个物体分离。分离轴适用的是凸多边形之间的检测,不适用于凹多边形,凹多边形的检测,可以通过算法将凹多边形分割成多个凸多边形再进行计算。
算法步骤如下:
步骤一:从需要检测的多边形中取出一条边,并找出它的法向量,这个向量将会是我们的一个“投影轴”。
步骤二:循环获取第一个多边形的每个点,并将它们投影到这个轴上。
步骤三:对第二个多边形做同样的处理。
步骤四:分别得到这两个多边形的投影,并检测这两段投影是否重叠。
如果你发现了这两个投影到轴上的“阴影”有间隙,那么这两个图形一定没有相交。但如果没有间隙,那么它们则可能接触,你需要继续检测直到把两个多边形的每条边都检测完。如果你检测完每条边后,都没有发现任何间隙,那么它们是相互碰撞的。
根据上面步骤两个凸多边形之间碰撞检测的关键代码如下(参考collision.py):
1 def flatten_points_on(points, normal, result): 2 minpoint = math.inf 3 maxpoint = -math.inf 4 5 for i in range(len(points)): 6 dot = points[i].dot(normal) 7 if dot < minpoint: 8 minpoint = dot 9 if dot > maxpoint: 10 maxpoint = dot 11 12 result[0] = minpoint 13 result[1] = maxpoint 14 15 16 def is_separating_axis(a_pos, b_pos, a_points, b_points, axis): 17 range_a = [0, 0] 18 range_b = [0, 0] 19 20 offset_v = b_pos-a_pos 21 22 projected_offset = offset_v.dot(axis) 23 24 flatten_points_on(a_points, axis, range_a) 25 flatten_points_on(b_points, axis, range_b) 26 27 range_b[0] += projected_offset 28 range_b[1] += projected_offset 29 30 if range_a[0] > range_b[1] or range_b[0] > range_a[1]: 31 return True 32 33 return False 34 35 36 def test_aabb(b1,b2): 37 return b1[0][0] <= b2[1][0] and b2[0][0] <= b1[1][0] and b1[0][1] <= b2[2][1] and b2[0][1] <= b1[2][1] 38 39 40 def test_poly_poly(a, b): 41 a_points = a.rel_points 42 b_points = b.rel_points 43 a_pos = a.pos 44 b_pos = b.pos 45 46 for n in a.normals: 47 if is_separating_axis(a_pos, b_pos, a_points, b_points, n): 48 return False 49 50 for n in b.normals: 51 if is_separating_axis(a_pos, b_pos, a_points, b_points, n): 52 return False 53 54 return True 55 56 57 def collide(a, b): 58 if not test_aabb(a.aabb, b.aabb): 59 return False 60 61 return test_poly_poly(a, b)
对于参数指定的两个凸多边形,碰撞检测函数collide先调用test_aabb来判断其AABB包围框是否相交,若外包围框不相交则证明两个多边形之间不可能发生碰撞,函数值返回False,反之则使用分离轴算法进行精细检测。函数test_poly_poly按照算法流程遍历两个多边形上的每一条边,若在某一条边上存在分离轴使得两个多边形在其上的投影不重合则证明多边形不相交,直接返回False。函数is_separating_axis根据给定的两个多边形的位置、多边形顶点的局部坐标以及分离轴向量,来计算多边形在分离轴向量上投影是否重合。
需要注意的是:对于很多图形视图和动画框架来说,图形项一般使用自己的局部坐标系来绘制,通常以其中心为原点,图形项的位置是其原点在其父图形项或者场景中的位置。分离轴判断函数中的坐标基准应一致,假如以第一个输入参数多边形$a$的位置为参考原点,则多边形$b$的顶点坐标在该参考系下,其局部坐标要加上$\overrightarrow{ab}$这个offset,因此多边形$b$在向分离轴投影时也要加上$\overrightarrow{ab}$投影后的偏移量$ \overrightarrow{ab} \cdot \overrightarrow{n}$
参考:
collision.py
Hyperplane separation theorem
SAT (Separating Axis Theorem)
碰撞检测之分离轴定理算法讲解
2D凸多边形碰撞检测算法(一) - SAT
这篇关于凸多边形碰撞检测的分离轴算法(SAT)的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-12-23线下车企门店如何实现线上线下融合?
- 2024-12-23鸿蒙Next ArkTS编程规范总结
- 2024-12-23物流团队冬至高效运转,哪款办公软件可助力风险评估?
- 2024-12-23优化库存,提升效率:医药企业如何借助看板软件实现仓库智能化
- 2024-12-23项目管理零负担!轻量化看板工具如何助力团队协作
- 2024-12-23电商活动复盘,为何是团队成长的核心环节?
- 2024-12-23鸿蒙Next ArkTS高性能编程实战
- 2024-12-23数据驱动:电商复盘从基础到进阶!
- 2024-12-23从数据到客户:跨境电商如何通过销售跟踪工具提升营销精准度?
- 2024-12-23汽车4S店运营效率提升的核心工具