POV-Ray : Newsgroups : povray.programming : Explanation of point inside a triangle code : Re: Explanation of point inside a triangle code Server Time
19 Apr 2024 04:35:27 EDT (-0400)
  Re: Explanation of point inside a triangle code  
From: clipka
Date: 6 Apr 2009 12:35:01
Message: <web.49da2ed2b10008142b82b7c80@news.povray.org>
"queercore" <nomail@nomail> wrote:
> Here is the code ray triangle intersection...


> static int Intersect_Triangle(RAY *Ray, TRIANGLE *Triangle, DBL *Depth)
> {
>   DBL NormalDotOrigin, NormalDotDirection;
>   DBL s, t;
>
>   Increase_Counter(stats[Ray_Triangle_Tests]);
>
>   if (Test_Flag(Triangle, DEGENERATE_FLAG))
>   {
>     return(false);
>   }
>
>   VDot(NormalDotDirection, Triangle->Normal_Vector, Ray->Direction);
>
>   if (fabs(NormalDotDirection) < EPSILON)
>   {
>     return(false);
>   }
>
>   VDot(NormalDotOrigin, Triangle->Normal_Vector, Ray->Initial);
>
>   *Depth = -(Triangle->Distance + NormalDotOrigin) / NormalDotDirection;
>
>   if ((*Depth < DEPTH_TOLERANCE) || (*Depth > Max_Distance))
>   {
>     return(false);
>   }

The above code mainly computes *Depth, which tells us the distance along the ray
at which it intersects the plane of the triangle. Aside from that, it's just
framework stuff and sanity checks.


Next thing we do is test whether the resulting intersection point is inside or
outside the triangle. As the problem is invariant to linear transformations
(except for pathological cases), and projection onto an arbitrary plane *is* a
linear transformation (being pathological to this problem only if the plane is
perpendicular to the triangle's plane), we take the liberty to project the
whole smash onto a plane of our liking.

Obviously, the XY, XZ and YZ planes lend themselves to this purpose, as
projecting onto these is brain-dead easy; to avoid pathological or
near-pathological cases, we choose between these three according to the most
dominant axis of the triangle's surface normal:

>   switch (Triangle->Dominant_Axis)
>   {
>
>     case X:

Determine (projection of) intersection point (s;t):

>       s = Ray->Initial[Y] + *Depth * Ray->Direction[Y];
>       t = Ray->Initial[Z] + *Depth * Ray->Direction[Z];

Use straightforward 2D linear math to check whether we're "offside" any of the
three lines along the (projected) triangle's edges:

>       if ((Triangle->P2[Y] - s) * (Triangle->P2[Z] - Triangle->P1[Z]) <
>           (Triangle->P2[Z] - t) * (Triangle->P2[Y] - Triangle->P1[Y]))
>       {
>         return(false);
>       }
>
>       if ((Triangle->P3[Y] - s) * (Triangle->P3[Z] - Triangle->P2[Z]) <
>           (Triangle->P3[Z] - t) * (Triangle->P3[Y] - Triangle->P2[Y]))
>       {
>         return(false);
>       }
>
>       if ((Triangle->P1[Y] - s) * (Triangle->P1[Z] - Triangle->P3[Z]) <
>           (Triangle->P1[Z] - t) * (Triangle->P1[Y] - Triangle->P3[Y]))
>       {
>         return(false);
>       }

That's it; it may appear disappointingly cheap, but it does the job ;). The
remainder is just framework stuff again, and the same algorithm for the other
two planes of our choice.

>       Increase_Counter(stats[Ray_Triangle_Tests_Succeeded]);
>
>       return(true);
>
>     case Y:
>       [...]
>
>     case Z:
>       [...]
>
>   }
>
>   return(false);
> }


Post a reply to this message

Copyright 2003-2023 Persistence of Vision Raytracer Pty. Ltd.