レイと球の交差点

ray-sphere.png

レイの定義

(1)
\begin{align} R(t)=P + td\newline t \geq 0 \end{align}

P….レイの原点
d…は正規化した方向ベクトルで長さ1$\|d\|=1$
球の定義は、
C….球の中心
r……球の半径
球の表面に存在するレイとの交差点は以下のように表現できます。

(2)
\begin{align} (P+td-C)\cdot (P+td-C)=r^2 \end{align}

tが何か分かれば、交差点がわかります。
なので、この式をtの2次方程式になるように展開しましょう。

(3)
\begin{align} t^2d\cdot d+2(P-C)td+(P-C)^2=r^2\newline t^2d\cdot d+2(P-C)td+(P-C)^2-r^2=0 \end{align}

dは正規化ベクトルなのでd・d=1なので消せます

(4)
\begin{equation} t^2+2(P-C)td+(P-C)^2-r^2=0 \end{equation}

tに関する2次方程式になりました。
2次方程式の解にあてはめると2次方程式の解はここ

(5)
\begin{align} t=\frac{-2(P-C)d\pm \sqrt{(2(P-C)d)^2-4((P-C)^2-r^2)}}{2}\newline t=-(P-C)d\pm \sqrt{((P-C)d)^2-((P-C)^2-r^2)} \end{align}

またd2が出てきましたが、これも結果が1になるので消せます

(6)
\begin{align} t=-(P-C)d\pm \sqrt{(P-C)^2-((P-C)^2-r^2)} \end{align}

ソースコード

int IntersectRaySphere(Point p,Vector d,Sphere s,float &t,Point &q){
   Vector m = p - s.c;
   float b = Dot(m,d);//2次方程式の係数b
   float c = Dot(m,m) - s.r * s.r;//2次方程式の係数c
   //b>0ならば、レイの方向は球と全く逆の方向に向いている P-C とdのなす角度が90~270の鈍角領域でないと、円の方角にすら向いていないということ
  //c>0ならば、ベクトルP-Cの長さが、円の半径より長いということ、つまりレイの原点が円の外にあるということになります
    if(c>0.0f && b > 0.0f) return 0;//これら2つの条件が重なると、円とレイは交差してません
    float discriminant = b*b -c;
    //もしルートの中身がマイナスならば、円とレイは交差してません
    if(discr < 0.0) return 0;
    //tを求める
    t=b - sqrt(discriminant);
    //tが負ならば、レイの始点が球の内側にあることを意味している
    if(t<0.0f) t = 0.0f;
    q = p + t*d;
    return 1;  
}

サポートサイト Wikidot.com