Search Unity

Question Procedural terrain issue with gaps between blocks

Discussion in 'Scripting' started by SourGummi, Apr 19, 2022.

  1. SourGummi

    SourGummi

    Joined:
    Nov 14, 2021
    Posts:
    96
    hey, i've got a problem. Here i have my terrain mesh thats using a (terrain_size / block_size) to get number of blocks needed to fill the mesh, as a fullscale mesh eats thru the cpu. i dont have a dedicated gpu.

    as you'll see, theres gaps between the blocks even though the blocks match with precision transforms.




    i create my blocks like so:
    Code (CSharp):
    1. private void GenerateBlocks()
    2.     {
    3.         int num_of_blocks = size / block_size;
    4.         int
    5.             idx = 0,
    6.             row = 0,
    7.             col = 0;
    8.  
    9.         for (int x = 0; x < num_of_blocks; x++)
    10.         {
    11.             for (int z = 0; z < num_of_blocks; z++)
    12.             {
    13.                 blocks[idx] = new GameObject("Block");
    14.                 blocks[idx].transform.position = new Vector3(row * block_size, 0, col * block_size);
    15.                 blocks[idx].AddComponent<TerraBlock>();
    16.                 blocks[idx].GetComponent<TerraBlock>().row = row;
    17.                 blocks[idx].GetComponent<TerraBlock>().col = col;
    18.                 blocks[idx].transform.parent = transform;
    19.                 blocks[idx].GetComponent<Renderer>().material = shader;
    20.                 col++;
    21.             }
    22.             row++;
    23.             col = 0;
    24.         }
    25.     }
    The height is determined like so:
    Code (CSharp):
    1. private float GetHeightForHeightMap(int x, int z)
    2.     {
    3.         return GetComponentInParent<TerraGen>().blackAndWhiteTerrainMap.GetPixel(x + (row * size), z + (col * size)).grayscale * 50.0f;
    4.     }
    anybody have any ideas why the vertices are not joining at ends even though their positions should be the same?
     
  2. Peeling

    Peeling

    Joined:
    Nov 10, 2013
    Posts:
    443
    Oh, sweet Jesus, you need to change that GetHeightForHeightMap function XD

    As for the gaps: this is because you have created a block mesh that has one too few rows and columns.

    Look at a chessboard. 8x8 squares, right? But to draw it as a mesh you would need 9x9 vertices.

    If you wanted to put a grid of chessboards next to each other with no gaps, the rightmost vertices of one chessboard would need to be a copy of the leftmost vertices of the next.

    ALSO

    Even after you close the gaps, with your technique you WILL get cracking between the blocks. This is due to floating point imprecision: a vertex at (100,100,0) on an object at (0,0,0) will not be in EXACTLY the same place on screen as a vertex at (0,0,0) on an object at (100,100,0).

    The answer is to put all your blocks at 0,0,0 and then offset the mesh vertices of each block.
     
  3. SourGummi

    SourGummi

    Joined:
    Nov 14, 2021
    Posts:
    96
    i
    i see, so what you propose is rather than offset the position of my object i actually just use my "row/col" method to place the vertices of each block?

    i have to say, it looks much, much better. now all i have to figure out is how to blend the seams together to remove the clear block edges!

    very appreciative of your help :)

     
  4. Peeling

    Peeling

    Joined:
    Nov 10, 2013
    Posts:
    443
    Can I ask: did you just move the blocks closer together, or did you actually duplicate the edge vertices in adjacent blocks? Because you shouldn't get any seams if you did the latter.

    EG if the blocks were 100x100 polys, the first block would use pixels 0 to 100 INCLUSIVE and then the next block would use pixels 100 to 200 INCLUSIVE.

    Also, like I said: you really, really, really need to change how you're getting the pixel height at each location. GetComponentInParent is incredibly slow, and you'll be doing it tens or hundreds of thousands of times.
     
    SourGummi likes this.
  5. SourGummi

    SourGummi

    Joined:
    Nov 14, 2021
    Posts:
    96
    i've changed the way i place the mesh
    Code (CSharp):
    1.         for (int z = 0; z <= size; z++)
    2.         {
    3.             for (int x = 0; x <= size; x++)
    4.             {
    5.                 float
    6.                     pos_x = x + (size * col),
    7.                     pos_z = z + (size * row);
    8.  
    9.                 verts[i] = new Vector3(pos_x, 0, pos_z);
    10.                 i++;
    11.  
    12.             }
    13.         }
    creating the individual blocks:
    Code (CSharp):
    1.         for (int x = 0; x < num_of_blocks; x++)
    2.         {
    3.             for (int z = 0; z < num_of_blocks; z++)
    4.             {
    5.                 blocks[idx] = new GameObject("Block");
    6.                 //blocks[idx].transform.position = new Vector3(row * block_size, 0, col * block_size);
    7.                 blocks[idx].AddComponent<TerraBlock>();
    8.                 blocks[idx].GetComponent<TerraBlock>().row = row;
    9.                 blocks[idx].GetComponent<TerraBlock>().col = col;
    10.                 blocks[idx].transform.parent = transform;
    11.                 blocks[idx].GetComponent<Renderer>().material = shader;
    12.                 col++;
    13.             }
    14.             row++;
    15.             col = 0;
    16.         }
    i keep all objects at (0, 0, 0) and use my old transform modifier depending on row/col position to now place vertices in the blocks themselves.

    I'll be changing the block to use a ref to texture so i can clean up the slower getHeightForHeightMap();