Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Question Error getting vertices and triangles

Discussion in 'Scripting' started by TTuPC, Apr 28, 2022.

  1. TTuPC

    TTuPC

    Joined:
    Mar 22, 2021
    Posts:
    36
    I'm trying to split my mesh in half.
    My idea is to create two different meshes, one made by vertices before a fixed value of Z and the other one after that value.
    So, to do this, I'm copying all vertices and triangles of the original mesh in another one.
    At the moment I'm testing only with the vertices before Z.
    This is my code:

    Code (CSharp):
    1. GameObject newObj = GameObject.Find("default");
    2.  
    3.         verts = new List<Vector3>();
    4.         tri = new List<int>();
    5.  
    6.         int[] trin;
    7.  
    8.  
    9.         mesh = GetComponent<MeshFilter>().mesh;
    10.         newMesh = newObj.GetComponent<MeshFilter>().mesh;
    11.  
    12.  
    13.  
    14.         trin = newMesh.triangles;
    15.  
    16.  
    17.         //Select all desired vertices and ignore the triangles that use undesired vertices
    18.         for (int i = 0; i < newMesh.vertices.Length; i++)
    19.         {
    20.             if (newMesh.vertices[i].z >= 0)
    21.             {
    22.                 verts.Add(newMesh.vertices[i]);
    23.             }
    24.             else
    25.             {
    26.                 for (int j = 0; j < newMesh.triangles.Length; j += 3)
    27.                 {
    28.                     if ((trin[j] == System.Array.IndexOf(newMesh.vertices, newMesh.vertices[i]))
    29.                         || (trin[j + 1] == System.Array.IndexOf(newMesh.vertices, newMesh.vertices[i]))
    30.                         || (trin[j + 2] == System.Array.IndexOf(newMesh.vertices, newMesh.vertices[i])))
    31.                     {
    32.                         trin[j] = 999;
    33.                         trin[j + 1] = 999;
    34.                         trin[j + 2] = 999;
    35.                     }
    36.                 }
    37.  
    38.             }
    39.         }
    40.  
    41.  
    42.         for (int i = 0; i < newMesh.triangles.Length; i++)
    43.         {
    44.             if (trin[i] != 999)
    45.             {
    46.                 tri.Add(newMesh.triangles[i]);
    47.             }
    48.         }
    49.  
    50.         Vector3[] ver = verts.ToArray();
    51.         int[] tr = tri.ToArray();
    52.  
    53.  
    54.  
    55.         //Change index in the new triangles array according to new vertices
    56.         for(int i = 0; i < ver.Length; i++)
    57.         {
    58.             for(int j = 0; j < newMesh.vertices.Length; j++)
    59.             {
    60.                 if(ver[i] == newMesh.vertices[j])
    61.                 {
    62.                     for(int h = 0; h < tr.Length; h++)
    63.                     {
    64.                         if(tr[h] == System.Array.IndexOf(newMesh.vertices, newMesh.vertices[j]))
    65.                         {
    66.                             tr[h] = System.Array.IndexOf(ver, ver[i]);
    67.                         }
    68.                     }
    69.                 }
    70.             }
    71.         }
    72.  
    73.  
    74.         mesh.Clear();
    75.         mesh.vertices = ver;
    76.         mesh.triangles = tr;
    77.  
    78.  
    Unfortunately, when I run my code I receive the error "Failed setting triangles. Some indices are referencing out of bounds vertices.", does someone know what I'm doing wrong in my code?

    P.S.: I know that the triple for cycle is a murder, but is just for testing simple model for now!
     
  2. PraetorBlue

    PraetorBlue

    Joined:
    Dec 13, 2012
    Posts:
    7,722
    I don't know precisely the problem yet but you really need to stop calling
    newmesh.vertices
    so many times. Every time you call that it creates a brand new fresh copy of the entire vertex array. Just save it once in a variable and reuse it.
    Vector3[] vertices = newMesh.vertices;

    Then replace every mention of
    newmesh.vertices
    with just
    vertices
    .

    You need to do the same with
    newMesh.triangles
    .

    Also this code is strange and extremely wasteful:
    System.Array.IndexOf(newMesh.vertices, newMesh.vertices[i])
    - as it is just equivalent to
    i

    Likewise
    System.Array.IndexOf(newMesh.vertices, newMesh.vertices[j])
    is just
    j

    and
    System.Array.IndexOf(ver, ver[i])
    is just
    i
     
  3. SourGummi

    SourGummi

    Joined:
    Nov 14, 2021
    Posts:
    96
    out of bounds means you're accessing array size + n which does not exist.
    also, use an array, not a list. a list is like a dynamic array which you can add elements and so its not a fixed size. setting a fixed sized array will never overflow.

    also, for loops are efficient if used correctly so 3 is not overkill.

    here is an example i used in one of my recent projects,
    Code (CSharp):
    1. private void CreateVertices()
    2.     {
    3.         vertexArray = new Vector3[(1 + vertexCount) * (1 + vertexCount)];
    4.  
    5.         int i = 0;
    6.         for (int z = 0; z <= vertexCount; z++)
    7.         {
    8.             for (int x = 0; x <= vertexCount; x++)
    9.             {
    10.                 vertexArray[i] = new Vector3(x, 0F, z);
    11.                 i++;
    12.             }
    13.         }
    14.  
    15.         CreateTriangles();
    16.     }
    17.  
    18.     private void CreateTriangles()
    19.     {
    20.         triangleArray = new int[vertexCount * vertexCount * 6];
    21.         int ver = 0;
    22.         int tri = 0;
    23.  
    24.         for (int z = 0; z < vertexCount; z++)
    25.         {
    26.             for (int x = 0; x < vertexCount; x++)
    27.             {
    28.                 triangleArray[tri] = ver;
    29.                 triangleArray[tri + 1] = ver + vertexCount;
    30.                 triangleArray[tri + 2] = ver + 1;
    31.                 triangleArray[tri + 3] = ver + 1;
    32.                 triangleArray[tri + 4] = ver + vertexCount + 1;
    33.                 triangleArray[tri + 5] = ver + vertexCount + 2;
    34.  
    35.                 ver++;
    36.                 tri += 6;
    37.             }
    38.             ver++;
    39.         }
    40.  
    41.     }
    just also while im reading your code, i noticed you never call RecalculateNormals on your new mesh. helps prevent odd shading or flipped faces i think (not fully read up on it yet)
     
    Last edited: Apr 28, 2022
  4. TTuPC

    TTuPC

    Joined:
    Mar 22, 2021
    Posts:
    36
    just also while im reading your code, i noticed you never call RecalculateNormals on your new mesh. helps prevent odd shading or flipped faces i think (not fully read up on it yet)[/QUOTE]

    Yes, because I'm not at that point, at the moment the new mesh is not displayed and I receive that error.
    The error is referring to the fact that some triangles have as vertex values an index outside the vertices index.
    How is this possible?
     
  5. SourGummi

    SourGummi

    Joined:
    Nov 14, 2021
    Posts:
    96
    your triangle array should be equal to the size of your (vertex array*6), have you set this? try a Debug.Log(trin.Length) and vert.Length
     
  6. TTuPC

    TTuPC

    Joined:
    Mar 22, 2021
    Posts:
    36
    Are you sure about this? I mean, I think that the only two conditions are that values of triangles must be in the range [0, Mesh.vertices.Length] and that the length of Mesh.triangles must be multiple of 3.
     
  7. SourGummi

    SourGummi

    Joined:
    Nov 14, 2021
    Posts:
    96
    untested
    Code (CSharp):
    1. private static int[] triangles_copy;
    2.     private static List<Vector3> vertices_copy;
    3.  
    4.     private static void CopyFromMeshToNew(ref Mesh old_mesh, Mesh new_mesh)
    5.     {
    6.         // vertices
    7.         vertices_copy = new List<Vector3>();
    8.         for (int vert = 0; vert < old_mesh.vertices.Length; vert++)
    9.             vertices_copy.Add(old_mesh.vertices[vert]);
    10.  
    11.         // triangles
    12.         triangles_copy = new int[old_mesh.triangles.Length];
    13.         for (int tri = 0; tri < old_mesh.triangles.Length; tri++)
    14.             triangles_copy[tri] = old_mesh.triangles[tri];
    15.  
    16.         // copy list to vector array
    17.         Vector3[] replace = new Vector3[vertices_copy.Count];
    18.         vertices_copy.CopyTo(replace);
    19.  
    20.         // add to mesh?
    21.         new_mesh.vertices = replace;
    22.         new_mesh.triangles = triangles_copy;
    23.  
    24.     }
     
  8. TTuPC

    TTuPC

    Joined:
    Mar 22, 2021
    Posts:
    36
    Sorry but this is meant to copy a mesh in another, no?
     
  9. SourGummi

    SourGummi

    Joined:
    Nov 14, 2021
    Posts:
    96
    sorry sorry, i didnt see the split, i know what you mean now
     
  10. SourGummi

    SourGummi

    Joined:
    Nov 14, 2021
    Posts:
    96
    when i did this, i simply did total size / block_size then make an array for each block