// Start is called before the first frame update
    void Start()
    {
        if (mode == MARCHING_MODE.TETRAHEDRON)
        {
            marching = new MarchingTertrahedron();
        }
        else
        {
            marching = new MarchingCubes();
        }
        marching.Surface = minValue;
        prevCubeLength   = cubeLength;
        prevMinValue     = minValue;

        generateMesh();
    }
Esempio n. 2
0
    public override bool Calculate()
    {
        Meshes = new List <GameObject>();
        VoxelBlock <Voxel> block = input.GetValue <VoxelBlock <Voxel> >();

        Marching marching = null;

        if (mode == MarchingMode.Tetrahedron)
        {
            marching = new MarchingTertrahedron();
        }
        else
        {
            marching = new MarchingCubes();
        }

        //Surface is the value that represents the surface of mesh
        //For example the perlin noise has a range of -1 to 1 so the mid point is where we want the surface to cut through.
        //The target value does not have to be the mid point it can be any value with in the range.
        //
        //This should be accesible by an input
        marching.Surface = 0.5f;

        //The size of voxel array.
        int width  = block.Width;
        int height = block.Height;
        int length = block.Length;

        float[] voxels = new float[width * height * length];

        for (int y = 0; y < height; y++)
        {
            Voxel[,] voxelLayer = block.Layers[y].Layer;
            for (int x = 0; x < width; x++)
            {
                for (int z = 0; z < length; z++)
                {
                    int idx = x + y * width + z * width * height;
                    voxels[idx] = voxelLayer[x, z].GetValue();
                }
            }
        }

        List <Vector3> verts   = new List <Vector3>();
        List <int>     indices = new List <int>();

        //The mesh produced is not optimal. There is one vert for each index.
        //Would need to weld vertices for better quality mesh.
        marching.Generate(voxels, width, height, length, verts, indices);

        int generatedVerts   = verts.Count;
        int generatedIndices = indices.Count;

        weldVertices(verts, indices);
        Debug.Log("Vertex Welding: " + generatedVerts + "=>" + verts.Count);
        Debug.Log("Vertex Welding indices: " + generatedIndices + "=>" + indices.Count);
        Debug.LogError("Out of Bounds: " + indices.Find(i => i >= verts.Count));

        //A mesh in unity can only be made up of 65000 verts.
        //Need to split the verts between multiple meshes.

        int maxVertsPerMesh = 30000;   //must be divisible by 3, ie 3 verts == 1 triangle
        int numMeshes       = verts.Count / maxVertsPerMesh + 1;

        for (int i = 0; i < numMeshes; i++)
        {
            List <Vector3> splitVerts   = new List <Vector3>();
            List <int>     splitIndices = new List <int>();

            for (int j = 0; j < maxVertsPerMesh; j++)
            {
                int idx = i * maxVertsPerMesh + j;

                if (idx < verts.Count)
                {
                    splitVerts.Add(verts[idx]);
                    splitIndices.Add(j);
                }
            }

            if (splitVerts.Count == 0)
            {
                continue;
            }
            splitVerts   = verts;
            splitIndices = indices;

            Mesh mesh = new Mesh();
            mesh.SetVertices(splitVerts);
            mesh.SetTriangles(splitIndices, 0);
            mesh.RecalculateBounds();
            mesh.RecalculateNormals();

            GameObject go = new GameObject("Mesh");
            // go.transform.parent = transform;
            go.AddComponent <MeshFilter>();
            go.AddComponent <MeshRenderer>();
            // go.GetComponent<Renderer>().material = m_material;
            go.GetComponent <MeshFilter>().mesh = mesh;
            go.transform.localPosition          = new Vector3(-width / 2, -height / 2, -length / 2);
            go.transform.localScale             = new Vector3(1.0f, 1.0f, 1.0f);

            Meshes.Add(go);
        }
        VertexDisplay.RenderNewMeshes(Meshes);
        return(true);
    }
