射線與球的相交

今天來(lái)說(shuō)說(shuō)射線和球的相交檢測(cè)。

從圖形來(lái)說(shuō)

![射線和圓相交, origin是射線起點(diǎn)奶甘, dir是射線的方向向量篷店。p0,p1是兩個(gè)交點(diǎn)臭家,center為圓心疲陕,半徑為R,d為圓心到射線的距離][ray-sphere]

我們先以2D切面圖來(lái)說(shuō)明钉赁,當(dāng)射線和圓相交的時(shí)候蹄殃,可以看到,球心 center 到射線 ray 的距離 d <= R你踩,這個(gè)即為相交的條件诅岩。那么射線與球相切就轉(zhuǎn)化為了球心到射線的距離d的判斷。先求出d:

  1. 設(shè)圓心在射線上的投影為c'带膜,則 origin吩谦,center, c' 形成了一個(gè)直角三角形。
  • 獲得射線起點(diǎn)到圓心的向量 Voc = Vcenter - Vorigin
  • 在射線方向上的投影為: Poc= Voc·(Voc·dir)
  • 勾股定理:d·d = Voc·Voc - Poc·Poc

可以求出d的數(shù)值膝藕,

  • d < R式廷,射線穿過(guò)圓,與圓有兩個(gè)交點(diǎn)芭挽。
  • d = R滑废,射線與圓相切,有一個(gè)交點(diǎn)為切點(diǎn)览绿。
  • d > R,射線在圓外穗慕,沒(méi)有交點(diǎn)饿敲。

接下來(lái)求P0,P1:

  1. c'逛绵,center怀各,P0 or P1點(diǎn)構(gòu)成直角三角形倔韭。
  • P0 or P1到c'的距離 tca·tca = R·R - d·d;
  • 有如下式子
P0 = dir·( |Poc| - tca );
P1 = dir·( |Poc| + tca );

要注意,沒(méi)有交點(diǎn)的時(shí)候瓢对, tca·tca < 0 是沒(méi)辦法開(kāi)平方的
推導(dǎo)三維情況可以照上面的去做寿酌,dot能保證投影點(diǎn)在同一個(gè)平面上的。

附代碼

bool Intersect(const Ray& ray, const Sphere& sphere, float& t0, float& t1)
{
    Vector3 oc = sphere.GetCenter() - ray.GetOrigin();
    float projoc = dot(ray.GetDirection(), oc);

    if (projoc < 0)
        return false;

    float oc2 = dot(oc, oc);
    float distance2 = oc2 - projoc * projoc;

    if (distance2 > sphere.GetRadiusSquare())
        return false;

    float discriminant = sphere.GetRadiusSquare() - distance2;
    if(discriminant < FLOAT_EPSILON)
        t0 = t1 = projoc;
    else
    {
        discriminant = sqrt(discriminant);
        t0 = projoc - discriminant;
        t1 = projoc + discriminant;
        if (t0 < 0)
            t0 = t1;
    }
    return true;
}

從方程角度來(lái)看

射線方程:ray : P(t) = O + D·t ( t >= 0 )
球的方程:sphere : sqr( P-C ) = R·R (sqr(x) = x^2 = x·x)

O=origin, D=direction, C=center, R=radius

射線方程表明的是如下一個(gè)點(diǎn)的集合P硕蛹,當(dāng)t從零增大時(shí), D·t會(huì)沿著D向量的方向從零逐步變長(zhǎng)醇疼,t 取值無(wú)限表示了射線單方向。從O點(diǎn)開(kāi)始在D方向上無(wú)限個(gè)點(diǎn)構(gòu)成了一條射線法焰。
球的方程表明了任何點(diǎn)P秧荆,只要到C點(diǎn)的距離等于半徑R,則表明點(diǎn)在球面上埃仪,這么一個(gè)球面上的點(diǎn)的集合乙濒。
因此當(dāng)射線與球相交的時(shí)候,這個(gè)點(diǎn)既在射線上卵蛉,又在球面上颁股。等式射線的P(t) = 球的P成立。

聯(lián)立兩個(gè)方程傻丝,試著求解 t 有:

sqr( O + D·t - C ) = R·R

設(shè) O-C=OC甘有,有:

sqr( OC+D·t ) - R·R = 0
//展開(kāi)得到如下式子
=> D·D·t·t + 2·OC·D·t + OC·OC - R·R = 0
=> (D·D)·t·t + 2·(OC·D)·t + OC·OC - R·R = 0

因?yàn)?D 是單位向量有D·D = dot(D, D) = 1最后方程為:

t·t + 2·(OC·D)·t +  OC·OC - R·R = 0;

