Search Unity

Building Mesh from Polygon

Discussion in 'Scripting' started by kaptured, Jul 20, 2017.

  1. kaptured

    kaptured

    Joined:
    Jun 20, 2017
    Posts:
    8
    Hello,

    I have a list of vertices which define a polygon that represent the base of a building. I would like to create simple 3D prism mesh for the building, up to a certain height.

    When I run my code, I get this as a result:


    I am wondering if anyone would know how to resolve this issue. I have attached my code. Any help would be greatly appreciated.

    As a note, the way the list of vertices works in the code is that the even indexed vertices mark a vertex on the ground, and the subsequent odd indexed vertex is the same XZ position, but a different Y level, showing the point on the roof.

    My code is here:
    Code (CSharp):
    1. void createBuildings(List<List<Vector3>> buildingVertices) {
    2.         Debug.Log (buildingVertices.Count);
    3.         for (int i = 0; i < buildingVertices.Count; i++) {
    4.             // Create a building game object
    5.             GameObject thisBuilding = new GameObject ("Building "+ i);
    6.             float height = buildingVertices [i] [1].y;
    7.             // Compute the center point of the polygon both on the ground, and at height
    8.             // Add center vertices to end of list
    9.             Vector3 center = findCenter (buildingVertices[i]);
    10.             buildingVertices[i].Add (center);
    11.             Vector3 raisedCenter = center;
    12.             raisedCenter.y += height;
    13.             buildingVertices[i].Add (raisedCenter);
    14.  
    15.             List<int> tris = new List<int> ();
    16.             // Convert vertices to array for mesh
    17.             Vector3[] vertices = buildingVertices [i].ToArray();
    18.             // Populate triangles list with triangles that are two outside vertices and the center vertex for the y level
    19.             for (int j = 0; j < vertices.Length-2; j++) {
    20.                 tris.Add(j);
    21.                 tris.Add(j + 2);
    22.                 // The center vertex is on the ground if it is in the even indeces
    23.                 if (j % 2 == 0) {
    24.                     tris.Add(vertices.Length - 2);
    25.                 } else {
    26.                     tris.Add(vertices.Length - 1);
    27.                 }
    28.  
    29.                 tris.Add (j);
    30.                 tris.Add (j + 1);
    31.                 tris.Add (j + 2);
    32.    
    33.             }
    34.                
    35.             int[] triangles = tris.ToArray();
    36.  
    37.             // Create and apply the mesh
    38.             MeshFilter mf = thisBuilding.AddComponent<MeshFilter>();
    39.             Mesh mesh = new Mesh();
    40.             mf.mesh = mesh;
    41.             Renderer rend = thisBuilding.AddComponent<MeshRenderer>();
    42.             rend.material = mat;
    43.             mesh.vertices = vertices;
    44.             mesh.triangles = triangles;
    45.             mesh.RecalculateBounds();
    46.             mesh.RecalculateNormals();
    47.  
    48.         }
    49.     }
    50.  
    51.     // Find the center X-Z position of the polygon.
    52.     Vector3 findCenter(List<Vector3> verts) {
    53.         Vector3 center = Vector3.zero;
    54.         // Only need to check every other spot since the odd indexed vertices are in the air, but have same XZ as previous
    55.         for (int i = 0; i < verts.Count; i+= 2) {
    56.             center += verts [i];
    57.         }
    58.         center.y = 0;
    59.         return center / (verts.Count / 2);
    60.  
    61.     }
     
  2. KelsoMRK

    KelsoMRK

    Joined:
    Jul 18, 2010
    Posts:
    5,539
    Looks like you're winding half the triangles in the wrong direction. The vertices have to be wound clockwise otherwise the engine thinks the triangle face is in the other direction.
     
  3. kaptured

    kaptured

    Joined:
    Jun 20, 2017
    Posts:
    8
    Yeah I noticed that as well, but I don't know what's causing it. I don't have much experience with meshes in Unity so this code probably has some issues in it.
     
  4. KelsoMRK

    KelsoMRK

    Joined:
    Jul 18, 2010
    Posts:
    5,539
  5. kaptured

    kaptured

    Joined:
    Jun 20, 2017
    Posts:
    8
  6. kaptured

    kaptured

    Joined:
    Jun 20, 2017
    Posts:
    8
    I figured it out, thanks so much! The vertices were in counterclockwise order, so I had to wind the other way. Finished code is here:

    Code (CSharp):
    1. void createBuildings(List<List<Vector3>> buildingVertices) {
    2.         Debug.Log (buildingVertices.Count);
    3.         for (int i = 0; i < buildingVertices.Count; i++) {
    4.             // Create a building game object
    5.             GameObject thisBuilding = new GameObject ("Building "+ i);
    6.             float height = buildingVertices [i] [1].y;
    7.             // Compute the center point of the polygon both on the ground, and at height
    8.             // Add center vertices to end of list
    9.             Vector3 center = findCenter (buildingVertices[i]);
    10.             buildingVertices[i].Add (center);
    11.             Vector3 raisedCenter = center;
    12.             raisedCenter.y += height;
    13.             buildingVertices[i].Add (raisedCenter);
    14.  
    15.             List<int> tris = new List<int> ();
    16.             // Convert vertices to array for mesh
    17.             Vector3[] vertices = buildingVertices [i].ToArray();
    18.  
    19.             // Do the triangles for the roof and the floor of the building
    20.             // Roof points are at odd indeces
    21.             for (int j = vertices.Length - 3; j >= 0; j--) {
    22.                 // Add the point
    23.                 tris.Add (j);
    24.                 // Check for wrap around
    25.                 if (j - 2 >= 0) {
    26.                     tris.Add (j - 2);
    27.                 } else {
    28.                     // If wrap around, add the first vertex
    29.                     int diff = j - 2;
    30.                     tris.Add (vertices.Length - 2 + diff);
    31.                 }
    32.                 // Check if its at ground or building height level, choose proper center point
    33.                 if (j % 2 == 0) {
    34.                     tris.Add (vertices.Length - 2);
    35.                 } else {
    36.                     tris.Add (vertices.Length - 1);
    37.                 }
    38.             }
    39.  
    40.             // Do triangles which connect roof to ground
    41.             for (int j = vertices.Length-3; j >= 2; j--){
    42.                 if (j % 2 == 1) {
    43.                     tris.Add (j);
    44.                     tris.Add (j - 1);
    45.                     tris.Add (j - 2);
    46.                 } else {
    47.                     tris.Add (j);
    48.                     tris.Add (j - 2);
    49.                     tris.Add (j - 1);
    50.                 }
    51.             }
    52.                
    53.             int[] triangles = tris.ToArray();
    54.  
    55.             // Create and apply the mesh
    56.             MeshFilter mf = thisBuilding.AddComponent<MeshFilter>();
    57.             Mesh mesh = new Mesh();
    58.             mf.mesh = mesh;
    59.             Renderer rend = thisBuilding.AddComponent<MeshRenderer>();
    60.             rend.material = mat;
    61.             mesh.vertices = vertices;
    62.             mesh.triangles = triangles;
    63.             mesh.RecalculateBounds();
    64.             mesh.RecalculateNormals();
    65.  
    66.         }
    67.     }
    68.  
    69.     // Find the center X-Z position of the polygon.
    70.     Vector3 findCenter(List<Vector3> verts) {
    71.         Vector3 center = Vector3.zero;
    72.         // Only need to check every other spot since the odd indexed vertices are in the air, but have same XZ as previous
    73.         for (int i = 0; i < verts.Count; i+= 2) {
    74.             center += verts [i];
    75.         }
    76.         return center / (verts.Count / 2);
    77.  
    78.     }
     
    idbrii and KelsoMRK like this.