Esempio n. 3
0
    private void createStructure(CloudFrame frame)
    {
        //Set the mode used to create the mesh.
        //Cubes is faster and creates less verts, tetrahedrons is slower and creates more verts but better represents the mesh surface.
        Marching marching = null;

        if (mode == MARCHING_MODE.TETRAHEDRON)
        {
            marching = new MarchingTertrahedron();
        }
        else
        {
            marching = new MarchingCubes();
        }

        //Surface is the value that represents the surface of mesh
        //For example the perlin noise has a range of -1 to 1 so the mid point is where we want the surface to cut through.
        //The target value does not have to be the mid point it can be any value with in the range.

        marching.Surface = surface;  //nothing at 1

        CloudFrame lowResFrame = frame.getLowResCloudFrame(30000);

        //The size of voxel array.
        int width  = lowResFrame.width;
        int height = lowResFrame.height;
        int length = 500;

        float[] voxels = setupVoxelArray(new float[width * height * length]);
        float[] points = lowResFrame.GetpointCloud();;

        //Fill voxels with values. I take the pointcloud and populate the voxel with it.
        List <float> t = new List <float>();

        for (int x = 0; x < width; x++)
        {
            for (int y = 0; y < height; y++)
            {
                float _z = points[x + y * width];
                int   z  = 0;
                if (_z >= 0)  //we are removing garbage value(s)...
                {
                    z = (int)Math.Floor(_z * length);
                    if (z < 1)
                    {
                        t.Add(z);
                    }

                    //we know that _z is normalized to 1 so we multiply
                    //by the length to get the length in voxels we subtract 1 because index is 0-9 but
                    //the index could be 0-10 so we subtract 1 and clamp to 0

                    //clamp z at 9
                    if (z >= length - 1)
                    {
                        z = length - 1;
                    }

                    int idx = x + y * width + z * width * height;
                    try
                    {
                        voxels[idx] = 0;  //put a 1 where the point is because thats where the surface is
                    }
                    catch (Exception e)
                    {
                        Debug.Log("Opps");
                        return;
                    }
                }
                else
                {
                    continue;
                }
            }
        }

        //test the voxel
        //testVoxel(voxels, width, height, length);


        List <Vector3> verts   = new List <Vector3>();
        List <int>     indices = new List <int>();

        //The mesh produced is not optimal. There is one vert for each index.
        //Would need to weld vertices for better quality mesh.
        marching.Generate(voxels, width, height, length, verts, indices);

        //A mesh in unity can only be made up of 65000 verts.
        //Need to split the verts between multiple meshes.

        int maxVertsPerMesh = 30000; //must be divisible by 3, ie 3 verts == 1 triangle
        int numMeshes       = verts.Count / maxVertsPerMesh + 1;

        for (int i = 0; i < numMeshes; i++)
        {
            List <Vector3> splitVerts   = new List <Vector3>();
            List <int>     splitIndices = new List <int>();

            for (int j = 0; j < maxVertsPerMesh; j++)
            {
                int idx = i * maxVertsPerMesh + j;

                if (idx < verts.Count)
                {
                    splitVerts.Add(verts[idx]);
                    splitIndices.Add(j);
                }
            }

            if (splitVerts.Count == 0)
            {
                continue;
            }

            Mesh mesh = new Mesh();
            mesh.SetVertices(splitVerts);
            mesh.SetTriangles(splitIndices, 0);
            mesh.RecalculateBounds();
            mesh.RecalculateNormals();

            GameObject go = new GameObject("Mesh");
            go.transform.parent = transform;
            go.AddComponent <MeshFilter>();
            go.AddComponent <MeshRenderer>();
            go.GetComponent <Renderer>().material = m_material;
            go.GetComponent <MeshFilter>().mesh   = mesh;
            go.transform.localPosition            = new Vector3(-width / 2, -height / 2, -length / 2);

            meshes.Add(go);
        }
        transform.Rotate(new Vector3(0, 0, -90));
    }
    void DrawIsoSurface()
    {
        float[] levels = new float[] { 5, 10, 20, 30, 40, 50 };

        foreach (Transform child in transform)
        {
            Destroy(child.gameObject);
        }
        //Set the mode used to create the mesh.
        //Cubes is faster and creates less verts, tetrahedrons is slower and creates more verts but better represents the mesh surface.
        Marching marching = null;

        if (mode == MARCHING_MODE.TETRAHEDRON)
        {
            marching = new MarchingTertrahedron();
        }
        else
        {
            marching = new MarchingCubes();
        }

        //Surface is the value that represents the surface of mesh
        //For example the perlin noise has a range of -1 to 1 so the mid point is where we want the surface to cut through.
        //The target value does not have to be the mid point it can be any value with in the range.
        for (int l = 0; l < levels.Length; l++)
        {
            marching.Surface = levels[l];
            m_material.color = Color.Lerp(new Color(1F, 0F, 0F, 0.1F), new Color(0F, 0F, 1F, 0.1F), Map(levels[l], 0F, 30F, 0F, 1F));

            //The size of voxel array.
            int width  = interpVals.GetLength(1);
            int height = interpVals.GetLength(0);
            int depth  = interpVals.GetLength(2);

            float[] voxels = new float[width * height * depth];
            InterpolateAllLayers(frame);

            //Fill voxels with values. Im using perlin noise but any method to create voxels will work.
            for (int x = 0; x < height; x++)
            {
                for (int y = 0; y < width; y++)
                {
                    for (int z = 0; z < depth; z++)
                    {
                        voxels[x + y * height + z * width * height] = interpVals[x, y, z]; //Random.Range(-1F, 1F);
                    }
                }
            }
            List <Vector3> verts = new List <Vector3>();
            List <int> indices   = new List <int>();

            //The mesh produced is not optimal. There is one vert for each index.
            //Would need to weld vertices for better quality mesh.
            marching.Generate(voxels, width, height, depth, verts, indices);

            //A mesh in unity can only be made up of 65000 verts.
            //Need to split the verts between multiple meshes.

            int maxVertsPerMesh = 30000; //must be divisible by 3, ie 3 verts == 1 triangle
            int numMeshes       = verts.Count / maxVertsPerMesh + 1;

            for (int i = 0; i < numMeshes; i++)
            {
                List <Vector3> splitVerts   = new List <Vector3>();
                List <int>     splitIndices = new List <int>();

                for (int j = 0; j < maxVertsPerMesh; j++)
                {
                    int idx = i * maxVertsPerMesh + j;

                    if (idx < verts.Count)
                    {
                        splitVerts.Add(verts[idx]);
                        splitIndices.Add(j);
                    }
                }

                if (splitVerts.Count == 0)
                {
                    continue;
                }

                Mesh mesh = new Mesh();
                mesh.SetVertices(TransformVerts(splitVerts));
                mesh.SetTriangles(splitIndices, 0);
                mesh.RecalculateBounds();
                mesh.RecalculateNormals();

                GameObject go = new GameObject("Mesh");
                go.transform.parent = transform;
                go.AddComponent <MeshFilter>();
                go.AddComponent <MeshRenderer>();
                go.GetComponent <Renderer>().material = new Material(m_material);
                go.GetComponent <MeshFilter>().mesh   = mesh;
                //go.transform.localPosition = new Vector3(-width / 2, -height / 2, -depth / 2);
            }
        }
    }
    public void ConvertToMesh(float cutoff = 0.5f)
    {
        //Set the mode used to create the mesh.
        //Cubes is faster and creates less verts, tetrahedrons is slower and creates more verts but better represents the mesh surface.
        Marching marching = null;

        if (mode == MARCHING_MODE.TETRAHEDRON)
        {
            marching = new MarchingTertrahedron();
        }
        else
        {
            marching = new MarchingCubes();
        }

        //Surface is the value that represents the surface of mesh
        //For example the perlin noise has a range of -1 to 1 so the mid point is where we want the surface to cut through.
        //The target value does not have to be the mid point it can be any value with in the range.
        marching.Surface = cutoff;

        VolumeFileLoader vfl = GetComponent <VolumeFileLoader>();

        //The size of voxel array.
        int width  = vfl.dataVolume.nx;
        int height = vfl.dataVolume.ny;
        int length = vfl.dataVolume.nz;

        float[] voxels = new float[width * height * length];
        Color[] pixels = vfl.dataVolume.texture.GetPixels();

        for (int x = 0; x < width; x++)
        {
            for (int y = 0; y < height; y++)
            {
                for (int z = 0; z < length; z++)
                {
                    float fx = x / (width - 1.0f);
                    float fy = y / (height - 1.0f);
                    float fz = z / (length - 1.0f);

                    int idx = x + y * width + z * width * height;

                    Color pixel = pixels[idx];
                    if (pixel.a > 0f)
                    {
                        voxels[idx] = pixel.a;
                    }
                }
            }
        }

        List <Vector3> verts   = new List <Vector3>();
        List <int>     indices = new List <int>();

        Debug.Log("Starting marching cubes...");

        //The mesh produced is not optimal. There is one vert for each index.
        //Would need to weld vertices for better quality mesh.
        marching.Generate(voxels, width, height, length, verts, indices);

        /*A mesh in unity can only be made up of 65000 verts,
         | and need to split the verts between multiple meshes. */

        int maxVertsPerMesh = 30000; //must be divisible by 3, ie 3 verts == 1 triangle
        int numMeshes       = verts.Count / maxVertsPerMesh + 1;

        Debug.Log(verts.Count + " vertices scanned.");
        GameObject marchingObject = new GameObject("MarchingObject");

        marchingObject.transform.parent = transform;

        for (int i = 0; i < numMeshes; i++)
        {
            List <Vector3> splitVerts   = new List <Vector3>();
            List <int>     splitIndices = new List <int>();

            for (int j = 0; j < maxVertsPerMesh; j++)
            {
                int idx = i * maxVertsPerMesh + j;

                if (idx < verts.Count)
                {
                    splitVerts.Add(verts[idx]);
                    splitIndices.Add(j);
                }
            }

            if (splitVerts.Count == 0)
            {
                continue;
            }

            /*
             | Creates mesh with default vertices and edges
             */
            Mesh mesh = new Mesh();
            mesh.SetVertices(splitVerts);
            mesh.SetTriangles(splitIndices, 0);
            mesh.RecalculateBounds();
            mesh.RecalculateNormals();

            /*
             |
             */
            GameObject go = new GameObject("Mesh");
            go.transform.parent = marchingObject.transform;
            go.AddComponent <MeshFilter>();
            go.AddComponent <MeshRenderer>();
            go.GetComponent <Renderer>().material = m_material;
            go.GetComponent <MeshFilter>().mesh   = mesh;
            go.transform.localRotation            = Quaternion.Euler(Vector3.zero);
            go.transform.localPosition            = new Vector3((float)-width / 2, (float)-height / 2, (float)-length / 2);

            meshes.Add(go);
        }
        marchingObject.transform.localPosition = Vector3.zero;
        marchingObject.transform.localRotation = Quaternion.Euler(Vector3.zero);
        marchingObject.transform.localScale    = new Vector3(1f / width, 1f / height, 1f / length);
        Debug.Log("Finishing marching cubes...");
        GetComponent <MeshRenderer>().enabled = false;
    }
