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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

高级碰撞检测及响应算法——碰撞检测

發(fā)布時(shí)間:2023/12/29 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 高级碰撞检测及响应算法——碰撞检测 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

1.概述

移動(dòng)的物體可以由橢球體近似表達(dá),這種橢球體更容易逼近類人和動(dòng)物的形狀,比如說人的頭,就是一個(gè)X-Y-Z軸半徑相等的橢球體,髖骨,盆骨等都可以較好地用橢球體體現(xiàn)出來。多個(gè)橢球體組成的集合的形狀也使它們易于在障礙物上平滑地移動(dòng),這一點(diǎn)在3D游戲中顯得特別重要,因?yàn)橥婕医^不希望在激烈的戰(zhàn)斗中自己被卡在某個(gè)死角里不能動(dòng)彈。

我們希望能在場景中來回移動(dòng)我們的物體(或者角色)。它可以由一個(gè)橢球體表現(xiàn),其中橢球體的中心位置代表了角色的位置,半徑向量則定義了橢球體沿三個(gè)軸向的尺寸。見圖3.1。

圖3.1:橢球體的半徑向量

通過對角色施加某方向的力,他就能在場景世界中移動(dòng)。這個(gè)過程由速度向量(velocity vector)表示。我們希望橢球體能夠在場景世界中移動(dòng),那么它的新的位置等于它當(dāng)前位置加上速度向量。見圖3.2。

圖3.2:通過一個(gè)速度移動(dòng)橢球體

但是我們還不清楚我們是否能成功完成這個(gè)移動(dòng),因?yàn)榭赡茉谶^程中會(huì)出現(xiàn)一些事情,例如組成場景世界的一個(gè)或者多個(gè)三角片擋住了橢球體的去路。我們不可能事先準(zhǔn)確地知道橢球體會(huì)撞上哪個(gè)三角片,所以我們應(yīng)該檢查所有的三角片(這里,可以將一個(gè)大的網(wǎng)格體化分成一個(gè)八叉樹,這個(gè)八叉樹被用來幫助我們檢查那些靠近角色的三角片)。同時(shí),我們還不能在檢測到一個(gè)可能碰撞的三角片后就立即停止檢測,因?yàn)槲覀円獧z測出所有潛在的障礙,近而找出最近的那一個(gè)碰撞。如果我們檢測到了一個(gè)與三角片A發(fā)生的碰撞后就停止,而沒有繼續(xù)檢測其它的三角片,例如三角片B,那么將發(fā)生如圖3.3所示的情況,即三角片B比三角片A更先發(fā)生碰撞。

圖3.3:必須檢測所有的三角片

碰撞檢測過程應(yīng)該為后繼的響應(yīng)階段提供至少兩個(gè)必要的信息:

?? *?? 球體在場景中的碰撞位置。

?? *?? 球體發(fā)生碰撞之前,沿速度方向到碰撞點(diǎn)的距離。

所以,對于單個(gè)三角片的碰撞檢測,我們首先要清楚是否會(huì)發(fā)生碰撞(這將產(chǎn)生一個(gè)bool值),如果發(fā)生了碰撞,算法應(yīng)該能夠?yàn)榕鲎岔憫?yīng)提供上述兩個(gè)必要的信息。

2.單個(gè)三角片的檢測

在e空間中,有一個(gè)三角片,它由p1,p2和p3三個(gè)頂點(diǎn)所定義,它們以順時(shí)鐘排序。另外有一個(gè)球體,它位于基點(diǎn),basePoint,并正沿著它的速度方向運(yùn)動(dòng),速度大小為velocity。如果我們用 t 作為自變量,用方程表達(dá)球體的運(yùn)動(dòng)過程,那么我們有球體的位置方程:

