Advertisement
_Data_

TriTriOverlap.cs

Jan 23rd, 2015
224
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 8.42 KB | None | 0 0
  1. using UnityEngine;
  2. using System.Collections;
  3.  
  4. /// <summary>
  5. /// Tri/Tri intersection. Implementation of Tomas Moller, 1997.
  6. /// See article "A Fast Triangle-Triangle Intersection Test", Journal of Graphics Tools, 2(2), 1997.
  7. /// </summary>
  8. public static class TriTriOverlap
  9. {
  10.     private static void Sort(ref Vector2 v)
  11.     {
  12.         if (v.x > v.y)
  13.         {
  14.             float c;
  15.             c = v.x;
  16.             v.x = v.y;
  17.             v.y = c;
  18.         }
  19.     }
  20.    
  21.     /// <summary>
  22.     /// This edge to edge test is based on Franlin Antonio's gem: "Faster Line Segment Intersection", in Graphics Gems III, pp. 199-202
  23.     /// </summary>
  24.     private static bool EdgeEdgeTest(Vector3 v0, Vector3 v1, Vector3 u0, Vector3 u1, int i0, int i1)
  25.     {
  26.         float Ax, Ay, Bx, By, Cx, Cy, e, d, f;
  27.         Ax = v1[i0] - v0[i0];
  28.         Ay = v1[i1] - v0[i1];
  29.        
  30.         Bx = u0[i0] - u1[i0];
  31.         By = u0[i1] - u1[i1];
  32.         Cx = v0[i0] - u0[i0];
  33.         Cy = v0[i1] - u0[i1];
  34.         f = Ay * Bx - Ax * By;
  35.         d = By * Cx - Bx * Cy;
  36.         if ((f > 0 && d >= 0 && d <= f) || (f < 0 && d <= 0 && d >= f))
  37.         {
  38.             e = Ax * Cy - Ay * Cx;
  39.             if (f > 0)
  40.             {
  41.                 if (e >= 0 && e <= f) { return true; }
  42.             }
  43.             else
  44.             {
  45.                 if (e <= 0 && e >= f) { return true; }
  46.             }
  47.         }
  48.        
  49.         return false;
  50.     }
  51.    
  52.     private static bool EdgeAgainstTriEdges(Vector3 v0, Vector3 v1, Vector3 u0, Vector3 u1, Vector3 u2, short i0, short i1)
  53.     {
  54.         // test edge u0,u1 against v0,v1
  55.         if (EdgeEdgeTest(v0, v1, u0, u1, i0, i1)) { return true; }
  56.        
  57.         // test edge u1,u2 against v0,v1
  58.         if (EdgeEdgeTest(v0, v1, u1, u2, i0, i1)) { return true; }
  59.        
  60.         // test edge u2,u1 against v0,v1
  61.         if (EdgeEdgeTest(v0, v1, u2, u0, i0, i1)) { return true; }
  62.        
  63.         return false;
  64.     }
  65.    
  66.     private static bool PointInTri(Vector3 v0, Vector3 u0, Vector3 u1, Vector3 u2, short i0, short i1)
  67.     {
  68.         float a, b, c, d0, d1, d2;
  69.        
  70.         // is T1 completly inside T2?
  71.         // check if v0 is inside tri(u0,u1,u2)
  72.         a = u1[i1] - u0[i1];
  73.         b = -(u1[i0] - u0[i0]);
  74.         c = -a * u0[i0] - b * u0[i1];
  75.         d0 = a * v0[i0] + b * v0[i1] + c;
  76.        
  77.         a = u2[i1] - u1[i1];
  78.         b = -(u2[i0] - u1[i0]);
  79.         c = -a * u1[i0] - b * u1[i1];
  80.         d1 = a * v0[i0] + b * v0[i1] + c;
  81.        
  82.         a = u0[i1] - u2[i1];
  83.         b = -(u0[i0] - u2[i0]);
  84.         c = -a * u2[i0] - b * u2[i1];
  85.         d2 = a * v0[i0] + b * v0[i1] + c;
  86.        
  87.         if (d0 * d1 > 0.0f)
  88.         {
  89.             if (d0 * d2 > 0.0f) { return true; }
  90.         }
  91.        
  92.         return false;
  93.     }
  94.    
  95.     private static bool TriTriCoplanar(Vector3 N, Vector3 v0, Vector3 v1, Vector3 v2, Vector3 u0, Vector3 u1, Vector3 u2)
  96.     {
  97.         float[] A = new float[3];
  98.         short i0, i1;
  99.        
  100.         // first project onto an axis-aligned plane, that maximizes the area
  101.         // of the triangles, compute indices: i0,i1.
  102.         A[0] = Mathf.Abs(N[0]);
  103.         A[1] = Mathf.Abs(N[1]);
  104.         A[2] = Mathf.Abs(N[2]);
  105.         if (A[0] > A[1])
  106.         {
  107.             if (A[0] > A[2])
  108.             {
  109.                 // A[0] is greatest
  110.                 i0 = 1;      
  111.                 i1 = 2;
  112.             }
  113.             else
  114.             {
  115.                 // A[2] is greatest
  116.                 i0 = 0;      
  117.                 i1 = 1;
  118.             }
  119.         }
  120.         else  
  121.         {
  122.             if (A[2] > A[1])
  123.             {
  124.                 // A[2] is greatest
  125.                 i0 = 0;      
  126.                 i1 = 1;
  127.             }
  128.             else
  129.             {
  130.                 // A[1] is greatest
  131.                 i0 = 0;      
  132.                 i1 = 2;
  133.             }
  134.         }
  135.        
  136.         // test all edges of triangle 1 against the edges of triangle 2
  137.         if (EdgeAgainstTriEdges(v0, v1, u0, u1, u2, i0, i1)) { return true; }
  138.         if (EdgeAgainstTriEdges(v1, v2, u0, u1, u2, i0, i1)) { return true; }
  139.         if (EdgeAgainstTriEdges(v2, v0, u0, u1, u2, i0, i1)) { return true; }
  140.        
  141.         // finally, test if tri1 is totally contained in tri2 or vice versa
  142.         if (PointInTri(v0, u0, u1, u2, i0, i1)) { return true; }
  143.         if (PointInTri(u0, v0, v1, v2, i0, i1)) { return true; }
  144.        
  145.         return false;
  146.     }
  147.    
  148.    
  149.    
  150.     private static bool ComputeIntervals(float VV0, float VV1, float VV2,
  151.                                          float D0, float D1, float D2, float D0D1, float D0D2,
  152.                                          ref float A, ref float B, ref float C, ref float X0, ref float X1)
  153.     {
  154.         if (D0D1 > 0.0f)
  155.         {
  156.             // here we know that D0D2<=0.0
  157.             // that is D0, D1 are on the same side, D2 on the other or on the plane
  158.             A = VV2; B = (VV0 - VV2) * D2; C = (VV1 - VV2) * D2; X0 = D2 - D0; X1 = D2 - D1;
  159.         }
  160.         else if (D0D2 > 0.0f)
  161.         {
  162.             // here we know that d0d1<=0.0
  163.             A = VV1; B = (VV0 - VV1) * D1; C = (VV2 - VV1) * D1; X0 = D1 - D0; X1 = D1 - D2;
  164.         }
  165.         else if (D1 * D2 > 0.0f || D0 != 0.0f)
  166.         {
  167.             // here we know that d0d1<=0.0 or that D0!=0.0
  168.             A = VV0; B = (VV1 - VV0) * D0; C = (VV2 - VV0) * D0; X0 = D0 - D1; X1 = D0 - D2;
  169.         }
  170.         else if (D1 != 0.0f)
  171.         {
  172.             A = VV1; B = (VV0 - VV1) * D1; C = (VV2 - VV1) * D1; X0 = D1 - D0; X1 = D1 - D2;
  173.         }
  174.         else if (D2 != 0.0f)
  175.         {
  176.             A = VV2; B = (VV0 - VV2) * D2; C = (VV1 - VV2) * D2; X0 = D2 - D0; X1 = D2 - D1;
  177.         }
  178.         else
  179.         {
  180.             return true;
  181.         }
  182.        
  183.         return false;
  184.     }
  185.    
  186.     /// <summary>
  187.     /// Checks if the triangle V(v0, v1, v2) intersects the triangle U(u0, u1, u2).
  188.     /// </summary>
  189.     /// <param name="v0">Vertex 0 of V</param>
  190.     /// <param name="v1">Vertex 1 of V</param>
  191.     /// <param name="v2">Vertex 2 of V</param>
  192.     /// <param name="u0">Vertex 0 of U</param>
  193.     /// <param name="u1">Vertex 1 of U</param>
  194.     /// <param name="u2">Vertex 2 of U</param>
  195.     /// <returns>Returns <c>true</c> if V intersects U, otherwise <c>false</c></returns>
  196.     public static bool TriTriIntersect(Vector3 v0, Vector3 v1, Vector3 v2, Vector3 u0, Vector3 u1, Vector3 u2)
  197.     {
  198.         Vector3 e1, e2;
  199.         Vector3 n1, n2;    
  200.         Vector3 dd;
  201.         Vector2 isect1 = Vector2.zero, isect2 = Vector2.zero;
  202.        
  203.         float du0, du1, du2, dv0, dv1, dv2, d1, d2;
  204.         float du0du1, du0du2, dv0dv1, dv0dv2;
  205.         float vp0, vp1, vp2;
  206.         float up0, up1, up2;
  207.         float bb, cc, max;
  208.        
  209.         short index;
  210.        
  211.         // compute plane equation of triangle(v0,v1,v2)
  212.         e1 = v1 - v0;
  213.         e2 = v2 - v0;
  214.         n1 = Vector3.Cross(e1, e2);
  215.         d1 = -Vector3.Dot(n1, v0);
  216.         // plane equation 1: N1.X+d1=0 */
  217.        
  218.         // put u0,u1,u2 into plane equation 1 to compute signed distances to the plane
  219.         du0 = Vector3.Dot(n1, u0) + d1;
  220.         du1 = Vector3.Dot(n1, u1) + d1;
  221.         du2 = Vector3.Dot(n1, u2) + d1;
  222.        
  223.         // coplanarity robustness check
  224.         if (Mathf.Abs(du0) < Mathf.Epsilon) { du0 = 0.0f; }
  225.         if (Mathf.Abs(du1) < Mathf.Epsilon) { du1 = 0.0f; }
  226.         if (Mathf.Abs(du2) < Mathf.Epsilon) { du2 = 0.0f; }
  227.        
  228.         du0du1 = du0 * du1;
  229.         du0du2 = du0 * du2;
  230.        
  231.         // same sign on all of them + not equal 0 ?
  232.         if (du0du1 > 0.0f && du0du2 > 0.0f)
  233.         {
  234.             // no intersection occurs
  235.             return false;                    
  236.         }
  237.        
  238.         // compute plane of triangle (u0,u1,u2)
  239.         e1 = u1 - u0;
  240.         e2 = u2 - u0;
  241.         n2 = Vector3.Cross(e1, e2);
  242.         d2 = -Vector3.Dot(n2, u0);
  243.        
  244.         // plane equation 2: N2.X+d2=0
  245.         // put v0,v1,v2 into plane equation 2
  246.         dv0 = Vector3.Dot(n2, v0) + d2;
  247.         dv1 = Vector3.Dot(n2, v1) + d2;
  248.         dv2 = Vector3.Dot(n2, v2) + d2;
  249.        
  250.         if (Mathf.Abs(dv0) < Mathf.Epsilon) { dv0 = 0.0f; }
  251.         if (Mathf.Abs(dv1) < Mathf.Epsilon) { dv1 = 0.0f; }
  252.         if (Mathf.Abs(dv2) < Mathf.Epsilon) { dv2 = 0.0f; }
  253.        
  254.        
  255.         dv0dv1 = dv0 * dv1;
  256.         dv0dv2 = dv0 * dv2;
  257.        
  258.         // same sign on all of them + not equal 0 ?
  259.         if (dv0dv1 > 0.0f && dv0dv2 > 0.0f)
  260.         {
  261.             // no intersection occurs
  262.             return false;                    
  263.         }
  264.        
  265.         // compute direction of intersection line
  266.         dd = Vector3.Cross(n1, n2);
  267.        
  268.         // compute and index to the largest component of D
  269.         max = (float)Mathf.Abs(dd[0]);
  270.         index = 0;
  271.         bb = (float)Mathf.Abs(dd[1]);
  272.         cc = (float)Mathf.Abs(dd[2]);
  273.         if (bb > max) { max = bb; index = 1; }
  274.         if (cc > max) { max = cc; index = 2; }
  275.        
  276.         // this is the simplified projection onto L
  277.         vp0 = v0[index];
  278.         vp1 = v1[index];
  279.         vp2 = v2[index];
  280.        
  281.         up0 = u0[index];
  282.         up1 = u1[index];
  283.         up2 = u2[index];
  284.        
  285.         // compute interval for triangle 1
  286.         float a = 0, b = 0, c = 0, x0 = 0, x1 = 0;
  287.         if (ComputeIntervals(vp0, vp1, vp2, dv0, dv1, dv2, dv0dv1, dv0dv2, ref a, ref b, ref c, ref x0, ref x1))
  288.         {
  289.             return TriTriCoplanar(n1, v0, v1, v2, u0, u1, u2);
  290.         }
  291.        
  292.         // compute interval for triangle 2
  293.         float d = 0, e = 0, f = 0, y0 = 0, y1 = 0;
  294.         if (ComputeIntervals(up0, up1, up2, du0, du1, du2, du0du1, du0du2, ref d, ref e, ref f, ref y0, ref y1))
  295.         {
  296.             return TriTriCoplanar(n1, v0, v1, v2, u0, u1, u2);
  297.         }
  298.        
  299.         float xx, yy, xxyy, tmp;
  300.         xx = x0 * x1;
  301.         yy = y0 * y1;
  302.         xxyy = xx * yy;
  303.        
  304.         tmp = a * xxyy;
  305.         isect1[0] = tmp + b * x1 * yy;
  306.         isect1[1] = tmp + c * x0 * yy;
  307.        
  308.         tmp = d * xxyy;
  309.         isect2[0] = tmp + e * xx * y1;
  310.         isect2[1] = tmp + f * xx * y0;
  311.        
  312.         Sort(ref isect1);
  313.         Sort(ref isect2);
  314.        
  315.         return !(isect1[1] < isect2[0] || isect2[1] < isect1[0]);
  316.     }
  317. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement