Пример #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));
    }
        public void Generate(CloudFrame frame, Material materialToApply, MeshTopology topology)
        {
            //deletes all previous mesh
            for (int c = transform.childCount - 1; c >= 0; --c)
            {
                Transform child = transform.GetChild(c);
                GameObject.DestroyImmediate(child.gameObject);
            }

            int vertexCount = frame.getVertexCount();
            int meshCount   = (int)Mathf.Ceil(vertexCount / (float)verticesMax);

            //we may need to split the mesh into multiple meshes
            meshArray      = new Mesh[meshCount];
            transformArray = new Transform[meshCount];

            int index       = 0;
            int meshIndex   = 0;
            int vertexIndex = 0;

            int resolution = GetNearestPowerOfTwo(Mathf.Sqrt(vertexCount));

            //create all the submeshes
            while (meshIndex < meshCount)
            {
                int count = verticesMax;
                if (vertexCount <= verticesMax)
                {
                    count = vertexCount;
                }
                else if (vertexCount > verticesMax && meshCount == meshIndex + 1)
                {
                    count = vertexCount % verticesMax;
                }

                Vector3[] subVertices = frame.GetpointCloud(0.01f).Skip(meshIndex * verticesMax).Take(count).ToArray();
                Color[]   subColors   = frame.GetColorCloud().Skip(meshIndex * verticesMax).Take(count).ToArray();
                //Vector3[] subVertices = meshInfos.vertices.Skip(meshIndex * verticesMax).Take(count).ToArray();
                //Vector3[] subNormals = meshInfos.normals.Skip(meshIndex * verticesMax).Take(count).ToArray();
                //Color[] subColors = meshInfos.colors.Skip(meshIndex * verticesMax).Take(count).ToArray();
                int[] subIndices = new int[count];
                for (int i = 0; i < count; ++i)
                {
                    subIndices[i] = i;
                }

                Mesh mesh = new Mesh();
                mesh.bounds   = new Bounds(Vector3.zero, Vector3.one * 100f);
                mesh.vertices = subVertices;
                //mesh.normals = subNormals;
                mesh.colors = subColors;
                mesh.SetIndices(subIndices, topology, 0);

                Vector2[] uvs2 = new Vector2[mesh.vertices.Length];
                for (int i = 0; i < uvs2.Length; ++i)
                {
                    float x = vertexIndex % resolution;
                    float y = Mathf.Floor(vertexIndex / (float)resolution);
                    uvs2[i] = new Vector2(x, y) / (float)resolution;
                    ++vertexIndex;
                }
                mesh.uv2 = uvs2;

                GameObject go = CreateGameObjectWithMesh(mesh, materialToApply, gameObject.name + "_" + meshIndex, transform);

                meshArray[meshIndex]      = mesh;
                transformArray[meshIndex] = go.transform;

                index += count;
                ++meshIndex;
            }
        }