Ejemplo n.º 1
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));
    }