日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

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

發布時間:2025/3/12 编程问答 18 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java计算一个多边形的重心_2D凸多边形碰撞检测算法(二) - GJK(上) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

2D凸多邊形碰撞檢測算法(二) - GJK(上)

原理

在 Narrow Phase 精細碰撞檢測中,除了 SAT ,另外一個就是 GJK(Gilbert–Johnson–Keerthi)算法。它足夠高效,且很容易了解它是如何進行碰撞檢測的。同樣的,它也只適用于 凸多邊形 間的碰撞檢測。

首先,重新回顧一下:當兩個物體碰撞,發生部分重疊的時候,我們是怎樣讓計算機知道他們發生了碰撞呢?在上一篇中,SAT 告訴我們:

如果存在一條直線,能夠將兩個物體分隔開,則兩個物體沒有發生碰撞。
反之,如果兩個物體發生碰撞,則找不到這一條直線,將兩個物體分隔開。

SAT 讓我們從 分離 的角度,去思考物體間的碰撞。

而 GJK ,則是從 重疊 的角度來探索物體之間的碰撞。

為了方便理解,我們先創建兩個相互重疊的多邊形,并標記兩個多邊形重疊的部分:

目光聚焦到紅色的重疊部分,并想一想,它的幾何意義究竟是什么?

我們在中學就已經學過,兩個直線相交,會產生一個點。這個點都在這兩條直線上,這意味著,反應在坐標系上,兩條直線享有一個 共同的坐標 。而對于平面,就是無數條直線構成。兩個圖形產生了重疊,意味著他們有著一組共同的點, 共享一組坐標 。

而產生碰撞的條件是,兩個圖形必須 至少重合一個點 ,否則將不會產生碰撞。翻譯成計算機能聽懂的話:

“是否能從兩個圖形中,各自找到一個點,使得它們相減后為原點?”

這就是 GJK 算法的核心目的。當兩個圖形發生重疊時,他們 必然會有一個坐標,相減后為原點。

計算機想要“看見”兩個圖形重疊的部分,可以利用自身的計算優勢,把左邊整個圖形所包含的坐標 減去 右邊圖形所包含的坐標,并得到一系列的點。將所有計算后的點包圍起來,如果這個新生成的圖形 包含原點,則意味著兩個圖形發生了重疊,從而判斷兩個圖形發生了碰撞。我們把計算后的點稱為 閔可夫斯基差 ( Minkowski Difference ),將生成的三角形/線形稱為 單純形 ( Simplex )。

為了直觀地理解,我將兩個圖形所有坐標相減后的結果稱為 Minkowski Difference。實際上,似乎只存在 Minkowski Sum (閔可夫斯基和)這個說法。其實也可以理解為,將第二個圖形的所有坐標點取反后,加到第一個圖形的所有坐標點。

將兩個圖形所有的坐標相減,顯然不是我們能夠手算的。但是,我們可以根據多邊形的特點,只需將他們的頂點相減,就可以達成我們的目的。但是這樣,排列組合后,需計算 20 個點,這顯然也不是我們想要的,并且可能會出現多余的計算結果。所以,我們需要盡量得到足夠大的單純形,這樣才會提升包含原點的幾率。

在GJK 算法中,我們定義一個名為 support 的函數。在這個例子中,它的作用是這樣的:

  • 假設初始方向為 ,那么將 黃色 多邊形的所有頂點投影到這個方向上,求出最大點。
  • 再將初始方向取反, 。然后將 藍色 多邊形的所有頂點投影到這個方向上,求出最大點。
  • 獲得的兩個點相減,即可得到兩個圖形的單純形上的一點。
  • 為了便于理解,我們創建兩個多邊形,并且規定

    為藍色圖形的位置坐標, 為黃色圖形的位置坐標,從 指向 為 support 函數的起始方向。我們的目標是至少能夠算出三個點,構成一個包含三個頂點的單純形。

    第一次

    依次按照上述步驟,我們得到這樣的一個結果:

    得到黃色圖形在

    方向上的最大投影點為來自于點 ,記錄坐標 ;得到藍色圖形在 方向 上的最大投影點為來自于點 ,記錄坐標 。

    將兩個坐標相減,得到單純形上的一個頂點 :

    第二次

    然后,我們將初始方向取反,作為新的初始方向,再進行如上的步驟:

    得到黃色圖形在

    方向上的最大投影點為來自于點 ,記錄坐標 ;得到藍色圖形在 方向上的最大投影點為來自于點 ,記錄坐標 。

    將兩個坐標相減,得到單純形上的一個新的頂點 :

    第三次

    之后,我們取與起始向量垂直的向量作為新的方向向量,值得注意的是,這樣的方向向量有兩個,一個是 指向原點的

    ,一個是 背離原點的 。

    我們不妨以先背離原點的

    作為新的方向,重復 support 函數。

    得到黃色圖形在

    方向上的最大投影點為來自于點 ,記錄坐標 ;得到藍色圖形在 方向 上的最大投影點為來自于點 ,記錄坐標 。

    將兩個坐標相減,得到單純形上的一個新的頂點 :

    構造單純形

    我們得到了三個點:

    ,畫出單純形:

    我們似乎沒能構成一個包含原點的單純形。

    如果我們換成

    ,計算后,我們將會得到一個新的點 。畫出這個新的單純形:

    這一次,我們 幸運地 包含了原點!

    從以上幾個步驟,不難看出, GJK 是一種 迭代算法,它需要不斷地檢測單純形是否包含原點。它退出迭代的條件是:

  • 單純形包含原點
  • 單純形最后添加的頂點與搜尋方向點乘小于0
  • 到目前為止,我們離真正實現 GJK 碰撞檢測還有一段距離,以及碰撞之后,如何通過EPA算法,獲得它的穿透向量。這些內容,將在稍后的篇章中詳細介紹。

    總結

    以上是生活随笔為你收集整理的java计算一个多边形的重心_2D凸多边形碰撞检测算法(二) - GJK(上)的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。