コード例 #1
0
ファイル: Utils.cs プロジェクト: shff/gk3tools
        public static bool TestLineLineIntersection(Math.Vector2 a1, Math.Vector2 a2, Math.Vector2 b1, Math.Vector2 b2, out Math.Vector2 intersection)
        {
            float denom = (b2.Y - b1.Y) * (a2.X - a1.X) - (b2.X - b1.X) * (a2.Y - a1.Y);

            if (denom == 0)
            {
                intersection = Math.Vector2.Zero;
                return(false); // lines are parallel
            }

            Math.Vector2 u;
            u.X = ((b2.X - b1.X) * (a1.Y - b1.Y) - (b2.Y - b1.Y) * (a1.X - b1.X)) / denom;
            //u.Y = ((a2.X - a1.X) * (a1.Y - b1.Y) - (a2.Y - a1.Y) * (a1.X - b1.X)) / denom;

            intersection.X = a1.X + u.X * (a2.X - a1.X);
            intersection.Y = a1.Y + u.X * (a2.Y - a1.Y);

            return(true);
        }
コード例 #2
0
ファイル: Utils.cs プロジェクト: shff/gk3tools
        public static bool IsPointInTriangle(Math.Vector2 point, Math.Vector2 a, Math.Vector2 b, Math.Vector2 c, out Math.Vector2 uv)
        {
            Math.Vector2 v0 = c - a;
            Math.Vector2 v1 = b - a;
            Math.Vector2 v2 = point - a;

            float dot00 = v0.Dot(v0);
            float dot01 = v0.Dot(v1);
            float dot02 = v0.Dot(v2);
            float dot11 = v1.Dot(v1);
            float dot12 = v1.Dot(v2);

            float invDenom = 1.0f / (dot00 * dot11 - dot01 * dot01);

            uv.X = (dot11 * dot02 - dot01 * dot12) * invDenom;
            uv.Y = (dot00 * dot12 - dot01 * dot02) * invDenom;

            return(uv.X >= 0 && uv.Y >= 0 && uv.X + uv.Y < 1.0f);
        }
コード例 #3
0
ファイル: Utils.cs プロジェクト: shff/gk3tools
        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);
        }
コード例 #4
0
ファイル: Utils.cs プロジェクト: shff/gk3tools
        public static bool TestTriangleBox(Math.Vector2 a, Math.Vector2 b, Math.Vector2 c, Math.Vector2 boxMin, Math.Vector2 boxMax)
        {
            Math.Vector2 ab = (b - a).Normalize();
            Math.Vector2 ac = (a - c).Normalize();
            Math.Vector2 bc = (c - b).Normalize();

            // calc the normals

            /*Utils.Swap(ref ab.X, ref ab.Y);
             * Utils.Swap(ref ac.X, ref ac.Y);
             * Utils.Swap(ref bc.X, ref bc.Y);
             * ab.X = -ab.X;
             * ac.X = -ac.X;
             * bc.X = -bc.X;*/

            // project the triangle onto the 1st axis of the triangle
            float dotA = a.Dot(ab);
            float dotB = b.Dot(ab);
            float dotC = c.Dot(ab);

            float dotMax = System.Math.Max(dotA, System.Math.Max(dotB, dotC));
            float dotMin = System.Math.Min(dotA, System.Math.Min(dotB, dotC));

            // project the box onto 1st axis of triangle
            float boxA = boxMin.X * ab.X + boxMin.Y * ab.Y;
            float boxB = boxMax.X * ab.X + boxMin.Y * ab.Y;
            float boxC = boxMax.X * ab.X + boxMax.Y * ab.Y;
            float boxD = boxMin.X * ab.X + boxMax.Y * ab.Y;

            float boxDotMax = System.Math.Max(boxA, System.Math.Max(boxB, System.Math.Max(boxC, boxD)));
            float boxDotMin = System.Math.Min(boxA, System.Math.Min(boxB, System.Math.Min(boxC, boxD)));

            if (boxDotMax < dotMin || dotMax < boxDotMin)
            {
                return(false);
            }

            // project the triangle onto 2nd axis of triangle
            dotA = a.Dot(ac);
            dotB = b.Dot(ac);
            dotC = c.Dot(ac);

            dotMax = System.Math.Max(dotA, System.Math.Max(dotB, dotC));
            dotMin = System.Math.Min(dotA, System.Math.Min(dotB, dotC));

            // project the box onto 1st axis of triangle
            boxA = boxMin.X * ac.X + boxMin.Y * ac.Y;
            boxB = boxMax.X * ac.X + boxMin.Y * ac.Y;
            boxC = boxMax.X * ac.X + boxMax.Y * ac.Y;
            boxD = boxMin.X * ac.X + boxMax.Y * ac.Y;

            boxDotMax = System.Math.Max(boxA, System.Math.Max(boxB, System.Math.Max(boxC, boxD)));
            boxDotMin = System.Math.Min(boxA, System.Math.Min(boxB, System.Math.Min(boxC, boxD)));

            if (boxDotMax < dotMin || dotMax < boxDotMin)
            {
                return(false);
            }

            // project the triangle onto 3rd axis of triangle
            dotA = a.Dot(bc);
            dotB = b.Dot(bc);
            dotC = c.Dot(bc);

            dotMax = System.Math.Max(dotA, System.Math.Max(dotB, dotC));
            dotMin = System.Math.Min(dotA, System.Math.Min(dotB, dotC));

            // project the box onto 1st axis of triangle
            boxA = boxMin.X * bc.X + boxMin.Y * bc.Y;
            boxB = boxMax.X * bc.X + boxMin.Y * bc.Y;
            boxC = boxMax.X * bc.X + boxMax.Y * bc.Y;
            boxD = boxMin.X * bc.X + boxMax.Y * bc.Y;

            boxDotMax = System.Math.Max(boxA, System.Math.Max(boxB, System.Math.Max(boxC, boxD)));
            boxDotMin = System.Math.Min(boxA, System.Math.Min(boxB, System.Math.Min(boxC, boxD)));

            if (boxDotMax < dotMin || dotMax < boxDotMin)
            {
                return(false);
            }

            return(true);
        }