円と光線(レイ)から交点を求める:C++コード

最初に

C++で書かれた、円(球体)と光線(レイ)から交点を求めるコードです。1次元増やせば球体にも使えます。

情報

【楽天ブックスならいつでも送料無料】ゲームプログラミングのためのリアルタイム衝突判定 [ ク…177P

C++コード

#include 
#include 
//-----------------------------------------------------------------------------------
//! @brief 光線が円に対して交差しているかどうか。
//! @param [in]  c     円
//! @param [in]  vPos  基点
//! @param [in]  vDir  方向ベクトル
//! @param [out] out1  接触点1
//! @param [out] out2  接触点2
//! @return 交差している場合、交差点の数を返す
//-----------------------------------------------------------------------------------
int IntersectRayCircle(
    const mcCircle& c,
    const mcVector2& vPos,
    const mcVector2& vDir,
    mcVector2 &out1,
    mcVector2 &out2)
{
    float t;
    mcVector2 vM = vPos - c.c;
    float a = vM.Dot(vDir);
    float b = vM.Dot() - c.r * c.r;
    // 光線の原点が円の外側にあり(c > 0)、
    // 光線が円から離れていく方向を指している場合(a > 0)交点は存在しない
    if (b > 0 && a > 0) return 0;
    float discr = a*a - b;
    // 必ず誤差問題が発生するのでイプシロン値使用する
    if( abs(discr) <= FLT_EPSILON ) discr = 0;
    // 負の判別式は光線が円を外れている
    if (discr < 0) return 0;
    // これで光線は円と交差していることが分かり、交差する最小の値 t を計算
    t = -a - sqrt(discr);
    // tが負である場合、光線は円の内側
    if (t < 0) {
        out1 = vPos + (t*-1) * vDir;
        return 1;
    }
    else if (discr == 0) {
        out1 = vPos + t * vDir;
        return 1;
    }
    out1 = vPos + t * vDir;
    out2 = vPos + (-a + sqrt(discr)) * vDir;
    return 2;
}

オンライン実行

コメント 

コメントを残す

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください