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); }
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); }
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); }
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); }
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); }
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); }
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); }
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)); }
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); }
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); }
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); }
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); }