public static void GenerateMarchingSquaresWithJob(NativeArray <Voxel> nativeVoxels, Vector2Int chunkSize, Vector2 chunkScale, bool interpolate, bool triangleIndexing, bool greedyMeshing, List <Vector3> vertices, List <int> triangles)
    {
        NativeArray <Vector3> nativeVertices  = new NativeArray <Vector3>(9 * chunkSize.x * chunkSize.y, Allocator.TempJob);
        NativeArray <int>     nativeTriangles = new NativeArray <int>(9 * chunkSize.x * chunkSize.y, Allocator.TempJob);
        NativeArray <bool>    nativeQuadMap   = new NativeArray <bool> (chunkSize.x * chunkSize.y, Allocator.TempJob);
        NativeCounter         counter         = new NativeCounter(Allocator.TempJob);

        MarchingSquaresJob marchingSquaresJob = new MarchingSquaresJob
        {
            vertices         = nativeVertices,
            quadMap          = nativeQuadMap,
            counter          = counter.ToConcurrent(),
            voxels           = nativeVoxels,
            chunkSize        = chunkSize,
            chunkScale       = chunkScale,
            interpolate      = interpolate,
            triangleIndexing = triangleIndexing,
            greedyMeshing    = greedyMeshing
        };

        JobHandle marchingSquaresJobHandle = marchingSquaresJob.Schedule(chunkSize.x * chunkSize.y, 32);

        marchingSquaresJobHandle.Complete();

        if (greedyMeshing)
        {
            GreedyMeshingForJob(chunkSize, chunkScale, nativeVertices, counter, nativeQuadMap);
        }
        else
        {
            MakeQuadJob quadJob = new MakeQuadJob
            {
                chunkSize  = chunkSize,
                chunkScale = chunkScale,
                vertices   = nativeVertices,
                triangles  = nativeTriangles,
                quadMap    = nativeQuadMap,
                counter    = counter.ToConcurrent()
            };

            JobHandle quadJobHandle = quadJob.Schedule(chunkSize.x * chunkSize.y, 32);
            quadJobHandle.Complete();
        }

        int verticeSize  = counter.Count * 3;
        int triangleSize = verticeSize;

        if (triangleIndexing)
        {
            verticeSize = TriangleIndexingForJob(nativeVertices, nativeTriangles, verticeSize);
        }
        else
        {
            AddTriangleIndexForNoIndexing triangleJob = new AddTriangleIndexForNoIndexing
            {
                triangles = nativeTriangles
            };

            JobHandle triangleJobHandle = triangleJob.Schedule(verticeSize, 32);
            triangleJobHandle.Complete();
        }

        NativeSlice <Vector3> nativeSliceVertices  = new NativeSlice <Vector3>(nativeVertices, 0, verticeSize);
        NativeSlice <int>     nativeSliceTriangles = new NativeSlice <int>(nativeTriangles, 0, triangleSize);

        vertices.Clear();
        triangles.Clear();

        vertices.NativeAddRange(nativeSliceVertices);
        triangles.NativeAddRange(nativeSliceTriangles);

        counter.Dispose();
        nativeQuadMap.Dispose();
        nativeVertices.Dispose();
        nativeTriangles.Dispose();
    }
    public static void GenerateMarchingCubesWithJob(Voxel[,,] voxels, Vector3Int cellSize, Vector3 chunkScale, bool triangleIndexing, List <Vector3> vertices, List <int> triangles, List <Color> colors)
    {
        NativeArray <Vector3> nativeVertices  = new NativeArray <Vector3>(15 * cellSize.x * cellSize.y * cellSize.z, Allocator.TempJob);
        NativeArray <int>     nativeTriangles = new NativeArray <int>(15 * cellSize.x * cellSize.y * cellSize.z, Allocator.TempJob);
        NativeArray <Color>   nativeColors    = new NativeArray <Color>(15 * cellSize.x * cellSize.y * cellSize.z, Allocator.TempJob);
        NativeCounter         counter         = new NativeCounter(Allocator.TempJob);
        NativeArray <Voxel>   nativeVoxels    = new NativeArray <Voxel>(voxels.Length, Allocator.TempJob);

        nativeVoxels.ManagedToNative(voxels);

        MarchingCubesJob marchingCubesJob = new MarchingCubesJob
        {
            vertices   = nativeVertices,
            counter    = counter.ToConcurrent(),
            voxels     = nativeVoxels,
            colors     = nativeColors,
            cellSize   = cellSize,
            gridSize   = cellSize + Vector3Int.one,
            chunkScale = chunkScale,
        };

        JobHandle marchingCubesJobHandle = marchingCubesJob.Schedule(voxels.Length, 32);

        marchingCubesJobHandle.Complete();

        if (counter.Count > 0)
        {
            int verticeSize  = counter.Count * 3;
            int triangleSize = verticeSize;

            if (triangleIndexing)
            {
                verticeSize = TriangleIndexingForJob(nativeVertices, nativeTriangles, nativeColors, verticeSize);
            }
            else
            {
                AddTriangleIndexForNoIndexing triangleJob = new AddTriangleIndexForNoIndexing
                {
                    triangles = nativeTriangles
                };

                JobHandle triangleJobHandle = triangleJob.Schedule(verticeSize, 32);
                triangleJobHandle.Complete();
            }

            NativeSlice <Vector3> nativeSliceVertices  = new NativeSlice <Vector3>(nativeVertices, 0, verticeSize);
            NativeSlice <Color>   nativeSliceColors    = new NativeSlice <Color>(nativeColors, 0, verticeSize);
            NativeSlice <int>     nativeSliceTriangles = new NativeSlice <int>(nativeTriangles, 0, triangleSize);

            colors.Clear();
            vertices.Clear();
            triangles.Clear();

            vertices.NativeAddRange(nativeSliceVertices);
            triangles.NativeAddRange(nativeSliceTriangles);
            colors.NativeAddRange(nativeSliceColors);
        }

        counter.Dispose();
        nativeVertices.Dispose();
        nativeTriangles.Dispose();
        nativeVoxels.Dispose();
        nativeColors.Dispose();
    }