Advertisement
Guest User

Untitled

a guest
Jun 9th, 2016
80
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 23.99 KB | None | 0 0
  1. using UnityEngine;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using System;
  5.  
  6. [RequireComponent(typeof(PolygonCollider2D))]
  7. public class DestructibleSprite : MonoBehaviour
  8. {
  9.  
  10.     public Texture2D tex;
  11.  
  12.     // Testing
  13.     public bool doInit = true;
  14.     public bool doSplit = false;
  15.  
  16.     public bool terrain = false;
  17.     public float terrainStretch = 10f;
  18.     public static string seed;
  19.  
  20.     public bool doRefresh;
  21.     public bool doBI;
  22.     public bool doErosion;
  23.     public bool doDilation;
  24.     public bool doSub;
  25.     public bool doSub2;
  26.     public bool doVert;
  27.     public bool doVertLong;
  28.     public bool doComplete;
  29.  
  30.     public float pixelsToUnits = 100f; // Pixels to unity units  100 to 1
  31.     public float pixelOffset = 0.5f;
  32.  
  33.     private BinaryImage binaryImage;
  34.  
  35.     PolygonCollider2D poly;
  36.  
  37.     public float xBounds;
  38.     public float yBounds;
  39.  
  40.     public int islandCount = 0;
  41.  
  42.     private List<Vector2> tempPath;
  43.     private Vector2 endPoint;
  44.  
  45.     // Use this for initialization
  46.     void Start()
  47.     {
  48.         poly = gameObject.GetComponent<PolygonCollider2D>();
  49.         tex = Instantiate(gameObject.GetComponent<SpriteRenderer>().sprite.texture) as Texture2D;
  50.  
  51.         xBounds = gameObject.GetComponent<SpriteRenderer>().sprite.bounds.extents.x;
  52.         yBounds = gameObject.GetComponent<SpriteRenderer>().sprite.bounds.extents.y;
  53.         if (doInit)
  54.         {
  55.             if (terrain)
  56.             {
  57.                 StartCoroutine(GenerateTerrain());
  58.             }
  59.             else
  60.             {
  61.                 binaryImage = BinaryImageFromTex(ref tex);
  62.                 binaryImage = tidyBinaryImage(binaryImage);
  63.                 updateCollider();
  64.             }
  65.         }
  66.     }
  67.  
  68.     IEnumerator GenerateTerrain()
  69.     {
  70.         float t = Time.time;
  71.         yield return new WaitForEndOfFrame();
  72.         SimplexNoiseGenerator sng = new SimplexNoiseGenerator(seed);
  73.         BinaryImage bi = new BinaryImage(tex.width, tex.height, false);
  74.         for (int x = 0; x < tex.width; x++)
  75.         {
  76.             float height = sng.coherentNoise(x / terrainStretch + (transform.position.x * terrainStretch), 0, 0, 1, 200, 1.75f, 2f, 0.9f);
  77.             height += sng.coherentNoise(x / terrainStretch + (transform.position.x * terrainStretch), 0, 0, 2, 25, 0.05f, 2f, 0.9f);
  78.             height += sng.coherentNoise(x / terrainStretch + (transform.position.x * terrainStretch), 0, 0, 1, 25, 0.1f, 2f, 0.9f);
  79.             for (int y = 0; y < tex.height; y++)
  80.             {
  81.                 if (y < height * tex.height + 500)
  82.                     bi.Set(x, y, true);
  83.                 else
  84.                     break;
  85.             }
  86.         }
  87.         binaryImage = bi;
  88.         binaryImage = tidyBinaryImage(binaryImage);
  89.         updateCollider();
  90.         Debug.Log((Time.time - t) * 1000f);
  91.     }
  92.  
  93.     public void SetBinaryImage(BinaryImage b)
  94.     {
  95.         binaryImage = b;
  96.         binaryImage = tidyBinaryImage(binaryImage);
  97.         updateCollider();
  98.     }
  99.  
  100.     void Update()
  101.     {
  102.  
  103.         if (doRefresh)
  104.         {
  105.             doRefresh = false;
  106.             gameObject.GetComponent<SpriteRenderer>().sprite = Sprite.Create(tex, gameObject.GetComponent<SpriteRenderer>().sprite.rect, new Vector2(0.5f, 0.5f));
  107.         }
  108.  
  109.         if (doBI)
  110.         {
  111.             doBI = false;
  112.  
  113.             binaryImage = BinaryImageFromTex(ref tex);
  114.  
  115.             gameObject.GetComponent<SpriteRenderer>().sprite = Sprite.Create(BinaryImage2Texture(binaryImage), gameObject.GetComponent<SpriteRenderer>().sprite.rect, new Vector2(0.5f, 0.5f));
  116.         }
  117.  
  118.         if (doErosion)
  119.         {
  120.             doErosion = false;
  121.  
  122.             binaryImage = BinaryImageFromTex(ref tex);
  123.  
  124.             gameObject.GetComponent<SpriteRenderer>().sprite = Sprite.Create(BinaryImage2Texture(erosion(binaryImage)), gameObject.GetComponent<SpriteRenderer>().sprite.rect, new Vector2(0.5f, 0.5f));
  125.         }
  126.  
  127.         if (doDilation)
  128.         {
  129.             doDilation = false;
  130.  
  131.             binaryImage = BinaryImageFromTex(ref tex);
  132.  
  133.             gameObject.GetComponent<SpriteRenderer>().sprite = Sprite.Create(BinaryImage2Texture(dilation(binaryImage)), gameObject.GetComponent<SpriteRenderer>().sprite.rect, new Vector2(0.5f, 0.5f));
  134.         }
  135.  
  136.         if (doSub)
  137.         {
  138.             doSub = false;
  139.  
  140.             binaryImage = BinaryImageFromTex(ref tex);
  141.             binaryImage = tidyBinaryImage(binaryImage);
  142.  
  143.             gameObject.GetComponent<SpriteRenderer>().sprite = Sprite.Create(BinaryImage2Texture(subtraction(binaryImage, erosion(binaryImage))), gameObject.GetComponent<SpriteRenderer>().sprite.rect, new Vector2(0.5f, 0.5f));
  144.         }
  145.  
  146.         if (doSub2)
  147.         {
  148.             doSub2 = false;
  149.  
  150.             binaryImage = BinaryImageFromTex(ref tex);
  151.             binaryImage = tidyBinaryImage(binaryImage);
  152.  
  153.             gameObject.GetComponent<SpriteRenderer>().sprite = Sprite.Create(BinaryImage2Texture(subtraction(binaryImage, erosion(binaryImage))), gameObject.GetComponent<SpriteRenderer>().sprite.rect, new Vector2(0.5f, 0.5f));
  154.         }
  155.  
  156.         if (doVert)
  157.         {
  158.             doVert = false;
  159.  
  160.             binaryImage = BinaryImageFromTex(ref tex);
  161.             binaryImage = tidyBinaryImage(binaryImage);
  162.             BinaryImage binaryImageOutline = subtraction(binaryImage, erosion(binaryImage));
  163.             List<List<Vector2>> paths = getPaths(ref binaryImageOutline);
  164.             gameObject.GetComponent<SpriteRenderer>().sprite = Sprite.Create(BinaryImage2TextureUsingPaths(binaryImageOutline, paths), gameObject.GetComponent<SpriteRenderer>().sprite.rect, new Vector2(0.5f, 0.5f));
  165.  
  166.             setCollider(ref paths);
  167.         }
  168.  
  169.         if (doVertLong)
  170.         {
  171.             doVertLong = false;
  172.  
  173.             // TODO: simplify paths farther
  174.             print("doVertLong has not been made yet :3");
  175.  
  176.             gameObject.GetComponent<SpriteRenderer>().sprite = Sprite.Create(BinaryImage2Texture(binaryImage), gameObject.GetComponent<SpriteRenderer>().sprite.rect, new Vector2(0.5f, 0.5f));
  177.         }
  178.  
  179.         if (doComplete)
  180.         {
  181.             doComplete = false;
  182.  
  183.             binaryImage = BinaryImageFromTex(ref tex);
  184.             binaryImage = tidyBinaryImage(binaryImage);
  185.             updateCollider();
  186.         }
  187.     }
  188.  
  189.     void split(BinaryImage b)
  190.     {
  191.         int startPos;
  192.  
  193.         // TODO: copy the binaryImage instead of setting it
  194.         BinaryImage t = new BinaryImage(b.x, b.y);
  195.         for (int x = 0; x < b.Length; x++) t.Set(x, b.Get(x));
  196.  
  197.         List<List<int>> islands = new List<List<int>>();
  198.  
  199.         // Find islands
  200.         while (findStartPos(ref t, out startPos))
  201.         {
  202.             List<int> island = new List<int>();
  203.  
  204.             floodFill(ref t, ref island, startPos);
  205.  
  206.             islands.Add(island);
  207.         }
  208.  
  209.         // If there is only 1 island we wont split anything
  210.         if (islands.Count <= 1) return;
  211.  
  212.         // Get bounding boxes for each island
  213.         for (int i = 0; i < islands.Count; i++)
  214.         {
  215.             int x1, y1, x2, y2;
  216.             x1 = x2 = islands[i][0] % b.x;
  217.             y1 = y2 = Mathf.FloorToInt((float)islands[i][0] / b.x);
  218.  
  219.             // Find the smallest and biggest points
  220.             for (int j = 0; j < islands[i].Count; j++)
  221.             {
  222.                 int x = islands[i][j] % b.x, y = Mathf.FloorToInt((float)islands[i][j] / b.x);
  223.                 if (x < x1) x1 = x;
  224.                 else if (x > x2) x2 = x;
  225.                 if (y < y1) y1 = y;
  226.                 else if (y > y2) y2 = y;
  227.             }
  228.  
  229.             int w = x2 - x1, h = y2 - y1; // bounds
  230.             int cx = (x2 + x1) / 2, cy = (y2 + y1) / 2; // new center for island
  231.  
  232.             // Create new gameobject
  233.             GameObject go = new GameObject("DestructibleSpritePiece");
  234.             go.AddComponent<SpriteRenderer>();
  235.             go.AddComponent<Rigidbody2D>();
  236.             go.AddComponent<DestructibleSprite>();
  237.             go.GetComponent<DestructibleSprite>().doSplit = true;
  238.  
  239.             // Copy part of the original texture to our new texture
  240.             Color32[] d = tex.GetPixels32();
  241.             Color32[] e = new Color32[w * h];
  242.             for (int x = 0, y = 0; x < d.Length; x++)
  243.             {
  244.                 if (x % tex.width >= x1 && x % tex.width < x2 && Mathf.FloorToInt((float)x / tex.width) < y2 && Mathf.FloorToInt((float)x / tex.width) >= y1)
  245.                 {
  246.                     e[y] = d[x];
  247.                     y++;
  248.                 }
  249.             }
  250.  
  251.             // Apply to our new texture
  252.             Texture2D texture = new Texture2D(w, h);
  253.             texture.SetPixels32(e);
  254.             texture.Apply();
  255.  
  256.             // Add the spriteRenderer and apply the texture and inherit parent options
  257.             SpriteRenderer s = go.GetComponent<SpriteRenderer>();
  258.             s.sprite = Sprite.Create(texture, new Rect(0, 0, texture.width, texture.height), new Vector2(0.5f, 0.5f));
  259.             s.color = gameObject.GetComponent<SpriteRenderer>().color;
  260.             s.sortingOrder = gameObject.GetComponent<SpriteRenderer>().sortingOrder;
  261.  
  262.             // Set the position to the new center
  263.             go.transform.position = new Vector3(transform.position.x + (cx + pixelOffset) / pixelsToUnits - xBounds, transform.position.y + (cy + pixelOffset) / pixelsToUnits - yBounds, transform.position.z);
  264.             // Put it in the same layer as the parent
  265.             go.layer = gameObject.layer;
  266.  
  267.         }
  268.         // We can destroy the orignal object
  269.         Destroy(gameObject);
  270.     }
  271.  
  272.     void floodFill(ref BinaryImage b, ref List<int> i, int pos)
  273.     {
  274.         int w = b.x;
  275.  
  276.         if (b.Get(pos))
  277.         {
  278.             i.Add(pos);
  279.             b.Set(pos, false);
  280.         }
  281.         else return;
  282.  
  283.         if ((pos % w) + 1 < w) floodFill(ref b, ref i, pos + 1);                // Right
  284.         if ((pos % w) - 1 >= 0) floodFill(ref b, ref i, pos - 1);           // Left
  285.         if (pos + w < b.Length) floodFill(ref b, ref i, pos + w);       // Top
  286.         if (pos - w >= 0) floodFill(ref b, ref i, pos - w);                 // Bottom
  287.     }
  288.  
  289.     /**
  290.      * Remove a part of the texture
  291.      * @param  {Vector2} point         World point
  292.      * @param  {int}     radius        Radius of destroyed area
  293.      */
  294.     public void ApplyDamage(Vector2 point, int radius)
  295.     {
  296.         StartCoroutine(AD(point, radius));
  297.     }
  298.  
  299.     IEnumerator AD(Vector2 point, int radius)
  300.     {
  301.         yield return new WaitForEndOfFrame();
  302.         // edit binaryImage
  303.         int w = binaryImage.x, h = binaryImage.y;
  304.  
  305.         // get relative position of the circle
  306.         Vector2 rPos = new Vector2(point.x - transform.position.x, point.y - transform.position.y);
  307.  
  308.         // get rotation matrix
  309.         float theta = transform.rotation.eulerAngles.z * Mathf.PI / 180f;
  310.         float sin = Mathf.Sin(theta);
  311.         float cos = Mathf.Cos(theta);
  312.  
  313.         // apply rotation to the circle centre
  314.         Vector2 c = new Vector2(rPos.x * cos + rPos.y * sin, -rPos.x * sin + rPos.y * cos);
  315.  
  316.         c.x = (xBounds + (c.x / transform.localScale.x)) / (xBounds * 2) * w;
  317.         c.y = (yBounds + (c.y / transform.localScale.y)) / (yBounds * 2) * h;
  318.         int loops = 0;
  319.         for (int x = 0; x < w; x++)
  320.         {
  321.             for (int y = 0; y < h; y++)
  322.             {
  323.                 float dx = x - c.x;
  324.                 float dy = y - c.y;
  325.                 float dist = Mathf.Sqrt(dx * dx + dy * dy);
  326.                 if (dist <= radius)
  327.                 {
  328.                     binaryImage.Set(x + y * w, false);
  329.                     loops++;
  330.                 }
  331.             }
  332.         }
  333.         Debug.Log(loops);
  334.         updateCollider();
  335.     }
  336.  
  337.     // TODO: make into a coroutine?/separate thread
  338.     private void updateCollider()
  339.     {
  340.         StartCoroutine(UC());
  341.     }
  342.  
  343.     IEnumerator UC()
  344.     {
  345.         yield return new WaitForEndOfFrame();
  346.         tex = ApplyBinaryImage2Texture(ref tex, ref binaryImage);
  347.         if (doSplit) split(binaryImage);
  348.  
  349.         // binaryImage = tidyBinaryImage(binaryImage);
  350.         BinaryImage binaryImageOutline = subtraction(binaryImage, erosion(binaryImage));
  351.         List<List<Vector2>> paths = getPaths(ref binaryImageOutline);
  352.  
  353.         gameObject.GetComponent<SpriteRenderer>().sprite = Sprite.Create(tex, gameObject.GetComponent<SpriteRenderer>().sprite.rect, new Vector2(0.5f, 0.5f));
  354.  
  355.         setCollider(ref paths);
  356.     }
  357.  
  358.     private void setCollider(ref List<List<Vector2>> paths)
  359.     {
  360.         poly.pathCount = paths.Count;
  361.         islandCount = paths.Count;
  362.  
  363.         for (int i = 0; i < paths.Count; i++)
  364.         {
  365.             for (int j = 0; j < paths[i].Count; j++)
  366.             {
  367.                 paths[i][j] = new Vector2((paths[i][j].x + pixelOffset) / pixelsToUnits - xBounds, (paths[i][j].y + pixelOffset) / pixelsToUnits - yBounds);
  368.             }
  369.             poly.SetPath(i, paths[i].ToArray());
  370.         }
  371.     }
  372.  
  373.     // returns true if found a start point
  374.     private bool findStartPos(ref BinaryImage b, out int startPos)
  375.     {
  376.         int w = b.x, h = b.y;
  377.  
  378.         for (int x = 0; x < w; x++)
  379.         {
  380.             for (int y = 0; y < h; y++)
  381.             {
  382.                 if (b.Get(x + y * w))
  383.                 {
  384.                     startPos = x + y * w;
  385.                     return true;
  386.                 }
  387.             }
  388.         }
  389.  
  390.         startPos = 0;
  391.         return false; // Cannot find any start points.
  392.     }
  393.  
  394.     private List<List<Vector2>> getPaths(ref BinaryImage b)
  395.     {
  396.         int startPos;
  397.         List<List<Vector2>> paths = new List<List<Vector2>>();
  398.  
  399.         while (findStartPos(ref b, out startPos))
  400.         {
  401.             List<Vector2> path = new List<Vector2>();
  402.  
  403.             // Find path
  404.             path = getPath(ref b, startPos);
  405.             if (path != null) paths.Add(path);
  406.         }
  407.  
  408.         for (int i = 0; i < paths.Count; i++) paths[i] = simplify(ref b, paths[i]);
  409.  
  410.         return paths;
  411.     }
  412.  
  413.     private List<Vector2> getPath(ref BinaryImage b, int startPos)
  414.     {
  415.         List<Vector2> path = new List<Vector2>();
  416.  
  417.         // Add start point to path
  418.         path.Add(new Vector2(startPos % b.x, startPos / b.x));
  419.  
  420.         int pos = 0, prevPos = startPos, currPos = startPos;
  421.         bool open = true;
  422.  
  423.         if (!nextPos(ref b, ref pos, prevPos))
  424.         {
  425.             // No other points found from the starting point means this is a single pixel island so we can remove it
  426.             b.Set(currPos, false);
  427.             return null;
  428.         }
  429.  
  430.         // While there is a next pos
  431.         while (open)
  432.         {
  433.             if (nextPos(ref b, ref pos, ref currPos, ref prevPos))
  434.             {
  435.                 // b.Set(pos, false);
  436.                 if (currPos == startPos) open = false; // We found a closed path
  437.                 path.Add(new Vector2(currPos % b.x, currPos / b.x));
  438.                 b.Set(currPos, false);
  439.             }
  440.             else
  441.             {
  442.                 // If no next position, backtrack till we find a closed path
  443.                 var index = backTrack(ref b, ref path, path.Count - 1);
  444.  
  445.                 if (index != -1)
  446.                 {
  447.                     // find next new point!
  448.                     path.RemoveRange(index + 1, path.Count - 1 - index);
  449.  
  450.                     pos = (int)path[index].x + (int)path[index].y * b.x;
  451.                     prevPos = (int)path[index - 1].x + (int)path[index - 1].y * b.x;
  452.                     currPos = pos;
  453.  
  454.                 }
  455.                 else open = false; // If we cannot, close the path (this is the worst case and will give us a buggy collider)
  456.             }
  457.         }
  458.  
  459.         return path;
  460.     }
  461.  
  462.     private int backTrack(ref BinaryImage b, ref List<Vector2> path, int start)
  463.     {
  464.         int w = b.x;
  465.  
  466.         if (start <= 1) return -1;
  467.         int currPos = (int)path[start].x + (int)path[start].y * w;
  468.         int prevPos = (int)path[start - 1].x + (int)path[start - 1].y * w;
  469.  
  470.         if (currPos + w < b.Length && b.Get(currPos + w) && (currPos + w) != prevPos ||     // Top
  471.             (currPos % w) + 1 < w && b.Get(currPos + 1) && (currPos + 1) != prevPos ||      // Right
  472.             currPos - w >= 0 && b.Get(currPos - w) && (currPos - w) != prevPos ||       // Bottom
  473.             (currPos % w) - 1 >= 0 && b.Get(currPos - 1) && (currPos - 1) != prevPos)
  474.         {           // Left
  475.             return start;
  476.         }
  477.         else
  478.         {           // if we cannot find any new points set back again.
  479.             start = backTrack(ref b, ref path, start - 1);
  480.         }
  481.  
  482.         return start > 0 ? start : -1;
  483.     }
  484.  
  485.     // Get the initial adjancent point
  486.     private bool nextPos(ref BinaryImage b, ref int pos, int prevPos)
  487.     {
  488.         int w = b.x;
  489.  
  490.         if (prevPos + w < b.Length && b.Get(prevPos + w)) pos = prevPos + w;        // Top
  491.         else if ((prevPos % w) + 1 < w && b.Get(prevPos + 1)) pos = prevPos + 1;        // Right
  492.         else if (prevPos - w >= 0 && b.Get(prevPos - w)) pos = prevPos - w;     // Bottom
  493.         else if ((prevPos % w) - 1 >= 0 && b.Get(prevPos - 1)) pos = prevPos - 1;       // Left
  494.         else return false; // single pixel island
  495.  
  496.         return true;
  497.     }
  498.  
  499.     // Get the adjancent point
  500.     private bool nextPos(ref BinaryImage b, ref int pos, ref int currPos, ref int prevPos)
  501.     {
  502.         int w = b.x;
  503.  
  504.         if (currPos + w < b.Length && b.Get(currPos + w) && (currPos + w) != prevPos) pos = currPos + w;        // Top
  505.         else if ((currPos % w) + 1 < w && b.Get(currPos + 1) && (currPos + 1) != prevPos) pos = currPos + 1;        // Right
  506.         else if (currPos - w >= 0 && b.Get(currPos - w) && (currPos - w) != prevPos) pos = currPos - w;     // Bottom
  507.         else if ((currPos % w) - 1 >= 0 && b.Get(currPos - 1) && (currPos - 1) != prevPos) pos = currPos - 1;       // Left
  508.         else return false;                                                                                                                                                      // None
  509.  
  510.         // Update values
  511.         prevPos = currPos;
  512.         currPos = pos;
  513.  
  514.         return true;
  515.     }
  516.  
  517.     // first stage of similification
  518.     // Determine if we need to add this point(vertex) to the path
  519.     private List<Vector2> simplify(ref BinaryImage b, List<Vector2> path)
  520.     {
  521.         List<Vector2> t = new List<Vector2>();
  522.  
  523.         t.Add(path[0]);
  524.  
  525.         // remove straight line vertices
  526.         for (int i = 1; i < path.Count - 1; i++)
  527.         {
  528.             if (path[i - 1].x != path[i + 1].x && path[i - 1].y != path[i + 1].y)
  529.             {
  530.                 t.Add(path[i]);
  531.             }
  532.         }
  533.  
  534.         // TODO: clean this up
  535.         // give the points a weight A(k)=ab/2, a = [k-1]-k, b = [k+1]-k
  536.         float[] weight = new float[t.Count];
  537.         for (int k = 1; k < t.Count - 1; k++)
  538.         {
  539.             Vector2 i = t[k - 1] - t[k], j = t[k + 1] - t[k];
  540.  
  541.             weight[k] = ((Mathf.Sqrt(i.x * i.x + i.y * i.y)) * (Mathf.Sqrt(j.x * j.x + j.y * j.y)) / 2);
  542.         }
  543.  
  544.         List<Vector2> p = new List<Vector2>();
  545.         p.Add(t[0]);
  546.         for (int i = 1; i < t.Count - 1; i++)
  547.         {
  548.             if (weight[i] > 1) p.Add(t[i]); // TODO: find better constant / average weight? W = (w0+..+wk) / k
  549.         }
  550.         p.Add(t[t.Count - 1]);
  551.  
  552.         return p;
  553.     }
  554.  
  555.     /**
  556.      * Subtracts one binaryImage from another
  557.      * @param  {BinaryImage}  b1            [description]
  558.      * @param  {BinaryImage}  b2            [description]
  559.      * @return {BinaryImage}             [description]
  560.      */
  561.     private BinaryImage subtraction(BinaryImage b1, BinaryImage b2)
  562.     {
  563.         BinaryImage t = new BinaryImage(b1.x, b1.y);
  564.  
  565.         int w = b1.x; // width
  566.         int h = b1.y; // height
  567.  
  568.         for (int x = 0; x < w; x++)
  569.         {
  570.             for (int y = 0; y < h; y++)
  571.             {
  572.                 t.Set(x + y * w, (b1.Get(x + y * w) != b2.Get(x + y * w)));
  573.             }
  574.         }
  575.         return t;
  576.     }
  577.  
  578.     /**
  579.      * If there is any true bits in a 3x3 grid make the centre bit false
  580.      * @param  {BinaryImage} ref BinaryImage   b [description]
  581.      * @return {BinaryImage}     The erosion image
  582.      */
  583.     private BinaryImage erosion(BinaryImage b)
  584.     {
  585.         int[,] dirs = { { 0, 1 }, { 1, 1 }, { 1, 0 }, { 1, -1 }, { 0, -1 }, { -1, -1 }, { -1, 0 }, { -1, 1 } };
  586.         BinaryImage t = new BinaryImage(b.x, b.y, true);
  587.  
  588.         int w = b.x; // width
  589.         int h = b.y;    // height
  590.  
  591.         for (int x = 0; x < w; x++)
  592.         {
  593.             for (int y = 0; y < h; y++)
  594.             {
  595.                 // t.Set(x + y*w, true);
  596.                 for (int z = 0; z < dirs.GetLength(0); z++)
  597.                 {
  598.                     int i = x + dirs[z, 0], j = y + dirs[z, 1];
  599.                     if (i < w && i >= 0 && j < h && j >= 0)
  600.                     {
  601.                         if (!b.Get(i + j * w)) t.Set(x + y * w, false);
  602.                     }
  603.                     else t.Set(x + y * w, false);
  604.                 }
  605.             }
  606.         }
  607.         return t;
  608.     }
  609.  
  610.     /**
  611.      * If the centre of a 3x3 is true then make the whole grid true
  612.      * @param  {BinaryImage} ref BinaryImage   b [description]
  613.      * @return {BinaryImage}     The dilated image
  614.      */
  615.     private BinaryImage dilation(BinaryImage b)
  616.     {
  617.         int[,] dirs = { { 0, 1 }, { 1, 1 }, { 1, 0 }, { 1, -1 }, { 0, -1 }, { -1, -1 }, { -1, 0 }, { -1, 1 } };
  618.         BinaryImage t = new BinaryImage(b.x, b.y);
  619.  
  620.         int w = b.x; // width
  621.         int h = b.y;    // height
  622.  
  623.         for (int x = 0; x < w; x++)
  624.         {
  625.             for (int y = 0; y < h; y++)
  626.             {
  627.                 if (b.Get(x + y * w))
  628.                 {
  629.                     for (int z = 0; z < dirs.GetLength(0); z++)
  630.                     {
  631.                         int i = x + dirs[z, 0], j = y + dirs[z, 1];
  632.                         if (i < w && i >= 0 && j < h && j >= 0)
  633.                             t.Set(i + j * w, true);
  634.                     }
  635.                 }
  636.             }
  637.         }
  638.         return t;
  639.     }
  640.  
  641.     /**
  642.      * Generates a BitArray from a Texture2D
  643.      * @param  {Texture2D} t []
  644.      * @return {BitArray} [description]
  645.      */
  646.     private BinaryImage BinaryImageFromTex(ref Texture2D t)
  647.     {
  648.         BinaryImage b = new BinaryImage(t.width, t.height);
  649.  
  650.         Color[] data = t.GetPixels();
  651.  
  652.         for (int x = 0; x < b.Length; x++) b.Set(x, data[x].a > 0);
  653.  
  654.         return b;
  655.     }
  656.  
  657.     private Texture2D ApplyBinaryImage2Texture(ref Texture2D tex, ref BinaryImage b)
  658.     {
  659.         Texture2D t = new Texture2D(b.x, b.y);
  660.         t.wrapMode = TextureWrapMode.Clamp;
  661.  
  662.         Color[] data = tex.GetPixels();
  663.  
  664.         for (int x = 0; x < b.Length; x++)
  665.         {
  666.             if (!b.Get(x)) data[x].a = 0;
  667.         }
  668.  
  669.         t.SetPixels(data);
  670.         t.Apply();
  671.  
  672.         return t;
  673.     }
  674.  
  675.     /**
  676.      * Helper function to generate a Texture2D from a BinaryImage
  677.      * @param  {BinaryImage} b The BinaryImage to be converted to a Texture2D
  678.      * @return {Texture2D}     The generated Texture2D
  679.      */
  680.     private Texture2D BinaryImage2Texture(BinaryImage b)
  681.     {
  682.         Texture2D t = new Texture2D(b.x, b.y);
  683.         t.wrapMode = TextureWrapMode.Clamp;
  684.  
  685.         for (int x = 0; x < t.width; x++)
  686.         {
  687.             for (int y = 0; y < t.height; y++)
  688.             {
  689.                 t.SetPixel(x, y, b.Get(x + y * b.x) ? Color.white : Color.black); // if true then white else black
  690.             }
  691.         }
  692.         t.Apply();
  693.         return t;
  694.     }
  695.  
  696.     private Texture2D BinaryImage2TextureUsingPaths(BinaryImage b, List<List<Vector2>> paths)
  697.     {
  698.         List<Color> colorList = new List<Color>() {
  699.             Color.red,
  700.             Color.green,
  701.             Color.blue,
  702.             Color.magenta,
  703.             Color.yellow
  704.         };
  705.  
  706.         Texture2D t = new Texture2D(b.x, b.y);
  707.         t.wrapMode = TextureWrapMode.Clamp;
  708.  
  709.         for (int i = 0; i < paths.Count && i < colorList.Count; i++)
  710.         {
  711.             for (int j = 0; j < paths[i].Count; j++)
  712.             {
  713.                 t.SetPixel((int)paths[i][j].x, (int)paths[i][j].y, colorList[i]);
  714.             }
  715.         }
  716.         t.Apply();
  717.         return t;
  718.     }
  719.  
  720.     private BinaryImage tidyBinaryImage(BinaryImage b)
  721.     {
  722.         return dilation(erosion(b));
  723.     }
  724. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement