I implemented the walking cube algorithm in the unit and wanted to reuse the vertices instead of creating new ones for each triangle. I loop through a 3D array of points while I generate the mesh in the order x y z. To cache points for reuse, I save the relevant vertices for each layer of yz cubes to refer to the following cubes, then after exiting the y loop, I save the currentLayer as behindLayer in order to be able to get the last vertex, along edge 8 of my case, from the cache.

I use the diagram on the first page of this article as a reference for numbering edges and vertices as well as for edgeTable and triTable: http://paulbourke.net/geometry/polygonise/

In the 3rd dimension of the cache tables (currentLayer and behindLayer):

edge 0 is stored in 0; 1 in 1; 4 in 2; 5 out of 3; 6 out of 4; 7 out of 5; 8 out of 6; 9 out of 7; 10 out of 8.

The exact problem I have is that there are double vertices in some intersections. In this example, there are double vertices in the central intersection and the left central intersection. These correspond to edges 8, 9, 10 or 11 as defined in the paper linked above.

```
public class MeshGenerator : MonoBehaviour {
private Vector3() vertices;
private Vector3() normals;
private int() triangles;
public Mesh GenerateMesh(float(,,) pointCloud, float surfaceLevel, int borderedSize, int height) {
Polygonize(pointCloud, surfaceLevel, borderedSize, height);
Mesh mesh = new Mesh();
mesh.vertices = vertices;
mesh.triangles = triangles;
mesh.normals = normals;
return mesh;
}
public void Polygonize(float(,,) pointCloud, float surfaceLevel, int borderedSize, int height) {
List vertList = new List();
List triList = new List();
int(,,) behindCache = new int(height, borderedSize, 9);
int(,,) currentCache;
for (int x = 0; x < borderedSize - 1; x++) {
currentCache = new int(height, borderedSize, 9);
for (int y = 0; y < height - 1; y++) {
for (int z = 0; z < borderedSize - 1; z++) {
int cubeIndex = 0;
//0
if (pointCloud(x, y, z + 1) < surfaceLevel) cubeIndex |= 1;
//1
if (pointCloud(x + 1, y, z + 1) < surfaceLevel) cubeIndex |= 2;
//2
if (pointCloud(x + 1, y, z) < surfaceLevel) cubeIndex |= 4;
//3
if (pointCloud(x, y, z) < surfaceLevel) cubeIndex |= 8;
//4
if (pointCloud(x, y + 1, z + 1) < surfaceLevel) cubeIndex |= 16;
//5
if (pointCloud(x + 1, y + 1, z + 1) < surfaceLevel) cubeIndex |= 32;
//6
if (pointCloud(x + 1, y + 1, z) < surfaceLevel) cubeIndex |= 64;
//7
if (pointCloud(x, y + 1, z) < surfaceLevel) cubeIndex |= 128;
if (edgeTable(cubeIndex) != 0) {
int() vertIndices = new int(12);
if ((edgeTable(cubeIndex) & 1) == 1) {
//Vertex 0
if (y > 0 && currentCache(y - 1, z, 2) != 0) {
vertIndices(0) = currentCache(y - 1, z, 2);
} else {
vertIndices(0) = vertList.Count;
vertList.Add(LerpVert(new Vector3(x, y, z + 1), pointCloud(x, y, z + 1), new Vector3(x + 1, y, z + 1), pointCloud(x + 1, y, z + 1), surfaceLevel));
currentCache(y, z, 0) = vertIndices(0);
}
}
if ((edgeTable(cubeIndex) & 2) == 2) {
//Vertex 1
if (y > 0 && currentCache(y - 1, z, 3) != 0) {
vertIndices(1) = currentCache(y - 1, z, 3);
} else {
vertIndices(1) = vertList.Count;
vertList.Add(LerpVert(new Vector3(x + 1, y, z + 1), pointCloud(x + 1, y, z + 1), new Vector3(x + 1, y, z), pointCloud(x + 1, y, z), surfaceLevel));
currentCache(y, z, 1) = vertIndices(1);
}
}
if ((edgeTable(cubeIndex) & 4) == 4) {
//Vertex 2 - Dont Cache
if (y > 0 && currentCache(y - 1, z, 4) != 0) {
vertIndices(2) = currentCache(y - 1, z, 4);
} else {
vertIndices(2) = vertList.Count;
vertList.Add(LerpVert(new Vector3(x + 1, y, z), pointCloud(x + 1, y, z), new Vector3(x, y, z), pointCloud(x, y, z), surfaceLevel));
}
}
if ((edgeTable(cubeIndex) & 8) == 8) {
//Vertex 3 - Dont Cache
if (y > 0 && currentCache(y - 1, z, 5) != 0) {
vertIndices(3) = currentCache(y - 1, z, 5);
} else {
vertIndices(3) = vertList.Count;
vertList.Add(LerpVert(new Vector3(x, y, z), pointCloud(x, y, z), new Vector3(x, y, z + 1), pointCloud(x, y, z + 1), surfaceLevel));
}
}
if ((edgeTable(cubeIndex) & 16) == 16) {
//Vertex 4 - Leading Edge
vertIndices(4) = vertList.Count;
vertList.Add(LerpVert(new Vector3(x, y + 1, z + 1), pointCloud(x, y + 1, z + 1), new Vector3(x + 1, y + 1, z + 1), pointCloud(x + 1, y + 1, z + 1), surfaceLevel));
currentCache(y, z, 2) = vertIndices(4);
}
if ((edgeTable(cubeIndex) & 32) == 32) {
//Vertex 5 - Leading Edge
vertIndices(5) = vertList.Count;
vertList.Add(LerpVert(new Vector3(x + 1, y + 1, z + 1), pointCloud(x + 1, y + 1, z + 1), new Vector3(x + 1, y + 1, z), pointCloud(x + 1, y + 1, z), surfaceLevel));
currentCache(y, z, 3) = vertIndices(5);
}
if ((edgeTable(cubeIndex) & 64) == 64) {
//Vertex 6
if (z > 0 && currentCache(y, z - 1, 2) != 0) {
vertIndices(6) = currentCache(y, z - 1, 2);
} else {
vertIndices(6) = vertList.Count;
vertList.Add(LerpVert(new Vector3(x + 1, y + 1, z), pointCloud(x + 1, y + 1, z), new Vector3(x, y + 1, z), pointCloud(x, y + 1, z), surfaceLevel));
currentCache(y, z, 4) = vertIndices(6);
}
}
if ((edgeTable(cubeIndex) & 128) == 128) {
//Vertex 7
if (x > 0 && behindCache(y, z, 3) != 0) {
vertIndices(7) = behindCache(y, z, 3);
} else {
vertIndices(7) = vertList.Count;
vertList.Add(LerpVert(new Vector3(x, y + 1, z), pointCloud(x, y + 1, z), new Vector3(x, y + 1, z + 1), pointCloud(x, y + 1, z + 1), surfaceLevel));
currentCache(y, z, 5) = vertIndices(7);
}
}
if ((edgeTable(cubeIndex) & 256) == 256) {
//Vertex 8
if (x > 0 && behindCache(y, z, 7) != 0) {
vertIndices(8) = behindCache(y, z, 7);
} else {
vertIndices(8) = vertList.Count;
vertList.Add(LerpVert(new Vector3(x, y, z + 1), pointCloud(x, y, z + 1), new Vector3(x, y + 1, z + 1), pointCloud(x, y + 1, z + 1), surfaceLevel));
currentCache(y, z, 6) = vertIndices(8);
}
}
if ((edgeTable(cubeIndex) & 512) == 512) {
//Vertex 9 - Leading Edge
vertIndices(9) = vertList.Count;
vertList.Add(LerpVert(new Vector3(x + 1, y, z + 1), pointCloud(x + 1, y, z + 1), new Vector3(x + 1, y + 1, z + 1), pointCloud(x + 1, y + 1, z + 1), surfaceLevel));
currentCache(y, z, 7) = vertIndices(9);
}
if ((edgeTable(cubeIndex) & 1024) == 1024) {
//Vertex 10
if (z > 0 && currentCache(y, z - 1, 7) != 0) {
vertIndices(10) = currentCache(y, z - 1, 7);
} else {
vertIndices(10) = vertList.Count;
vertList.Add(LerpVert(new Vector3(x + 1, y, z), pointCloud(x + 1, y, z), new Vector3(x + 1, y + 1, z), pointCloud(x + 1, y + 1, z), surfaceLevel));
currentCache(y, z, 8) = vertIndices(10);
}
}
if ((edgeTable(cubeIndex) & 2048) == 2048) {
//Vertex 11 - Dont Cache
if (z > 0 && currentCache(y, z - 1, 6) != 0) {
vertIndices(11) = currentCache(y, z - 1, 6);
} else if (x > 0 && behindCache(y, z, 8) != 0) {
vertIndices(11) = behindCache(y, z, 8);
} else {
vertIndices(11) = vertList.Count;
vertList.Add(LerpVert(new Vector3(x, y, z), pointCloud(x, y, z), new Vector3(x, y + 1, z), pointCloud(x, y + 1, z), surfaceLevel));
}
}
for (int i = 0; triTable(cubeIndex, i) != -1; i += 3) {
triList.Add(vertIndices(triTable(cubeIndex, i)));
triList.Add(vertIndices(triTable(cubeIndex, i + 1)));
triList.Add(vertIndices(triTable(cubeIndex, i + 2)));
}
}
}
}
behindCache = currentCache;
}
triangles = triList.ToArray();
vertices = vertList.ToArray();
normals = CalculateNormals(triangles, vertices);
}
Vector3 LerpVert(Vector3 p1, float v1, Vector3 p2, float v2, float surfaceLevel) {
float percent = (surfaceLevel - v1) / (v2 - v1);
return Vector3.Lerp(p1, p2, percent);
}
Vector3() CalculateNormals(int() tris, Vector3() verts) {
Vector3() normals = new Vector3(verts.Length);
for (int i = 0; i < tris.Length; i += 3) {
Vector3 pointA = verts(tris(i));
Vector3 pointB = verts(tris(i + 1));
Vector3 pointC = verts(tris(i + 2));
Vector3 normal = Vector3.Cross(pointA - pointB, pointA - pointC);
normals(tris(i)) += normal;
normals(tris(i + 1)) += normal;
normals(tris(i + 2)) += normal;
}
for (int i = 0; i < normals.Length; i++) {
normals(i).Normalize();
}
return normals;
}
```

Any help is greatly appreciated. I've been watching this for far too long now, unable to understand what's wrong.