/**This function should generate the mesh that surrounds all of the metaballs. * Although there may be many metaballs, it will technically only generate a single mesh. **/ void generateMesh() { if (metaballs.Count <= 0) { return; } //STEP 1. Iterate through the cubic region surrounding each metaball. //Determine the largest size of the region to explore. Need to locate the largest and smallest X, Y and Z values. vertices.Clear(); triangles.Clear(); float minX, maxX, minY, maxY, minZ, maxZ; minX = maxX = minY = maxY = minZ = maxZ = 0; for (int i = 0; i < metaballs.Count; i++) { Metaball m = metaballs[i]; Vector3 position = m.transform.position; float r = m.maxSquaredRadius; if ((i == 0) || (position.x - r < minX)) { minX = position.x - r; } if ((i == 0) || (position.x + r > maxX)) { maxX = position.x + r; } if ((i == 0) || (position.y - r < minY)) { minY = position.y - r; } if ((i == 0) || (position.y + r > maxY)) { maxY = position.y + r; } if ((i == 0) || (position.z - r < minZ)) { minZ = position.z - r; } if ((i == 0) || (position.z + r > maxZ)) { maxZ = position.z + r; } } int xResolution = Mathf.CeilToInt((maxX - minX) / cubeLength); int yResolution = Mathf.CeilToInt((maxY - minY) / cubeLength); int zResolution = Mathf.CeilToInt((maxZ - minZ) / cubeLength); Vector3 corner = new Vector3(minX, minY, minZ); for (int x = 0; x < xResolution; x++) { for (int y = 0; y < yResolution; y++) { for (int z = 0; z < zResolution; z++) { //Start in left, bottom, back corner, slowly work your way to the right, top, front corner. //For each cube you will examine 8 points, and determine the value at that point //Each cube is going to need 8 vertices - Order is strange because it needs to fit with the Marching Cubes library //1. Left Bottom Back int i = (x * xResolution * xResolution) + (y * yResolution) + z; float[] cube = new float[8]; cube[0] = getValueAtPoint(new Vector3(corner.x + (cubeLength * x), corner.y + (cubeLength * y), corner.z + (cubeLength * z))); //2. Left Bottom Front cube[4] = getValueAtPoint(new Vector3(corner.x + (cubeLength * x), corner.y + (cubeLength * y), corner.z + (cubeLength * (z + 1)))); //3. Left Top Back cube[3] = getValueAtPoint(new Vector3(corner.x + (cubeLength * x), corner.y + (cubeLength * (y + 1)), corner.z + (cubeLength * z))); //4. Left Top Front cube[7] = getValueAtPoint(new Vector3(corner.x + (cubeLength * x), corner.y + (cubeLength * (y + 1)), corner.z + (cubeLength * (z + 1)))); //5. Right Bottom Back cube[1] = getValueAtPoint(new Vector3(corner.x + (cubeLength * (x + 1)), corner.y + (cubeLength * y), corner.z + (cubeLength * z))); //6. Right Bottom Front cube[5] = getValueAtPoint(new Vector3(corner.x + (cubeLength * (x + 1)), corner.y + (cubeLength * y), corner.z + (cubeLength * (z + 1)))); //7. Right Top Back cube[2] = getValueAtPoint(new Vector3(corner.x + (cubeLength * (x + 1)), corner.y + (cubeLength * (y + 1)), corner.z + (cubeLength * z))); //8. Right Top Front cube[6] = getValueAtPoint(new Vector3(corner.x + (cubeLength * (x + 1)), corner.y + (cubeLength * (y + 1)), corner.z + (cubeLength * (z + 1)))); marching.March(corner.x + (cubeLength * x), corner.y + (cubeLength * y), corner.z + (cubeLength * z), cube, cubeLength, vertices, triangles); } } } mesh.Clear(); mesh.vertices = vertices.ToArray(); mesh.triangles = triangles.ToArray(); mesh.RecalculateNormals(); }