Getting a mirrored mesh from my data structure
- by Steve
Here's the background: I'm in the beginning stages of an RTS game in Unity. I have a procedurally generated terrain with a perlin-noise height map, as well as a function to generate a river. The problem is that the graphical creation of the map is taking the data structure of the map and rotating it by 180 degrees.
I noticed this problem when I was creating my rivers. I would set the River's height to flat, and noticed that the actual tiles that were flat in the graphical representation were flipped and mirrored.
Here's 3 screenshots of the map from different angles: http://imgur.com/a/VLHHq
As you can see, if you flipped (graphically) the river by 180 degrees on the z axis, it would fit where the terrain is flattened. I have a suspicion it is being caused by a misunderstanding on my part of how vertices work. Alas, here is a snippet of the code that is used:
This code here creates a new array of Tile objects, which hold the information for each tile, including its type, coordinate, height, and it's 4 vertices
public DTileMap (int size_x, int size_y)
{
this.size_x = size_x;
this.size_y = size_y;
//Initialize Map_Data Array of Tile Objects
map_data = new Tile[size_x, size_y];
for (int j = 0; j < size_y; j++) {
for (int i = 0; i < size_x; i++) {
map_data [i, j] = new Tile ();
map_data[i,j].coordinate.x = (int)i;
map_data[i,j].coordinate.y = (int)j;
map_data[i,j].vertices[0] = new Vector3 (i * GTileMap.TileMap.tileSize, map_data[i,j].Height, -j * GTileMap.TileMap.tileSize);
map_data[i,j].vertices[1] = new Vector3 ((i+1) * GTileMap.TileMap.tileSize, map_data[i,j].Height, -(j) * GTileMap.TileMap.tileSize);
map_data[i,j].vertices[2] = new Vector3 (i * GTileMap.TileMap.tileSize, map_data[i,j].Height, -(j-1) * GTileMap.TileMap.tileSize);
map_data[i,j].vertices[3] = new Vector3 ((i+1) * GTileMap.TileMap.tileSize, map_data[i,j].Height, -(j-1) * GTileMap.TileMap.tileSize);
}
}
This code sets the river tiles to height 0
foreach (Tile t in map_data)
{
if (t.realType == "Water")
{
t.vertices[0].y = 0f;
t.vertices[1].y = 0f;
t.vertices[2].y = 0f;
t.vertices[3].y = 0f;
}
}
And below is the code to generate the actual graphics from the data:
public void BuildMesh ()
{
DTileMap.DTileMap map = new DTileMap.DTileMap (size_x, size_z);
int numTiles = size_x * size_z;
int numTris = numTiles * 2;
int vsize_x = size_x + 1;
int vsize_z = size_z + 1;
int numVerts = vsize_x * vsize_z;
// Generate the mesh data
Vector3[] vertices = new Vector3[ numVerts ];
Vector3[] normals = new Vector3[numVerts];
Vector2[] uv = new Vector2[numVerts];
int[] triangles = new int[ numTris * 3 ];
int x, z;
for (z=0; z < vsize_z; z++) {
for (x=0; x < vsize_x; x++) {
normals [z * vsize_x + x] = Vector3.up;
uv [z * vsize_x + x] = new Vector2 ((float)x / size_x, 1f - (float)z / size_z);
}
}
for (z=0; z < vsize_z; z+=1) {
for (x=0; x < vsize_x; x+=1) {
if (x == vsize_x - 1 && z == vsize_z - 1) {
vertices [z * vsize_x + x] = DTileMap.DTileMap.map_data [x - 1, z - 1].vertices [3];
} else if (z == vsize_z - 1) {
vertices [z * vsize_x + x] = DTileMap.DTileMap.map_data [x, z - 1].vertices [2];
} else if (x == vsize_x - 1) {
vertices [z * vsize_x + x] = DTileMap.DTileMap.map_data [x - 1, z].vertices [1];
} else {
vertices [z * vsize_x + x] = DTileMap.DTileMap.map_data [x, z].vertices [0];
vertices [z * vsize_x + x+1] = DTileMap.DTileMap.map_data [x, z].vertices [1];
vertices [(z+1) * vsize_x + x] = DTileMap.DTileMap.map_data [x, z].vertices [2];
vertices [(z+1) * vsize_x + x+1] = DTileMap.DTileMap.map_data [x, z].vertices [3];
}
}
}
}
for (z=0; z < size_z; z++) {
for (x=0; x < size_x; x++) {
int squareIndex = z * size_x + x;
int triOffset = squareIndex * 6;
triangles [triOffset + 0] = z * vsize_x + x + 0;
triangles [triOffset + 2] = z * vsize_x + x + vsize_x + 0;
triangles [triOffset + 1] = z * vsize_x + x + vsize_x + 1;
triangles [triOffset + 3] = z * vsize_x + x + 0;
triangles [triOffset + 5] = z * vsize_x + x + vsize_x + 1;
triangles [triOffset + 4] = z * vsize_x + x + 1;
}
}
// Create a new Mesh and populate with the data
Mesh mesh = new Mesh ();
mesh.vertices = vertices;
mesh.triangles = triangles;
mesh.normals = normals;
mesh.uv = uv;
// Assign our mesh to our filter/renderer/collider
MeshFilter mesh_filter = GetComponent<MeshFilter> ();
MeshCollider mesh_collider = GetComponent<MeshCollider> ();
mesh_filter.mesh = mesh;
mesh_collider.sharedMesh = mesh;
calculateMeshTangents (mesh);
BuildTexture (map);
}
If this looks familiar to you, its because i got most of it from Quill18. I've been slowly adapting it for my uses. And please include any suggestions you have for my code. I'm still in the very early prototyping stage.