Пример #1
0
    // 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);
    }
Пример #2
0
    // 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);
    }
Пример #3
0
    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);
    }
Пример #4
0
    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
        }
    }
Пример #5
0
    /**
     * 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);
    }
Пример #6
0
    /**
     * 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);
    }
Пример #7
0
    /**
     * 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);
    }
Пример #8
0
    // 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.
    }
Пример #9
0
    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;
    }
Пример #17
0
    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;
    }