Marching cubes problem, some tris not drawing properly

I’m trying to get a marching squares algorithm from a tutorial working in 3D as a bit of an exercise, but I’m having a problem with the code. I’m not exactly sure what it is, as I’ve checked it numerous times.

The problem should be obivous.

using UnityEngine;
using System.Collections.Generic;

public class Chunk : MonoBehaviour {

	public Voxel[] Voxels;

	public GameObject voxelFab;

	private int chunkResolution;
	private float voxelSize;

	public Mesh mesh;
	private List<Vector3> vertices;
	private List<Vector2> uv;
	private List<int> triangles;

	public void Awake (/*int resolution, float size*/) {
		chunkResolution = 8;
		voxelSize = 1f / chunkResolution;
		Voxels = new Voxel[chunkResolution * chunkResolution * chunkResolution];

		vertices = new List<Vector3>();
		uv = new List<Vector2>();
		triangles = new List<int>();
		GetComponent<MeshFilter>().mesh = mesh = new Mesh();

		GenerateChunkData();
		RefreshChunk();
	}

	public void GenerateChunkData() {
		for (int i = 0, y = 0; y < chunkResolution; y++)
		{
			for (int z = 0; z < chunkResolution; z++)
			{
				for (int x = 0; x < chunkResolution; x++, i++)
				{
					CreateVoxel (i, x, y, z);
					Debug.Log ("Voxel at: " + Voxels<em>.position + "has it's edge positions as follows: " + "x: " + Voxels<em>.xEdge + " z: " + Voxels_.zEdge + " y: " + Voxels*.yEdge);*_</em></em>

* }*
* }*
* }*
* SetVoxels();*
* }*

* //Creates helper objects at the position of each voxel. Also create the voxel objects.*
* public void CreateVoxel (int i, int x, int y, int z) {*
* GameObject o = Instantiate (voxelFab) as GameObject;*
* o.transform.parent = transform;*
* o.transform.localPosition = new Vector3 (x + 0.5f, y + 0.5f, z + 0.5f);*
* o.transform.localScale = Vector3.one;*
* o.GetComponent().material.color = new Color (0.3f, 0.3f, 0.3f, 0.15f);*

_ Voxels = new Voxel (x, y, z, 1f);
* }*_

_ //Manually set the state of each voxel. The index is y * chunkResolution squared + z * chunkResolution + x;
* void SetVoxels() {
Voxels[5 * chunkResolution * chunkResolution + 5 * chunkResolution + 8].State = true;
Voxels[2 * chunkResolution * chunkResolution + 1 * chunkResolution + 0].State = true;
}*_

* //Function for refreshing the chunk. Currently only does the triangulation.*
* public void RefreshChunk() {*
* Triangulate();*
* }*

* //Clears the old lists of vertices, uvs and triangle indices and triangulates the mesh, then sets the new mesh variables.*
* public void Triangulate() {*
* mesh.Clear ();*
* vertices.Clear ();*
* uv.Clear ();*
* triangles.Clear ();*

* TriangulateCellRows();*

* mesh.vertices = vertices.ToArray ();*
* mesh.uv = uv.ToArray ();*
* mesh.triangles = triangles.ToArray ();*
* mesh.RecalculateNormals ();*
* }*

* //Loops through each cell and triangulates it.*
* public void TriangulateCellRows() {*
* int cells = chunkResolution - 1;*
* for (int i = 0, y = 0; y < cells; y++, i++)*
* {*
* for (int z = 0; z < cells; z++, i++)*
* {*
* for (int x = 0; x < cells; x++, i++)*
* {*
* TriangulateCell (*
_ Voxels*,
Voxels[i + 1],
Voxels[i + chunkResolution],
Voxels[i + chunkResolution + 1],
Voxels[i + chunkResolution * chunkResolution],
Voxels[i + chunkResolution * chunkResolution + 1],
Voxels[i + chunkResolution * chunkResolution + chunkResolution],
Voxels[i + chunkResolution * chunkResolution + chunkResolution + 1]
);*_

* }*
* }*
* }*
* }*

* public void TriangulateCell (Voxel a, Voxel b, Voxel c, Voxel d, Voxel e, Voxel f, Voxel g, Voxel h) {*
* int cellType = 0;*
* //Add a number to cellType depending on which voxels of that cell are active.*
* if (a.State)*
* cellType |= 1;*

* if (b.State)*
* cellType |= 2;*

* if (c.State)*
* cellType |= 4;*

* if (d.State)*
* cellType |= 8;*

* if (e.State)*
* cellType |= 16;*

* if (f.State)*
* cellType |= 32;*

* if (g.State)*
* cellType |= 64;*

* if (h.State)*
* cellType |= 128;*

* #region Single Triangles and 0, 255 cases*
* //Adds a triangle when either one voxel of the cell is cell active, or only one is inactive.*
* switch (cellType)*
* {*
* //None of the voxels are active, don’t draw the cell.*
* case 0:*
* return;*

* //The bottom left front (0,0,0) of the cell is the only active/inactive, draw a triangle there.*
* case 1:*
* AddTriangle (a.yEdge, a.zEdge, a.xEdge);*
* break;*
* case 254:*
* AddTriangle (a.xEdge, a.zEdge, a.yEdge);*
* break;*

* //The bottom right front (1,0,0) of the cell is the only active/inactive, draw a triangle there.*
* case 2:*
* AddTriangle (b.yEdge, a.xEdge, b.zEdge);*
* break;*
* case 253:*
* AddTriangle (b.zEdge, a.xEdge, b.yEdge);*
* break;*

* //The bottom left back (0,0,1) of the cell is the only active/inactive, draw a triangle there.*
* case 4:*
* AddTriangle (c.yEdge, c.xEdge, a.zEdge);*
* break;*
* case 251:*
* AddTriangle (a.zEdge, c.xEdge, c.yEdge);*
* break;*

* //The bottom right back (1,0,1) of the cell is the only active/inactive, draw a triangle there.*
* case 8:*
* AddTriangle (d.yEdge, b.zEdge, c.xEdge);*
* break;*
* case 247:*
* AddTriangle (c.xEdge, b.zEdge, d.yEdge);*
* break;*

* //The top left front (0,1,0) of the cell is the only active/inactive, draw a triangle there.*
* case 16:*
* AddTriangle (a.yEdge, e.xEdge, e.zEdge);*
* break;*
* case 239:*
* AddTriangle (e.zEdge, e.xEdge, a.yEdge);*
* break;*

* //The top right front (1,1,0) of the cell is the only active/inactive, draw a triangle there.*
* case 32:*
* AddTriangle (b.yEdge, f.zEdge, e.xEdge);*
* break;*
* case 223:*
* AddTriangle (e.xEdge, f.zEdge, b.yEdge);*
* break;*

* //The top left back (0,1,1) of the cell is the only active/inactive, draw a triangle there.*
* case 64:*
* AddTriangle (c.yEdge, e.zEdge, g.xEdge);*
* break;*
* case 191:*
* AddTriangle (c.yEdge, g.xEdge, e.zEdge);*
* break;*

* //The top right back (1,1,1) of the cell is the only active/inactive, draw a triangle there.*
* case 128:*
* AddTriangle (d.yEdge, g.xEdge, f.zEdge);*
* break;*
* case 127:*
* AddTriangle (f.zEdge, g.xEdge, d.yEdge);*
* break;*

* //All voxels are active, don’t draw the cell.*
* case 255:*
* return;*
* }*
* #endregion*
* }*

* //Adds a triangle based on the given points. The UV values are arbitrary guesses for now.*
* void AddTriangle (Vector3 a, Vector3 b, Vector3 c) {*
* int triIndex = vertices.Count;*
* vertices.Add (a);*
* vertices.Add (b);*
* vertices.Add (c);*
* uv.Add (new Vector2 (0,0));*
* uv.Add (new Vector2 (0.5f,1));*
* uv.Add (new Vector2 (1,0));*
* triangles.Add (triIndex);*
* triangles.Add (triIndex + 1);*
* triangles.Add (triIndex + 2);*
* }*

}

