Madmenyo Madmenyo - 3 years ago 161
C# Question

Drawing a terrain mesh by script

I am trying to draw some terrain with scripting. However I get strange results and cannot seem to pinpoint the issue.

At the

Start
method I'm building my initial mesh.

Vector3[] verts = new Vector3[mapWidth * mapHeight * 6];
Vector2[] uvs = new Vector2[mapWidth * mapHeight * 6];
int[] triangles = new int[mapWidth * mapHeight * 6];

for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
verts[x * y * 6 + 0] = new Vector3(x, 0, y);
verts[x * y * 6 + 1] = new Vector3(x + 1, 0, y);
verts[x * y * 6 + 2] = new Vector3(x + 1, 0, y + 1);

verts[x * y * 6 + 3] = new Vector3(x, 0, y);
verts[x * y * 6 + 4] = new Vector3(x + 1, 0, y + 1);
verts[x * y * 6 + 5] = new Vector3(x, 0, y + 1);

uvs[x * y * 6 + 0] = new Vector2(0, 0);
uvs[x * y * 6 + 1] = new Vector2(1, 0);
uvs[x * y * 6 + 2] = new Vector2(1, 1);

uvs[x * y * 6 + 3] = new Vector2(0, 0);
uvs[x * y * 6 + 4] = new Vector2(1, 1);
uvs[x * y * 6 + 5] = new Vector2(0, 1);

for (int t = 0; t < 6; t++)
{
triangles[x * y * 6 + t] = x * y * 6 + 5 - t;
}
}
}

terrain.vertices = verts;
terrain.uv = uvs;
terrain.triangles = triangles;
terrain.RecalculateNormals();


All I do to draw my mesh is
Graphics.DrawMesh(terrain, Vector3.zero, Quaternion.identity, mat, 1);
. Material(mat) is just a simple grid texture and seems to be working correctly. However Unity is deciding to not draw triangle couples at seemingly random.

enter image description here

The gizmo is at
0, 0, 0
and each run it renders the same shape. I need to be drawing a
10 x 10
shape. I am creating duplicate vertices because I need hard edges eventually.

yes yes
Answer Source

The problem with the way you do it are your indices. The formula for "flattening" a 2D array is x + y * width (or x * height + y), not x * y.

IMO the best way to approach such issues is to manually calculate values that work and dont work as expected and see if you find a pattern.

In your case it seems (0|0) does not work, while (0|9) does work, lets see why.

So if we use x = 0 and y = 0, we get verts[0 * 0 * 6 + num] = 0 + num. Now we do it for x = 0, y = 9 and alas verts[0 * 9 * 6 + num] still is 0 + num. Since (0|9) is calculated later, the problem is that the verts, uvs, and triangles of (0|0) are overwritten by those values - the same is the problem for everything inbetween, like for example, 3 * 5 is the same as 5 * 3.

So to fix your code, the following should work.

    Vector3[] verts = new Vector3[mapWidth * mapHeight * 6];
    Vector2[] uvs = new Vector2[mapWidth * mapHeight * 6];
    int[] triangles = new int[mapWidth * mapHeight * 6];

    for (int y = 0; y < height; y++) {
        for (int x = 0; x < width; x++) {

            int tileIndex = x + y * width;

            verts[tileIndex * 6 + 0] = new Vector3(x, 0, y);
            verts[tileIndex * 6 + 1] = new Vector3(x + 1, 0, y);
            verts[tileIndex * 6 + 2] = new Vector3(x + 1, 0, y + 1);

            verts[tileIndex * 6 + 3] = new Vector3(x, 0, y);
            verts[tileIndex * 6 + 4] = new Vector3(x + 1, 0, y + 1);
            verts[tileIndex * 6 + 5] = new Vector3(x, 0, y + 1);

            uvs[tileIndex * 6 + 0] = new Vector2(0, 0);
            uvs[tileIndex * 6 + 1] = new Vector2(1, 0);
            uvs[tileIndex * 6 + 2] = new Vector2(1, 1);

            uvs[tileIndex * 6 + 3] = new Vector2(0, 0);
            uvs[tileIndex * 6 + 4] = new Vector2(1, 1);
            uvs[tileIndex * 6 + 5] = new Vector2(0, 1);

            for (int t = 0; t < 6; t++) {
                triangles[tileIndex * 6 + t] = tileIndex * 6 + 5 - t;
            }
        }
    }

    terrain.vertices = verts;
    terrain.uv = uvs;
    terrain.triangles = triangles;
    terrain.RecalculateNormals();
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download