Esempio n. 6
0
    void GenerateTerrain(Vector3Int terrainOffset, bool scu)
    {
        Marching marching = null;

        if (mode == MARCHING_MODE.TETRAHEDRON)
        {
            marching = new MarchingTertrahedron();
        }
        else
        {
            marching = new MarchingCubes();
        }

        marching.Surface = surface;

        // bool newChunk = false;
        Voxel[] chunkVoxels;
        if (!voxels.ContainsKey(terrainOffset))
        {
            //newChunk = true;
            chunkVoxels = generation.Voxels(/*,s*/ terrainOffset, activeOres);
            voxels.Add(terrainOffset, chunkVoxels);
        }
        else
        {
            chunkVoxels = voxels[terrainOffset];
            //chunkVoxels = new Voxel[cS*cS*cS];
            // for(int i = 0; i<chunkVoxels.Length; i++){
            //     chunkVoxels[i] = voxels[terrainOffset][i];
            // }
        }
        float[] chunkvoxs = new float[chunkVoxels.Length];

        for (int i = 0; i < chunkVoxels.Length; i++)
        {
            chunkvoxs[i] = chunkVoxels[i].value;
        }


        List <Vector3> verts   = new List <Vector3>();
        List <int>     indices = new List <int>();


        //The mesh produced is not optimal. There is one vert for each index.
        //Would need to weld vertices for better quality mesh.
        marching.Generate(chunkvoxs, cS, cS, cS, verts, indices);
        indices = null;
        //indices.Reverse();

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

        for (int i = 0; i < materials.materialList.Count; i++)
        {
            subIndices.Add(new List <int>());
        }
        //System.Random random = new System.Random();
        //spawnObject.spawn(terrainOffset,terrainOffset,-1);
        bool canCC = false;

        for (int i = 0; i < verts.Count; i = i + 3)
        {
            //bool normal = true;

            Vector3    triPos  = (verts[i] + verts[i + 1] + verts[i + 2]) / 3;
            Vector3Int voxeloV = Vector3Int.RoundToInt(triPos);
            int        idx     = voxeloV.x + voxeloV.y * cS + voxeloV.z * cS * cS;
            int        mat     = chunkVoxels[idx].material;
            if (!canCC)
            {
                int zeroDiffs = 0;
                if (triPos.x == verts[i].x)
                {
                    zeroDiffs += 1;
                }
                if (triPos.y == verts[i].y)
                {
                    zeroDiffs += 1;
                }
                if (triPos.z == verts[i].z)
                {
                    zeroDiffs += 1;
                }
                if (zeroDiffs < 2)
                {
                    canCC = true;
                }
            }
            subIndices[mat].Add(i + 2);
            subIndices[mat].Add(i + 1);
            subIndices[mat].Add(i);
            //System.Random random = new System.Random();

            // if(newChunk && random.NextDouble() < spawnProbability){
            //  spawnObject.spawn(triPos+terrainOffset,terrainOffset,-1);
            // }// spawn objects
        }
        for (int i = 0; i < verts.Count; i++)
        {
            verts[i] = verts[i] / resolution;

            //Indices.Add(i);
        }

        Action generateMesh;

        if (verts.Count == 0 || !canCC)
        {
            generateMesh = () => {
                if (meshes.ContainsKey(terrainOffset))
                {
                    Destroy(meshes[terrainOffset]);
                }
            };
        }
        else
        {
            generateMesh = () => {
                GameObject go = meshGeneration.genMesh(verts, subIndices, materials.materialList, transform);
                go.transform.localPosition = terrainOffset;

                if (meshes.ContainsKey(terrainOffset))
                {
                    Destroy(meshes[terrainOffset]);
                    meshes[terrainOffset] = go;
                }
                else
                {
                    meshes.Add(terrainOffset, go);
                }
            };
        }

        if (scu)
        {
            FunctionsToRunInMainThread2.Add(generateMesh);
        }
        else
        {
            FunctionsToRunInMainThread.Add(generateMesh);
        }
    }
