Intersection between line and triangle in 3D

前端 未结 3 1718
盖世英雄少女心
盖世英雄少女心 2020-12-28 23:12

I have a line and a triangle somewhere in 3D space. In other words, I have 3 points ([x,y,z] each) for the triangle, and two points (also [x,y,z]) for the line.

I ne

3条回答
  •  北荒
    北荒 (楼主)
    2020-12-28 23:44

    To find the intersection between a line and a triangle in 3D, follow this approach:

    • Compute the plane supporting the triangle,
    • Intersect the line with the plane supporting the triangle:

      • If there is no intersection, then there is no intersection with the triangle.
      • If there is an intersection, verify that the intersection point indeed lies in the triangle:

        • Each edge of the triangle together with the normal of the plane supporting the triangle determines a half-space bounding the inside of the triangle (the corresponding bounding plane can be derived from the normal and the edge vertices),
        • Verify that the intersection point lies on the inside of all the edge half-spaces.

    Here is some sample code with detailed computations that should work:

    // Compute the plane supporting the triangle (p1, p2, p3)
    //     normal: n
    //     offset: d
    //
    // A point P lies on the supporting plane iff n.dot(P) + d = 0
    //
    ofVec3f v21 = p2 - p1;
    ofVec3f v31 = p3 - p1;
    
    ofVec3f n = v21.getCrossed(v31);
    float d = -n.dot(p1);
    
    // A point P belongs to the line from P1 to P2 iff
    //     P = P1 + t * (P2 - P1)
    //
    // Find the intersection point P(t) between the line and
    // the plane supporting the triangle:
    //     n.dot(P) + d = 0
    //                  = n.dot(P1 + t (P2 - P1)) + d
    //                  = n.dot(P1) + t n.dot(P2 - P1) + d
    //
    //     t = -(n.dot(P1) + d) / n.dot(P2 - P1)
    //
    ofVec3f P21 = P2 - P1;
    float nDotP21 = n.dot(P21);
    
    // Ignore line parallel to (or lying in) the plane
    if (fabs(nDotP21) < Epsilon)
        return false;
    
    float t = -(n.dot(P1) + d) / nDotP21;
    ofVec3f P = P1 + t * P21;
    
    // Plane bounding the inside half-space of edge (p1, p2): 
    //     normal: n21 = n x (p2 - p1)
    //     offset: d21 = -n21.dot(p1)
    //
    // A point P is in the inside half-space iff n21.dot(P) + d21 > 0
    //
    
    // Edge (p1, p2)
    ofVec3f n21 = n.cross(v21);
    float d21 = -n21.dot(p1);
    
    if (n21.dot(P) + d21 <= 0)
        return false;
    
    // Edge (p2, p3)
    ofVec3f v32 = p3 - p2;
    ofVec3f n32 = n.cross(v32);
    float d32 = -n32.dot(p2);
    
    if (n32.dot(P) + d32 <= 0)
        return false;
    
    // Edge (p3, p1)
    ofVec3f n13 = n.cross(-v31);
    float d13 = -n13.dot(p3);
    
    if (n13.dot(P) + d13 <= 0)
        return false;
    
    return true;
    

    Some comments on the code posted with the question:

    • Predefined operations of ofVec3f (.dot() and .cross() for geometric products, etc...) should be preferred when available (more readable, avoids implementation mistakes, etc...),
    • The code initially follows the approach above but then only checks that the intersection point is in the 3D axis-aligned bounding box of the line segment [P1, P2]. This combined with possible other errorscould explain why the results are incorrect.
    • One can verify that the intersection point is in the 3D axis-aligned bounding box of the (whole) triangle. While this is not enough to guarantee intersection, it can however be used to cull points clearly not intersecting and avoid further complex computations.

提交回复
热议问题