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