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!"); } }
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); // } }
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); }