Esempio n. 7
0
        //public NativeArray<Vector3> m_verts;
        //public NativeArray<int> m_indices;
        public void Execute(int index)
        {
            int x = index / (h * d);
            int y = (index - x * h * d) / d;
            int z = (index - x * h * d) % h;

            float[] Cube = new float[8];
            for (int ii = 0; ii < 8; ii++)
            {
                ix       = x + Marching.VertexOffset[ii, 0];
                iy       = y + Marching.VertexOffset[ii, 1];
                iz       = z + Marching.VertexOffset[ii, 2];
                Cube[ii] = m_voxels[ix + iy * w + iz * w * h];
            }

            //perform algorithm
            int   i, j, vert, idx;
            int   flagIndex = 0;
            float offset    = 0f;
            NativeArray <Vector3> EdgeVertex = new NativeArray <Vector3>(12, Allocator.TempJob);

            for (i = 0; i < 8; i++)
            {
                //Debug.Log("Cube[i] " + Cube[i] + " Surface " + Surface);
                if (Cube[i] <= Surface)
                {
                    flagIndex |= 1 << i;
                }
            }
            //Debug.Log("b4 intersection : " + flagIndex);
            int edgeFlags = MarchingCube.CubeEdgeFlags[flagIndex];

            if (edgeFlags == 0)
            {
                return;
            }

            //Debug.Log("Got intersection");
            for (i = 0; i < 12; i++)
            {
                //intersection happens
                if ((edgeFlags & (1 << i)) != 0)
                {
                    offset = Marching.GetOffset(Cube[MarchingCube.EdgeConnection[i, 0]], Cube[MarchingCube.EdgeConnection[i, 1]]);

                    EdgeVertex[i] = new Vector3(x + (Marching.VertexOffset[MarchingCube.EdgeConnection[i, 0], 0]
                                                     + offset * MarchingCube.EdgeDirection[i, 0]),
                                                y + (Marching.VertexOffset[MarchingCube.EdgeConnection[i, 0], 1]
                                                     + offset * MarchingCube.EdgeDirection[i, 1]),
                                                z + (Marching.VertexOffset[MarchingCube.EdgeConnection[i, 0], 2]
                                                     + offset * MarchingCube.EdgeDirection[i, 2]));
                }
            }

            for (i = 0; i < 5; i++)
            {
                if (MarchingCube.TriangleConnectionTable[flagIndex, 3 * i] < 0)
                {
                    break;
                }

                //idx = x * w * d + y * d  + z;
                for (j = 0; j < 3; j++)
                {
                    vert = MarchingCube.TriangleConnectionTable[flagIndex, 3 * i + j];
                    m_indices[currentVertIndex] = currentVertIndex + WindingOrder[j];
                    m_verts[currentVertIndex++] = EdgeVertex[vert];
                    // Debug.Log("zzz " + currentVertIndex);
                }
            }

            EdgeVertex.Dispose();
        }
