I'm creating a tile-based game in Unity (C#) with a hexagonal grid. I am making hills and mountains in my game, and to optimize, I only activate the top layer of tiles and leave the rest of them inactive. I render each tile with a noise-based height map (please note the colors on the grid itself such as brown, green, and grey do not correspond to height).
However, I encounter issues when the hills become high and a vertical gap between one tile and the next reveals a hole in the map due to height disparities.
To fix this, I am making a retroactive function which cycles through each pixel on the noise map and if it detects a disparity between one pixel and another which borders it, then it will activate the tile below the higher tile in the disparity. The blue tiles below represent the tiles that it detected as being in a disparity, and the red ones are the tiles activated as a result of their higher counterparts being detected as such.
Most the time, however, the disparities are not recognized in the right positions. You can see in the image above that the brown tile which should be considered as having a disparity (since it's leaving a gap) has a gaping hole and no red tile beneath it, while others which have no gaps are considered as having disparities and are thus blue. Here is a representation of how there's little correlation between the height map and the disparities detected:
You can see above that the white on the height map, representing high areas, does not correspond with the blue on the grid, which should correspond with disparities (and thus mainly correspond with where the white and the black converge on the noise map, outlining the location between high and low areas).
Here is my code to detect disparities:
//ADD BLOCKS BELOW WHERE MAGNITUDE IS HIGH SO NO OPEN SPACES
int wi = -1;
int thisChunkX = 0;
for (int w = 0; w < thisTexture.width; w++)
{
wi++;
if (wi == chunkSize.x) { wi = 0; thisChunkX++; }
int hi = -1;
int thisChunkZ = 0;
for (int h = 0; h < thisTexture.height; h++)
{
hi++;
if (hi == chunkSize.z) { hi = 0; thisChunkZ++; }
if (w - 1 >= 0 && h - 1 >= 0 && w + 1 < thisTexture.width && h + 1 < thisTexture.height)//for all non-direct borders in the texture
{
List<float> surroundingHexes = new List<float>
{
thisTexture.GetPixel(w+1, h).maxColorComponent,//top
thisTexture.GetPixel(w-1, h).maxColorComponent,//bottom
thisTexture.GetPixel(w-1, h+1).maxColorComponent,//top left
thisTexture.GetPixel(w+1, h+1).maxColorComponent,//top right
thisTexture.GetPixel(w-1, h).maxColorComponent,//bottom left
thisTexture.GetPixel(w+1, h).maxColorComponent//bottom right
};
float thisHex = thisTexture.GetPixel(w, h).maxColorComponent;
foreach (float thisSurroundingHex in surroundingHexes)
{
float hexMagnitude = thisHex - thisSurroundingHex;//IMPORTANT!!!
if (thisTexture.GetPixel(w, h) != new Color(1, 0, 0) && hexMagnitude > 0.25f)//IMPORTANT!!!
{
//DISPARITY IS DETECTED
//other stuff
break;
}
}
}
}
Even if hexMagnitude > 0.25f is not the most accurate, wouldn't there still be a strongish correlation representing height disparities since hexMagnitude = thisHex - thisSurroundingHex, where thisHex and thisSurroundingHex are each values which correspond with height? Any help would be greatly appreciated. Thank you!
May i suggest naming your for-loop-variables x and y instead of w and h? I think x and y are more obviously assigned for the two coordinates. Anyway. I haven't entirely checked if this is the only issue, but I feel like you've set your pixel-checks up wrong. (see below)
thisTexture.GetPixel(w+1, h).maxColorComponent,//top << shouldn't this be (w, h+1)?
thisTexture.GetPixel(w-1, h).maxColorComponent,//bottom << Shouldn't this be (w, h-1)?
thisTexture.GetPixel(w-1, h+1).maxColorComponent,//top left << Looks fine
thisTexture.GetPixel(w+1, h+1).maxColorComponent,//top right << Looks fine
thisTexture.GetPixel(w-1, h).maxColorComponent,//bottom left << This is the same as "bottom". Shouldn't this be (w-1, h-1)?
thisTexture.GetPixel(w+1, h).maxColorComponent//bottom right << This is the same as "top". shouldn't this be (w+1, h-1)?
Also, in theory you don't need every pixel around the pixel. When you check the pixel on the bottom right and later get to that same pixel you no longer need to check the pixel on the top left, since that check has already been made. So all you really need there is
thisTexture.GetPixel(w, h+1).maxColorComponent,//top
thisTexture.GetPixel(w+1, h+1).maxColorComponent,//top right
thisTexture.GetPixel(w+1, h-1).maxColorComponent,//bottom right
depending on the order of tiles checked you might need to change the check-directions or even add a fourth one (haven't worked with hex-gird before)