- Home /
Separating Procedurally Generated Mesh, Based On Triangle Height
Hello! I have been working on creating a procedurally generated world. The image attached shows a simplified representation of the terrain. I have spent so many hours trying to figure this out, and I have been unsuccessful; hence why I am asking anyone for help.
- Picture showing a basic terrain generation - Picture showing any triangles from 'x' height or above to be moved onto a separate mesh
My problem, is that I want to create biomes, and the only way I can possibly think of doing this, is by splitting the terrain into a sub-mesh to give it a different color.
So my question is: how can I divide a mesh into two separate meshes, by the y position of the triangles?
If you have any other questions please let me know!
Answer by sSuite · Dec 04, 2018 at 05:52 AM
Tricky one!
So, broadly speaking, you'll want to loop through all of the triangles and build the information for two new meshes as you go along. You'll need at least a collection each for triangles and vertices. You'll probably want normals as well, but you could recalculate those automatically if you wanted to. For now, let's just pretend you only want vertices and triangles.
I like to store these as lists, since I'm lazy. Let's start with:
List<int> upper_mesh_triangles = new List<int>();
List<int> lower_mesh_triangles = new List<int>();
We'll get to the vertices later. That's going to be a little harder. So, now you want to loop through all of your triangles, figure out which ones you want in each mesh, and add them to the lists. Remember that triangles come in groups of 3, so we're stepping through this array 3 at a time:
for (int i = 0; i < old_triangles.Length; i+=3) {
if (old_vertices[old_triangles[i+0]].y > threshold ||
old_vertices[old_triangles[i+1]].y > threshold ||
old_vertices[old_triangles[i+2]].y > threshold) {
upper_mesh_triangles.Add(old_triangles[i+0]);
upper_mesh_triangles.Add(old_triangles[i+1]);
upper_mesh_triangles.Add(old_triangles[i+2]);
}
else {
lower_mesh_triangles.Add(old_triangles[i+0]);
lower_mesh_triangles.Add(old_triangles[i+1]);
lower_mesh_triangles.Add(old_triangles[i+2]);
}
}
Here's the funky part: Now we need to take our lists of triangles and build lists of vertices -- while ALSO modifying the list of triangles because the indices are now wrong, AND making sure we don't duplicate any vertices that we don't want to. I'll just show you what this would look like for the upper mesh, since the lower mesh will basically be exactly the same.
List<Vector3> upper_mesh_vertices = new List<Vector3>();
Dictionary<int,int> upper_mesh_triangle_translations = new Dictionary<int,int>();
for (int i = 0; i < upper_mesh_triangles.Count; i+=3) {
if (!upper_mesh_triangle_translations.ContainsKey(upper_mesh_triangles[i+0])) {
upper_mesh_triangle_translations[upper_mesh_triangles[i+0]] = upper_mesh_vertices.Count;
upper_mesh_vertices.Add(old_vertices[upper_mesh_triangles[i+0]]);
}
upper_mesh_triangles[i+0] = upper_mesh_triangle_translations[upper_mesh_triangles[i+0]];
if (!upper_mesh_triangle_translations.ContainsKey(upper_mesh_triangles[i+1])) {
upper_mesh_triangle_translations[upper_mesh_triangles[i+1]] = upper_mesh_vertices.Count;
upper_mesh_vertices.Add(old_vertices[upper_mesh_triangles[i+1]]);
}
upper_mesh_triangles[i+1] = upper_mesh_triangle_translations[upper_mesh_triangles[i+1]];
if (!upper_mesh_triangle_translations.ContainsKey(upper_mesh_triangles[i+2])) {
upper_mesh_triangle_translations[upper_mesh_triangles[i+2]] = upper_mesh_vertices.Count;
upper_mesh_vertices.Add(old_vertices[upper_mesh_triangles[i+2]]);
}
upper_mesh_triangles[i+2] = upper_mesh_triangle_translations[upper_mesh_triangles[i+2]];
}
And there you have it! A list of triangles and vertices for each of your new meshes. You should be able to turn these into actual meshes relatively easily.
Let me know if you have any questions. Hope this helps!
Thank you so much for this detailed explanation. Not only did you help me understand it, but your answer was also extremely detailed as well. Thanks a lot!
Hope this answer eventually helps any others down the track who have similar issues!