在三維空間中,一個(gè)球體可以由它的位置和半徑唯一表示(在e空間中半徑是1)。對于運(yùn)動(dòng)的球體,半徑是常數(shù)但是位置是不斷變化的。上面的公式給出了球體在任何時(shí)刻 t 的位置,這就是所謂的掃掠球(swept sphere)。圖3.4表示了這種關(guān)系,這一點(diǎn)很重要。由于velocity的大小不清楚,但它與時(shí)間的乘積直接影響著掃掠球的位置,而掃掠球每次所作的檢測只在一個(gè)velocity的長度范圍內(nèi)。那么問題可以轉(zhuǎn)化為:能否在一個(gè)[ 0,velocity ]范圍內(nèi)找到碰撞的情況,或者說能否在[0,1]的范圍內(nèi),找到能滿足碰撞特征的t值。在此過程中,解二次方程所得到的t 值的情況,跟velocity的大小有關(guān),圖3.9說明了這種關(guān)系。

圖3.9:速度大小與碰撞的可能情況

同時(shí),對于當(dāng)前掃掠球的位置而言,可能與它所面對的三角片發(fā)生5種關(guān)系。具體來講:

?? ***?? 當(dāng)VN=0時(shí),此時(shí)球體平行于平面運(yùn)動(dòng),球體中心到平面的距離要么為1, 要么小于等于1。對于前一種情況,檢測提前退出;對于后一種情況,顯然在t[0,1]范圍內(nèi)的所有球體位置中,球體與平面均保持相交。

?? ***?? 當(dāng)VN不等于0時(shí),此時(shí)球體總會(huì)與平面發(fā)生碰撞(前提是速度方向有正對平面正面的分量),其形式無非有4種。第一種就是與三角片平面相交,但是不與三角片相交。

?? ***?? 球體與三角片內(nèi)部某點(diǎn)相交。

?? ***?? 球體與三角片某頂點(diǎn)相交。

?? ***?? 球體與三角片某邊緣相交。

圖3.4:球體的位置方程

算法的檢測程序就從這里開始。其功能是用檢測函數(shù)將一個(gè)掃掠球信息體(空間速度與位置、碰撞是否發(fā)生、什么地方發(fā)生和發(fā)生距離等)與單個(gè)三角片信息體(主要是三個(gè)頂點(diǎn)坐標(biāo)信息)進(jìn)行碰撞檢測。并不斷循環(huán)調(diào)用該函數(shù),同時(shí)更換函數(shù)中的三角片信息體,使當(dāng)前掃掠球與所有的三角片都被檢測到,最后整理并填入掃掠球信息體中的碰撞信息,并在響應(yīng)過程中更新速度與位置信息。

下面,第一個(gè)任務(wù)是檢測掃掠球是否與三角片所在的平面相交。如果不相交,掃掠球當(dāng)然不會(huì)跟三角片相交。所以我們構(gòu)造一個(gè)平面,叫三角片平面trianglePlane,它是由三角片的三個(gè)頂點(diǎn)所確定的平面。如果我們有單位化的平面法向量N和平面常數(shù)Cp,那么我們可以計(jì)算點(diǎn)p到平面的有符號距離(signed distance):

圖3.5可以看出該方法的原理。

圖3.5:點(diǎn)p到平面的有符號距離的計(jì)算

圖中OP為p點(diǎn)的方向向量,圖中OI線段是N?p的絕對值,Cp是ON段所表示的距離,兩者之和為p點(diǎn)到三角片平面的符號距離。之所以叫符號距離,是因?yàn)楫?dāng)點(diǎn)p位于三角片的正面區(qū)域(即法向量所指的一側(cè))時(shí),該距離為正值;如果點(diǎn)p位于三角片的反面區(qū)域,該距離為負(fù)值。

如果掃掠球與三角片平面相交,如果速度大小剛好合適,那么總存在一個(gè)時(shí)刻 t0,掃掠球剛好位于平面的“前邊”(front side),此時(shí)掃掠球(中心點(diǎn))到三角片平面的有符號距離剛好為1;如果速度足夠大,則它會(huì)穿越三角片平面,在某時(shí)刻 t1,它剛好位于平面"后邊"(back side),則在時(shí)間t∈[t0,t1]上,掃掠球與平面處于相交狀態(tài)。那么我們可以這樣計(jì)算時(shí)刻 t0:

時(shí)刻 t1 是掃掠球到三角片平面的有符號距離剛好為-1時(shí)的時(shí)間點(diǎn)。同樣,我們可以得到 t1:

