Now I use a simplex noise 2d function with x( voxel's x location ) and y(voxel's y location) to generate heightmap. How do we use simplex noise 3d to generate overhangs? What should the x y z inputs be? Pseudo code would help a lot.
2D Perlin noise is used to generate a heightmap. This heightmap is then converted to a mesh for the renderer.
float[,] heights; // initialize the map using some 2D height function. foreach (i, j): heights[i,j] = noise2D(i, j); // convert the data to a mesh foreach(cell in heights): generate a square with corners at (x,y,heights[x,y]), (x+1,y,heights[x+1,y]), (x,y+1,heights[x,y+1]), (x+1,y+1,heights[x+1,y+1])
3D Perlin noise is used to generate basically a density map. If the "density" at a 3D point is greater than a threshold, you "generate" a block at that point
// for the sake of the demo, this is a bool. // Realistically you'd have some struct that allows for different block types bool[,,] isSolid; // initialize the map using some 3D density function foreach (i, j, k): isSolid(i, j, k) = noise3D(i, j, k) > 0.5 // convert the data to a mesh foreach i,j,k: if isSolid[i,j,k]: generate a unit cube centered at i, j, k.
Of course, the above code simplifies some things -- you could use less naive meshing strategies like marching cubes or dual contouring. the density function gets more dense with depth if you want "ground at the bottom, sky at the top, etc."