Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to do ray plane intersection?

Tags:

c++

raytracing

How do I calculate the intersection between a ray and a plane?

Code

This produces the wrong results.

float denom = normal.dot(ray.direction);

if (denom > 0)
{
    float t = -((center - ray.origin).dot(normal)) / denom;

    if (t >= 0)
    {
        rec.tHit = t;
        rec.anyHit = true;
        computeSurfaceHitFields(ray, rec);
        return true;
    }
}

Parameters

ray represents the ray object.
ray.direction is the direction vector.
ray.origin is the origin vector.
rec represents the result object.
rec.tHit is the value of the hit.
rec.anyHit is a boolean.

My function has access to the plane:
center and normal defines the plane

like image 301
Pontus Magnusson Avatar asked May 31 '14 23:05

Pontus Magnusson


People also ask

How do you know if two rays intersect?

In 2D, you have to check the slope. If the slope is not equal then they intersect. If the slope is equal, they intersect if a point on them has the same x-coordinate or the same y-coordinate.

What is an intersecting ray?

For lines, rays, and line segments, intersect means to meet or cross. When two lines, rays, or line segments intersect, they have one common point.

What is the intersection of 2 intersecting planes?

The intersection of two planes is a line. If the planes do not intersect, they are parallel. They cannot intersect at only one point because planes are infinite.


3 Answers

As wonce commented, you want to also allow the denominator to be negative, otherwise you will miss intersections with the front face of your plane. However, you still want a test to avoid a division by zero, which would indicate the ray being parallel to the plane. You also have a superfluous negation in your computation of t. Overall, it should look like this:

float denom = normal.dot(ray.direction);
if (abs(denom) > 0.0001f) // your favorite epsilon
{
    float t = (center - ray.origin).dot(normal) / denom;
    if (t >= 0) return true; // you might want to allow an epsilon here too
}
return false;
like image 166
Trillian Avatar answered Oct 22 '22 10:10

Trillian


First consider the math of the ray-plane intersection:

In general one intersects the parametric form of the ray, with the implicit form of the geometry.

So given a ray of the form x = a * t + a0, y = b * t + b0, z = c * t + c0;

and a plane of the form: A x * B y * C z + D = 0;

now substitute the x, y and z ray equations into the plane equation and you will get a polynomial in t. you then solve that polynomial for the real values of t. With those values of t you can back substitute into the ray equation to get the real values of x, y and z. Here it is in Maxima:

enter image description here

Note that the answer looks like the quotient of two dot products! The normal to a plane is the first three coefficients of the plane equation A, B, and C. You still need D to uniquely determine the plane. Then you code that up in the language of your choice like so:

Point3D intersectRayPlane(Ray ray, Plane plane)
{
    Point3D point3D;

    //  Do the dot products and find t > epsilon that provides intersection.


    return (point3D);
}
like image 8
vwvan Avatar answered Oct 22 '22 09:10

vwvan


implementation of vwvan's answer

Vector3 Intersect(Vector3 planeP, Vector3 planeN, Vector3 rayP, Vector3 rayD)
{
    var d = Vector3.Dot(planeP, -planeN);
    var t = -(d + Vector3.Dot(rayP, planeN)) / Vector3.Dot(rayD, planeN);
    return rayP + t * rayD;
}
like image 4
Bas Smit Avatar answered Oct 22 '22 10:10

Bas Smit