如果 t0和 t1都不在[0,1]的范圍內(nèi),即不在一次掃掠檢測范圍內(nèi),那么我們可以知道在速度方向上,掃掠球沒有(或者說還沒有)跟平面相交,于是不可能與三角片相交。否則,我們知道碰撞應(yīng)該發(fā)生在時(shí)刻tcollisoin∈[t0,t1]。注意有一個(gè)特殊情況,如果N*velocity=0——那么我們不能使用上面的公式。但是這種情況在什么時(shí)候發(fā)生呢?它發(fā)生在速度向量垂直于平面法向量,或者說球體平行于平面運(yùn)動(dòng)的時(shí)候。這種情況下,有兩種可能,一種是從basePoint點(diǎn)到三角片平面的絕對距離小于1,即嵌入三角片平面中。如果是這樣,我們直接將變量設(shè)為:t0=0、t1=1,那么掃掃掠球?qū)⒃谝淮螜z測范圍內(nèi)總是與平面相交。另一種是絕對距離大于1,那么我們知道碰撞不可能發(fā)生,可以提前結(jié)束檢測。

既然我們知道了兩個(gè)時(shí)刻 t0和 t1的值(可能兩個(gè)值相同),那么出現(xiàn)了三種潛在的碰撞情況:

?? *?? 在三角片內(nèi)碰撞。

?? *?? 與三角片其中一個(gè)頂點(diǎn)碰撞。

?? *?? 與三角片其中一條邊緣碰撞。

3.三角片內(nèi)碰撞

這種碰撞情況最常見(當(dāng)然取決于三角片的面積),如果掃掠球確實(shí)在三角片內(nèi)部相交,那么可以說與頂點(diǎn)或者邊緣的碰撞幾率將變得很小,所以如果我們能快速地檢測出發(fā)生在三角片內(nèi)的碰撞,那么我們將節(jié)約大量的用于檢測發(fā)生在頂點(diǎn)或者邊緣的碰撞情況的時(shí)間。所以,我們先看這種情況。注意,這種情況只會(huì)發(fā)生在球體并沒有嵌入平面的時(shí)候,即N*velocity≠0時(shí)。一個(gè)嵌入到平面的球體只可能與頂點(diǎn)或者邊緣碰撞,就像游泳的人只能撞到島嶼的邊緣或者頂角一樣。

這里,主要計(jì)算出平面上的球體的接觸點(diǎn),我們將它叫作planeIntersectionPoint。我們已經(jīng)知道接觸發(fā)生在時(shí)刻 t0,該時(shí)刻是球體位于平面前邊的臨界時(shí)刻,但是這個(gè)接觸點(diǎn)究竟在平面上哪個(gè)位置?這個(gè)平面接觸點(diǎn)用如下的公式計(jì)算:

圖3.6解釋了這個(gè)公式的具體意義。球體上首先撞擊平面的點(diǎn)由basePoint-planeNormal給出,接觸點(diǎn)發(fā)生在時(shí)刻t0。

圖3.6:三角片平面上的交點(diǎn)

現(xiàn)在我們要做的就是檢查planeIntersectionPoint是否在三角片內(nèi)部。有很多種函數(shù)方法完成這個(gè)功能。如果點(diǎn)在三角片內(nèi),那么我們得到了碰撞檢測的結(jié)論:

?? *?? 三角片平面上的交點(diǎn)就是三角片內(nèi)的碰撞點(diǎn),intersectionPoint=planeIntersectionPoint

?? *?? 速度方向上,當(dāng)前位置與發(fā)生碰撞的位置之間的距離,intersectionDistance=t0*|velocity|

4.掃掠測試(the sweep test)

如果球體沒有碰撞三角片內(nèi)部,那么我們不得不進(jìn)行掃掠測試,從而判斷是否與三角片的頂點(diǎn)或者邊緣碰撞。這種情況下,主要的問題是檢查是否存在一個(gè)時(shí)刻t,t∈[t0,t1]。在這個(gè)時(shí)刻點(diǎn),掃掠球與頂點(diǎn)或者邊緣發(fā)生了碰撞。

