I'm creating a mesh programmatically in Unity3D. Each section of the mesh is setup with 4 verts:
// 1 ----- 2
// | a / |
// | / b |
// 3 ----- 4
My UVs are:
1 = 0, 1
2 = 0.125, 1
3 = 0, 0.875
4 = 0.125, 0.875
My texture is 2048x2048. The tile is in the top left of the image and is 256x256 in size. I've updated the texture a bit with some additional tiles to better give an idea of what I'm trying to do.
Im getting white edges around each tile on the mesh.
I'm importing the image with the following settings.
The code the generate the mesh (manual normals):
IEnumerator BuildMesh (int width, int height, float tileSize) {
float halfSize = tileSize / 2f;
List<Vector3> vertices = new List<Vector3> ();
List<Vector3> normals = new List<Vector3> ();
List<Vector2> uv = new List<Vector2> ();
List<int> triangles = new List<int> ();
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
int tileVertIdx = vertices.Count;
float h = map.GetHeight(startX + x, startY + y);
float n = map.GetHeight(startX + x, startY + y - 1);
float s = map.GetHeight(startX + x, startY + y + 1);
float e = map.GetHeight(startX + x + 1, startY + y);
float w = map.GetHeight(startX + x - 1, startY + y);
float ne = map.GetHeight(startX + x + 1, startY + y - 1);
float nw = map.GetHeight(startX + x - 1, startY + y - 1);
float se = map.GetHeight(startX + x + 1, startY + y + 1);
float sw = map.GetHeight(startX + x - 1, startY + y + 1);
Vector3 tileCenter = new Vector3 (x * tileSize, h, y * tileSize);
Rect topUV = map.GetTopUV ((int)h);
if (n == h && s == h && e == h && w == h && ne == h && nw == h && se == h && sw == h) {
// Each tile
// 1 ----- 2
// | a / |
// | / b |
// 3 ----- 4
// top row
vertices.Add (new Vector3 (tileCenter.x - halfSize, tileCenter.y, tileCenter.z - halfSize));
vertices.Add (new Vector3 (tileCenter.x + halfSize, tileCenter.y, tileCenter.z - halfSize));
// bottom row
vertices.Add (new Vector3 (tileCenter.x - halfSize, tileCenter.y, tileCenter.z + halfSize));
vertices.Add (new Vector3 (tileCenter.x + halfSize, tileCenter.y, tileCenter.z + halfSize));
normals.Add (Vector3.up);
normals.Add (Vector3.up);
normals.Add (Vector3.up);
normals.Add (Vector3.up);
uv.Add (new Vector2(topUV.x, topUV.y));
uv.Add (new Vector2(topUV.x - topUV.width, topUV.y));
uv.Add (new Vector2(topUV.x, topUV.y - topUV.height));
uv.Add (new Vector2(topUV.x - topUV.width, topUV.y - topUV.height));
// a
triangles.Add (tileVertIdx + 0);
triangles.Add (tileVertIdx + 2);
triangles.Add (tileVertIdx + 1);
// b
triangles.Add (tileVertIdx + 1);
triangles.Add (tileVertIdx + 2);
triangles.Add (tileVertIdx + 3);
} else {
// Each tile
// 1 - 2 - 3 14 --- 16
// |a\b|c/d\ | k / |
// 4 - 5 - 6 | / |
// |e/f|g\h| | / l |
// 7 - 8 - 9 15 --- 17
// 10 --- 11
// | i / j |
// 12 --- 13
// top row
vertices.Add (new Vector3 (tileCenter.x - halfSize, tileCenter.y, tileCenter.z - halfSize));
vertices.Add (new Vector3 (tileCenter.x, tileCenter.y, tileCenter.z - halfSize));
vertices.Add (new Vector3 (tileCenter.x + halfSize, tileCenter.y, tileCenter.z - halfSize));
// middle row
vertices.Add (new Vector3 (tileCenter.x - halfSize, tileCenter.y, tileCenter.z));
vertices.Add (new Vector3 (tileCenter.x, tileCenter.y, tileCenter.z));
vertices.Add (new Vector3 (tileCenter.x + halfSize, tileCenter.y, tileCenter.z));
// bottom row
vertices.Add (new Vector3 (tileCenter.x - halfSize, tileCenter.y, tileCenter.z + halfSize));
vertices.Add (new Vector3 (tileCenter.x, tileCenter.y, tileCenter.z + halfSize));
vertices.Add (new Vector3 (tileCenter.x + halfSize, tileCenter.y, tileCenter.z + halfSize));
// bottom square
vertices.Add (new Vector3 (tileCenter.x - halfSize, h, tileCenter.z + halfSize));
vertices.Add (new Vector3 (tileCenter.x + halfSize, h, tileCenter.z + halfSize));
vertices.Add (new Vector3 (tileCenter.x - halfSize, s, tileCenter.z + halfSize));
vertices.Add (new Vector3 (tileCenter.x + halfSize, s, tileCenter.z + halfSize));
// right square
vertices.Add (new Vector3 (tileCenter.x + halfSize, h, tileCenter.z + halfSize));
vertices.Add (new Vector3 (tileCenter.x + halfSize, h, tileCenter.z - halfSize));
vertices.Add (new Vector3 (tileCenter.x + halfSize, e, tileCenter.z + halfSize));
vertices.Add (new Vector3 (tileCenter.x + halfSize, e, tileCenter.z - halfSize));
normals.Add (Vector3.up);
normals.Add (Vector3.up);
normals.Add (Vector3.up);
normals.Add (Vector3.up);
normals.Add (Vector3.up);
normals.Add (Vector3.up);
normals.Add (Vector3.up);
normals.Add (Vector3.up);
normals.Add (Vector3.up);
normals.Add (Vector3.up);
normals.Add (Vector3.up);
normals.Add (Vector3.up);
normals.Add (Vector3.up);
normals.Add (Vector3.up);
normals.Add (Vector3.up);
normals.Add (Vector3.up);
normals.Add (Vector3.up);
uv.Add (new Vector2(topUV.x, topUV.y));
uv.Add (new Vector2(topUV.x - (topUV.width / 2), topUV.y));
uv.Add (new Vector2(topUV.x - topUV.width, topUV.y));
uv.Add (new Vector2(topUV.x, topUV.y - (topUV.height / 2)));
uv.Add (new Vector2(topUV.x - (topUV.width / 2), topUV.y - (topUV.height / 2)));
uv.Add (new Vector2(topUV.x - topUV.width, topUV.y - (topUV.height / 2)));
uv.Add (new Vector2(topUV.x, topUV.y - topUV.height));
uv.Add (new Vector2(topUV.x - (topUV.width / 2), topUV.y - topUV.height));
uv.Add (new Vector2(topUV.x - topUV.width, topUV.y - topUV.height));
uv.Add (Vector2.up);
uv.Add (Vector2.up);
uv.Add (Vector2.up);
uv.Add (Vector2.up);
uv.Add (Vector2.up);
uv.Add (Vector2.up);
uv.Add (Vector2.up);
uv.Add (Vector2.up);
// a
triangles.Add (tileVertIdx + 0);
triangles.Add (tileVertIdx + 3);
triangles.Add (tileVertIdx + 4);
// b
triangles.Add (tileVertIdx + 0);
triangles.Add (tileVertIdx + 4);
triangles.Add (tileVertIdx + 1);
// c
triangles.Add (tileVertIdx + 1);
triangles.Add (tileVertIdx + 4);
triangles.Add (tileVertIdx + 2);
// d
triangles.Add (tileVertIdx + 2);
triangles.Add (tileVertIdx + 4);
triangles.Add (tileVertIdx + 5);
// e
triangles.Add (tileVertIdx + 3);
triangles.Add (tileVertIdx + 6);
triangles.Add (tileVertIdx + 4);
// f
triangles.Add (tileVertIdx + 4);
triangles.Add (tileVertIdx + 6);
triangles.Add (tileVertIdx + 7);
// g
triangles.Add (tileVertIdx + 4);
triangles.Add (tileVertIdx + 7);
triangles.Add (tileVertIdx + 8);
// h
triangles.Add (tileVertIdx + 4);
triangles.Add (tileVertIdx + 8);
triangles.Add (tileVertIdx + 5);
// i
triangles.Add (tileVertIdx + 9);
triangles.Add (tileVertIdx + 11);
triangles.Add (tileVertIdx + 10);
// j
triangles.Add (tileVertIdx + 10);
triangles.Add (tileVertIdx + 11);
triangles.Add (tileVertIdx + 12);
// k
triangles.Add (tileVertIdx + 13);
triangles.Add (tileVertIdx + 15);
triangles.Add (tileVertIdx + 14);
// l
triangles.Add (tileVertIdx + 15);
triangles.Add (tileVertIdx + 16);
triangles.Add (tileVertIdx + 14);
}
}
yield return null;
}
Mesh mesh = _meshFilter.mesh;
mesh.vertices = vertices.ToArray ();
mesh.triangles = triangles.ToArray ();
mesh.normals = normals.ToArray ();
mesh.uv = uv.ToArray ();
// mesh.RecalculateNormals ();
// mesh.Optimize ();
map.ChunkFinished ();
}
The code to generate the mesh (auto normals):
IEnumerator BuildMesh (int width, int height, float tileSize) {
float halfSize = tileSize / 2f;
List<Vector3> vertices = new List<Vector3> ();
List<Vector3> normals = new List<Vector3> ();
List<Vector2> uv = new List<Vector2> ();
List<int> triangles = new List<int> ();
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
int tileVertIdx = vertices.Count;
float h = map.GetHeight(startX + x, startY + y);
float n = map.GetHeight(startX + x, startY + y - 1);
float s = map.GetHeight(startX + x, startY + y + 1);
float e = map.GetHeight(startX + x + 1, startY + y);
float w = map.GetHeight(startX + x - 1, startY + y);
float ne = map.GetHeight(startX + x + 1, startY + y - 1);
float nw = map.GetHeight(startX + x - 1, startY + y - 1);
float se = map.GetHeight(startX + x + 1, startY + y + 1);
float sw = map.GetHeight(startX + x - 1, startY + y + 1);
Vector3 tileCenter = new Vector3 (x * tileSize, h, y * tileSize);
Rect topUV = map.GetTopUV ((int)h);
if (n == h && s == h && e == h && w == h && ne == h && nw == h && se == h && sw == h) {
// Each tile
// 1 ----- 2
// | a / |
// | / b |
// 3 ----- 4
// top row
vertices.Add (new Vector3 (tileCenter.x - halfSize, tileCenter.y, tileCenter.z - halfSize));
vertices.Add (new Vector3 (tileCenter.x + halfSize, tileCenter.y, tileCenter.z - halfSize));
// bottom row
vertices.Add (new Vector3 (tileCenter.x - halfSize, tileCenter.y, tileCenter.z + halfSize));
vertices.Add (new Vector3 (tileCenter.x + halfSize, tileCenter.y, tileCenter.z + halfSize));
uv.Add (new Vector2(topUV.x, topUV.y));
uv.Add (new Vector2(topUV.x - topUV.width, topUV.y));
uv.Add (new Vector2(topUV.x, topUV.y - topUV.height));
uv.Add (new Vector2(topUV.x - topUV.width, topUV.y - topUV.height));
// a
triangles.Add (tileVertIdx + 0);
triangles.Add (tileVertIdx + 2);
triangles.Add (tileVertIdx + 1);
// b
triangles.Add (tileVertIdx + 1);
triangles.Add (tileVertIdx + 2);
triangles.Add (tileVertIdx + 3);
} else {
// Each tile
// 1 - 2 - 3 14 --- 16
// |a\b|c/d\ | k / |
// 4 - 5 - 6 | / |
// |e/f|g\h| | / l |
// 7 - 8 - 9 15 --- 17
// 10 --- 11
// | i / j |
// 12 --- 13
// top row
vertices.Add (new Vector3 (tileCenter.x - halfSize, tileCenter.y, tileCenter.z - halfSize));
vertices.Add (new Vector3 (tileCenter.x, tileCenter.y, tileCenter.z - halfSize));
vertices.Add (new Vector3 (tileCenter.x + halfSize, tileCenter.y, tileCenter.z - halfSize));
// middle row
vertices.Add (new Vector3 (tileCenter.x - halfSize, tileCenter.y, tileCenter.z));
vertices.Add (new Vector3 (tileCenter.x, tileCenter.y, tileCenter.z));
vertices.Add (new Vector3 (tileCenter.x + halfSize, tileCenter.y, tileCenter.z));
// bottom row
vertices.Add (new Vector3 (tileCenter.x - halfSize, tileCenter.y, tileCenter.z + halfSize));
vertices.Add (new Vector3 (tileCenter.x, tileCenter.y, tileCenter.z + halfSize));
vertices.Add (new Vector3 (tileCenter.x + halfSize, tileCenter.y, tileCenter.z + halfSize));
// bottom square
vertices.Add (new Vector3 (tileCenter.x - halfSize, h, tileCenter.z + halfSize));
vertices.Add (new Vector3 (tileCenter.x + halfSize, h, tileCenter.z + halfSize));
vertices.Add (new Vector3 (tileCenter.x - halfSize, s, tileCenter.z + halfSize));
vertices.Add (new Vector3 (tileCenter.x + halfSize, s, tileCenter.z + halfSize));
// right square
vertices.Add (new Vector3 (tileCenter.x + halfSize, h, tileCenter.z + halfSize));
vertices.Add (new Vector3 (tileCenter.x + halfSize, h, tileCenter.z - halfSize));
vertices.Add (new Vector3 (tileCenter.x + halfSize, e, tileCenter.z + halfSize));
vertices.Add (new Vector3 (tileCenter.x + halfSize, e, tileCenter.z - halfSize));
uv.Add (new Vector2(topUV.x, topUV.y));
uv.Add (new Vector2(topUV.x - (topUV.width / 2), topUV.y));
uv.Add (new Vector2(topUV.x - topUV.width, topUV.y));
uv.Add (new Vector2(topUV.x, topUV.y - (topUV.height / 2)));
uv.Add (new Vector2(topUV.x - (topUV.width / 2), topUV.y - (topUV.height / 2)));
uv.Add (new Vector2(topUV.x - topUV.width, topUV.y - (topUV.height / 2)));
uv.Add (new Vector2(topUV.x, topUV.y - topUV.height));
uv.Add (new Vector2(topUV.x - (topUV.width / 2), topUV.y - topUV.height));
uv.Add (new Vector2(topUV.x - topUV.width, topUV.y - topUV.height));
uv.Add (Vector2.up);
uv.Add (Vector2.up);
uv.Add (Vector2.up);
uv.Add (Vector2.up);
uv.Add (Vector2.up);
uv.Add (Vector2.up);
uv.Add (Vector2.up);
uv.Add (Vector2.up);
// a
triangles.Add (tileVertIdx + 0);
triangles.Add (tileVertIdx + 3);
triangles.Add (tileVertIdx + 4);
// b
triangles.Add (tileVertIdx + 0);
triangles.Add (tileVertIdx + 4);
triangles.Add (tileVertIdx + 1);
// c
triangles.Add (tileVertIdx + 1);
triangles.Add (tileVertIdx + 4);
triangles.Add (tileVertIdx + 2);
// d
triangles.Add (tileVertIdx + 2);
triangles.Add (tileVertIdx + 4);
triangles.Add (tileVertIdx + 5);
// e
triangles.Add (tileVertIdx + 3);
triangles.Add (tileVertIdx + 6);
triangles.Add (tileVertIdx + 4);
// f
triangles.Add (tileVertIdx + 4);
triangles.Add (tileVertIdx + 6);
triangles.Add (tileVertIdx + 7);
// g
triangles.Add (tileVertIdx + 4);
triangles.Add (tileVertIdx + 7);
triangles.Add (tileVertIdx + 8);
// h
triangles.Add (tileVertIdx + 4);
triangles.Add (tileVertIdx + 8);
triangles.Add (tileVertIdx + 5);
// i
triangles.Add (tileVertIdx + 9);
triangles.Add (tileVertIdx + 11);
triangles.Add (tileVertIdx + 10);
// j
triangles.Add (tileVertIdx + 10);
triangles.Add (tileVertIdx + 11);
triangles.Add (tileVertIdx + 12);
// k
triangles.Add (tileVertIdx + 13);
triangles.Add (tileVertIdx + 15);
triangles.Add (tileVertIdx + 14);
// l
triangles.Add (tileVertIdx + 15);
triangles.Add (tileVertIdx + 16);
triangles.Add (tileVertIdx + 14);
}
}
yield return null;
}
Mesh mesh = _meshFilter.mesh;
mesh.vertices = vertices.ToArray ();
mesh.triangles = triangles.ToArray ();
mesh.uv = uv.ToArray ();
mesh.RecalculateNormals ();
mesh.Optimize ();
map.ChunkFinished ();
}
Both versions of the code produce the same issue.