//
-------------------------------------------------------------------------
eiBool eiSphere::intersect(eiRay
*
ray, eiObject
*
po, eiFloat
&
oldt,
eiPrimitive
* &
ret_pri, eiFloat
*
cust_data,
HitParam
*
hparam)

{
if( oldt == 0.0f || ray_box( ray->src, hparam->hitPoint )

{
//compute intersecting point

eiVector oc = add( ray->src, - center );
eiFloat oc_len = dist( oc );
if( oc_len > radius || po->material->doubleSide )

{
eiFloat a = dot( ray->dir, ray->dir );
eiFloat b = 2.0f * dot( oc, ray->dir);
eiFloat c = dot( oc, oc ) - RR;
eiFloat dt = b * b - 4.0f * a * c;

eiFloat t;

if(a == 0.0f || dt < 0.0f)
return false;
else if(dt == 0.0f)

{
t = - b / a * 0.5f;

if(t < 0.0f)
return false;
}
else

{
a = 0.5f / a;
eiFloat t1 = (- b + sqrtf( dt )) * a;
eiFloat t2 = (- b - sqrtf( dt )) * a;

if(t1 > 0.0f && t2 < 0.0f)
t = t1;
else if(t1 < 0.0f && t2 > 0.0f)
t = t2;
else if(t1 > 0.0f && t2 > 0.0f)
t = (t1 < t2) ? t1 : t2;
else
return false;
}

eiVector tmpIntersection = add(ray->src, mulvf(ray->dir,t));

//affect shadow factor

if(ray->type == RAY_SHADOW)
hparam->shadow_factor *= 1.0f - po->material->opacity;

//find nearest hit point

if(oldt == 0.0f || t < oldt)

{
hparam->hitPoint = tmpIntersection;
hparam->hitObj = po;
ret_pri = this;
oldt = t;

//fill custom data

return true;
}
}
}

return false;
}
转载于:https://www.cnblogs.com/len3d/archive/2005/07/28/202305.html