0

I have created procedural terrain generated in Unity using the CoherentNoise library. The generation itself works just fine, each terrain object that is added to the scene correctly generates heightmaps and applies them. The issue is that my generated noise isn't continuous from terrain object to terrain object, as seen from the image below.

9 Terrain GameObjects that don't lineup

The function that generates the noise for each terrain object is listed below

public void GenerateHeightMap() {
    for (int z = 0; z < zRes; z++) {
        for (int x = 0; x < xRes; x++) {
            var xCoord = (float)((size.x * position.x) + x) / (xRes - 1);
            var zCoord = (float)((size.z * position.z) + z) / (zRes - 1);

            var value = settings.GetModule().GetValue(xCoord, zCoord, 0);
            heights[x, z] = (float)(value / 2f) + 0.5f;
        }
    }
}

To quickly explain xCoord and zCoord:

First these x and z coordinates find their starting generation position (size * position). Then they add the loop offset (either x or z) and divide by the terrain's resolution. In theory, this should allow the noise generator to grab a neighboring terrain object's x,z coordinates and return a heightmap that lines up.

Any ideas as to why these terrain GameObjects do not line up?

If anyone would like to take a look at the project as a whole, I have uploaded the project to Github where it can be viewed and downloaded.

Walker Christie
  • 531
  • 1
  • 3
  • 18
  • Actually are you sure that you don't suffer from texture coordinate system issues? – Felix K. Nov 12 '15 at 22:39
  • I don't believe so, the CoherentNoise library does use a texture coordinate space when using the GetValue function, however.. I have made sure to enter Unity's coordinate space into the correct parameters in the GetValue function. – Walker Christie Nov 12 '15 at 22:56

2 Answers2

2

There's something fishy because your premise doesn't hold

In theory, this should allow the noise generator...

If your premise was right, then if you compute one coord, lets say zCoord for two adjacent tiles, it should be equal.

So, let's say position=(0,0), z=zRes (theoretical index after the last z element of the loop) and compare with position(0, 1), z=0.

In one case, you end up with zCoord=zRes / (zRes-1) and with the other zCoord=size.z / (zRes-1). Hence the discrepancy.

Try something like this (sorry, I'm traveling, no unity to try it out):

public void GenerateHeightMap() {
    for (int z = 0; z < zRes; z++) {
        for (int x = 0; x < xRes; x++) {
            var xCoord = (float)((size.x * position.x) + x * size.x/xRes) / (xRes - 1);
            var zCoord = (float)((size.z * position.z) + z * size.z/zRes) / (zRes - 1);

            var value = settings.GetModule().GetValue(xCoord, zCoord, 0);
            heights[x, z] = (float)(value / 2f) + 0.5f;
        }
    }
}
mprivat
  • 21,582
  • 4
  • 54
  • 64
  • Hmm, I tried what you suggested and it created some funky looking terrain http://i.imgur.com/r7KXjz8.png – Walker Christie Nov 12 '15 at 22:04
  • yikes. on the bright side, it looks more continuous. It's kinda hard to tell from that screenshot what exactly is going on. One thing with what I proposed is the scale of (x,z) changed so that's probably what caused the noise function to freak out. I've never used CoherentNoise but if it's Perlin based, that could be the problem. Just to test, try to scale xCoord and zCoord down by multiplying by 0.05 or something like that. Meanwhile, I'll rethink this to stay in the same scale. – mprivat Nov 12 '15 at 22:14
  • Thanks for helping me out with this, I'll keep working with what you suggested. As for CoherentNoise, it is Perlin based. They also use X, Y, Z where Y is horizontal and Z is vertical, which is annoying to convert to Unity's coordinate system. CoherentNoise is actually just an implementation of libNoise (which I'm sure you've heard of before) for .NET – Walker Christie Nov 12 '15 at 22:19
  • Oh duh. I bet it's because the (x,z) is used to index the array. Change the last line to `heights[x*xRes/size.x, z*zRes/size.z] = ...` – mprivat Nov 12 '15 at 22:35
  • Same spiky result again, http://i.imgur.com/jlpec5E.png BUT this is definitely continuous. I think its an issue with xStep and zStep not hitting all of the terrain with the for loop. – Walker Christie Nov 12 '15 at 22:46
  • Be sure to use the code I've updated in the answer. It should work. – mprivat Nov 12 '15 at 22:48
  • I did originally, however it produced basically the same result as before. http://i.imgur.com/HObuDHx.png The usage of xStep and zStep produced a continuous result, but it was spiky. The current code generated the terrain correctly, but it was sadly discontinuous. – Walker Christie Nov 12 '15 at 22:52
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/94988/discussion-between-walker-christie-and-mprivat). – Walker Christie Nov 12 '15 at 22:59
0

I had recently similiar problem with my code for procedural terrain generation, this is how it fixed my issues of incontinuety:

public void GenerateHeightMap() 
{
  for (int z = 0; z < zRes; z++) 
  {
    //         ratio                    annotation1          annotation2
    var zCoord=((float)z/(float)zRes) + (position.z/size.z)*((zRes-1)/zRes); // place the zCoord here so the calculation won't be repeated (zRes-1) times
    for (int x = 0; x < xRes; x++) 
    {
      var xCoord=((float)x/(float)xRes) + (position.x/size.x)*((xRes-1)/xRes);
      var value = settings.GetModule().GetValue(xCoord, zCoord, 0);
      heights[x, z] = (float)(value / 2f) + 0.5f;
    }
  }
}

annotation1: one divides the position by size to normalize the coordinates (e.g.: pos(200,50) size(50,50) means that between this terrain and the origin there are 4 terrains along the x-axis and 1 terrain along the z-axis)

annotation2: a terrain's relative coordinates don't go from 0 to 1, but from 0 to almost 1 (becasue z goes only to (zRes-1)).