Search code examples
unity-game-enginemarching-cubes

"Failed setting triangles. Some indices are referencing out of bounds vertices." when the the edge index is greater than the number of vertices


I'm trying to get the the marching cubes algorithm to work in unity, but when I try to add triangles to my vertices based on a triangulation table I get the error stated in the title

If I try drawing the triangle using numbers less than the length of the vertices, it works.

//Store the values and corner positions of the cube
public class Cube
{

    public int[] values;
    public Vector3[] corners;

    public Cube() { 
    }
    public Cube(int[] val, Vector3[] cor)
    {
        values = val;
        corners = cor;
    }


}

//Generate the grid
        gridOfPoints = new Vector3[8];
        gridOfPoints[0] = new Vector3(0, 0, 1);
        gridOfPoints[1] = new Vector3(1, 0, 1);
        gridOfPoints[2] = new Vector3(1, 0, 0);
        gridOfPoints[3] = new Vector3(0, 0, 0);
        gridOfPoints[4] = new Vector3(0, 1, 1);
        gridOfPoints[5] = new Vector3(1, 1, 1);
        gridOfPoints[6] = new Vector3(1, 1, 0);
        gridOfPoints[7] = new Vector3(0, 1, 0);

//Add values and poistions
Cube firstCube = new Cube(new int[8] { -1, -1, 0, 0, 0, 0, 0, 0 }, gridOfPoints);

//Populate cubes array with cubes
cubes = new Cube[] { firstCube };

List<Vector3> vertices = new List<Vector3>();

List<int> triangles = new List<int>();


//Triangulation lookup table
int[,] triTable = new int[256,16]{ ... 
{5, 0, 1, 5, 4, 0, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1}
...}


int cubeIndex = 162;

//Getting the array of edges
int[] triangulation = new int[16];


        for (int i = 0; i < 16; i++)
        {
            triangulation[i] = triTable[cubeIndex, i];
        }

//corners connected to edges lookup table
int[,] cornerPointsToEdge = new int[12, 2] { 
                                                { 0, 1 }, 
                                                { 1, 2 }, 
                                                { 2, 3 }, 
                                                { 3, 0 }, 
                                                { 4, 5 }, 
                                                { 5, 6 }, 
                                                { 6, 7 },
                                                { 7, 4 }, 
                                                { 4, 0 }, 
                                                { 5, 1 }, 
                                                { 6, 2 }, 
                                                { 7, 3 } 
                                            };
//Getting the centre point of the edge in given by the triangulation table
foreach (int edgeIndex in triangulation)
        {   

            if(edgeIndex == -1) {
                continue;
            }


            int indexA = cornerPointsToEdge[edgeIndex, 0];
            int indexB = cornerPointsToEdge[edgeIndex, 1];

            Vector3 vertexPos = (cubes[0].corners[indexA] + cubes[0].corners[indexB]) / 2;

            //Adding the centre point to the vertices
            vertices.Add(vertexPos);
            //Adding the edge to the triangles list 
            triangles.Add(edgeIndex);

        }


mesh.vertices = vertices.ToArray();
mesh.triangles = triangles.ToArray();
mesh.RecalculateNormals();

This is the full error message I'm getting "Failed setting triangles. Some indices are referencing out of bounds vertices. IndexCount: 9, VertexCount: 9 UnityEngine.Mesh:set_triangles(Int32[])"

An image of my corners and vertices I want to draw triangles between

An image of the way I have my edges mapped


Solution

  • The integers in Mesh.triangles are indices of Mesh.vertices.

    3 sequential indices make a triangle. so:

    • Value must be in the range: [0, Mesh.vertices.Length)
    • Length of Mesh.triangles must be multiple of 3.
    • Front face of the triangle is defined by the order of 3 indices using left-handed rule

    For example you have 4 vertices:

    mesh.vertices = new Vector3[]
    {
        new Vector3(0, 0, 0), //0
        new Vector3(0, 1, 0), //1
        new Vector3(1, 0, 0), //2
        new Vector3(1, 1, 0), //3
    };
    

    You can generate a vertical rectangle with 2 triangles

    mesh.triangles = new int[]
    {
         0, 1, 3, //triangle 0
         0, 3, 2, //triangle 1
    };