Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Carpathian mapgen #6015

Merged
merged 1 commit into from Jul 6, 2017
Merged

Conversation

vlapsley
Copy link
Contributor

@vlapsley vlapsley commented Jun 19, 2017

A new mapgen with mountain ranges and sometimes large flattish areas.

EDIT by paramat:
See forum post for some screenshots.

@Fixer-007
Copy link
Contributor

Fixer-007 commented Jun 19, 2017

Nice! Screenshots? Bigger description?

@vlapsley
Copy link
Contributor Author

See forum post for some screenshots.

Features:

  • Plains, sometimes vast. Average y-level between 5-10
  • Rolling hills - small hills.
  • Ridged mountains - mountains of a similar height will connect with a ridge.
  • Step (terrace) mountains - sometimes a stair like effect, or mini-plateaus.
  • Fjords - particularly where the larger mountains meet the sea. Rare.
  • Really big mountains - where two or even three mountain noise meet, spectacular and unpredictable peaks form.


struct MapgenCarpathianParams : public MapgenParams
{
u32 spflags = MGCARPATHIAN_CAVERNS;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice ! C++11 constructor :D

src/mapgen.h Outdated
@@ -114,6 +114,7 @@ enum MapgenType {
MAPGEN_V5,
MAPGEN_V6,
MAPGEN_V7,
MAPGEN_CARPATHIAN,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if i remember this enum should be ordered by mapgen addition instead of names, @paramat can you confirm ?

It prevents mapgen ID mismatch

Copy link
Contributor

@paramat paramat Jun 19, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This enum was created in this form in hmmmm's mapgen reorganisation commit 9270530
So i'm sure it's fine as it is.
However any new mapgens should perhaps be added after 'invalid', not sure if that is essential but seems the safest thing to do with an enum.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I changed the enum to this order:
enum MapgenType { MAPGEN_V5, MAPGEN_V6, MAPGEN_V7, MAPGEN_FLAT, MAPGEN_FRACTAL, MAPGEN_VALLEYS, MAPGEN_SINGLENODE, MAPGEN_INVALID, MAPGEN_CARPATHIAN, };

but it compiles with error:

/Users/vlapsley/games/minetest/src/mapgen.cpp:93:1: error: 'registered_mapgens_is_wrong_size'
declared as an array with a negative size
STATIC_ASSERT(
^~~~~~~~~~~~~~
/Users/vlapsley/games/minetest/src/util/basic_macros.h:50:36: note: expanded from macro
'STATIC_ASSERT'
UNUSED_ATTRIBUTE typedef char msg[!!(expr) * 2 - 1]
^~~~~~~~~~~~~~~~
1 error generated.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

STATIC_ASSERT(
	ARRLEN(g_reg_mapgens) == MAPGEN_INVALID,
registered_mapgens_is_wrong_size);

Looks like 'invalid' needs to be the last one, so add it just before 'invalid'?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah invalid should be last

@SmallJoker
Copy link
Member

I haven't seen your mapgen in the forums before, thus I'm very surprised and happy to see this PR. The code is well written - unlike what LINT (TravisCI) tries to suggest. Will check it out ASAP.

@paramat paramat added @ Mapgen Feature ✨ PRs that add or enhance a feature labels Jun 19, 2017
@paramat
Copy link
Contributor

paramat commented Jun 19, 2017

I'll test of course. From the forum thread i see there are some nice mountain shapes.
It will take me a while to test and review.

@nerzhul
Copy link
Member

nerzhul commented Jun 20, 2017

please migrate all your constructors to C++11 form (look at mapgenflat for example)

@vlapsley
Copy link
Contributor Author

@nerzhul Can you elaborate please? I thought I'd already migrated to C++11 constructors. Am I missing something else?
https://github.com/minetest/minetest/pull/6015/files#r122705713

@nerzhul
Copy link
Member

nerzhul commented Jun 20, 2017

I think i was fallen in my breakfast this morning... ignore my comment

@Zeno-
Copy link
Contributor

Zeno- commented Jun 21, 2017

Nice

@paramat
Copy link
Contributor

paramat commented Jun 23, 2017

Thanks, lint suggested some sensible fixes which you have done with good judgement while avoiding the unreasonable ones.

@SmallJoker
Copy link
Member

The generated terrain looks very promising for builders. Large plains but also mountains and forests - everything what they need. I got a bit confused about the grass generating on sand but that seems to be intended behaviour from MTG.

Screenshot carpathian
👍

@paramat
Copy link
Contributor

paramat commented Jun 25, 2017

You can silence the linter requests by adding the files to the whitelist here https://github.com/minetest/minetest/blob/master/util/travis/clang-format-whitelist.txt

@paramat
Copy link
Contributor

paramat commented Jun 25, 2017

Please don't merge this until i have reviewed.

@red-001
Copy link
Contributor

red-001 commented Jun 25, 2017

raising the water level still seems to mess up the mapgen, is that impossible to fix?

@Zeno-
Copy link
Contributor

Zeno- commented Jun 25, 2017

👍

@paramat
Copy link
Contributor

paramat commented Jun 25, 2017

raising the water level still seems to mess up the mapgen, is that impossible to fix?

That will be addressed by #5981, if that is merged then it is a simple change here.
EDIT: I was wrong, see below.

@red-001
Copy link
Contributor

red-001 commented Jun 25, 2017

water level isn't suppose to change the shape of the land scape right?

@paramat
Copy link
Contributor

paramat commented Jun 25, 2017

Correct, in what way does it mess it up? Only biomes should be a mess. Any screenshots?

@vlapsley
Copy link
Contributor Author

This block of code is responsible for mess associated with changing the water level:

// Gradient
int grad = (water_level - y);
// Shallow seabed
if (y < water_level) {
	grad *= 3;
}

I did a quick test changing it to this:

// Gradient
int grad = (1 - y);
// Shallow seabed
if (y < 1) {
	grad *= 3;
}

A water level setting of 1 gives a terrain that's unchanged. But altering water level by a significant amount (I tried -10 and 10) produced different terrain results even with the code above. Maybe I missed something?

I'll run some further tests to see I can fix this up.

@paramat
Copy link
Contributor

paramat commented Jun 26, 2017

I see you're using a density gradient as in my 'watershed' mapgen and linking that to water_level, that makes sense because you alter the density gradient below water level to make seabed variation smaller.
So yes this is fine and expected.

@vlapsley
Copy link
Contributor Author

Wow, I must've eaten the wrong mushrooms. Those spotty red ones. ;)

It seems I had edited the spawn point gradient and forgot to edit the terrain gradient as well.

I've changed that and testing works well with a variable water level. Tested with water_level = 1, -10, -100, 10 and 50.

Terrain now remains unaffected.

@red-001
Copy link
Contributor

red-001 commented Jun 26, 2017

thanks

this->cave_width = params->cave_width;
this->cavern_limit = params->cavern_limit;
this->cavern_taper = params->cavern_taper;
this->cavern_threshold = params->cavern_threshold;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since you are using large pseudorandom caves 2 more parameters are needed to be able to shift those caves and the lava they contain vertically if terrain is shifted vertically, see mgv7:

	this->large_cave_depth    = params->large_cave_depth;
	this->lava_depth          = params->lava_depth;

Copy link
Contributor

@paramat paramat Jun 28, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can leave out lava_depth if you want as it has a default of y = -256, but only if terrain is locked to y = 1.

// Lerp function
float MapgenCarpathian::getLerp(float noise1, float noise2, float mod)
{
return (1.f - mod) * noise1 + mod * noise2;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mnt_var noise is:

+	np_mnt_var       = NoiseParams(0,  1,  v3f(499,  499,  499),  2490,  5, 0.6,  2.0);

in case you did not know, with scale 1 and 5 octaves persistence 0.6 the value will actually vary between roughly -2 and 2.
Specifically the variation will be 1 + 0.6 + 0.6^2 + 0.6^3 + 0.6^4.
So if you want you might prefer to limit mod to -1 to 1.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

However, when such limits are hit they can create 'edges' visible in the terrain. If you are happy with the current terrain no need to change it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm happy with the way it is. As you say, clamping the upper and lower limit will create edges.

I played with the noise, reducing scale and octaves separately, but I found some of my favourite features where the noise is amplified by two ranges meeting together lost its charm.

If a player wants to reduce the occasional craziness of some mountains, this is the noise parameter to change.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could speed up this function a bit:

  1. Inline
  2. One multiplication less: return noise1 - mod * (noise1 + noise2)
    We already have a similar, simplified function in the noise code but that one would be for (1 - mod)

float w = fabs(noise2);
float k = floor(noise1 / w);
float f = (noise1 - k * w) / w;
float s = fmin(2.f * f, 1.f);
Copy link
Contributor

@paramat paramat Jun 27, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not essential but i was advised to use MTs builtin functions MYMIN() and MYMAX().

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've got no problem changing to MYMIN and MYMAX functions.

I was going to ask why use these functions over the cmath library, but I've just read that fmin/fmax were introduced in C++11 and may not work with older compilers.

So I will make the changes.

Copy link
Contributor

@red-001 red-001 Jun 27, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we are using c++11 now so it's fine, leave it as it is.

Copy link
Contributor

@paramat paramat Jun 27, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, i was advised by hmmmm to use MYMIN/MYMAX but this was a while ago.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah its was at the era of non portable C++

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now that we use C++11, std::fmax is probably the better choice - more a standard than our Minetest-specific MYMAX function.

Copy link
Contributor

@paramat paramat Jun 28, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes i will start to use std::fmain/std::fmax from now on.

float ground = noise_base->result[index2d];

// Gradient
int grad = (1 - y);
Copy link
Contributor

@paramat paramat Jun 27, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems here you are using y = 1 (sea level) as the grad zero point and compressing the terrain variation below sea level.
Sea level is actually variable using the global mapgen parameter water_level so:

+				int grad = (water_level - y);
+				if (y < water_level) {
+					grad *= 3;
+				}

This must be why it was reported that changing water_level messes stuff up.

Copy link
Contributor

@paramat paramat Jun 27, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll tell you one of my mapgen tricks.
If you add a vertical_scale parameter, default 1, and do:

+				int grad = (water_level - y) / vertical_scale;

The parameter acts like a master control on terrain vertical scale, easily changed without editing many confusing noise parameters.

The main use for this is the following:
Set vertical_scale to 0.1.
Divide all noise parameter 'spread' values (v3f(1889, 1889, 1889)) by 10.
This shrinks the terrain by a factor of 10 both vertically and horizontally, creating a 1/10th scale 3D map of your mapgen. To create a map disable biomes, caves and decorations (clear the registered biomes in a mod).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My initial work did use a vertical_scale parameter. But I had awful problems with worlds sometimes not spawning stone - only air and water.

Or, sometimes you would spawn in the ground and the ground (completely flat) would be at y=180 and mountains would be going up to y=400 or 500 and canyons down to water level. It was beautiful and wrong at the same time.

Perhaps I had something else incorrect in the code that caused this though.

Don't ask how many times I rewrote this mapgen from scratch. I'm still coding with learner-plates on.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No problem, i'm not asking for this to be included.

float mnt_var = NoisePerlin3D(&noise_mnt_var->np, x, y, z, seed);

// Grad at water_level
int grad_wl = 1 - water_level;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s32 instead of int
grad_wl can be a private class member calculated once at line 63 in the .cpp constructor

// Grad at water_level
int grad_wl = 1 - water_level;
// Gradient
int grad = (1 - y);
Copy link
Contributor

@paramat paramat Jul 3, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s32 instead of int
no brackets

// Gradient
int grad = (1 - y);
// Shallow seabed
if (y < water_level) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

since action is a single line no need for curly brackets

float ground = noise_base->result[index2d];

// Grad at water_level
int grad_wl = 1 - water_level;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s32 instead of int
grad_wl can be a private class member calculated once at line 63 in the .cpp constructor

// Grad at water_level
int grad_wl = 1 - water_level;
// Gradient
int grad = (1 - y);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s32 instead of int
no brackets

// Gradient
int grad = (1 - y);
// Shallow seabed
if (y < water_level) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

since action is a single line no need for curly brackets


private:
s16 large_cave_depth;

Copy link
Contributor

@paramat paramat Jul 3, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add s32 grad_wl;

int grad = (1 - y);
// Shallow seabed
if (y < water_level) {
grad = grad_wl + (water_level - y) * 3;
Copy link
Contributor

@paramat paramat Jul 3, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could use a ternary operator to reduce all this to a single line:

s32 grad = (y < water_level) ? grad_wl + (water_level - y) * 3 : 1 - y;

int grad = (1 - y);
// Shallow seabed
if (y < water_level) {
grad = grad_wl + (water_level - y) * 3;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could use a ternary operator to reduce all this to a single line:

s32 grad = (y < water_level) ? grad_wl + (water_level - y) * 3 : 1 - y;

@paramat paramat removed the Action / change needed Code still needs changes (PR) / more information requested (Issues) label Jul 3, 2017
@vlapsley
Copy link
Contributor Author

vlapsley commented Jul 4, 2017

Ok, added @paramat recommendations and it looks good to me.

@@ -60,6 +60,7 @@ MapgenCarpathian::MapgenCarpathian(
cavern_limit = params->cavern_limit;
cavern_taper = params->cavern_taper;
cavern_threshold = params->cavern_threshold;
s32 grad_wl = 1 - water_level;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need for s32 as the variable has been initialised as s32 in the .h file.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, thanks. Now I understand about the unused variable warning. Fixed.

@paramat
Copy link
Contributor

paramat commented Jul 5, 2017

Ok we can add the lava depth parameter after merge.

@paramat
Copy link
Contributor

paramat commented Jul 5, 2017

Ok time to test again, looks close to a merge.

@paramat
Copy link
Contributor

paramat commented Jul 5, 2017

Confirmed that, because of how 'grad' works here, the mapgen terrain itself is locked in position and can't be shifted vertically by altering the 'base' noise. This is not a problem.

@paramat
Copy link
Contributor

paramat commented Jul 5, 2017

screenshot_20170705_075027

Found a mountain up to 500, this is good, and it doesn't have too much mad 3D noise stuff.
The amount of flat land will be good for builders.
All seems good 👍

@paramat
Copy link
Contributor

paramat commented Jul 5, 2017

Squash on merge.
Commit message:
Mapgen: Add Carpathian mapgen

@nerzhul nerzhul merged commit a80ecbe into minetest:master Jul 6, 2017
@vlapsley vlapsley deleted the mapgen_carpathian branch July 6, 2017 12:46
BeeeWall pushed a commit to BeeeWall/minetest that referenced this pull request Jul 6, 2017
BeeeWall pushed a commit to BeeeWall/minetest that referenced this pull request Jul 6, 2017
@paramat
Copy link
Contributor

paramat commented Jul 7, 2017

screenshot_20170705_074915

Seed and location.

Eurybot pushed a commit to MT-Eurythmia/minetest that referenced this pull request Jul 10, 2017
Eurybot pushed a commit to MT-Eurythmia/minetest that referenced this pull request Jul 25, 2017
Conflicts:
	builtin/settingtypes.txt
	minetest.conf.example
	src/mapgen_carpathian.cpp
	src/mapgen_carpathian.h
osjc pushed a commit to osjc/minetest that referenced this pull request Jan 11, 2019
osjc pushed a commit to osjc/minetest that referenced this pull request Jan 23, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

7 participants