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): void createBuildings(List<List<Vector3>> buildingVertices) { Debug.Log (buildingVertices.Count); for (int i = 0; i < buildingVertices.Count; i++) { // Create a building game object GameObject thisBuilding = new GameObject ("Building "+ i); float height = buildingVertices [i] [1].y; // Compute the center point of the polygon both on the ground, and at height // Add center vertices to end of list Vector3 center = findCenter (buildingVertices[i]); buildingVertices[i].Add (center); Vector3 raisedCenter = center; raisedCenter.y += height; buildingVertices[i].Add (raisedCenter); List<int> tris = new List<int> (); // Convert vertices to array for mesh Vector3[] vertices = buildingVertices [i].ToArray(); // Populate triangles list with triangles that are two outside vertices and the center vertex for the y level for (int j = 0; j < vertices.Length-2; j++) { tris.Add(j); tris.Add(j + 2); // The center vertex is on the ground if it is in the even indeces if (j % 2 == 0) { tris.Add(vertices.Length - 2); } else { tris.Add(vertices.Length - 1); } tris.Add (j); tris.Add (j + 1); tris.Add (j + 2); } int[] triangles = tris.ToArray(); // Create and apply the mesh MeshFilter mf = thisBuilding.AddComponent<MeshFilter>(); Mesh mesh = new Mesh(); mf.mesh = mesh; Renderer rend = thisBuilding.AddComponent<MeshRenderer>(); rend.material = mat; mesh.vertices = vertices; mesh.triangles = triangles; mesh.RecalculateBounds(); mesh.RecalculateNormals(); } } // Find the center X-Z position of the polygon. Vector3 findCenter(List<Vector3> verts) { Vector3 center = Vector3.zero; // Only need to check every other spot since the odd indexed vertices are in the air, but have same XZ as previous for (int i = 0; i < verts.Count; i+= 2) { center += verts [i]; } center.y = 0; return center / (verts.Count / 2); }
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.
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.
This might help: https://gamedev.stackexchange.com/questions/30537/how-to-determine-counter-clockwise-vertex-winding
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): void createBuildings(List<List<Vector3>> buildingVertices) { Debug.Log (buildingVertices.Count); for (int i = 0; i < buildingVertices.Count; i++) { // Create a building game object GameObject thisBuilding = new GameObject ("Building "+ i); float height = buildingVertices [i] [1].y; // Compute the center point of the polygon both on the ground, and at height // Add center vertices to end of list Vector3 center = findCenter (buildingVertices[i]); buildingVertices[i].Add (center); Vector3 raisedCenter = center; raisedCenter.y += height; buildingVertices[i].Add (raisedCenter); List<int> tris = new List<int> (); // Convert vertices to array for mesh Vector3[] vertices = buildingVertices [i].ToArray(); // Do the triangles for the roof and the floor of the building // Roof points are at odd indeces for (int j = vertices.Length - 3; j >= 0; j--) { // Add the point tris.Add (j); // Check for wrap around if (j - 2 >= 0) { tris.Add (j - 2); } else { // If wrap around, add the first vertex int diff = j - 2; tris.Add (vertices.Length - 2 + diff); } // Check if its at ground or building height level, choose proper center point if (j % 2 == 0) { tris.Add (vertices.Length - 2); } else { tris.Add (vertices.Length - 1); } } // Do triangles which connect roof to ground for (int j = vertices.Length-3; j >= 2; j--){ if (j % 2 == 1) { tris.Add (j); tris.Add (j - 1); tris.Add (j - 2); } else { tris.Add (j); tris.Add (j - 2); tris.Add (j - 1); } } int[] triangles = tris.ToArray(); // Create and apply the mesh MeshFilter mf = thisBuilding.AddComponent<MeshFilter>(); Mesh mesh = new Mesh(); mf.mesh = mesh; Renderer rend = thisBuilding.AddComponent<MeshRenderer>(); rend.material = mat; mesh.vertices = vertices; mesh.triangles = triangles; mesh.RecalculateBounds(); mesh.RecalculateNormals(); } } // Find the center X-Z position of the polygon. Vector3 findCenter(List<Vector3> verts) { Vector3 center = Vector3.zero; // Only need to check every other spot since the odd indexed vertices are in the air, but have same XZ as previous for (int i = 0; i < verts.Count; i+= 2) { center += verts [i]; } return center / (verts.Count / 2); }