예제 #1
0
        public void Load(ContentManager content)
        {
            _splatTexture = content.Load <Texture2D>("Content/Terrain");

            //Create an array to hold the data from the texture
            uint[] data = new uint[_splatTexture.Width * _splatTexture.Height];

            //Transfer the texture data to the array
            _splatTexture.GetData(data);

            // get a set of vertices from a texture
            PolygonCreationAssistance pca = new PolygonCreationAssistance(data, _splatTexture.Width, _splatTexture.Height);

            pca.HullTolerance      = 6f;
            pca.HoleDetection      = false;
            pca.MultipartDetection = false;
            pca.AlphaTolerance     = 20;

            // extract those vertices into a Vertices structure
            _splatTextureVertices = Vertices.CreatePolygon(ref pca)[0];

            // create a body
            _splatBody          = BodyFactory.Instance.CreatePolygonBody(_physicsSimulator, _splatTextureVertices, 1);
            _splatBody.Position = _position;

            // use AutoDivide to find up to 25 convex geoms from a set of vertices
            GeomFactory.Instance.CreateSATPolygonGeom(_physicsSimulator, _splatBody, _splatTextureVertices, 25);
        }
예제 #2
0
        private static bool GetNextHullPoint(
            PolygonCreationAssistance assistance,
            ref Vector2 last,
            ref Vector2 current,
            out Vector2 next)
        {
            var firstPixel = GetIndexOfFirstPixelToCheck(last, current);

            for (var i = 0; i < 8; i++)
            {
                var pixel = (firstPixel + i) % 8;
                var x     = (int)current.X + ClosePixels[pixel, 0];
                var y     = (int)current.Y + ClosePixels[pixel, 1];

                if (x >= 0 && x < assistance.Width && y >= 0 && y <= assistance.Height)
                {
                    if (assistance.IsSolid(x, y))
                    {
                        next = new Vector2(x, y);
                        return(true);
                    }
                }
            }

            next = Vector2.Zero;
            return(false);
        }
예제 #3
0
        public void Load(ContentManager content)
        {
            _splatTexture = content.Load<Texture2D>("Content/Terrain");

            //Create an array to hold the data from the texture
            uint[] data = new uint[_splatTexture.Width * _splatTexture.Height];

            //Transfer the texture data to the array
            _splatTexture.GetData(data);

            // get a set of vertices from a texture
            PolygonCreationAssistance pca = new PolygonCreationAssistance(data, _splatTexture.Width, _splatTexture.Height);
            pca.HullTolerance = 6f;
            pca.HoleDetection = false;
            pca.MultipartDetection = false;
            pca.AlphaTolerance = 20;

            // extract those vertices into a Vertices structure
            _splatTextureVertices = Vertices.CreatePolygon(ref pca)[0];

            // create a body
            _splatBody = BodyFactory.Instance.CreatePolygonBody(_physicsSimulator, _splatTextureVertices, 1);
            _splatBody.Position = _position;

            // use AutoDivide to find up to 25 convex geoms from a set of vertices
            GeomFactory.Instance.CreateSATPolygonGeom(_physicsSimulator, _splatBody, _splatTextureVertices, 25);
        }
예제 #4
0
        private static bool GetNextHullEntrance(
            PolygonCreationAssistance assistance, Vector2 start, out Vector2?entrance)
        {
            // Search for first solid pixel.
            var size = assistance.Height * assistance.Width;

            var foundTransparent = false;

            for (var i = (int)start.X + (int)start.Y * assistance.Width; i <= size; i++)
            {
                if (assistance.IsSolid(i))
                {
                    if (foundTransparent)
                    {
                        var x = i % assistance.Width;
                        entrance = new Vector2(x, (i - x) / (float)assistance.Width);
                        return(true);
                    }
                }
                else
                {
                    foundTransparent = true;
                }
            }

            // If there are no solid pixels.
            entrance = null;
            return(false);
        }
