Example #1
0
        void Start()
        {
            INoise       perlin  = new PerlinNoise(seed, 2.0f);
            FractalNoise fractal = new FractalNoise(perlin, 3, 1.0f);

            //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 = 0.0f;

            //The size of voxel array.
            int width  = 32;
            int height = 32;
            int length = 10;

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

            //Fill voxels with values. Im using perlin noise but any method to create voxels will work.
            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;

                        voxels[idx] = fractal.Sample3D(fx, fy, fz);
                    }
                }
            }

            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);
            }
        }
        public void CreateNewSurface(float[] voxels, MARCHING_MODE mode, float iso, int width, int height, int length)
        {
            // Reset meshes
            foreach (GameObject lgo in meshes)
            {
                Destroy(lgo);
            }

            meshes.Clear();

            //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.
            //print("generating surface..");
            marching = null;
            if (mode == MARCHING_MODE.Tetrahedron)
            {
                marching = new MarchingTertrahedron();
            }

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

            else
            {
                marching = new NaiveMarchingTetrahedron();
            }

            //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 = iso;

            verts   = new List <Vector3>();
            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.

            print("w:" + width + " h:" + height + " l:" + length);
            marching.Generate(voxels, width, height, length, verts, indices);

            print("marching alg complete. Creating meshes from " + verts.Count + " vertices...");

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

            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);

                if (pointmode)
                {
                    mesh.SetIndices(splitIndices.ToArray(), MeshTopology.Points, 0);
                }
                else
                {
                    mesh.SetTriangles(splitIndices, 0);
                    mesh.RecalculateNormals();
                }
                print("triangle count: " + splitIndices.Count);
                mesh.RecalculateBounds();

                if (disableBackfaceCulling)
                {
                    DisableBackfaceCulling(mesh);
                }

                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.localScale    = new Vector3(1f, 1f, 1f);
                go.transform.localPosition = new Vector3(-width / 2f, -height / 2f, -length / 2f);

                meshes.Add(go);

                print("surfaces generated!");
            }
        }
Example #3
0
        void Generate()
        {
            //INoise perlin = new PerlinNoise(seed, 2.0f);
            //FractalNoise fractal = new FractalNoise(perlin, 3, 1.0f);

            //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.



            //The size of voxel array.
            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 = 0.0f;

            if (voxels == null)
            {
                voxels = new Voxel[width * height * length];

                //Fill voxels with values. Im using perlin noise but any method to create voxels will work.
                for (int x = 0; x < width; x++)
                {
                    for (int y = 0; y < height; y++)
                    {
                        for (int z = 0; z < length; z++)
                        {
                            float voxel    = 0;
                            float distance = Vector3.Distance(new Vector3(x + 0.5f, y + 0.5f, z + 0.5f), new Vector3((float)width / 2, (float)height / 2, (float)length / 2));
                            voxel = -Mathf.Clamp(((0.7f / distance) * 2 - 1), -0.3f, 0.3f);
                            float fx = x;
                            float fy = y;
                            float fz = z;

                            int idx = x + y * width + z * width * height;
                            voxels[idx] = new Voxel(voxel, 0);
                        }
                    }
                }
            }



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

            float[] chunkVox = new float[voxels.Length];
            for (int i = 0; i < voxels.Length; i++)
            {
                chunkVox[i] = voxels[i].value;
            }

            //The mesh produced is not optimal. There is one vert for each index.
            //Would need to weld vertices for better quality mesh.
            marching.Generate(chunkVox, 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 = 60000; //must be divisible by 3, ie 3 verts == 1 triangle

            //int numMeshes = verts.Count / maxVertsPerMesh + 1;
            if (verts.Count == 0 || verts.Count > maxVertsPerMesh)
            {
                return;
            }

            // for (int i = 0; i < numMeshes; i++)
            // {
            //  print(numMeshes);
            //     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);
            //         }
            //     }
            // List<int> splitIndices = new List<int>();
            List <List <int> > subIndices = new List <List <int> >();

            subIndices.Add(indices);
            for (int i = 0; i < verts.Count; i++)
            {
                verts[i] *= scale;
            }



            Action createMesh = () => {
                foreach (Transform child in transform)
                {
                    Destroy(child.gameObject);
                }
                GameObject go = meshGeneration.genMesh(verts, subIndices, m_materials, transform);
                // Mesh mesh = new Mesh();
                // mesh.SetVertices(verts);
                // mesh.SetTriangles(indices, 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.AddComponent<MeshCollider>();

                meshes.Add(go);
            };

            actions.Add(createMesh);
            // }
        }
Example #4
0
        void Start()
        {
            INoise       perlin  = new PerlinNoise(seed, 2.0f);
            FractalNoise fractal = new FractalNoise(perlin, 3, 1.0f);

            //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 = 0.0f;

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

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

            //Fill voxels with values. Im using perlin noise but any method to create voxels will work.
            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;

                        voxels[idx] = fractal.Sample3D(fx, fy, fz);
                    }
                }
            }

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

            System.Diagnostics.Stopwatch measure = new System.Diagnostics.Stopwatch();
            measure.Start();

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

            verts = MeshUtils.WeldVertices(verts, indices);

            measure.Stop();

            Debug.Log(string.Format("Time elapsed: {0}", measure.Elapsed));

            Mesh mesh = new Mesh();

            mesh.indexFormat = UnityEngine.Rendering.IndexFormat.UInt32;
            mesh.SetVertices(verts);
            mesh.SetTriangles(indices, 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);
        }