0
\$\begingroup\$
public class ChunkReader : MonoBehaviour
{
    public int chunk_width = 128;
    public int chunk_height = 64;

    public int map_width = 2048;
    public int map_height = 1024;

    public Texture2D HeightMap;

    private int chunk_count = 0;

    //private int CurXChunk, CurYChunk; //Which chunk are we parsing?
    private void Start()
    {
        HeightMap = Resources.Load("EarthBumpMap") as Texture2D;
        //LoadChunk(0, 0);
        LoadChunks(map_width, map_height);
    }
    void LoadChunks(int map_width, int map_height)
    {
        for(int i = 0; i < map_width; i+=chunk_width)
        {
            for(int j = 0; j < map_width; j+=chunk_height)
            {
                LoadChunk(i, j);
            }
        }
    }

    void LoadChunk(int chunk_x, int chunk_y)
    {
        List<Vector3> verts = new List<Vector3>();
        List<int> tris = new List<int>();

        //Bottom left section of the map, other sections are similar
        for (int i = chunk_x; i < chunk_width; i++)
        {
            for (int j = chunk_y; j < chunk_height; j++)
            {
                //Add each new vertex in the plane
                verts.Add(new Vector3(i, HeightMap.GetPixel(i, j).grayscale * 100, j));
                //Skip if a new square on the plane hasn't been formed
                if (i == 0 || j == 0) continue;
                //Adds the index of the three vertices in order to make up each of the two tris
                tris.Add(chunk_height * i + j); //Top right
                tris.Add(chunk_height * i + j - 1); //Bottom right
                tris.Add(chunk_height * (i - 1) + j - 1); //Bottom left - First triangle
                tris.Add(chunk_height * (i - 1) + j - 1); //Bottom left 
                tris.Add(chunk_height * (i - 1) + j); //Top left
                tris.Add(chunk_height * i + j); //Top right - Second triangle
            }
        }

        Vector2[] uvs = new Vector2[verts.Count];
        for (var i = 0; i < uvs.Length; i++) //Give UV coords X,Z world coords
            uvs[i] = new Vector2(verts[i].x, verts[i].z);

        GameObject plane = new GameObject("Chunk  " + chunk_count); //Create GO and add necessary components
        chunk_count++;
        plane.AddComponent<MeshFilter>();
        plane.AddComponent<MeshRenderer>();
        Mesh procMesh = new Mesh();
        procMesh.vertices = verts.ToArray(); //Assign verts, uvs, and tris to the mesh
        procMesh.uv = uvs;
        procMesh.triangles = tris.ToArray();
        procMesh.RecalculateNormals(); //Determines which way the triangles are facing
        plane.GetComponent<MeshFilter>().mesh = procMesh; //Assign Mesh object to MeshFilter
    }
    // Update is called once per frame
    void Update()
    {
    
    }
}

Basically, I'm trying to load a map into my game using Unity3D using the above code and the below-linked heightmap, but only the first chunk (at 0,0) actually loads, and the rest don't render for whatever reason. I really don't understand what I'm doing wrong. Probably super basic.

heightmap

As you can see below, Chunk 0 generates fine, but all concurrent chunks generate with no functional mesh and at the exact same location.

results1

\$\endgroup\$
0

1 Answer 1

1
\$\begingroup\$

There are a couple of issues with your algorithm:

First, in LoadChunks, you use the same boundary for both of your loops (map_width). This wouldn't be an issue if your map were square. The line

for(int j = 0; j < map_width; j+=chunk_height)

should be

for(int j = 0; j < map_height; j+=chunk_height)

This is not the cause of having only the first chunk generate. The reason why only the first chunk generates is that there is an issue in the loops boundaries in the LoadChunk function.

for (int i = chunk_x; i < chunk_width; i++)
{
    for (int j = chunk_y; j < chunk_height; j++)
    {

This will work for the first chunk, but when you get to the other ones, chunk_x or chunk_y will necessarily be greater-or-equal than-to chunk_width or chunk_height because they were the upper-bound of the previous run.

Some parts of the inner loop appear to expect the indices i and j to be in the range [0..chunk_size), while some other parts expect them to be in the range [0..map_size).

To make the code a bit easier to read, I suggest you stick with the concept of [0..chunk_size):

for (int i = 0; i < chunk_width; i++)
{
    for (int j = 0; j < chunk_height; j++)
    {
        int world_index_x = chunk_x + i;
        int world_index_y = chunk_y + j;
        verts.Add(new Vector3(world_index_x, HeightMap.GetPixel(world_index_x, world_index_y).grayscale * 100, world_index_y));

The final code should be something like this:

public class ChunkReader : MonoBehaviour
{
    public int chunk_width = 128;
    public int chunk_height = 64;

    public int map_width = 2048;
    public int map_height = 1024;

    public Texture2D HeightMap;

    private int chunk_count = 0;

    //private int CurXChunk, CurYChunk; //Which chunk are we parsing?
    private void Start()
    {
        HeightMap = Resources.Load("EarthBumpMap") as Texture2D;
        //LoadChunk(0, 0);
        LoadChunks(map_width, map_height);
    }
    void LoadChunks(int map_width, int map_height)
    {
        for(int i = 0; i < map_width; i+=chunk_width)
        {
            for(int j = 0; j < map_height; j+=chunk_height)
            {
                LoadChunk(i, j);
            }
        }
    }

    void LoadChunk(int chunk_x, int chunk_y)
    {
        List<Vector3> verts = new List<Vector3>();
        List<int> tris = new List<int>();

        //Bottom left section of the map, other sections are similar
        for (int i = 0; i < chunk_width; i++)
        {
            for (int j = 0; j < chunk_height; j++)
            {
                //Add each new vertex in the plane
                int world_index_x = chunk_x + i;
                int world_index_y = chunk_y + j;
                verts.Add(new Vector3(world_index_x, HeightMap.GetPixel(world_index_x, world_index_y).grayscale * 100, world_index_y));
                //Skip if a new square on the plane hasn't been formed
                if (i == 0 || j == 0) continue;
                //Adds the index of the three vertices in order to make up each of the two tris
                tris.Add(chunk_height * i + j); //Top right
                tris.Add(chunk_height * i + j - 1); //Bottom right
                tris.Add(chunk_height * (i - 1) + j - 1); //Bottom left - First triangle
                tris.Add(chunk_height * (i - 1) + j - 1); //Bottom left 
                tris.Add(chunk_height * (i - 1) + j); //Top left
                tris.Add(chunk_height * i + j); //Top right - Second triangle
            }
        }

        Vector2[] uvs = new Vector2[verts.Count];
        for (var i = 0; i < uvs.Length; i++) //Give UV coords X,Z world coords
            uvs[i] = new Vector2(verts[i].x, verts[i].z);

        GameObject plane = new GameObject("Chunk  " + chunk_count); //Create GO and add necessary components
        chunk_count++;
        plane.AddComponent<MeshFilter>();
        plane.AddComponent<MeshRenderer>();
        Mesh procMesh = new Mesh();
        procMesh.vertices = verts.ToArray(); //Assign verts, uvs, and tris to the mesh
        procMesh.uv = uvs;
        procMesh.triangles = tris.ToArray();
        procMesh.RecalculateNormals(); //Determines which way the triangles are facing
        plane.GetComponent<MeshFilter>().mesh = procMesh; //Assign Mesh object to MeshFilter
    }
    // Update is called once per frame
    void Update()
    {
    
    }
}
\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .