When you want to compute a heightmap and use for 3d voxel binary, it's easy.
solid are maybe 1, and air are 0, easy.
But in my case I would like to have a smooth terrain, so the solution is the floating point value. But now I cannot say "Hey, it's 1 so it's solid !" because when I use 1 or -1 with a threshold to 0. It's will work, sure, but look like blocky, not smooth.
When you compute a 3d noise, it's easy you just have to set the computed value (scaled from -1 to 1, threshold to 0). It's will look nice. But for 2d noise...
Let's say, 0 is the minHeight and 500 maxHeight. The 2d noise function is scaled between 0 and 1.
At x:0, y:0, let's say the final value of the height is 250, that the middle. (noise output 0.5 scaled from 0/1 to 0/500)
But for each height, what I am supposed to set ? In binary case, solid are 1, air 0. But in floating point case, what should be the value ?
I tried to apply the noise result (0 to 1), and where y > computedHeight (computedHeight=250) the value is -1.
It's look blocky (That normal) but I don't have the right solution.
So what I am supposed to set to each y voxel ?
Ok my question look confusing, sorry for that.
I can easily get a smooth terrain based on heightmap value. Here is a screenshot.
As you can see, when I combine it with 3d layer, there is a problem, cave is blocky.
Why this problem, I guess it because the cave value are between -1 to 0, nice. But the ground layer that computeNoise*maxHeight-y
which give nice result but the value is wrong ! And I'm looking for a better way to compute the heightmap (ground layer) to have correct value and get a smooth cave. :)
Here is my pseudo code of how I generate my voxel array.
for (var x = 0; x < sizeXz + 1; x++) {
for (var z = 0; z < sizeXz + 1; z++) {
var compute = Biome.ComputeXz(voxelX, voxelZ);
for (var y = 0; y < sizeY + 1; y++) {
data[x, y, z] = Biome.GetY(compute, voxelX, voxelY, voxelZ);
}
}
}
Then
public ... GetY(...){
var computedHeight = Scale(compute.value, 0, maxHeight, 0, 1); //Scale noise 0-1 to 0-MaxHeight
var currentValue = computedHeight-pos.y;
var currentType = BlockType.Rock;
if(pos.y > computedHeight)
currentType = BlockType.Air;
return new Block(currentType, currentValue);
}
This work, this look nice (see ground layer image), but the value are wrong because if you lower, you'll get some value like -82.28389, because of the -y to the currentValue which means further you are from the threshold further from 0 the value will be.
And the cave layer which is a raw output from the noise function (so a value between -1 and 1).
As you know Marching cube do a interpolation between each voxel so I let you imagine why the result is so blocky between the cave which output value like 0.0x and ground output like xx.x
Sorry for the long post.