Ray Sphere Intersection
To perform a ray-sphere intersection test we need:
- A ray with a known point of origin
, and direction vector
.
- a sphere with a known centre at a point
and a known radius r
- A ray with a known point of origin
Contents |
Mathematical Formulation
Given the above mentioned sphere, a point
lies on the surface of the sphere if
Given a ray with a point of origin
, and a direction vector
:
we can find the t at which the ray intersects the sphere by setting ray(t) equal to
To solve for t we first expand the above into a more recognisable quadratic equation form
or
- At2 + Bt + C = 0
where
which can be solved using a standard quadratic formula.
Note that in the absence of positive, real, roots, the ray does not intersect the sphere.
Practical Simplification
In a renderer, we often differentiate between world space and object space. In the object space of a sphere it is centred at origin, meaning that if we first transform the ray from world space into object space, the mathematical solution presented above can be simplified significantly.
If a sphere is centred at origin, a point
lies on a sphere of radius r2 if
and we can find the t at which the (transformed) ray intersects the sphere by
According to the reasoning above, we expand the above quadratic equation into the general form
- At2 + Bt + C = 0
which now has coefficients:
Solving the Quadratic Equation
There are two possible solutions to the quadratic equation:
Firstly, if the discriminant is negative, i.e. (B2 − 4AC) < 0, we know that there are no real roots, and consequently we also know that the ray has missed the sphere.
To avoid poor numeric precision when
t0 and t1 can be rewritten:
where
External Links
Example Code
The following C++ code snippet is an example how the simplified version of the ray/sphere intersection described above might be implemented. Note that it assumes the ray has already been transformed into object space, and be aware that the code below is not necessarily the most efficient implementation available!
bool SpherePrimitive::intersect(const Ray& ray, float* t)
{
//Compute A, B and C coefficients
float a = dot(ray.d, ray.d);
float b = 2 * dot(ray.d, ray.o);
float c = dot(ray.o, ray.o) - (r * r);
//Find discriminant
float disc = b * b - 4 * a * c;
// if discriminant is negative there are no real roots, so return
// false as ray misses sphere
if (disc < 0)
return false;
// compute q as described above
float distSqrt = sqrtf(disc);
float q;
if (b < 0)
q = (-b - distSqrt)/2.0;
else
q = (-b + distSqrt)/2.0;
// compute t0 and t1
float t0 = q / a;
float t1 = c / q;
// make sure t0 is smaller than t1
if (t0 > t1)
{
// if t0 is bigger than t1 swap them around
float temp = t0;
t0 = t1;
t1 = temp;
}
// if t1 is less than zero, the object is in the ray's negative direction
// and consequently the ray misses the sphere
if (t1 < 0)
return false;
// if t0 is less than zero, the intersection point is at t1
if (t0 < 0)
{
t = t1;
return true;
}
// else the intersection point is at t0
else
{
t = t0;
return true;
}
}
- This page was last modified 11:36, 27 September 2006.
- This page has been accessed 46,289 times.
- Content is available under GNU Free Documentation License.
- About CGWiki
- Disclaimers