예제 #5
0
        private static bool IsNearPixel(PolygonCreationAssistance assistance, ref Vector2 current, ref Vector2 near)
        {
            for (var i = 0; i < 8; i++)
            {
                var x = (int)current.X + ClosePixels[i, 0];
                var y = (int)current.Y + ClosePixels[i, 1];

                if (x >= 0 && x <= assistance.Width && y >= 0 && y <= assistance.Height &&
                    x == (int)near.X && y == (int)near.Y)
                {
                    return(true);
                }
            }
            return(false);
        }
예제 #6
0
 private static bool GetHullEntrance(PolygonCreationAssistance assistance, out Vector2 entrance)
 {
     // Search for first solid pixel.
     for (var y = 0; y <= assistance.Height; y++)
     {
         for (var x = 0; x <= assistance.Width; x++)
         {
             if (assistance.IsSolid(x, y))
             {
                 entrance = new Vector2(x, y);
                 return(true);
             }
         }
     }
     entrance = Vector2.Zero;
     return(false);
 }
예제 #7
0
        private static bool SearchNearPixels(
            PolygonCreationAssistance assistance, bool searchingForSolidPixel, Vector2 current, out Vector2 foundPixel)
        {
            for (var i = 0; i < 8; i++)
            {
                var x = (int)current.X + ClosePixels[i, 0];
                var y = (int)current.Y + ClosePixels[i, 1];

                if (!searchingForSolidPixel ^ assistance.IsSolid(x, y))
                {
                    foundPixel = new Vector2(x, y);
                    return(true);
                }
            }
            foundPixel = Vector2.Zero;
            return(false);
        }
예제 #8
0
        public static List <List <Vector2> > DetectVertices(
            uint[] data,
            int width,
            int height,
            float hullTolerance     = 1.5f,
            byte alphaTolerance     = 20,
            bool multiPartDetection = false)
        {
            var assistance = new PolygonCreationAssistance(data, width, height)
            {
                HullTolerance      = hullTolerance,
                AlphaTolerance     = alphaTolerance,
                MultipartDetection = multiPartDetection
            };

            return(DetectVertices(ref assistance));
        }
예제 #9
0
        private static bool InPolygon(PolygonCreationAssistance assistance, List <Vector2> polygon, Vector2 point)
        {
            if (!DistanceToHullAcceptable(assistance, polygon, point))
            {
                return(true);
            }

            var edges = GetCrossingEdges(polygon, (int)point.Y);

            if (edges.Count > 0 && edges.Count % 2 == 0)
            {
                for (var i = 0; i < edges.Count; i += 2)
                {
                    if (edges[i].CrossingPoint.X <= point.X && edges[i + 1].CrossingPoint.X >= point.X)
                    {
                        return(true);
                    }
                }
            }

            return(false);
        }
예제 #10
0
        private static bool DistanceToHullAcceptable(
            PolygonCreationAssistance assistance, List <Vector2> polygon, Vector2 point)
        {
            if (polygon == null || polygon.Count <= 2)
            {
                return(false);
            }

            var lastVertex = polygon[polygon.Count - 1];

            foreach (var vertex in polygon)
            {
                if (DistanceBetweenPointAndLineSegment(point, vertex, lastVertex) <= assistance.HullTolerance ||
                    Vector2.Distance(point, vertex) <= assistance.HullTolerance)
                {
                    return(false);
                }
                lastVertex = vertex;
            }

            return(true);
        }
