2D凸多边形碰撞检测算法(二) - GJK(上)

原理

在 Narrow Phase 精细碰撞检测中,除了 SAT ,另外一个就是 GJK(Gilbert–Johnson–Keerthi)算法。它足够高效,且很容易了解它是如何进行碰撞检测的。同样的,它也只适用于 凸多边形 间的碰撞检测。

首先,重新回顾一下:当两个物体碰撞,发生部分重叠的时候,我们是怎样让计算机知道他们发生了碰撞呢?在上一篇中,SAT 告诉我们:

如果存在一条直线,能够将两个物体分隔开,则两个物体没有发生碰撞。
反之,如果两个物体发生碰撞,则找不到这一条直线,将两个物体分隔开。

SAT 让我们从 分离 的角度,去思考物体间的碰撞。

而 GJK ,则是从 重叠 的角度来探索物体之间的碰撞。

为了方便理解,我们先创建两个相互重叠的多边形,并标记两个多边形重叠的部分:

目光聚焦到红色的重叠部分,并想一想,它的几何意义究竟是什么?

我们在中学就已经学过,两个直线相交,会产生一个点。这个点都在这两条直线上,这意味着,反应在坐标系上,两条直线享有一个 共同的坐标 。而对于平面,就是无数条直线构成。两个图形产生了重叠,意味着他们有着一组共同的点, 共享一组坐标

而产生碰撞的条件是,两个图形必须 至少重合一个点 ,否则将不会产生碰撞。翻译成计算机能听懂的话:

“是否能从两个图形中,各自找到一个点,使得它们相减后为原点?”

这就是 GJK 算法的核心目的。当两个图形发生重叠时,他们 必然会有一个坐标,相减后为原点

计算机想要“看见”两个图形重叠的部分,可以利用自身的计算优势,把左边整个图形所包含的坐标 减去 右边图形所包含的坐标,并得到一系列的点。将所有计算后的点包围起来,如果这个新生成的图形 包含原点,则意味着两个图形发生了重叠,从而判断两个图形发生了碰撞。我们把计算后的点称为 闵可夫斯基差 ( Minkowski Difference ),将生成的三角形/线形称为 单纯形 ( Simplex )。

为了直观地理解,我将两个图形所有坐标相减后的结果称为 Minkowski Difference。实际上,似乎只存在 Minkowski Sum (闵可夫斯基和)这个说法。其实也可以理解为,将第二个图形的所有坐标点取反后,加到第一个图形的所有坐标点。

将两个图形所有的坐标相减,显然不是我们能够手算的。但是,我们可以根据多边形的特点,只需将他们的顶点相减,就可以达成我们的目的。但是这样,排列组合后,需计算 20 个点,这显然也不是我们想要的,并且可能会出现多余的计算结果。所以,我们需要尽量得到足够大的单纯形,这样才会提升包含原点的几率。

在GJK 算法中,我们定义一个名为 support 的函数。在这个例子中,它的作用是这样的:

  1. 假设初始方向为

    ,那么将

    黄色 多边形的所有顶点投影到这个方向上,求出最大点。

  2. 再将初始方向取反,
    。然后将

    蓝色 多边形的所有顶点投影到这个方向上,求出最大点。

  3. 获得的两个点相减,即可得到两个图形的单纯形上的一点。

为了便于理解,我们创建两个多边形,并且规定

为蓝色图形的位置坐标,
为黄色图形的位置坐标,从
指向
为 support 函数的起始方向。我们的目标是至少能够算出三个点,构成一个包含三个顶点的单纯形。

第一次

依次按照上述步骤,我们得到这样的一个结果:

得到黄色图形在

方向上的最大投影点为来自于点
,记录坐标
;得到蓝色图形在 方向
上的最大投影点为来自于点
,记录坐标

将两个坐标相减,得到单纯形上的一个顶点 :

第二次

然后,我们将初始方向取反,作为新的初始方向,再进行如上的步骤:

得到黄色图形在

方向上的最大投影点为来自于点
,记录坐标
;得到蓝色图形在
方向上的最大投影点为来自于点
,记录坐标

将两个坐标相减,得到单纯形上的一个新的顶点 :

第三次

之后,我们取与起始向量垂直的向量作为新的方向向量,值得注意的是,这样的方向向量有两个,一个是 指向原点的

,一个是

背离原点的

我们不妨以先背离原点的

作为新的方向,重复 support 函数。

得到黄色图形在

方向上的最大投影点为来自于点
,记录坐标
;得到蓝色图形在 方向
上的最大投影点为来自于点
,记录坐标

将两个坐标相减,得到单纯形上的一个新的顶点 :

构造单纯形

我们得到了三个点:

,画出单纯形:

我们似乎没能构成一个包含原点的单纯形。

如果我们换成

,计算后,我们将会得到一个新的点
。画出这个新的单纯形:

这一次,我们 幸运地 包含了原点!

从以上几个步骤,不难看出, GJK 是一种 迭代算法,它需要不断地检测单纯形是否包含原点。它退出迭代的条件是:

  1. 单纯形包含原点
  2. 单纯形最后添加的顶点与搜寻方向点乘小于0

