0
\$\begingroup\$

I am trying to set the terrain's heights data at runtime with a simplex noise function, while stumbling with converting the local position of the vertices to global position to use as input to keep the simplex noise continuous.

At this time I am setting up multiple terrains tiles, which I added in the editor.

The UnityEngine.Terrain has a size of 1000 units on x and z and a (default) heightmap resolution of 513.

My actual question is; What am I missing?

I have the impression that next I should convert the vertex position of one terrain to a world position, so the tiles would be seamless, but the result shows a difference at the borders. The simplex noise function has been tested and is correct.

private Vector3 toGlobal(Vector3 position, UnityEngine.Terrain terrain)
{

    int     res     = terrain.terrainData.heightmapResolution;
    Vector3 size    = terrain.terrainData.size;

    Vector3 global = new Vector3( position.x / res * size.x, 0, position.z / res * size.z);

    global += terrain.transform.position;

    return global;

}

And less interesting, how I use it:

// Get all terrain tiles and cycle through them
UnityEngine.Terrain[] terrains = Resources.FindObjectsOfTypeAll(typeof(UnityEngine.Terrain)) as UnityEngine.Terrain[];
foreach(UnityEngine.Terrain terrain in terrains)
{

    int         res     = terrain.terrainData.heightmapResolution;
    float[,]    heights = new float[res, res];
    float       height  = 0;

    for (int z = 0; z < res; ++z)
    {

        for (int x = 0; x < res; ++x)
        {

            Vector3 v = toGlobal(new Vector3(x, 0, z), terrain);
            height  = (float)(simplex.Noise(v.x * 0.0001, v.z * 0.0001, 0) + 1) * 0.5);
            heights[x, z] = height;

        }
        
    }

    terrain.terrainData.SetHeights(0, 0, heights);
                
}

Gaps between terrain tiles

\$\endgroup\$

2 Answers 2

1
\$\begingroup\$

It happend to be the way I used the heights array. After my fight with how the Terrain.terrainData stores its data, I neglected this aspect.

Within the foreach-loop I've assigned the heights to the bidimensional array `float[,] heights' like this:

heights[x, z] = height;

The Terrain uses the rows as first parameter and so it should be:

heights[z, x] = height;

This solved the main problem. @DMGregory was one step ahead, and solved the next issue already which saved me some time.

\$\endgroup\$
0
\$\begingroup\$

This looks like a fencepost error.

A terrain with a resolution of 513 has 513 rows, numbered 0 to 512. When you divide by 513 you get a number between 0 and 0.998, instead of reaching all the way to 1. That means your last vertex gets placed slightly less than a full size away from the start of the terrain, leaving a narrow gap between this terrain and the next one that's been shifted over by one full size.

You need to divide by the number of beams in the fence, not the number of posts:

position.x / (res - 1) * size

and similarly for z.

\$\endgroup\$
3
  • \$\begingroup\$ Actually I just found what the problem is. These gabs are the result of not knowing the float[,] array has the order of float[z, x]. The fun part is that you have answer my next question, which I would have figured myself. But thanks, this speeds it up a bit. Because you are right I upped still. \$\endgroup\$
    – Willem
    Commented May 26, 2023 at 12:23
  • \$\begingroup\$ But I need some rep first before I can up. \$\endgroup\$
    – Willem
    Commented May 26, 2023 at 12:24
  • \$\begingroup\$ I can edit to fold both aspects into this answer, or you can post your own answer about the index order aspect. \$\endgroup\$
    – DMGregory
    Commented May 26, 2023 at 13:17

You must log in to answer this question.

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