//Sets the color of the triangles inside x,y,z grid cell
 public void SetColor(int x, int y, int z, Color32 color)
 {
     //if there are triangles in the cell
     if (triangleSeparation[x, y, z] != null)
     {
         int numberOfTris = triangleSeparation[x, y, z].Count;
         for (int p = 0; p < numberOfTris; p++)
         {
             MeshGridTriangle t = triangleSeparation[x, y, z].Dequeue();
             t.triangleColor     = color;
             finalColors[t.v[0]] = color;
             finalColors[t.v[1]] = color;
             finalColors[t.v[2]] = color;
             triangleSeparation[x, y, z].Enqueue(t);
         }
         m.SetColors(finalColors);
     }
 }
 //Slices the triangle into three default , firstTris and secondTris
 //Each slice can make a triangle and a quad that gets split into two triangles (firstTris and secondTris)
 public void SliceByPlane(Vector3 planePoint, Vector3 planeNormal, MeshGridIndicator meshGridIndicator)
 {
     triangleSide = 0;
     int[] sides = new int[3];
     sides[0] = CalculatePointSideOfPlane(meshGridIndicator.finalVertices[v[0]], planePoint, planeNormal);
     sides[1] = CalculatePointSideOfPlane(meshGridIndicator.finalVertices[v[1]], planePoint, planeNormal);
     sides[2] = CalculatePointSideOfPlane(meshGridIndicator.finalVertices[v[2]], planePoint, planeNormal);
     if (sides[0] == sides[1] && sides[0] == sides[2])
     {
         triangleSide = sides[0];
     }
     else if (sides[0] != sides[1] && sides[1] != sides[2] && sides[0] != sides[2])
     {
         int z = 0; int f = 1; int s = 2; int t;
         if (sides[1] == -1)
         {
             z = 1; f = 2; s = 0;
         }
         if (sides[2] == -1)
         {
             z = 2; f = 0; s = 1;
         }
         meshGridIndicator.finalVertices.Add(LinePlaneIntersection(meshGridIndicator.finalVertices[v[f]], meshGridIndicator.finalVertices[v[s]], planePoint, planeNormal));
         meshGridIndicator.finalNormals.Add((meshGridIndicator.finalNormals[v[f]] + meshGridIndicator.finalNormals[v[s]]) / 2);
         meshGridIndicator.finalUvs.Add((meshGridIndicator.finalUvs[v[f]] + meshGridIndicator.finalUvs[v[s]]) / 2);
         meshGridIndicator.finalColors.Add(meshGridIndicator.defaultColor);
         t = meshGridIndicator.finalVertices.Count - 1;
         int[] temp = new int[3] {
             v[0], v[1], v[2]
         };
         v[0] = temp[z]; v[1] = temp[f]; v[2] = t;
         AddNewTriangleVertex(meshGridIndicator, temp[z]);
         AddNewTriangleVertex(meshGridIndicator, t);
         firstTris = new MeshGridTriangle(temp[s], t + 1, t + 2, meshGridIndicator.defaultColor);
         firstTris.triangleSide = sides[s];
         triangleSide           = sides[f];
     }
     else if (sides[0] == -1 || sides[1] == -1 || sides[2] == -1)
     {
         if (sides[0] == 1 || sides[1] == 1 || sides[2] == 1)
         {
             triangleSide = 1;
         }
         else
         {
             triangleSide = 0;
         }
     }
     else
     {
         int z = 0; int f = 1; int s = 2; int t; int t2;
         if (sides[1] == sides[2])
         {
             z = 0; f = 1; s = 2;
         }
         if (sides[0] == sides[2])
         {
             z = 1; f = 2; s = 0;
         }
         if (sides[1] == sides[0])
         {
             z = 2; f = 0; s = 1;
         }
         meshGridIndicator.finalVertices.Add(LinePlaneIntersection(meshGridIndicator.finalVertices[v[z]], meshGridIndicator.finalVertices[v[f]], planePoint, planeNormal));
         t = meshGridIndicator.finalVertices.Count - 1;
         meshGridIndicator.finalNormals.Add((meshGridIndicator.finalNormals[v[z]] + meshGridIndicator.finalNormals[v[f]]) / 2);
         meshGridIndicator.finalUvs.Add((meshGridIndicator.finalUvs[v[z]] + meshGridIndicator.finalUvs[v[f]]) / 2);
         meshGridIndicator.finalColors.Add(meshGridIndicator.defaultColor);
         //second
         meshGridIndicator.finalVertices.Add(LinePlaneIntersection(meshGridIndicator.finalVertices[v[s]], meshGridIndicator.finalVertices[v[z]], planePoint, planeNormal));
         meshGridIndicator.finalNormals.Add((meshGridIndicator.finalNormals[v[s]] + meshGridIndicator.finalNormals[v[z]]) / 2);
         meshGridIndicator.finalUvs.Add((meshGridIndicator.finalUvs[v[s]] + meshGridIndicator.finalUvs[v[z]]) / 2);
         meshGridIndicator.finalColors.Add(meshGridIndicator.defaultColor);
         int[] temp = new int[3] {
             v[0], v[1], v[2]
         };
         AddNewTriangleVertex(meshGridIndicator, temp[s]);
         AddNewTriangleVertex(meshGridIndicator, t);
         firstTris = new MeshGridTriangle(temp[f], t + 2, t + 3, meshGridIndicator.defaultColor);
         firstTris.triangleSide = sides[s];
         AddNewTriangleVertex(meshGridIndicator, t);
         AddNewTriangleVertex(meshGridIndicator, t + 1);
         secondTris = new MeshGridTriangle(t + 4, temp[s], t + 5, meshGridIndicator.defaultColor);
         secondTris.triangleSide = sides[s];
         v[0]         = temp[z]; v[1] = t; v[2] = t + 1;
         triangleSide = sides[z];
     }
 }
        //Generates the sliced mesh with triangles organized in 3d grid
        public void MakeSeparation()
        {
            if (m == null)
            {
                m = new Mesh();
            }
            outside                     = null;
            triangleSeparation          = new Queue <MeshGridTriangle> [gridX.Length, gridY.Length, gridZ.Length];
            triangleSeparation[0, 0, 0] = new Queue <MeshGridTriangle>();
            int[]     tris    = mesh.triangles;
            Vector3[] verts   = mesh.vertices;
            Vector3[] normals = mesh.normals;
            Vector2[] uvs     = mesh.uv;
            finalVertices  = new List <Vector3>();
            finalNormals   = new List <Vector3>();
            finalUvs       = new List <Vector2>();
            finalColors    = new List <Color32>();
            finalTriangles = new List <int>();
            //Convert mesh triangles into MeshGridTriangle triangle
            for (int i = 0; i < tris.Length; i += 3)
            {
                triangleSeparation[0, 0, 0].Enqueue(new MeshGridTriangle(i, i + 1, i + 2, defaultColor));
                finalVertices.Add(meshPosition + Quaternion.Euler(meshRotation) * Vector3.Scale(meshScale, verts[tris[i]]));
                finalNormals.Add(Quaternion.Euler(meshRotation) * normals[tris[i]]);
                finalUvs.Add(uvs[tris[i]]);
                finalColors.Add(defaultColor);
                //second
                finalVertices.Add(meshPosition + Quaternion.Euler(meshRotation) * Vector3.Scale(meshScale, verts[tris[i + 1]]));
                finalNormals.Add(Quaternion.Euler(meshRotation) * normals[tris[i + 1]]);
                finalUvs.Add(uvs[tris[i + 1]]);
                finalColors.Add(defaultColor);
                //third
                finalVertices.Add(meshPosition + Quaternion.Euler(meshRotation) * Vector3.Scale(meshScale, verts[tris[i + 2]]));
                finalNormals.Add(Quaternion.Euler(meshRotation) * normals[tris[i + 2]]);
                finalUvs.Add(uvs[tris[i + 2]]);
                finalColors.Add(defaultColor);
            }
            //Seperate the triangles that are outside of the grid
            SeperateTriangleZones(gridOffset, Vector3.left, ref triangleSeparation[0, 0, 0], ref outside);
            SeperateTriangleZones(gridOffset, Vector3.down, ref triangleSeparation[0, 0, 0], ref outside);
            SeperateTriangleZones(gridOffset, Vector3.back, ref triangleSeparation[0, 0, 0], ref outside);

            Vector3 planePoint = gridOffset;
            float   distanceX  = 0;
            float   distanceY  = 0;
            float   distanceZ  = 0;

            //Split triangles into each cell
            for (int i = 0; i < gridX.Length; i++)
            {
                distanceY  = 0;
                distanceX += gridX[i];
                if (triangleSeparation[i, 0, 0] != null)
                {
                    if (i != gridX.Length - 1)
                    {
                        SeperateTriangleZones(gridOffset + new Vector3(distanceX, 0, 0), Vector3.right, ref triangleSeparation[i, 0, 0], ref triangleSeparation[i + 1, 0, 0]);
                    }
                    else
                    {
                        SeperateTriangleZones(gridOffset + new Vector3(distanceX, 0, 0), Vector3.right, ref triangleSeparation[i, 0, 0], ref outside);
                    }
                    distanceY = 0;
                    for (int j = 0; j < gridY.Length; j++)
                    {
                        distanceY += gridY[j];
                        if (triangleSeparation[i, j, 0] != null)
                        {
                            if (j != gridY.Length - 1)
                            {
                                SeperateTriangleZones(gridOffset + new Vector3(0, distanceY, 0), Vector3.up, ref triangleSeparation[i, j, 0], ref triangleSeparation[i, j + 1, 0]);
                            }
                            else
                            {
                                SeperateTriangleZones(gridOffset + new Vector3(0, distanceY, 0), Vector3.up, ref triangleSeparation[i, j, 0], ref outside);
                            }
                            distanceZ = 0;
                            for (int k = 0; k < gridZ.Length; k++)
                            {
                                distanceZ += gridZ[k];
                                if (triangleSeparation[i, j, k] != null)
                                {
                                    if (k != gridZ.Length - 1)
                                    {
                                        SeperateTriangleZones(gridOffset + new Vector3(0, 0, distanceZ), Vector3.forward, ref triangleSeparation[i, j, k], ref triangleSeparation[i, j, k + 1]);
                                    }
                                    else
                                    {
                                        SeperateTriangleZones(gridOffset + new Vector3(0, 0, distanceZ), Vector3.forward, ref triangleSeparation[i, j, k], ref outside);
                                    }
                                }
                            }
                        }
                    }
                }
            }
            //Set color of outside triangles
            if (outside != null)
            {
                int numberOfTris = outside.Count;
                for (int p = 0; p < numberOfTris; p++)
                {
                    MeshGridTriangle t = outside.Dequeue();
                    t.triangleColor     = outsideColor;
                    finalColors[t.v[0]] = outsideColor;
                    finalColors[t.v[1]] = outsideColor;
                    finalColors[t.v[2]] = outsideColor;
                    finalTriangles.Add(t.v[0]);
                    finalTriangles.Add(t.v[1]);
                    finalTriangles.Add(t.v[2]);
                    outside.Enqueue(t);
                }
            }
            //Set color and triangles in each cell
            for (int i = 0; i < gridX.Length; i++)
            {
                for (int j = 0; j < gridY.Length; j++)
                {
                    for (int k = 0; k < gridZ.Length; k++)
                    {
                        if (triangleSeparation[i, j, k] != null)
                        {
                            int numberOfTris = triangleSeparation[i, j, k].Count;
                            for (int p = 0; p < numberOfTris; p++)
                            {
                                MeshGridTriangle t = triangleSeparation[i, j, k].Dequeue();
                                finalTriangles.Add(t.v[0]);
                                finalTriangles.Add(t.v[1]);
                                finalTriangles.Add(t.v[2]);
                                triangleSeparation[i, j, k].Enqueue(t);
                            }
                        }
                    }
                }
            }
            //Set the mesh
            m.Clear();
            m.SetVertices(finalVertices);
            m.SetUVs(0, finalUvs);
            m.SetTriangles(finalTriangles, 0);
            m.SetColors(finalColors);
            m.RecalculateBounds();
            m.RecalculateNormals();
            m.SetNormals(finalNormals);
            m.UploadMeshData(false);
            GetComponent <MeshFilter>().mesh = m;
        }
        //Slices the mesh triangles into the next cell
        private void SeperateTriangleZones(Vector3 planePoint, Vector3 planeNormal, ref Queue <MeshGridTriangle> mainZone, ref Queue <MeshGridTriangle> other)
        {
            int numberOfTris = mainZone.Count;

            for (int j = 0; j < numberOfTris; j++)
            {
                MeshGridTriangle triangle = mainZone.Dequeue();
                triangle.SliceByPlane(planePoint, planeNormal, this);
                if (triangle.triangleSide != 0)
                {
                    if (mainZone == null)
                    {
                        mainZone = new Queue <MeshGridTriangle>();
                    }
                    mainZone.Enqueue(triangle);
                }
                else
                {
                    if (other == null)
                    {
                        other = new Queue <MeshGridTriangle>();
                    }
                    other.Enqueue(triangle);
                }
                if (triangle.firstTris != null)
                {
                    if (triangle.firstTris.triangleSide != 0)
                    {
                        if (mainZone == null)
                        {
                            mainZone = new Queue <MeshGridTriangle>();
                        }
                        mainZone.Enqueue(triangle.firstTris); triangle.firstTris = null;
                    }
                    else
                    {
                        if (other == null)
                        {
                            other = new Queue <MeshGridTriangle>();
                        }
                        other.Enqueue(triangle.firstTris); triangle.firstTris = null;
                    }
                }
                if (triangle.secondTris != null)
                {
                    if (triangle.secondTris.triangleSide != 0)
                    {
                        if (mainZone == null)
                        {
                            mainZone = new Queue <MeshGridTriangle>();
                        }
                        mainZone.Enqueue(triangle.secondTris); triangle.secondTris = null;
                    }
                    else
                    {
                        if (other == null)
                        {
                            other = new Queue <MeshGridTriangle>();
                        }
                        other.Enqueue(triangle.secondTris); triangle.secondTris = null;
                    }
                }
            }
        }