public void dfsChains(GameObject component)
        {
            List <Transform> properChildren       = this.getProperChildren(component);
            bool             previousSpheresExist = (properChildren.Count != component.transform.childCount);

            // Generate crossing for parent sphere
            Vector3[] parentCorners;
            // Cross a section through the middle of the sphere if it is a normal node.
            // If it's a leaf, cross a tiny section through its top side, so that the total mesh ends
            // with a corner.
            if (properChildren.Count == 0)
            {
                parentCorners = MeshGenerationUtils.generateQuadSection(this.container, component, MeshGenerationUtils.sphereRadius, .5f);
            }
            else if (component.Equals(this.parentSphere))
            {
                parentCorners = MeshGenerationUtils.generateQuadSection(this.container, component, -MeshGenerationUtils.sphereRadius, .5f);
            }
            else
            {
                parentCorners = MeshGenerationUtils.generateQuadSection(this.container, component);
            }
            this.sphereCrosses.Add(component.GetInstanceID(), parentCorners);

            foreach (Transform child in properChildren)
            {
                dfsChains(child.gameObject);
            }

            if (properChildren.Count == 1)
            {
                // Populate linear path between parent sphere and child sphere with spheres
                if (!previousSpheresExist)
                {
                    MeshGenerationUtils.generateParentChildSpheres(component, properChildren[0].gameObject);
                }

                // Get all child spheres, before adding other things to the hierarchy of the Transform.
                List <Transform> sphereChildren = getSphereChildren(component);

                // Place a quad in each of the spheres on the way from parent to child
                // In order to get the 4 points that the sphere contributes to creating the mesh.
                List <Vector3[]> meshPoints = generateQuadSections(component, sphereChildren);
                //Vector3[] parentPoints =

                List <Vector3> points = new List <Vector3> ();
                foreach (Vector3[] meshPoint in meshPoints)
                {
                    points.AddRange(meshPoint);
                }
                Mesh       m         = MeshGenerationUtils.createConvexHullMesh(points);
                GameObject selection = MeshGenerationUtils.createGOFromMesh(MeshGenerationUtils.PARTIAL_MESH_NAME, this.container, m);
                meshes.Add(selection);

                // Create a mesh out of the corner points obtained in generateQuadSections
                //GameObject mesh = generateMesh (parentSphere, meshPoints);
                //meshes.Add (mesh);
            }
        }
        /*
         *      HC (Humphrey’s Classes) Smooth Algorithm - Reduces Shrinkage of Laplacian Smoother
         *
         *      Where sv - original points
         *                      pv - previous points,
         *                      alpha [0..1] influences previous points pv, e.g. 0
         *                      beta  [0..1] e.g. > 0.5
         */
        public static Vector3[] hcFilter(Vector3[] sv, Vector3[] pv, int[] t, float alpha, float beta)
        {
            Vector3[] wv = new Vector3[sv.Length];
            Vector3[] bv = new Vector3[sv.Length];



            // Perform Laplacian Smooth
            wv = laplacianFilter(sv, t);

            // Compute Differences
            for (int i = 0; i < wv.Length; i++)
            {
                bv[i].x = wv[i].x - (alpha * sv[i].x + (1 - alpha) * sv[i].x);
                bv[i].y = wv[i].y - (alpha * sv[i].y + (1 - alpha) * sv[i].y);
                bv[i].z = wv[i].z - (alpha * sv[i].z + (1 - alpha) * sv[i].z);
            }

            List <int> adjacentIndexes = new List <int>();

            float dx = 0.0f;
            float dy = 0.0f;
            float dz = 0.0f;

            for (int j = 0; j < bv.Length; j++)
            {
                adjacentIndexes.Clear();

                // Find the bv neighboring vertices
                adjacentIndexes = MeshGenerationUtils.findAdjacentNeighborIndexes(sv, t, sv[j]);

                dx = 0.0f;
                dy = 0.0f;
                dz = 0.0f;

                for (int k = 0; k < adjacentIndexes.Count; k++)
                {
                    dx += bv[adjacentIndexes[k]].x;
                    dy += bv[adjacentIndexes[k]].y;
                    dz += bv[adjacentIndexes[k]].z;
                }

                wv[j].x -= beta * bv[j].x + ((1 - beta) / adjacentIndexes.Count) * dx;
                wv[j].y -= beta * bv[j].y + ((1 - beta) / adjacentIndexes.Count) * dy;
                wv[j].z -= beta * bv[j].z + ((1 - beta) / adjacentIndexes.Count) * dz;
            }

            return(wv);
        }
        public static Vector3[] generateQuadSection(GameObject container, GameObject sphere)
        {
            List <Vector3> quads = new List <Vector3> ();

            quads.AddRange(MeshGenerationUtils.generateQuadSection(container, sphere, 0, 1, 0));
            quads.AddRange(MeshGenerationUtils.generateQuadSection(container, sphere, 0, 1, 10));
            quads.AddRange(MeshGenerationUtils.generateQuadSection(container, sphere, 0, 1, 20));
            quads.AddRange(MeshGenerationUtils.generateQuadSection(container, sphere, 0, 1, 30));
            quads.AddRange(MeshGenerationUtils.generateQuadSection(container, sphere, 0, 1, 40));
            quads.AddRange(MeshGenerationUtils.generateQuadSection(container, sphere, 0, 1, 50));
            quads.AddRange(MeshGenerationUtils.generateQuadSection(container, sphere, 0, 1, 60));
            quads.AddRange(MeshGenerationUtils.generateQuadSection(container, sphere, 0, 1, 70));
            quads.AddRange(MeshGenerationUtils.generateQuadSection(container, sphere, 0, 1, 80));
            return(quads.ToArray());
        }
        public void dfsSplits(GameObject component)
        {
            List <Transform> properChildren = this.getProperChildren(component);

            foreach (Transform child in properChildren)
            {
                dfsSplits(child.gameObject);
            }
            if (properChildren.Count > 1)
            {
                List <Vector3> points = new List <Vector3>();
                foreach (Transform child in properChildren)
                {
                    points.AddRange(this.sphereCrosses [child.gameObject.GetInstanceID()]);
                }
                points.AddRange(this.sphereCrosses[component.GetInstanceID()]);
                // Mesh mesh = MeshGenerationUtils.createMesh (points);

                Mesh       m         = MeshGenerationUtils.createConvexHullMesh(points);
                GameObject selection = MeshGenerationUtils.createGOFromMesh(MeshGenerationUtils.PARTIAL_MESH_NAME, this.container, m);
                meshes.Add(selection);
            }
        }
        /*
         *      Standard Laplacian Smooth Filter
         */
        public static Vector3[] laplacianFilter(Vector3[] sv, int[] t)
        {
            Vector3[]      wv = new Vector3[sv.Length];
            List <Vector3> adjacentVertices = new List <Vector3>();

            float dx = 0.0f;
            float dy = 0.0f;
            float dz = 0.0f;

            for (int vi = 0; vi < sv.Length; vi++)
            {
                // Find the sv neighboring vertices
                adjacentVertices = MeshGenerationUtils.findAdjacentNeighbors(sv, t, sv[vi]);

                if (adjacentVertices.Count != 0)
                {
                    dx = 0.0f;
                    dy = 0.0f;
                    dz = 0.0f;

                    //Debug.Log("Vertex Index Length = "+vertexIndexes.Length);
                    // Add the vertices and divide by the number of vertices
                    for (int j = 0; j < adjacentVertices.Count; j++)
                    {
                        dx += adjacentVertices[j].x;
                        dy += adjacentVertices[j].y;
                        dz += adjacentVertices[j].z;
                    }

                    wv[vi].x = dx / adjacentVertices.Count;
                    wv[vi].y = dy / adjacentVertices.Count;
                    wv[vi].z = dz / adjacentVertices.Count;
                }
            }

            return(wv);
        }
        private List <Vector3[]> generateQuadSections(GameObject parentSphere, List <Transform> sphereChildren)
        {
            List <Vector3[]> allChildrenCorners = new List <Vector3[]>();

            //TODO (cmocan): Defensive coding. Check dictionary first, and generate if it's not there.
            Vector3[] parentCorners = this.sphereCrosses[parentSphere.gameObject.GetInstanceID()];
            allChildrenCorners.Add(parentCorners);

            foreach (Transform child in sphereChildren)
            {
                Vector3[] currChildCorners;
                if (this.sphereCrosses.ContainsKey(child.gameObject.GetInstanceID()))
                {
                    currChildCorners = this.sphereCrosses [child.gameObject.GetInstanceID()];
                }
                else
                {
                    currChildCorners = MeshGenerationUtils.generateQuadSection(this.container, child.gameObject);
                }
                allChildrenCorners.Add(currChildCorners);
            }

            return(allChildrenCorners);
        }