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

670b8fd8b18b297fbc960a4c62a96a35.png

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

原理

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

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

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

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

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

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

8a6e9ac35de17a754826d79f6a80caf4.png

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

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

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

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

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

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

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

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

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

  1. 假设初始方向为
    ,那么将
    黄色 多边形的所有顶点投影到这个方向上,求出最大点。
  2. 再将初始方向取反,
    。然后将
    蓝色 多边形的所有顶点投影到这个方向上,求出最大点。
  3. 获得的两个点相减,即可得到两个图形的单纯形上的一点。

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

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

76efb578ce55aaf344a319c7f4e3f69f.png

第一次

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

4e7d9521e764e13cc87c2df23f388bf1.png

得到黄色图形在

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

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

第二次

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

6799aed737df315797429de2b1398ac5.png

得到黄色图形在

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

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

第三次

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

,一个是
背离原点的

9a92d958dc0c22689992ceeb391efe89.png

我们不妨以先背离原点的

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

e3eb5fe8b5566d545b15ea1afff2a6eb.png

得到黄色图形在

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

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

构造单纯形

我们得到了三个点:

,画出单纯形:

326b394a656dac0be1438bbc6c594a21.png

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

如果我们换成

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

a25bdaac74f71e95d43cc21c570a2d5e.png

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

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

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

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/555348.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

高性能对象存储MinIO学习API使用使用api创建文件夹MinIO工具类

MinIO 是GlusterFS创始人之一Anand Babu Periasamy发布的开源项目,基于Apache V2 license 100% 开放源代码。MinIO采用Golang实现,客户端支持Java、Python、Javacript、Golang语言等。 其设计的主要目标是作为私有云对象存储的标准方案。非常适合于存储…

rmi远程反序列化rce漏洞_Apache Dubbo Provider默认反序列化远程代

背景近日,Apache Dubbo披露了Provider默认反序列化远程代码执行漏洞(CVE-2020-1948),攻击者可构造恶意请求,从而执行任意代码。具体信息如上图所示。在官方邮件中,漏洞报告者还提供了官方的PoC脚本,感兴趣的读者可以自…

操作痕迹包括那些_高级消防设施操作员专题之:走近气体灭火系统

按照《消防设施操作员职业技能标准》的规定,安装有气体灭火系统的单位,应当配置高级消防设施操作员。由于这些单位通常情况下都是消防安全重点单位、火灾高危单位,可以预见,高级消防设施操作员作为消防行业的高技能人才&#xff0…

flutter不支持热更新_Flutter 在安卓上可以实现热更新了

本文由 句号君 授权投稿原文链接:https://blog.csdn.net/qizewei123/article/details/102963340Flutter 官方在 GitHub 上声明是暂时不支持热更新的,但是在 Flutter 的源码里,是有一部分预埋的热更新相关的代码,并且通过一些我们自…

jar包在windows后台运行,通过.bat文件

jar包在windows后台运行.bat 一、IDEA打成jar包 这里不再赘述 二、在windows后台运行jar包 在cmd中可以使用java -jar xxxxx.jar方式运行一个jar文件,这种方法运行一旦关闭该cmd界面就会停止运行。编辑.bat文件,使用javaw方式运行不用担心文件会在不小…

java 枚举(enum) 全面解读

枚举类型是单例模式的。你需要实例化一次,然后再整个程序之中就可以调用他的方法和成员变量了。 枚举类型使用单例模式是因为他的值是固定的,不需要发生改变。 简介 枚举是Java1.5引入的新特性,通过关键字enum来定义枚举类。枚举类是一种特殊…

修改表名_面试官:如何批量修改mysql表字段、表、数据库字符集和排序规则

概述目前数据库字符集统一用的utf8,由于项目需要,引进了表情,但是utf8mb5才支持表情字符,所以需统一修改数据库字符集,下面介绍批量修改数据库字符集的办法。修正顺序是字段级别>表级别>库级别。一、批量修改整个…

Maven命令 install 和 package的区别

Maven命令 install 和 package的区别 Maven是目前十分流行的项目构建工具以及依赖解决工具,其提供的常用指令中有两个很容易引起使用者的疑惑, 那就是 install 和 package , 那么这两个命令到底有啥区别呢? Maven install 安装…

