How to do ray plane intersection?

亡梦爱人 提交于 2019-11-27 13:06:40

问题


How do I calculate the intersection between a ray and a plane? I have been visiting every possible website I can find and this is what I have achieved so far:

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;
    }
}

This does not work :s
My function input is:
ray: that contains origin and direction.
rec: a container class for storing hit information (bool, t, etc)

My function has access to the plane:
point: the point that defines the plane
normal: the normal that defines the plane


回答1:


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;



回答2:


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:

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);
}



回答3:


implementation of vwvan's answer

Vector3 Intersect(Vector3 planeP, Vector3 planeN, Vector3 rayP, Vector3 rayD)
{
    var d = Vector3.Dot(planeP, -planeN);
    var t = -(d + rayP.z * planeN.z + rayP.y * planeN.y + rayP.x * planeN.x) / (rayD.z * planeN.z + rayD.y * planeN.y + rayD.x * planeN.x);
    return rayP + t * rayD;
}



回答4:


Let the ray be given parametrically by p = p0 + t*v for initial point p0 and direction vector v for t >= 0.

Let the plane be given by dot(n, p) + d = 0 for normal vector n = (a, b, c) and constant d. If r is a point on the plane, then d = - dot(n, r). Fully expanded, the plane equation may also be written ax + by + cz + d = 0.

Substituting the ray into the plane equation gives:

t = - (dot(n, p) + d) / dot(n, v)

Example implementation:

std::optional<vec3> intersectRayWithPlane(
    vec3 p, vec3 v,  // ray
    vec3 n, float d  // plane
) {
    float denom = dot(n, v);

    // Prevent divide by zero:
    if (abs(denom) <= 1e-4f)
        return std::nullopt;

    // If you want to ensure the ray reflects off only
    // the "top" half of the plane, use this instead:
    if (-denom <= 1e-4f)
        return std::nullopt;

    float t = -(dot(n, p) + d) / dot(n, v);

    // Use pointy end of the ray.
    // It is technically correct to compare t < 0,
    // but that may be undesirable in a raytracer.
    if (t <= 1e-4)
        return std::nullopt;

    return p + t * v;
}


来源:https://stackoverflow.com/questions/23975555/how-to-do-ray-plane-intersection

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!