I don’t use voxel’s, but I do dynamically generate a lot of meshes. For MeshFilter meshes you draw faces as a pair of triangles, in triangle list form. So for every face, you have 4 verts, 4 uvs, 4 normals, but then 6 triangle points.

The vertex indicies look like this, with these triangles

       3 ------ 0
         |   /|
         |  / |
         | /  |
         |/   |
       2 ------ 1

If you do this your tris to be added will be 0, 1, 2, 0, 2, 3. If this is out of order, then the triangles will be flipped on the same face. If you only do 4 of the 6 required triangle points then you loose some triangles, and the points are all over the place. Maybe your triangle points aren’t right?
Looking at your code, the second triangle of every quad would have it’s first vertex off by one. The second triangle would need something like triangles.Add(triIndex - 1); as it’s first point.

EDIT From here on out:
I made a test case for the 4th example from the wikipedia page’s picture. Here’s the (heavily commented) script I attached to the cube:

using UnityEngine;
using System.Collections;

public class CreateTrianglesFromVoxels : MonoBehaviour {

    public bool[] isVoxelSet;
    private Vector3[] voxels;
    private byte voxelSum;

    void Awake()
    {
        byte voxelZero = 1;

        for(int i = 0; i < 8; i++)
        {
            if (isVoxelSet*) voxelSum += (byte)(voxelZero << i);*

}

voxels = new Vector3[8];
SetOriginalCubeVerts();
}

private Vector3[] vertices;
private int[] triangles;

void Start()
{
switch (voxelSum)
{
case 0:
break;
case 136:
// voxel 3 requires a triangle covering the corner of the voxel.
// Thus edges are to cube verts 0, 2, and 4.
// voxel 7 requires a similar thing, with edges going to 0, 4, and 6.

// So we need 2 separate tris, with 6 total verts.
vertices = new Vector3[6];
triangles = new int[6];

// voxel 3 tri, ensuring clockwise order
vertices[0] = Vector3.Lerp(voxels[3], voxels[2], 0.5f);
vertices[1] = Vector3.Lerp(voxels[3], voxels[4], 0.5f);
vertices[2] = Vector3.Lerp(voxels[3], voxels[0], 0.5f);
triangles[0] = 0;
triangles[1] = 1;
triangles[2] = 2;

// voxel 7 tri, again ordering matters
vertices[3] = Vector3.Lerp(voxels[7], voxels[0], 0.5f);
vertices[4] = Vector3.Lerp(voxels[7], voxels[4], 0.5f);
vertices[5] = Vector3.Lerp(voxels[7], voxels[6], 0.5f);
triangles[3] = 3;
triangles[4] = 4;
triangles[5] = 5;

break;
default:
break;
}

Mesh mesh = new Mesh();
mesh.vertices = vertices;
mesh.triangles = triangles;
mesh.RecalculateNormals();
GetComponent().mesh = mesh;
}

/* There are 8 voxels total, one at each of the corners in the cube.
*
* The top four are indexed 0 through 3 starting at the top-front-left
* point, going clockwise around the top of the cube.
*
* The other 4 are indexed 4 through 7 and start at the bottom-front-right
* corner, again going clockwise around the bottom.
*
* Thus voxels = { false, true, false, false, true, true, true, false } would
* mean that the back-left corner was set on the top, and all the voxels except
* the one on the bottom-left-front.
*
* The example I am doing is number 136; voxels 3 and 7 are set (0-indexed).
*
* I doing the fourth one in the top row here:
_* http://upload.wikimedia.org/wikipedia/commons/thumb/a/a7/MarchingCubes.svg/501px-MarchingCubes.svg.png_
*/
private void SetOriginalCubeVerts()
{
voxels[0] = new Vector3(-0.5f, 0.5f, -0.5f);
voxels[1] = new Vector3(-0.5f, 0.5f, 0.5f);
voxels[2] = new Vector3(0.5f, 0.5f, 0.5f);
voxels[3] = new Vector3(0.5f, 0.5f, -0.5f);

voxels[4] = new Vector3(0.5f, -0.5f, -0.5f);
voxels[5] = new Vector3(0.5f, -0.5f, 0.5f);
voxels[6] = new Vector3(-0.5f, -0.5f, 0.5f);
voxels[7] = new Vector3(-0.5f, -0.5f, -0.5f);
}
}

Take a look at the cube properties from this image:

[39061-marchingcubesproblem.png|39061]*
*

I’ve solved the problem. Turns out that when looping through Y on TriangulateCellRows(), I had to increment i by chunkResolution, and not by 1. The glitchy triangles weren’t even supposed to draw.