如何重启_消费市场按下重启键,企业该如何提前布局

2020广发卡携手企业和消费者,共同按下重启键,让我们放下包袱,轻松前行。当疫情结束后,你想做什么?也许是去见想见的人,和他一起去吃想吃的美食;也许是约上三五好友,或带着最亲的家人…

Linux中使用netstat命令的基本操作,排查端口号的占用情况

Linux中netstat命令详解 Netstat是控制台命令,是一个监控TCP/IP网络的非常有用的工具,它可以显示路由表、实际的网络连接以及每一个网络接口设备的状态信息。Netstat用于显示与IP、TCP、UDP和ICMP协议相关的统计数据,一般用于检验本机各端口的网络连接情…

与context的关系_Android-Context

一.简介Context 翻译为上下文环境,是一个应用程序环境信息的接口。如果以 Android 系统角度来看可以理解为某一与操作系统的交互的具体场景,比如 Activity 的具体功能,Service 的后台运行等。如果以程序的角度看,Context 是一个抽…

Linux中sudo、su和su -命令的区别

Linux中sudo、su和su -命令的区别小结 我们知道,在Linux下对很多文件进行修改都需要有root(管理员)权限,比如对/ect/profile等文件的修改。下面这篇文章主要给大家总结介绍了关于Linux中sudo、su和su -命令的区别的相关资料&…

如何根据进程号去查端口号?

1.查出进程号 eg: ps -ef |grep conet- 2.根据当前进程号获得端口号: eg: netstat -anp |grep 4118 得到当前的端口是8761

Linux中如何查看某个端口是否被占用的方法

LINUX中如何查看某个端口是否被占用的方法 之前查询端口是否被占用一直搞不明白,现在总结下: 1.netstat -anp |grep 端口号 如下,我以3306为例,netstat -anp |grep 3306(此处备注下,我是以普通用户操作&…

深入理解synchronized底层原理

文章目录前言一、synchronized的特性1.1 原子性1.2 可见性1.3 有序性1.4 可重入性二、synchronized的用法三、synchronized锁的实现3.1 同步方法3.2 同步代码块四、synchronized锁的底层实现五、JVM对synchronized的优化5.1 锁膨胀5.1.1 偏向锁5.1.2 轻量级锁5.1.3 重量级锁5.2…

centos7重新加载服务的命令_CentOS7 从查看、启动、停止服务说起systemctl

执行命令“systemctl status 服务名.service”可查看服务的运行状态,其中服务名后的.service 可以省略,这是CenOS7以后采用systemd作为初始化进程后产生的变化。Systemctl是一个systemd工具,主要负责控制systemd系统和服务管理器。Systemd是一…

一体化住户调查_曲麻莱县2020年城乡一体化住户调查表彰会暨年报部署会

为全面推进我县城乡一体化住户调查工作,总结经验、鼓励优秀,提高统计员和辅助调查员的工作积极性,提高账本数据质量,11月25日下午,县统计局组织召开2020年全县城乡一体化住户调查工作表彰会暨年报部署会。全县6个镇的统…

电力系统继电保护第二版张保会_电力系统继电保护试题

一、填空题(每小题1分,共20分)1.电气元件配置两套保护,一套保护不动作时另一套保护动作于跳闸,称为_近后备_保护。2.电流继电器的_返回_电流与动作电流的比值称为继电器的返回系数。3.反应电流增大而瞬时动作的保护称为__无时限电流速断保护_…

Linux中shell脚本详解

文章目录1、第一个脚本程序:2、shell获取字符串长度:3、shell变量:4、**引用shell变量**:5、shell变量的赋值、修改、删除:5、shell特殊变量:6、shell中字符串的拼接:**7、字符串的截取**8、she…

java递归实现多级菜单栏_Java构建树形菜单以及支持多级菜单的实例代码

这篇文章主要介绍了Java构建树形菜单的实例代码(支持多级菜单),非常不错,具有参考借鉴价值,需要的朋友可以参考下效果图:支持多级菜单。菜单实体类:public class Menu {// 菜单idprivate String id;// 菜单名称private String nam…