绝地无双
取E是射线的起点,L是射线的终点,C是你要测试的球体的中心r是那个球体的半径计算:d=L-E(射线的方向矢量,从头到尾)f=E-C(从中心球到射线起始的矢量)然后交叉口被.。堵塞:P=E+t*d这是一个参数方程:Px=Ex+TDxPy=Ey+TDy进(X-h)2+(y-k)2=r2(h,k)=圆心。注意:我们将问题简化为2D,我们得到的解决方案也适用于3D得到:扩张x2-2xh+h2+y2-2yk+k2-r2 = 0塞子X=ex+TDxY=ey+TDy(E)x+TDx )2-2(E)x+TDx)h+h2+(E)y+TDy )2-2(E)y+TDy)k+k2-r2 = 0爆炸ex2+2Ex白破疫苗x+t2dx2-2exH-2TdxH+h2+ey2+2Ey白破疫苗y+t2dy2-2eyK-2tdyK+k2-r2 = 0群t2(D)x2+dy2)+2t(E)xdx+eydy-dx氢-dyk)+ex2+ey2-2ex氢-2eyK+h2+k2-r2 = 0最后,t2(_d*_d)+2t(_e*_d-_d*_c)+_e*_e-2(_e*_c)+_c*_c-r2 = 0*其中_d是向量d,*是点积。然后,t2(_d*_d)+2t(_d*(_e-c)+(_e-c)*(_e-c)-r2 = 0让f=_e-_ct2(_d*_d)+2t(_d*_f)+_f*_f-r2 = 0所以我们得到:t2*(D DOT D)+2t*(F DOT D)+(f DOT f-r)2 ) = 0所以解二次方程:float a = d.Dot( d ) ;
float b = 2*f.Dot( d ) ;
float c = f.Dot( f ) - r*r ;
float discriminant = b*b-4*a*c;
if( discriminant < 0 )
{
// no intersection
}
else
{
// ray didn't totally miss sphere,
// so there is a solution to
// the equation.
discriminant = sqrt( discriminant );
// either solution may be on or off the ray so need to test both
// t1 is always the smaller value, because BOTH discriminant and
// a are nonnegative.
float t1 = (-b - discriminant)/(2*a);
float t2 = (-b + discriminant)/(2*a);
// 3x HIT cases:
// -o-> --|--> | | --|->
// Impale(t1 hit,t2 hit), Poke(t1 hit,t2>1), ExitWound(t1<0, t2 hit),
// 3x MISS cases:
// -> o o -> | -> |
// FallShort (t1>1,t2>1), Past (t1<0,t2<0), CompletelyInside(t1<0, t2>1)
if( t1 >= 0 && t1 <= 1 )
{
// t1 is the intersection, and it's closer than t2
// (since t1 uses -b - discriminant)
// Impale, Poke
return true ;
}
// here t1 didn't intersect so we are either started
// inside the sphere or completely past it
if( t2 >= 0 && t2 <= 1 )
{
// ExitWound
return true ;
}
// no intn: FallShort, Past, CompletelyInside
return false ;
}