最初に
C++で書かれた、円(球体)と光線(レイ)から交点を求めるコードです。1次元増やせば球体にも使えます。
情報
【楽天ブックスならいつでも送料無料】ゲームプログラミングのためのリアルタイム衝突判定 [ ク…177P
C++コード
#include <cmath>
#include <cfloat>
//-----------------------------------------------------------------------------------
//! @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;
}
オンライン実行
関連