# How to compute a heightmap and use as 3d voxel floating point

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.

• The obvious answer to this question would be to use a smoothing algorithm like marching cubes. But the question mentions that the author already know about that algorithm, but not why it isn't applicable to the problem. That makes me wonder what exactly is the problem here. Jan 1, 2018 at 4:22
• The question is not about how to use the smooth marching cube 'cause as the two layer alone are smooth. But when combined they aren't anymore. The question is how to play with the value on each voxel when we merge two layer. Even 1 year later I still don't know. Jan 1, 2018 at 9:35
• I'm trying to understand the question. You have 2 objects. A surface generated from a heightmap, and a volume generated by a binary 3d matrix. How are you combining these 2 objects? Are you trying to combine them by converting the surface to a binary 3d matrix and interpolate between them? Aug 16, 2018 at 18:37