// Get the adjancent point private bool nextPos(ref BinaryImage b, ref int pos, ref int currPos, ref int prevPos) { int w = b.x; if (currPos + w < b.Length && b.Get(currPos + w) && (currPos + w) != prevPos) { pos = currPos + w; // Top } else if ((currPos % w) + 1 < w && b.Get(currPos + 1) && (currPos + 1) != prevPos) { pos = currPos + 1; // Right } else if (currPos - w >= 0 && b.Get(currPos - w) && (currPos - w) != prevPos) { pos = currPos - w; // Bottom } else if ((currPos % w) - 1 >= 0 && b.Get(currPos - 1) && (currPos - 1) != prevPos) { pos = currPos - 1; // Left } else { return(false); // None } // Update values prevPos = currPos; currPos = pos; return(true); }
// Get the initial adjancent point private bool nextPos(ref BinaryImage b, ref int pos, int prevPos) { int w = b.x; if (prevPos + w < b.Length && b.Get(prevPos + w)) { pos = prevPos + w; // Top } else if ((prevPos % w) + 1 < w && b.Get(prevPos + 1)) { pos = prevPos + 1; // Right } else if (prevPos - w >= 0 && b.Get(prevPos - w)) { pos = prevPos - w; // Bottom } else if ((prevPos % w) - 1 >= 0 && b.Get(prevPos - 1)) { pos = prevPos - 1; // Left } else { return(false); // single pixel island } return(true); }
private int backTrack(ref BinaryImage b, ref List <Vector2> path, int start) { int w = b.x; if (start <= 1) { return(-1); } int currPos = (int)path[start].x + (int)path[start].y * w; int prevPos = (int)path[start - 1].x + (int)path[start - 1].y * w; if (currPos + w < b.Length && b.Get(currPos + w) && (currPos + w) != prevPos || // Top (currPos % w) + 1 < w && b.Get(currPos + 1) && (currPos + 1) != prevPos || // Right currPos - w >= 0 && b.Get(currPos - w) && (currPos - w) != prevPos || // Bottom (currPos % w) - 1 >= 0 && b.Get(currPos - 1) && (currPos - 1) != prevPos) { // Left return(start); } else { // if we cannot find any new points set back again. start = backTrack(ref b, ref path, start - 1); } return(start > 0 ? start : -1); }
void floodFill(ref BinaryImage b, ref List <int> i, int pos) { int w = b.x; if (b.Get(pos)) { i.Add(pos); b.Set(pos, false); } else { return; } if ((pos % w) + 1 < w) { floodFill(ref b, ref i, pos + 1); // Right } if ((pos % w) - 1 >= 0) { floodFill(ref b, ref i, pos - 1); // Left } if (pos + w < b.Length) { floodFill(ref b, ref i, pos + w); // Top } if (pos - w >= 0) { floodFill(ref b, ref i, pos - w); // Bottom } }
/** * If the centre of a 3x3 is true then make the whole grid true * @param {BinaryImage} ref BinaryImage b [description] * @return {BinaryImage} The dilated image */ private BinaryImage dilation(BinaryImage b) { int[,] dirs = { { 0, 1 }, { 1, 1 }, { 1, 0 }, { 1, -1 }, { 0, -1 }, { -1, -1 }, { -1, 0 }, { -1, 1 } }; BinaryImage t = new BinaryImage(b.x, b.y); int w = b.x; // width int h = b.y; // height for (int x = 0; x < w; x++) { for (int y = 0; y < h; y++) { if (b.Get(x + y * w)) { for (int z = 0; z < dirs.GetLength(0); z++) { int i = x + dirs[z, 0], j = y + dirs[z, 1]; if (i < w && i >= 0 && j < h && j >= 0) { t.Set(i + j * w, true); } } } } } return(t); }
/** * Subtracts one binaryImage from another * @param {BinaryImage} b1 [description] * @param {BinaryImage} b2 [description] * @return {BinaryImage} [description] */ private BinaryImage subtraction(BinaryImage b1, BinaryImage b2) { BinaryImage t = new BinaryImage(b1.x, b1.y); int w = b1.x; // width int h = b1.y; // height for (int x = 0; x < w; x++) { for (int y = 0; y < h; y++) { t.Set(x + y * w, (b1.Get(x + y * w) != b2.Get(x + y * w))); } } return(t); }
/** * Helper function to generate a Texture2D from a BinaryImage * @param {BinaryImage} b The BinaryImage to be converted to a Texture2D * @return {Texture2D} The generated Texture2D */ private Texture2D BinaryImage2Texture(BinaryImage b) { Texture2D t = new Texture2D(b.x, b.y); t.wrapMode = TextureWrapMode.Clamp; for (int x = 0; x < t.width; x++) { for (int y = 0; y < t.height; y++) { t.SetPixel(x, y, b.Get(x + y * b.x) ? Color.white : Color.black); // if true then white else black } } t.Apply(); return(t); }
// returns true if found a start point private bool findStartPos(ref BinaryImage b, ref int startPos) { int w = b.x, h = b.y; for (int x = 0; x < w; x++) { for (int y = 0; y < h; y++) { if (b.Get(x + y * w)) { startPos = x + y * w; return(true); } } } return(false); // Cannot find any start points. }
private Texture2D ApplyBinaryImage2Texture(ref Texture2D tex, ref BinaryImage b) { Texture2D t = new Texture2D(b.x, b.y); t.wrapMode = TextureWrapMode.Clamp; Color[] data = tex.GetPixels(); for (int x = 0; x < b.Length; x++) { if (!b.Get(x)) { data[x].a = 0; } } t.SetPixels(data); t.Apply(); return(t); }
/** * Subtracts one binaryImage from another * @param {BinaryImage} b1 [description] * @param {BinaryImage} b2 [description] * @return {BinaryImage} [description] */ private BinaryImage subtraction(BinaryImage b1, BinaryImage b2) { BinaryImage t = new BinaryImage(b1.x, b1.y); int w = b1.x; // width int h = b1.y; // height for(int x=0; x<w; x++){ for(int y=0; y<h; y++){ t.Set(x+y*w, (b1.Get(x+y*w)!=b2.Get(x+y*w)) ); } } return t; }
void split(BinaryImage b) { int startPos; // TODO: copy the binaryImage instead of setting it BinaryImage t = new BinaryImage(b.x, b.y); for(int x=0; x<b.Length; x++) t.Set(x, b.Get(x)); List<List<int> > islands = new List<List<int> >(); // Find islands while(findStartPos(ref t, out startPos)) { List<int> island = new List<int>(); floodFill(ref t, ref island, startPos); islands.Add(island); } // If there is only 1 island we wont split anything if(islands.Count <= 1) return; // Get bounding boxes for each island for(int i=0; i<islands.Count; i++) { int x1, y1, x2, y2; x1 = x2 = islands[i][0]%b.x; y1 = y2 = Mathf.FloorToInt((float)islands[i][0]/b.x); // Find the smallest and biggest points for(int j=0; j<islands[i].Count; j++) { int x = islands[i][j]%b.x, y = Mathf.FloorToInt((float)islands[i][j]/b.x); if(x < x1) x1 = x; else if(x > x2) x2 = x; if(y < y1) y1 = y; else if(y > y2) y2 = y; } int w = x2-x1, h = y2-y1; // bounds int cx = (x2+x1)/2, cy = (y2+y1)/2; // new center for island // Create new gameobject GameObject go = new GameObject("DestructibleSpritePiece"); go.AddComponent<SpriteRenderer>(); go.AddComponent<Rigidbody2D>(); go.AddComponent<DestructibleSprite>(); go.GetComponent<DestructibleSprite>().doSplit = true; // Copy part of the original texture to our new texture Color32[] d = tex.GetPixels32(); Color32[] e = new Color32[w*h]; for(int x=0, y=0; x<d.Length; x++) { if(x%tex.width>=x1 && x%tex.width<x2 && Mathf.FloorToInt((float)x/tex.width)<y2 && Mathf.FloorToInt((float)x/tex.width)>=y1) { e[y] = d[x]; y++; } } // Apply to our new texture Texture2D texture = new Texture2D(w,h); texture.SetPixels32(e); texture.Apply(); // Add the spriteRenderer and apply the texture and inherit parent options SpriteRenderer s = go.GetComponent<SpriteRenderer>(); s.sprite = Sprite.Create(texture, new Rect(0, 0, texture.width, texture.height), new Vector2(0.5f, 0.5f)); s.color = gameObject.GetComponent<SpriteRenderer>().color; s.sortingOrder = gameObject.GetComponent<SpriteRenderer>().sortingOrder; // Set the position to the new center go.transform.position = new Vector3(transform.position.x + (cx + pixelOffset)/pixelsToUnits - xBounds, transform.position.y + (cy + pixelOffset)/pixelsToUnits - yBounds, transform.position.z); // Put it in the same layer as the parent go.layer = gameObject.layer; } // We can destroy the orignal object Destroy(gameObject); }
// Get the adjancent point private bool nextPos(ref BinaryImage b, ref int pos, ref int currPos, ref int prevPos) { int w = b.x; if( currPos+w < b.Length && b.Get(currPos+w) && (currPos+w)!=prevPos) pos = currPos+w; // Top else if((currPos%w)+1 < w && b.Get(currPos+1) && (currPos+1)!=prevPos) pos = currPos+1; // Right else if(currPos-w >= 0 && b.Get(currPos-w) && (currPos-w)!=prevPos) pos = currPos-w; // Bottom else if((currPos%w)-1 >= 0 && b.Get(currPos-1) && (currPos-1)!=prevPos) pos = currPos-1; // Left else return false; // None // Update values prevPos = currPos; currPos = pos; return true; }
// Get the initial adjancent point private bool nextPos(ref BinaryImage b, ref int pos, int prevPos) { int w = b.x; if( prevPos+w < b.Length && b.Get(prevPos+w)) pos = prevPos+w; // Top else if((prevPos%w)+1 < w && b.Get(prevPos+1)) pos = prevPos+1; // Right else if(prevPos-w >= 0 && b.Get(prevPos-w)) pos = prevPos-w; // Bottom else if((prevPos%w)-1 >= 0 && b.Get(prevPos-1)) pos = prevPos-1; // Left else return false; // single pixel island return true; }
void floodFill(ref BinaryImage b, ref List<int> i, int pos) { int w = b.x; if(b.Get(pos)) { i.Add(pos); b.Set(pos, false); } else return; if((pos%w)+1 < w) floodFill(ref b, ref i, pos+1); // Right if((pos%w)-1 >= 0) floodFill(ref b, ref i, pos-1); // Left if(pos+w < b.Length) floodFill(ref b, ref i, pos+w); // Top if(pos-w >= 0) floodFill(ref b, ref i, pos-w); // Bottom }
// returns true if found a start point private bool findStartPos(ref BinaryImage b, out int startPos) { int w = b.x, h = b.y; for(int x= 0; x<w; x++){ for(int y= 0; y<h; y++){ if(b.Get(x + y*w)) { startPos = x + y*w; return true; } } } startPos = 0; return false; // Cannot find any start points. }
/** * If there is any true bits in a 3x3 grid make the centre bit false * @param {BinaryImage} ref BinaryImage b [description] * @return {BinaryImage} The erosion image */ private BinaryImage erosion(BinaryImage b) { int[,] dirs = {{0,1},{1,1},{1,0},{1,-1},{0,-1},{-1,-1},{-1,0},{-1,1}}; BinaryImage t = new BinaryImage(b.x, b.y, true); int w = b.x; // width int h = b.y; // height for(int x=0; x<w; x++) { for(int y=0; y<h; y++) { // t.Set(x + y*w, true); for(int z=0; z<dirs.GetLength(0); z++) { int i = x+dirs[z,0], j = y+dirs[z,1]; if(i<w && i>=0 && j<h && j>=0) { if(!b.Get(i + j*w)) t.Set(x + y*w, false); } else t.Set(x + y*w, false); } } } return t; }
void split(BinaryImage b) { int startPos; // TODO: copy the binaryImage instead of setting it BinaryImage t = new BinaryImage(b.x, b.y); for (int x = 0; x < b.Length; x++) { t.Set(x, b.Get(x)); } List <List <int> > islands = new List <List <int> >(); // Find islands while (findStartPos(ref t, out startPos)) { List <int> island = new List <int>(); floodFill(ref t, ref island, startPos); islands.Add(island); } // If there is only 1 island we wont split anything if (islands.Count <= 1) { return; } // Get bounding boxes for each island for (int i = 0; i < islands.Count; i++) { int x1, y1, x2, y2; x1 = x2 = islands[i][0] % b.x; y1 = y2 = Mathf.FloorToInt((float)islands[i][0] / b.x); // Find the smallest and biggest points for (int j = 0; j < islands[i].Count; j++) { int x = islands[i][j] % b.x, y = Mathf.FloorToInt((float)islands[i][j] / b.x); if (x < x1) { x1 = x; } else if (x > x2) { x2 = x; } if (y < y1) { y1 = y; } else if (y > y2) { y2 = y; } } int w = x2 - x1, h = y2 - y1; // bounds int cx = (x2 + x1) / 2, cy = (y2 + y1) / 2; // new center for island // Create new gameobject GameObject go = new GameObject("DestructibleSpritePiece"); go.AddComponent <SpriteRenderer>(); go.AddComponent <Rigidbody2D>(); go.AddComponent <DestructibleSprite>(); go.GetComponent <DestructibleSprite>().doSplit = true; // Copy part of the original texture to our new texture Color32[] d = tex.GetPixels32(); Color32[] e = new Color32[w * h]; for (int x = 0, y = 0; x < d.Length; x++) { if (x % tex.width >= x1 && x % tex.width < x2 && Mathf.FloorToInt((float)x / tex.width) < y2 && Mathf.FloorToInt((float)x / tex.width) >= y1) { e[y] = d[x]; y++; } } // Apply to our new texture Texture2D texture = new Texture2D(w, h); texture.SetPixels32(e); texture.Apply(); // Add the spriteRenderer and apply the texture and inherit parent options SpriteRenderer s = go.GetComponent <SpriteRenderer>(); s.sprite = Sprite.Create(texture, new Rect(0, 0, texture.width, texture.height), new Vector2(0.5f, 0.5f)); s.color = gameObject.GetComponent <SpriteRenderer>().color; s.sortingOrder = gameObject.GetComponent <SpriteRenderer>().sortingOrder; // Set the position to the new center go.transform.position = new Vector3(transform.position.x + (cx + pixelOffset) / pixelsToUnits - xBounds, transform.position.y + (cy + pixelOffset) / pixelsToUnits - yBounds, transform.position.z); // Put it in the same layer as the parent go.layer = gameObject.layer; } // We can destroy the orignal object Destroy(gameObject); }
private Texture2D ApplyBinaryImage2Texture(ref Texture2D tex, ref BinaryImage b) { Texture2D t = new Texture2D(b.x, b.y); t.wrapMode = TextureWrapMode.Clamp; Color[] data = tex.GetPixels(); for(int x=0; x<b.Length; x++){ if(!b.Get(x)) data[x].a = 0; } t.SetPixels(data); t.Apply(); return t; }
private int backTrack(ref BinaryImage b, ref List<Vector2> path, int start) { int w = b.x; if(start <= 1) return -1; int currPos = (int)path[start].x + (int)path[start].y*w; int prevPos = (int)path[start-1].x + (int)path[start-1].y*w; if(currPos+w < b.Length && b.Get(currPos+w) && (currPos+w)!=prevPos || // Top (currPos%w)+1 < w && b.Get(currPos+1) && (currPos+1)!=prevPos || // Right currPos-w >= 0 && b.Get(currPos-w) && (currPos-w)!=prevPos || // Bottom (currPos%w)-1 >= 0 && b.Get(currPos-1) && (currPos-1)!=prevPos) { // Left return start; } else { // if we cannot find any new points set back again. start = backTrack(ref b, ref path, start-1); } return start>0?start:-1; }
/** * Helper function to generate a Texture2D from a BinaryImage * @param {BinaryImage} b The BinaryImage to be converted to a Texture2D * @return {Texture2D} The generated Texture2D */ private Texture2D BinaryImage2Texture(BinaryImage b) { Texture2D t = new Texture2D(b.x, b.y); t.wrapMode = TextureWrapMode.Clamp; for(int x=0; x<t.width; x++) { for(int y=0; y<t.height; y++) { t.SetPixel(x, y, b.Get(x + y*b.x) ? Color.white : Color.black); // if true then white else black } } t.Apply(); return t; }