到目前为止,我们离真正实现 GJK 碰撞检测还有一段距离,以及碰撞之后,如何通过EPA算法,获得它的穿透向量。这些内容,将在稍后的篇章中详细介绍。

java计算一个多边形的重心_2D凸多边形碰撞检测算法(二) - GJK(上)相关推荐

  1. java计算一个多边形的重心_多边形重心问题 java

    多边形重心问题 java 看题目 点这里 题目描述: 描述 在某个多边形上,取n个点,这n个点顺序给出,按照给出顺序将相邻的点用直线连接, (第一个和最后一个连接),所有线段不和其他线段相交,但是可以 ...

  2. java计算一个多边形的重心_Java多边形重心计算

    多边形重心计算 三角形重心 顶点为a,b,c的三角形重心为x = (xa + xb + xc) / 3,y = (ya + yb + yc) / 3 多边形重心 x = (x1w1 + x2w2 + ...

  3. java 算出下一个工作日,Java:计算一个日期加下指定工作日数(排除周六周日和一系列节日)...

    Java:计算一个日期加上指定工作日数(排除周六周日和一系列节日) 工作时遇到的,随便写了个,欢迎高手点评: 核心代码: package www.sjjjob.com.date; import jav ...

  4. Java计算一个字符串的HashCode

    计算hashcode的原理步详解: import java.math.BigInteger;import java.security.MessageDigest; import java.securi ...

  5. 使用计算机计算一个多边形,计算机几何基础,计算多边形的面积, HDU-2036

    还记得我们是怎么计算多边形面积的么? 让你先思考10秒钟,Any good idea? 好吧相信你心中已经有了想法. 还记得我们学过的叉乘么,两个向量同一起点的叉乘积再乘1/2就是三角形的面积(哦哦哦 ...

  6. java计算一个月有几周_java 如何获取 一个月 有多少周

    展开全部 你说需要计算一个月有多少周,若是指,一月,二月一直到十二月每个月有多少周的话,可以用32313133353236313431303231363533e59b9ee7ad94313333613 ...

  7. 使用计算机计算一个多边形,多边形面积计算器

    多边形面积计算器顾名思义是一款能够计算多边形面积的软件.而且软件支持手绘功能,还可以将喜欢的图片作为绘画的底图,软件界面变为可调节大小,这样就可以把绘图区域.坐标表格区域任意调整,方便坐标输入和绘制大 ...

  8. java 计算一个月有多少天和多少周

    import java.util.Calendar; /** * 功能概述:计算指定年月的天数和周数<br> * 创建时间:2010-5-17 下午05:25:58<br> * ...

  9. Java计算一个时间段与当前时间的进度百分比

    Date nowDate = new Date(); //当前时间Date startDate = p.getPro().getStartDate(); //开始时间Date endDate = p. ...

最新文章

  1. 面试:说说你对 Java 中 final 的理解?
  2. docker ubuntu 安装包_史上最全Docker环境安装指南
  3. Kubernetes二进制部署——Flannel网络
  4. 前端学习(2672): vue3.0脚手架路由改变
  5. a人工智能b大数据c云计算_你清楚5G物联网、大数据、云计算、人工智能之间的关联吗?...
  6. 《3D打印:正在到来的工业革命》——1.1节3D 技术打印是如何工作的
  7. 如何去掉腾讯网址安全中心提醒
  8. Servlet实现上传下载
  9. 文字转语音开源软件-espeak
  10. ID3算法(含实例)
  11. vue中使用highCharts的drilldown钻取图、3D等图
  12. PostgreSQL数据库——Pigsty configure
  13. 如何在服务器替换apk文件,如何修改apk文件的服务器地址
  14. 艺考生冬日穿泳装秀三围
  15. wirehark数据分析与取证flag.pcap
  16. 新冠无情人间有情,欣隆农业保民生共抗疫——慰问抗疫一线及爱老助困送欣隆酵醒鸡蛋蔬菜进社区公益行动
  17. ros2 foxy 报错缺少“diagnostic_updater“,By not providing “Finddiagnostic_updater.cmake“ in CMAKE_MODULE_P
  18. 2018国内各大互联网公司前端面试题汇总【转:公众号~~高级前端进阶公众号】
  19. 封头名义厚度如何圆整_封头规格
  20. CRC-CCITT 标准CRC16(1021) 算法校验类

热门文章

  1. Python | 如何使用pip升级所有Python软件包?
  2. python爬取酷狗音乐top500_python获取酷狗音乐top500的下载地址 MP3格式
  3. lightgbm 保存模型 过大_机器学习之12—Lightgbm
  4. 第 6-2 课:SpringMVC 核心 + 面试题
  5. javascript数字格式化通用类——accounting.js使用
  6. 页面分栏LayoutInflater
  7. 操作系统(王道笔记第三章内存)
  8. 常量指针与指针常量勘误
  9. c加加中print是什么意思_砖家财经:基金名字后面的A、B和C,分别代表什么意思?...
  10. 【IDEA】IDEA中使用git将项目上传到码云上