這是一個(gè)關(guān)于 t 的二次方程at^2 + bt + c = 0那么解就已經(jīng)出來(lái)了:

  • t0 = -(b + √Δ) / 2a
  • t1 = -(b - √Δ) / 2a
  • a = D·D = dot(D, D) = 1;
  • b = 2·OC·D = 2·dot(OC, D);
  • c = OC·OC - R·R = dot(OC, OC) - R·R;
  • 判別式 Δ = sqr(b) - 4ac
    = 4·sqr( OC·D ) - 4·( OC·OC - R·R )
    = 4·( sqr( OC·D ) - OC·OC + R·R );
    如果判別式 Δ > 0,則表明球與射線相交桑滩。

根據(jù)以上方程梧疲,我們其中試著展開(kāi) t 的式子
t0 = -(b + √Δ) / 2a = -(b + √Δ) / 2·1
= -b/2 - √(Δ/4)
= -dot(OC, D) - √( sqr( dot(OC, D) ) - dot(OC, OC) + R·R )

求出 t 后可以根據(jù) P(t) = O + D * t 得到交點(diǎn)。

附代碼

bool Intersect(const Ray& ray, const Sphere& sphere, float& t0, float& t1)
{
    Vector3 oc = ray.GetOrigin() - sphere.GetCenter();
    float dotOCD = dot(ray.GetDirection(), oc);

    if (dotOCD > 0)
        return false;

    float dotOC = dot(oc, oc);
    float discriminant = dotOCD*dotOCD - dotOC + sphere.GetRadiusSquare();

    if (discriminant < 0)
        return false;
    else if (discriminant < FLOAT_EPISLON)
        t0 = t1 = -dotOCD;
    else
    {
        discriminant = sqrt(discriminant);
        t0 = -dotOCD - discriminant;
        t1 = -dotOCD + discriminant;
        if (t0 < 0)
            t0 = t1;
    }
    return true;
}

補(bǔ)充一些內(nèi)容:

交點(diǎn)的法線

因?yàn)榻稽c(diǎn)在球面上运准,球面法線反向是從球心指向球面的點(diǎn)幌氮。
設(shè)交點(diǎn)為 IntersecionP,只需要簡(jiǎn)單的計(jì)算:

normal = ( IntersectionP - sphere.GetCenter() ).Normalize();
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末胁澳,一起剝皮案震驚了整個(gè)濱河市该互,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌韭畸,老刑警劉巖宇智,帶你破解...
    沈念sama閱讀 211,817評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異胰丁,居然都是意外死亡随橘,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,329評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門(mén)锦庸,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)机蔗,“玉大人,你說(shuō)我怎么就攤上這事÷茑遥” “怎么了梆掸?”我有些...
    開(kāi)封第一講書(shū)人閱讀 157,354評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)牙言。 經(jīng)常有香客問(wèn)我酸钦,道長(zhǎng),這世上最難降的妖魔是什么咱枉? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,498評(píng)論 1 284
  • 正文 為了忘掉前任卑硫,我火速辦了婚禮,結(jié)果婚禮上庞钢,老公的妹妹穿的比我還像新娘拔恰。我一直安慰自己,他們只是感情好基括,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,600評(píng)論 6 386
  • 文/花漫 我一把揭開(kāi)白布颜懊。 她就那樣靜靜地躺著,像睡著了一般风皿。 火紅的嫁衣襯著肌膚如雪河爹。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 49,829評(píng)論 1 290
  • 那天桐款,我揣著相機(jī)與錄音咸这,去河邊找鬼。 笑死魔眨,一個(gè)胖子當(dāng)著我的面吹牛媳维,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播遏暴,決...
    沈念sama閱讀 38,979評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼侄刽,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了朋凉?” 一聲冷哼從身側(cè)響起州丹,我...
    開(kāi)封第一講書(shū)人閱讀 37,722評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎杂彭,沒(méi)想到半個(gè)月后墓毒,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,189評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡亲怠,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,519評(píng)論 2 327
  • 正文 我和宋清朗相戀三年所计,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片团秽。...
    茶點(diǎn)故事閱讀 38,654評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡主胧,死狀恐怖钾腺,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情讥裤,我是刑警寧澤,帶...
    沈念sama閱讀 34,329評(píng)論 4 330
  • 正文 年R本政府宣布姻报,位于F島的核電站己英,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏吴旋。R本人自食惡果不足惜损肛,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,940評(píng)論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望荣瑟。 院中可真熱鬧治拿,春花似錦、人聲如沸笆焰。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,762評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)嚷掠。三九已至捏检,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間不皆,已是汗流浹背贯城。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,993評(píng)論 1 266
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留霹娄,地道東北人能犯。 一個(gè)月前我還...
    沈念sama閱讀 46,382評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像犬耻,于是被迫代替她去往敵國(guó)和親踩晶。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,543評(píng)論 2 349

推薦閱讀更多精彩內(nèi)容