我們先看兩種最簡單的情況——掃掠球與一個(gè)頂點(diǎn)p碰撞。掃掠球與頂點(diǎn)的碰撞發(fā)生在什么時(shí)候呢?如果掃掠球中心與頂點(diǎn)之間的距離為1,那么認(rèn)為兩者發(fā)生了碰撞。為了便于計(jì)算,當(dāng)球中心與頂點(diǎn)中心的距離的平方是1時(shí)發(fā)生碰撞。我們可以先定義一個(gè)等式:

上面的式子可以化為一個(gè)二次方程的形式:

這里,

二次方程通常有兩個(gè)解,這在此例中是有意義的。掃掠球與頂點(diǎn)的距離為1的時(shí)間點(diǎn)可能有兩個(gè)——三角片的正面與反面都存在這個(gè)時(shí)間點(diǎn)。我們關(guān)心的是與頂點(diǎn)的第一個(gè)碰撞(或者說最先與之發(fā)生的碰撞),所以我們?nèi)∽钚≈?#xff08;因?yàn)榻饩褪桥鲎驳臅r(shí)間值)。如果有了合法的最小解x1,那么我們所需的交點(diǎn)數(shù)據(jù)可以得到:

intersectPoint = p

intersectionDistance=x1*|velocity|

即使與頂點(diǎn)發(fā)生了碰撞,我們?nèi)匀灰獧z測三角片的邊緣,看是否可能在更短的時(shí)間點(diǎn)時(shí),與某一個(gè)片邊緣發(fā)生了碰撞。這種檢測比檢測頂點(diǎn)碰撞更復(fù)雜,但是在本質(zhì)上是一樣的。考慮由p1到p2的邊緣,令

首先我們檢測是否存在某時(shí)間點(diǎn),掃掠球與一條沿著邊緣方向的直線(infinite line)發(fā)生碰撞。這種情況發(fā)生在掃描球中心與無窮線的距離為1時(shí)。圖3.7描述了這種情況。

?圖3.7:掃掠球與邊緣所在直線碰撞這個(gè)關(guān)系也可以得到一個(gè)二次方程,其中的方程變量系數(shù)為:

?如果該方程有最小值x1,那么我們知道掃掠球會(huì)與直線相交于同一點(diǎn),但是我們還不知道這個(gè)點(diǎn)是否在三角邊的邊緣線段內(nèi)。所以,如果我們用函數(shù) f 來描述直線L,使得L(f0),那么L(0)=p1,L(1)=p2,圖3.8說明了f0的意義。

圖3.8:判斷交點(diǎn)是否在邊緣線段內(nèi)

于是我們可以在直線上能過計(jì)算f0 判斷交點(diǎn)是否在邊緣線段內(nèi):

如果f0∈[0,1],那么交點(diǎn)在邊緣線段中,并且在時(shí)刻x1球碰撞了三角片的邊緣。有關(guān)交點(diǎn)的數(shù)據(jù)如下:

intersectionPoint=p1+f0*edge

intersetionDistance=x1*|velocity|

5.總結(jié)

以上就是碰撞檢測部分的全部內(nèi)容。總結(jié)一下整個(gè)流程:

?? *?? 首先計(jì)算三角片平面

?? *?? 然后找出掃掠球與三角片平面相交的時(shí)間點(diǎn) t0和 t1

?? *?? 接下來檢測發(fā)生在三角片內(nèi)部的碰撞。由于安排在頂點(diǎn)或者邊緣碰撞的前面,所以我們可以節(jié)省下掃掠測試的時(shí)間

?? *?? 然后,我們將球體掃掠三角片的頂點(diǎn)和邊緣

?? *?? 完成以上步驟,我們就知道是否發(fā)生碰撞(bool),在哪里發(fā)生碰撞(intersectionPoint),距離如何(intersectionDistance),于是我們可以找出最先發(fā)生的那個(gè)碰撞

?? *?? 繼續(xù)檢測下一個(gè)三角片直到所有的三角片都被檢測,最后可知道角色有沒有碰撞,與哪些三角片以何種形式碰撞,以及最先的碰撞是哪個(gè)。

總結(jié)

以上是生活随笔為你收集整理的高级碰撞检测及响应算法——碰撞检测的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。