Esempio n. 8
0
    public override bool Calculate()
    {
        bool isPMB = false;

        if (!input.connected())
        {
            return(false);
        }
        VoxelBlock <Voxel> block = input.GetValue <VoxelBlock <Voxel> >();

        if (surfaceConnection.connected())
        {
            surface = surfaceConnection.GetValue <float>();
        }

        Marching marching = null;

        switch (mode)
        {
        case VerteGenerationMode.Tetrahedron:
            marching = new MarchingTertrahedron();
            break;

        case VerteGenerationMode.Cubes:
            marching = new MarchingCubes();
            break;

        case VerteGenerationMode.Voxel:
            marching = new VoxelGeneration();
            break;

        case VerteGenerationMode.PMB:
            isPMB = true;
            break;
        }

        //The size of voxel array.
        Vector3Int count  = block.VoxelCount;
        int        width  = count.x;
        int        height = count.y;
        int        length = count.z;

        float[] voxels = new float[width * height * length];

        for (int y = 0; y < height; y++)
        {
            Voxel[,] voxelLayer = block.Layers[y].Layer;
            for (int x = 0; x < width; x++)
            {
                for (int z = 0; z < length; z++)
                {
                    int idx = x + y * width + z * width * height;
                    voxels[idx] = voxelLayer[x, z].GetValue();
                }
            }
        }

        if (isPMB)
        {
            var pmbTask = MainThreadHelper.instance().scheduleOnMainThread(() =>
            {
                pmb.ReInit(block);
                Stopwatch pmbWatch = Stopwatch.StartNew();
                buffers            = pmb.calculate(voxels, width, height, length, surface);
                pmbWatch.Stop();
                UnityEngine.Debug.LogFormat("PMB took {0}ms\n\t{1} voxels\n\t{2} triangles", pmbWatch.ElapsedMilliseconds, voxels.Count(), buffers.indexBuffer.count / 3);
            });

            pmbTask.wait();

            if (!pmbTask.completed)
            {
                return(false);
            }

            Block = block;
            return(true);
        }

        //Surface is the value that represents the surface of mesh
        //For example the perlin noise has a range of -1 to 1 so the mid point is where we want the surface to cut through.
        //The target value does not have to be the mid point it can be any value with in the range.
        //
        //This should be accesible by an input
        marching.Surface = surface;

        List <Vector3> verts   = new List <Vector3>();
        List <int>     indices = new List <int>();
        List <Vector3> normals = new List <Vector3>();

        Stopwatch sw = Stopwatch.StartNew();

        marching.Generate(voxels, width, height, length, verts, indices, normals);

        sw.Stop();

        UnityEngine.Debug.LogFormat("Marching took {0}ms\n\t{1} vertices; {2} triangles", sw.ElapsedMilliseconds, verts.Count(), indices.Count() / 3);

        sw.Restart();
        weldVertices(verts, indices, normals);
        sw.Stop();

        UnityEngine.Debug.LogFormat("Vertex welding took {0}ms\n\t {1} vertices left", sw.ElapsedMilliseconds, verts.Count());

        var task = MainThreadHelper.instance().scheduleOnMainThread(() =>
        {
            buffers = new RenderBuffers {
                vertexBuffer = new ComputeBuffer(verts.Count, sizeof(float) * 3),
                indexBuffer  = new ComputeBuffer(indices.Count, sizeof(int)),
                normalBuffer = new ComputeBuffer(normals.Count, sizeof(float) * 3),
                argsBuffer   = new ComputeBuffer(4, sizeof(int), ComputeBufferType.IndirectArguments),
            };

            buffers.vertexBuffer.SetData(verts);
            buffers.indexBuffer.SetData(indices);
            buffers.normalBuffer.SetData(normals);
            buffers.argsBuffer.SetData(new int[] { indices.Count, 1, 0, 0 });
        });

        task.wait();

        if (!task.completed)
        {
            return(false);
        }

        Block = block;

        return(true);
    }