예제 #11
0
        private static List <Vector2> CreateSimplePolygon(
            PolygonCreationAssistance assistance, Vector2 entrance, Vector2 last)
        {
            var entranceFound = false;
            var endOfHull     = false;

            var polygon       = new List <Vector2>(32);
            var hullArea      = new List <Vector2>(32);
            var endOfHullArea = new List <Vector2>(32);

            var current = Vector2.Zero;

            // Get the entrance point. //todo: test all possibilities
            if (entrance == Vector2.Zero || !assistance.InBounds(entrance))
            {
                entranceFound = GetHullEntrance(assistance, out entrance);

                if (entranceFound)
                {
                    current = new Vector2(entrance.X - 1f, entrance.Y);
                }
            }
            else
            {
                if (assistance.IsSolid(entrance))
                {
                    if (IsNearPixel(assistance, ref entrance, ref last))
                    {
                        current       = last;
                        entranceFound = true;
                    }
                    else
                    {
                        Vector2 temp;
                        if (SearchNearPixels(assistance, false, entrance, out temp))
                        {
                            current       = temp;
                            entranceFound = true;
                        }
                    }
                }
            }

            if (entranceFound)
            {
                polygon.Add(entrance);
                hullArea.Add(entrance);

                var next = entrance;

                do
                {
                    // Search in the pre vision list for an outstanding point.
                    Vector2 outstanding;
                    if (SearchForOutstandingVertex(hullArea, assistance.HullTolerance, out outstanding))
                    {
                        if (endOfHull)
                        {
                            // We have found the next pixel, but is it on the last bit of the hull?
                            if (endOfHullArea.Contains(outstanding))
                            {
                                // Indeed.
                                polygon.Add(outstanding);
                            }

                            // That's enough, quit.
                            break;
                        }

                        // Add it and remove all vertices that don't matter anymore
                        // (all the vertices before the outstanding).
                        polygon.Add(outstanding);
                        hullArea.RemoveRange(0, hullArea.IndexOf(outstanding));
                    }

                    // Last point gets current and current gets next. Our little spider is moving forward on the hull ;).
                    last    = current;
                    current = next;

                    // Get the next point on hull.
                    if (GetNextHullPoint(assistance, ref last, ref current, out next))
                    {
                        // Add the vertex to a hull pre vision list.
                        hullArea.Add(next);
                    }
                    else
                    {
                        // Quit
                        break;
                    }

                    if (next == entrance && !endOfHull)
                    {
                        // It's the last bit of the hull, search on and exit at next found vertex.
                        endOfHull = true;
                        endOfHullArea.AddRange(hullArea);
                    }
                } while (true);
            }

            return(polygon);
        }
예제 #12
0
        private static List <List <Vector2> > DetectVertices(ref PolygonCreationAssistance assistance)
        {
            // Check the array we just got.
            Debug.Assert(
                assistance.IsValid(),
                "Sizes don't match: Color array must contain texture width * texture height elements.");

            var     polygons        = new List <List <Vector2> >();
            Vector2?polygonEntrance = null;

            do
            {
                List <Vector2> polygon;
                if (polygons.Count == 0)
                {
                    polygon = CreateSimplePolygon(assistance, Vector2.Zero, Vector2.Zero);

                    if (polygon != null && polygon.Count > 2)
                    {
                        polygonEntrance = GetTopMostVertex(polygon);
                    }
                }
                else if (polygonEntrance.HasValue)
                {
                    polygon = CreateSimplePolygon(
                        assistance,
                        polygonEntrance.Value,
                        new Vector2(polygonEntrance.Value.X - 1f, polygonEntrance.Value.Y));
                }
                else
                {
                    break;
                }

                var done = true;

                if (polygon != null && polygon.Count > 2)
                {
                    polygons.Add(polygon);

                    if (assistance.MultipartDetection)
                    {
                        // 1:  95 / 151
                        // 2: 232 / 252
                        while (GetNextHullEntrance(assistance, polygonEntrance.Value, out polygonEntrance))
                        {
                            var inPolygon = false;
                            foreach (var vertices in polygons)
                            {
                                if (InPolygon(assistance, vertices, polygonEntrance.Value))
                                {
                                    inPolygon = true;
                                    break;
                                }
                            }

                            if (!inPolygon)
                            {
                                done = false;
                                break;
                            }
                        }
                    }
                }

                if (done)
                {
                    break;
                }
            } while (true);

            return(polygons);
        }