private VertexList GenerateVertexList(VoxelCorners <float> voxelDensities, VoxelCorners <int3> voxelCorners,
                                              int edgeIndex, float isolevel)
        {
            var vertexList = new VertexList();

            for (int i = 0; i < 12; i++)
            {
                if ((edgeIndex & (1 << i)) == 0)
                {
                    continue;
                }

                int edgeStartIndex = LookupTables.EdgeIndexTable[2 * i + 0];
                int edgeEndIndex   = LookupTables.EdgeIndexTable[2 * i + 1];

                int3 corner1 = voxelCorners[edgeStartIndex];
                int3 corner2 = voxelCorners[edgeEndIndex];

                float density1 = voxelDensities[edgeStartIndex];
                float density2 = voxelDensities[edgeEndIndex];

                vertexList[i] = VertexInterpolate(corner1, corner2, density1, density2, isolevel);
            }

            return(vertexList);
        }
        private VoxelCorners <int3> GetCorners(int3 position)
        {
            VoxelCorners <int3> corners = new VoxelCorners <int3>();

            for (int i = 0; i < 8; i++)
            {
                corners[i] = position + LookupTables.CubeCorners[i];
            }

            return(corners);
        }
        private VoxelCorners <float> GetDensities(int3 localPosition)
        {
            VoxelCorners <float> densities = new VoxelCorners <float>();

            for (int i = 0; i < 8; i++)
            {
                int3 voxelCorner  = localPosition + LookupTables.CubeCorners[i];
                int  densityIndex = voxelCorner.x * (chunkSize + 1) * (chunkSize + 1) + voxelCorner.y * (chunkSize + 1) + voxelCorner.z;
                densities[i] = this.densities[densityIndex];
            }

            return(densities);
        }
        /// <summary>
        /// The execute method required by the Unity Job System's IJobParallelFor
        /// </summary>
        /// <param name="index">The iteration index</param>
        public void Execute(int index)
        {
            // Voxel's position inside the chunk. Goes from (0, 0, 0) to (chunkSize-1, chunkSize-1, chunkSize-1)
            int3 voxelLocalPosition = new int3(
                index / (chunkSize * chunkSize),
                index / chunkSize % chunkSize,
                index % chunkSize);

            VoxelCorners <float> densities = GetDensities(voxelLocalPosition);

            int cubeIndex = CalculateCubeIndex(densities, isolevel);

            if (cubeIndex == 0 || cubeIndex == 255)
            {
                return;
            }

            VoxelCorners <int3> corners = GetCorners(voxelLocalPosition);

            int edgeIndex = LookupTables.EdgeTable[cubeIndex];

            VertexList vertexList = GenerateVertexList(densities, corners, edgeIndex, isolevel);

            // Index at the beginning of the row
            int rowIndex = 15 * cubeIndex;

            for (int i = 0; LookupTables.TriangleTable[rowIndex + i] != -1 && i < 15; i += 3)
            {
                int triangleIndex = counter.Increment() * 3;

                vertices[triangleIndex + 0]  = vertexList[LookupTables.TriangleTable[rowIndex + i + 0]];
                triangles[triangleIndex + 0] = triangleIndex + 0;

                vertices[triangleIndex + 1]  = vertexList[LookupTables.TriangleTable[rowIndex + i + 1]];
                triangles[triangleIndex + 1] = triangleIndex + 1;

                vertices[triangleIndex + 2]  = vertexList[LookupTables.TriangleTable[rowIndex + i + 2]];
                triangles[triangleIndex + 2] = triangleIndex + 2;
            }
        }
        private int CalculateCubeIndex(VoxelCorners <float> voxelDensities, float isolevel)
        {
            int cubeIndex = 0;

            if (voxelDensities.Corner1 < isolevel)
            {
                cubeIndex |= 1;
            }
            if (voxelDensities.Corner2 < isolevel)
            {
                cubeIndex |= 2;
            }
            if (voxelDensities.Corner3 < isolevel)
            {
                cubeIndex |= 4;
            }
            if (voxelDensities.Corner4 < isolevel)
            {
                cubeIndex |= 8;
            }
            if (voxelDensities.Corner5 < isolevel)
            {
                cubeIndex |= 16;
            }
            if (voxelDensities.Corner6 < isolevel)
            {
                cubeIndex |= 32;
            }
            if (voxelDensities.Corner7 < isolevel)
            {
                cubeIndex |= 64;
            }
            if (voxelDensities.Corner8 < isolevel)
            {
                cubeIndex |= 128;
            }

            return(cubeIndex);
        }