Exemple #1
0
        public static bool TestTriangleBoxAndGetCenterOfMassUV(Math.Vector2 a, Math.Vector2 b, Math.Vector2 c, Math.Vector2 boxMin, Math.Vector2 boxMax, out Math.Vector2 centerUV)
        {
            if (TestTriangleBox(a, b, c, boxMin, boxMax) == false)
            {
                centerUV = Math.Vector2.Zero;
                return(false);
            }

            // we know the box and the triangle intersect, but do we need to find the cetroid?
            centerUV.X = (boxMin.X + boxMax.X) * 0.5f;
            centerUV.Y = (boxMin.Y + boxMax.Y) * 0.5f;
            if (IsPointInTriangle(centerUV, a, b, c, out centerUV))
            {
                return(true);
            }

            if (float.IsNaN(centerUV.X) || float.IsNaN(centerUV.Y))
            {
                // ugh... whatever... just keep going
                return(true);
            }

            // apparently the texel intersects 1 or more triangle edges, which means we need
            // to clip the triangle and square.
            List <Math.Vector2> subject = new List <Math.Vector2>();

            subject.Add(boxMin);
            subject.Add(new Math.Vector2(boxMin.X, boxMax.Y));
            subject.Add(boxMax);
            subject.Add(new Math.Vector2(boxMax.X, boxMin.Y));

            List <Math.Vector2> outputList = subject;

            // UV coords may be mirrored, which means winding order is backwards, will screw up everything below.
            // So check to see if they are, and if they are, rearrange them so they aren't.
            Math.Vector2 center   = (a + b + c) / 3.0f;
            Math.Plane2D ab       = Math.Plane2D.CreateFromEdge(a, b);
            Math.Plane2D bc       = Math.Plane2D.CreateFromEdge(b, c);
            Math.Plane2D ca       = Math.Plane2D.CreateFromEdge(c, a);
            bool         reversed = false;

            if (Math.Plane2D.IsPointInFrontOfPlane(ab, center) == false ||
                Math.Plane2D.IsPointInFrontOfPlane(bc, center) == false ||
                Math.Plane2D.IsPointInFrontOfPlane(ca, center) == false)
            {
                // doh, winding order seems to be reversed. Swap c and a.
                Math.Vector2 d = a;
                a = c;
                c = d;

                ab = Math.Plane2D.CreateFromEdge(a, b);
                bc = Math.Plane2D.CreateFromEdge(b, c);
                ca = Math.Plane2D.CreateFromEdge(c, a);

                reversed = true;
            }

            // side A
            List <Math.Vector2> inputList = new List <Math.Vector2>(outputList);

            outputList.Clear();
            Math.Vector2 S = inputList[inputList.Count - 1];
            foreach (Math.Vector2 E in inputList)
            {
                if (Math.Plane2D.IsPointInFrontOfPlane(ab, E))
                {
                    if (Math.Plane2D.IsPointInFrontOfPlane(ab, S) == false)
                    {
                        Math.Vector2 i;
                        TestLineLineIntersection(S, E, a, b, out i);
                        outputList.Add(i);
                    }
                    outputList.Add(E);
                }
                else if (Math.Plane2D.IsPointInFrontOfPlane(ab, S))
                {
                    Math.Vector2 i;
                    TestLineLineIntersection(S, E, a, b, out i);
                    outputList.Add(i);
                }
                S = E;
            }
            if (outputList.Count == 0)
            {
                return(true);
            }

            // side B
            inputList = new List <Math.Vector2>(outputList);
            outputList.Clear();
            S = inputList[inputList.Count - 1];
            foreach (Math.Vector2 E in inputList)
            {
                if (Math.Plane2D.IsPointInFrontOfPlane(bc, E))
                {
                    if (Math.Plane2D.IsPointInFrontOfPlane(bc, S) == false)
                    {
                        Math.Vector2 i;
                        TestLineLineIntersection(S, E, b, c, out i);
                        outputList.Add(i);
                    }
                    outputList.Add(E);
                }
                else if (Math.Plane2D.IsPointInFrontOfPlane(bc, S))
                {
                    Math.Vector2 i;
                    TestLineLineIntersection(S, E, b, c, out i);
                    outputList.Add(i);
                }
                S = E;
            }
            if (outputList.Count == 0)
            {
                return(true);
            }

            // side C
            inputList = new List <Math.Vector2>(outputList);
            outputList.Clear();
            S = inputList[inputList.Count - 1];
            foreach (Math.Vector2 E in inputList)
            {
                if (Math.Plane2D.IsPointInFrontOfPlane(ca, E))
                {
                    if (Math.Plane2D.IsPointInFrontOfPlane(ca, S) == false)
                    {
                        Math.Vector2 i;
                        TestLineLineIntersection(S, E, c, a, out i);
                        outputList.Add(i);
                    }
                    outputList.Add(E);
                }
                else if (Math.Plane2D.IsPointInFrontOfPlane(ca, S))
                {
                    Math.Vector2 i;
                    TestLineLineIntersection(S, E, c, a, out i);
                    outputList.Add(i);
                }
                S = E;
            }
            if (outputList.Count == 0)
            {
                return(true);
            }

            // at this point we've got a clipped list of points, so now we need to find the "center of mass"
            centerUV = Math.Vector2.Zero;
            float area = 0;

            outputList.Add(outputList[0]);
            for (int i = 0; i < outputList.Count - 1; i++)
            {
                float second = outputList[i].X * outputList[i + 1].Y - outputList[i + 1].X * outputList[i].Y;
                centerUV += (outputList[i] + outputList[i + 1]) * second;
                area     += second;
            }

            centerUV /= 6 * area * 0.5f;

            // if we reversed the windings, undo it, so that the output UV coords are correct
            if (reversed)
            {
                Math.Vector2 d = a;
                a = c;
                c = d;
            }

            if (float.IsNaN(centerUV.X) || float.IsNaN(centerUV.Y))
            {
                centerUV = boxMax;
            }

            IsPointInTriangle(centerUV, a, b, c, out centerUV);

            return(true);
        }
Exemple #2
0
 public static bool IsPointInFrontOfPlane(Plane2D plane, Vector2 point)
 {
     return(plane.Normal.Dot(point) + plane.Distance >= 0);
 }