/// <summary>
        /// Generate vertices and normals for cube
        /// </summary>
        /// <param name="vertex"></param>
        /// <param name="corners"></param>
        private void GenerateVertex(Vertex vertex, Voxel[] corners)
        {
            var data = new HermiteData
            {
                intersectionPoints = new List <Vector3>(),
                gradientVectors    = new List <Vector3>()
            };

            // Find the point of intersection of the surface in each of the 12 edges
            for (int i = 0; i < 12; i++)
            {
                int n1 = Tables.EdgeConnection[i, 0];
                int n2 = Tables.EdgeConnection[i, 1];

                if ((vertex.edgeFlags & (1 << i)) == 0)
                {
                    continue;
                }

                if (Mathf.Abs(corners[n1].density) < ToleranceDensity)
                {
                    data.intersectionPoints.Add(corners[n1].pos);
                }
                else if (Mathf.Abs(corners[n2].density) < ToleranceDensity)
                {
                    data.intersectionPoints.Add(corners[n2].pos);
                }
                else
                {
                    Vector3 vDiff = corners[n1].pos - corners[n2].pos;
                    if (Mathf.Abs(vDiff.x) > ToleranceDensity)
                    {
                        Vector3 pos = IntersectXAxis(corners[n1], corners[n2]);
                        data.intersectionPoints.Add(pos);
                    }
                    if (Mathf.Abs(vDiff.y) > ToleranceDensity)
                    {
                        Vector3 pos = IntersectYAxis(corners[n1], corners[n2]);
                        data.intersectionPoints.Add(pos);
                    }
                    if (Mathf.Abs(vDiff.z) > ToleranceDensity)
                    {
                        Vector3 pos = IntersectZAxis(corners[n1], corners[n2]);
                        data.intersectionPoints.Add(pos);
                    }
                }

                Vector3 normal = GetNormal(data.intersectionPoints[data.intersectionPoints.Count - 1]);
                data.gradientVectors.Add(normal);
            }

            vertex.pos    = SchmitzVertexFromHermiteData(data, 0.001f);
            vertex.normal = GetNormal(vertex.pos);
            vertex.pos   -= offset;
        }
        /// <summary>
        /// Calculates an approximated vertex for a row.
        /// Based on the algorithm described in the paper "Analysis and Acceleration of High Quality Isosurface Contouring".
        /// </summary>
        /// <param name="data">The hermite data for a row</param>
        /// <param name="threshold">When has a force has a value below it will return the approximated position</param>
        /// <returns>Approximated vertex for the row</returns>
        private static Vector3 SchmitzVertexFromHermiteData(HermiteData data, float threshold)
        {
            threshold *= threshold;

            List <Vector3> xPoints     = data.intersectionPoints;
            List <Vector3> grads       = data.gradientVectors;
            int            pointsCount = xPoints.Count;

            if (pointsCount == 0)
            {
                return(new Vector3());
            }

            // start mass point
            // calculated by mean of intersection points
            Vector3 c = new Vector3();

            for (int i = 0; i < pointsCount; i++)
            {
                c += xPoints[i];
            }
            c /= pointsCount;

            for (int i = 0; i < MaxParticleIterations; i++)
            {
                // force that acts on mass
                Vector3 force = new Vector3();

                for (int j = 0; j < pointsCount; j++)
                {
                    Vector3 xPoint  = xPoints[j];
                    Vector3 xNormal = grads[j];

                    force += xNormal * -1 * Vector3.Dot(xNormal, c - xPoint);
                }

                // dampen force
                float damping = 1 - (float)i / MaxParticleIterations;
                c += force * damping / pointsCount;

                if (force.sqrMagnitude < threshold)
                {
                    break;
                }
            }

            return(c);
        }