Page 1 of 1

Preventing caves from generating at surface level

PostPosted: Wed Dec 07, 2016 03:47
by sorcerykid
In mapgen v7 is there any way to prevent cave generation above a certain height, specifically to avoid large gaping holes in the terrain? I've struggled with this dilemma for quite some time, but have yet to find a solution. I've tweaked all of the relevant the noise parameters, yet certain caves seem to ignore both "mgv7_np_cave1" and "mgv7_np_cave2". I've searched Google the past two days, but there is very little technical documentation about customizing mapgen v7, just a lot of screenshots. What am I missing?

Any help or direction would be greatly appreciated.

Re: Preventing caves from generating at surface level

PostPosted: Wed Dec 07, 2016 04:38
by maikerumine
Please paramat, help! The only way I found was to disable all cave generation, as well as rivers. It messes up the map. :(
Moreover, I forgot how to disable this.

Re: Preventing caves from generating at surface level

PostPosted: Wed Dec 07, 2016 13:06
by sorcerykid
Thanks maikerumine. Indeed the only workaround I've found is to set mg_flags to "nocaves". But that undermines my goal, since I do want caves in my world. If only there was a cave_depth_min and cave_depth_max parameter to restrict the cave generation range.

Re: Preventing caves from generating at surface level

PostPosted: Thu Dec 08, 2016 00:31
by sorcerykid
It seems I successfully devised an interim solution at least for Minetest 0.4.13, by reworking the following code in cavegen.cpp:

Your phone or window isn't wide enough to display the code box. If it's a phone, try rotating it to landscape mode.
Code: Select all
CaveV7::CaveV7(MapgenV7 *mg, PseudoRandom *ps)
{
        this->mg             = mg;
        this->vm             = mg->vm;
        this->ndef           = mg->ndef;
        this->water_level    = mg->water_level;
// SK fix begin
        this->surface_level  = mg->terrain_surface_level;
// SK fix end
:


Your phone or window isn't wide enough to display the code box. If it's a phone, try rotating it to landscape mode.
Code: Select all
void CaveV7::makeCave(v3s16 nmin, v3s16 nmax, int max_stone_height) {
:
// SK fix begin
   // Allow tunnel radius to project above surface
   route_y_max = -of.Y + max_stone_y + max_tunnel_diameter / 2;

   // Limit maximum to area
   route_y_max = rangelim(route_y_max, 0, ar.Y - 1);
   // Limit maximum to area
   route_y_max = rangelim(route_y_max, 0, ar.Y - 1);

   s16 min = 0;
   if (node_min.Y < surface_level && node_max.Y > surface_level) {
      min = surface_level - max_tunnel_diameter/3 - of.Y;
      route_y_max = surface_level + max_tunnel_diameter/3 - of.Y;
   }
// SK fix end
:


I also defined "surface_level" and "terrain_surface_level" within the appropriate structs and classes of cavegen.h and mapgen.h. And, of course, I added "terrain_surface_level" to mapgen.cpp, as a user-definable parameter.

I was hoping to implement a "terrain_bedrock_level" as a counterpart to "terrain_surface_level" thereby setting the minimum cave generation range, but that would have required far more substantial changes to cavegen.cpp (as it stands, the upper limit was already conditional on "mg->water_level", so that was an easy enough replacement.) Since I'm fairly unfamiliar with the mapgen logic, I didn't venture much further for fear of breaking something important.

This of course is just a quick and dirty fix. Ideally there would be a formalized specification for cavegen parameters, maybe in a future release I hope :)

Re: Preventing caves from generating at surface level

PostPosted: Thu Dec 08, 2016 00:34
by paramat
There are 2 types of cave in mgv7: the web of narrow tunnels, and the large blob-shaped caverns which sometimes have water or lava. The surface holes are mostly the tunnels, you can't limit these according to y but you can remove the tunnels without removing the large caverns, if this sounds good to you i'll tell you how.

Re: Preventing caves from generating at surface level

PostPosted: Thu Dec 08, 2016 00:37
by paramat
Your code above only affects the large caves, not the tunnels.

Re: Preventing caves from generating at surface level

PostPosted: Thu Dec 08, 2016 01:35
by sorcerykid
Hi paramat, I would be interested in learning more about any solutions you can suggest. I tested a number of different caves, including those with tunnels. Each time I reduced "terrain_surface_level", the depth of the caves would adjust accordingly and any non-conforming tunnels would disappear.

Trial #1: http://imgur.com/a/Z62Qt
Trial #2: http://imgur.com/a/mIsIC
Trial #3: http://imgur.com/a/Z0vLs

Perhaps I'm missing something, but each of the test cases above worked. On a sidenote, I overlooked these two snippets of code that I changed as well in cavegen.cpp.

Your phone or window isn't wide enough to display the code box. If it's a phone, try rotating it to landscape mode.
Code: Select all
void CaveV7::makeTunnel(bool dirswitch) {
:
} else if (p.Y > surface_level) {
      return; // If it's not in our heightmap, use a simple heuristic
}
:
} else if (p.Y > surface_level) {
      return;
}

Re: Preventing caves from generating at surface level

PostPosted: Fri Dec 09, 2016 05:07
by paramat
0.4.13 has these 3D noise tunnels https://github.com/minetest/minetest/blob/0.4.13/src/mapgen_v7.cpp#L864
But you can easily limit those on a per-mapchunk basis in line 861.

Re: Preventing caves from generating at surface level

PostPosted: Fri Dec 16, 2016 23:14
by sorcerykid
Thanks for the tip paramat. I can see from mapgen_v7.cpp that the tunnels can only be limited on a per-mapchunk basis.

However, am I to understand correctly that while the function "generateCaves( )" creates the tunnels, the function "makeTunnel( )" is what actually creates the caverns? Isn't that backwards? O_o

Re: Preventing caves from generating at surface level

PostPosted: Sat Dec 17, 2016 19:02
by paramat
In non-mgv6 mapgens generateCaves() creates the 3D noise tunnels and also the classic large caves from mgv6.

makeTunnel() was named for mgv6 where that code creates both the large caverns and the smaller tunnels by varying the width, both are essentially tunnels because they are a string of excavated volumes.