Custom c++ mapgen using 3D simplex noise

Post Reply
User avatar
Blockabilly
Member
Posts: 10
Joined: Sun Mar 05, 2023 04:49
GitHub: Blockabilly
IRC: Blockabilly
In-game: Blockabilly
Location: United States
Contact:

Custom c++ mapgen using 3D simplex noise

by Blockabilly » Post

Pretty cool, huh? 😎
0.jpg
0.jpg (54.2 KiB) Viewed 2043 times
1.jpg
1.jpg (125.02 KiB) Viewed 2043 times
2.jpg
2.jpg (219.57 KiB) Viewed 2043 times

User avatar
Blockabilly
Member
Posts: 10
Joined: Sun Mar 05, 2023 04:49
GitHub: Blockabilly
IRC: Blockabilly
In-game: Blockabilly
Location: United States
Contact:

Re: Custom c++ mapgen using 3D simplex noise

by Blockabilly » Post

Simplex rivers 🤯
rivers.jpg
rivers.jpg (248.13 KiB) Viewed 2033 times

User avatar
Blockhead
Moderator
Posts: 2178
Joined: Wed Jul 17, 2019 10:14
GitHub: Montandalar
IRC: Blockhead256
In-game: Blockhead Blockhead256
Location: Land Down Under
Contact:

Re: Custom c++ mapgen using 3D simplex noise

by Blockhead » Post

That is pretty cool, though 3D noise can be slower than 2D. Simplex does produce nice results, and should be faster when done right. If you'd like to share, Minetest would definitely benefit from adding simplex noise parameters and maybe a new showcase generator - #11468. (also previous discussion on IRC).
/˳˳_˳˳]_[˳˳_˳˳]_[˳˳_˳˳\ Advtrains enthusiast | My map: Noah's Railyard | My Content on ContentDB ✝️♂

User avatar
Blockabilly
Member
Posts: 10
Joined: Sun Mar 05, 2023 04:49
GitHub: Blockabilly
IRC: Blockabilly
In-game: Blockabilly
Location: United States
Contact:

Re: Custom c++ mapgen using 3D simplex noise

by Blockabilly » Post

Blockhead wrote:
Wed Sep 18, 2024 04:19
That is pretty cool, though 3D noise can be slower than 2D. Simplex does produce nice results, and should be faster when done right. If you'd like to share, Minetest would definitely benefit from adding simplex noise parameters and maybe a new showcase generator - #11468. (also previous discussion on IRC).
Hmm... I suppose I could run some benchmarks to compare.

MapgenV7:

Code: Select all

void MapgenV7::makeChunk(BlockMakeData *data)
{
	std::cout
		<< "Generating chunk:"
		<< " blockpos_min=(" << data->blockpos_min.X << ","
		<< " " << data->blockpos_min.Y << ","
		<< " " << data->blockpos_min.Z << ")"
		<< " blockpos_max=(" << data->blockpos_max.X << ","
		<< " " << data->blockpos_max.Y << ","
		<< " " << data->blockpos_max.Z << ")";
	auto tbegin = std::chrono::high_resolution_clock::now();
	//...existing code
	auto tend = std::chrono::high_resolution_clock::now();
	std::cout
		<< " duration="
		<< std::chrono::duration_cast<std::chrono::milliseconds>(tend-tbegin).count()
		<< "ms" << std::endl;
}

output:
Generating chunk: blockpos_min=(-6, -2, -2) blockpos_max=(-3, 1, 1) duration=252ms
Generating chunk: blockpos_min=(-6, -2, 2) blockpos_max=(-3, 1, 5) duration=260ms
Generating chunk: blockpos_min=(-6, 2, -2) blockpos_max=(-3, 5, 1) duration=205ms
Generating chunk: blockpos_min=(-6, 2, 2) blockpos_max=(-3, 5, 5) duration=222ms
Generating chunk: blockpos_min=(-6, -6, -2) blockpos_max=(-3, -3, 1) duration=124ms
Generating chunk: blockpos_min=(-6, -6, 2) blockpos_max=(-3, -3, 5) duration=127ms
Generating chunk: blockpos_min=(-6, -2, -6) blockpos_max=(-3, 1, -3) duration=259ms
Generating chunk: blockpos_min=(-6, 2, -6) blockpos_max=(-3, 5, -3) duration=225ms
Generating chunk: blockpos_min=(-2, -6, -2) blockpos_max=(1, -3, 1) duration=152ms
Generating chunk: blockpos_min=(-2, -6, 2) blockpos_max=(1, -3, 5) duration=155ms
Generating chunk: blockpos_min=(-2, -6, -6) blockpos_max=(1, -3, -3) duration=123ms
Generating chunk: blockpos_min=(-2, -2, -6) blockpos_max=(1, 1, -3) duration=274ms
Generating chunk: blockpos_min=(-2, -2, -2) blockpos_max=(1, 1, 1) duration=282ms
Generating chunk: blockpos_min=(-2, -2, 2) blockpos_max=(1, 1, 5) duration=343ms
Generating chunk: blockpos_min=(-2, 2, -6) blockpos_max=(1, 5, -3) duration=237ms
Generating chunk: blockpos_min=(-2, 2, -2) blockpos_max=(1, 5, 1) duration=260ms
Generating chunk: blockpos_min=(-2, 2, 2) blockpos_max=(1, 5, 5) duration=254ms
Generating chunk: blockpos_min=(2, -6, -2) blockpos_max=(5, -3, 1) duration=132ms
Generating chunk: blockpos_min=(2, -6, 2) blockpos_max=(5, -3, 5) duration=141ms
Generating chunk: blockpos_min=(2, -6, -6) blockpos_max=(5, -3, -3) duration=127ms
Generating chunk: blockpos_min=(2, -2, -6) blockpos_max=(5, 1, -3) duration=271ms
Generating chunk: blockpos_min=(2, -2, -2) blockpos_max=(5, 1, 1) duration=283ms
Generating chunk: blockpos_min=(2, -2, 2) blockpos_max=(5, 1, 5) duration=286ms
Generating chunk: blockpos_min=(2, 2, -6) blockpos_max=(5, 5, -3) duration=234ms
Generating chunk: blockpos_min=(2, 2, -2) blockpos_max=(5, 5, 1) duration=260ms
Generating chunk: blockpos_min=(2, 2, 2) blockpos_max=(5, 5, 5) duration=251ms
mgv7.jpg
mgv7.jpg (124.87 KiB) Viewed 1999 times
MapgenSimplex:

Code: Select all

void MapgenSimplex::makeChunk(BlockMakeData *data)
{
	std::cout
		<< "Generating chunk:"
		<< " blockpos_min=(" << data->blockpos_min.X << ","
		<< " " << data->blockpos_min.Y << ","
		<< " " << data->blockpos_min.Z << ")"
		<< " blockpos_max=(" << data->blockpos_max.X << ","
		<< " " << data->blockpos_max.Y << ","
		<< " " << data->blockpos_max.Z << ")";
	auto tbegin = std::chrono::high_resolution_clock::now();
	//...existing code
	auto tend = std::chrono::high_resolution_clock::now();
	std::cout
		<< " duration="
		<< std::chrono::duration_cast<std::chrono::milliseconds>(tend-tbegin).count()
		<< "ms" << std::endl;
}

output:
Generating chunk: blockpos_min=(10, -2, -10) blockpos_max=(13, 1, -7) duration=70ms
Generating chunk: blockpos_min=(10, -2, -6) blockpos_max=(13, 1, -3) duration=74ms
Generating chunk: blockpos_min=(10, 2, -10) blockpos_max=(13, 5, -7) duration=147ms
Generating chunk: blockpos_min=(10, 2, -6) blockpos_max=(13, 5, -3) duration=164ms
Generating chunk: blockpos_min=(10, -2, -14) blockpos_max=(13, 1, -11) duration=80ms
Generating chunk: blockpos_min=(10, 2, -14) blockpos_max=(13, 5, -11) duration=164ms
Generating chunk: blockpos_min=(14, -6, -10) blockpos_max=(17, -3, -7) duration=22ms
Generating chunk: blockpos_min=(14, -6, -6) blockpos_max=(17, -3, -3) duration=23ms
Generating chunk: blockpos_min=(14, -2, -14) blockpos_max=(17, 1, -11) duration=81ms
Generating chunk: blockpos_min=(14, -2, -10) blockpos_max=(17, 1, -7) duration=95ms
Generating chunk: blockpos_min=(14, -2, -6) blockpos_max=(17, 1, -3) duration=90ms
Generating chunk: blockpos_min=(14, 2, -14) blockpos_max=(17, 5, -11) duration=175ms
Generating chunk: blockpos_min=(14, 2, -10) blockpos_max=(17, 5, -7) duration=201ms
Generating chunk: blockpos_min=(14, 2, -6) blockpos_max=(17, 5, -3) duration=194ms
Generating chunk: blockpos_min=(18, -6, -10) blockpos_max=(21, -3, -7) duration=24ms
Generating chunk: blockpos_min=(18, -6, -6) blockpos_max=(21, -3, -3) duration=25ms
Generating chunk: blockpos_min=(18, -2, -14) blockpos_max=(21, 1, -11) duration=84ms
Generating chunk: blockpos_min=(18, -2, -10) blockpos_max=(21, 1, -7) duration=102ms
Generating chunk: blockpos_min=(18, -2, -6) blockpos_max=(21, 1, -3) duration=98ms
Generating chunk: blockpos_min=(18, 2, -14) blockpos_max=(21, 5, -11) duration=175ms
Generating chunk: blockpos_min=(18, 2, -10) blockpos_max=(21, 5, -7) duration=201ms
Generating chunk: blockpos_min=(18, 2, -6) blockpos_max=(21, 5, -3) duration=193ms
Generating chunk: blockpos_min=(14, 6, -10) blockpos_max=(17, 9, -7) duration=171ms
Generating chunk: blockpos_min=(14, 6, -6) blockpos_max=(17, 9, -3) duration=179ms
Generating chunk: blockpos_min=(18, 6, -10) blockpos_max=(21, 9, -7) duration=182ms
Generating chunk: blockpos_min=(18, 6, -6) blockpos_max=(21, 9, -3) duration=195ms
Generating chunk: blockpos_min=(10, 6, -6) blockpos_max=(13, 9, -3) duration=177ms
Generating chunk: blockpos_min=(10, 6, -10) blockpos_max=(13, 9, -7) duration=199ms
Generating chunk: blockpos_min=(14, 6, -14) blockpos_max=(17, 9, -11) duration=187ms
Generating chunk: blockpos_min=(18, 6, -14) blockpos_max=(21, 9, -11) duration=193ms
simplex-current.jpg
simplex-current.jpg (119.3 KiB) Viewed 1999 times
Hmm... Actually... it looks like my 3D simplex noise is about 2-3x faster than V7 defaults.

User avatar
Skamiz Kazzarch
Member
Posts: 656
Joined: Fri Mar 09, 2018 20:34
GitHub: Skamiz
In-game: Skamiz
Location: la lojbaugag.

Re: Custom c++ mapgen using 3D simplex noise

by Skamiz Kazzarch » Post

As a writer of many a Lua mapgen I concur. Having simplex noise available in the engine would be very nice.
I am guessing the first screenshots are the result of trying to add a grass layer? Had the same thing happen to me before.

User avatar
Blockabilly
Member
Posts: 10
Joined: Sun Mar 05, 2023 04:49
GitHub: Blockabilly
IRC: Blockabilly
In-game: Blockabilly
Location: United States
Contact:

Re: Custom c++ mapgen using 3D simplex noise

by Blockabilly » Post

Just added a second 3D noise generator to create some lakes and caverns. Still beating V7:

Code: Select all

Generating chunk: blockpos_min=(-6, -2, -2) blockpos_max=(-3, 1, 1) duration=197ms
Generating chunk: blockpos_min=(-6, -2, 2) blockpos_max=(-3, 1, 5) duration=152ms
Generating chunk: blockpos_min=(-6, 2, -2) blockpos_max=(-3, 5, 1) duration=167ms
Generating chunk: blockpos_min=(-6, 2, 2) blockpos_max=(-3, 5, 5) duration=184ms
Generating chunk: blockpos_min=(-6, -2, -6) blockpos_max=(-3, 1, -3) duration=164ms
Generating chunk: blockpos_min=(-6, 2, -6) blockpos_max=(-3, 5, -3) duration=184ms
Generating chunk: blockpos_min=(-2, -6, -2) blockpos_max=(1, -3, 1) duration=38ms
Generating chunk: blockpos_min=(-2, -6, 2) blockpos_max=(1, -3, 5) duration=38ms
Generating chunk: blockpos_min=(-2, -2, -6) blockpos_max=(1, 1, -3) duration=176ms
Generating chunk: blockpos_min=(-2, -2, -2) blockpos_max=(1, 1, 1) duration=178ms
Generating chunk: blockpos_min=(-2, -2, 2) blockpos_max=(1, 1, 5) duration=167ms
Generating chunk: blockpos_min=(-2, 2, -6) blockpos_max=(1, 5, -3) duration=197ms
Generating chunk: blockpos_min=(-2, 2, -2) blockpos_max=(1, 5, 1) duration=223ms
Generating chunk: blockpos_min=(-2, 2, 2) blockpos_max=(1, 5, 5) duration=214ms
Generating chunk: blockpos_min=(2, -6, -2) blockpos_max=(5, -3, 1) duration=37ms
Generating chunk: blockpos_min=(2, -6, 2) blockpos_max=(5, -3, 5) duration=41ms
Generating chunk: blockpos_min=(2, -2, -6) blockpos_max=(5, 1, -3) duration=164ms
Generating chunk: blockpos_min=(2, -2, -2) blockpos_max=(5, 1, 1) duration=178ms
Generating chunk: blockpos_min=(2, -2, 2) blockpos_max=(5, 1, 5) duration=183ms
Generating chunk: blockpos_min=(2, 2, -6) blockpos_max=(5, 5, -3) duration=197ms
Generating chunk: blockpos_min=(2, 2, -2) blockpos_max=(5, 5, 1) duration=228ms
Generating chunk: blockpos_min=(2, 2, 2) blockpos_max=(5, 5, 5) duration=213ms
Generating chunk: blockpos_min=(-6, 6, 2) blockpos_max=(-3, 9, 5) duration=175ms
Generating chunk: blockpos_min=(-2, 6, 2) blockpos_max=(1, 9, 5) duration=197ms
Generating chunk: blockpos_min=(-6, 2, 6) blockpos_max=(-3, 5, 9) duration=180ms
Generating chunk: blockpos_min=(-2, 2, 6) blockpos_max=(1, 5, 9) duration=204ms
Generating chunk: blockpos_min=(2, 2, 6) blockpos_max=(5, 5, 9) duration=194ms
Generating chunk: blockpos_min=(2, -2, 6) blockpos_max=(5, 1, 9) duration=189ms
Generating chunk: blockpos_min=(-6, -2, 6) blockpos_max=(-3, 1, 9) duration=176ms
Generating chunk: blockpos_min=(-2, -2, 6) blockpos_max=(1, 1, 9) duration=217ms
Generating chunk: blockpos_min=(-6, 6, 6) blockpos_max=(-3, 9, 9) duration=196ms
Generating chunk: blockpos_min=(-2, 6, 6) blockpos_max=(1, 9, 9) duration=219ms
Generating chunk: blockpos_min=(2, 2, 10) blockpos_max=(5, 5, 13) duration=176ms
double-3d-simplex.jpg
double-3d-simplex.jpg (132.42 KiB) Viewed 1983 times
double-3d-simplex-3.jpg
double-3d-simplex-3.jpg (153.15 KiB) Viewed 1983 times
double-3d-simplex-2.jpg
double-3d-simplex-2.jpg (57.19 KiB) Viewed 1983 times

User avatar
Blockabilly
Member
Posts: 10
Joined: Sun Mar 05, 2023 04:49
GitHub: Blockabilly
IRC: Blockabilly
In-game: Blockabilly
Location: United States
Contact:

Re: Custom c++ mapgen using 3D simplex noise

by Blockabilly » Post

P.S. in case anyone is wondering what the oddly-placed stone is doing there in some screenshots, I wanted a fixed-size map (768^3) split into 9 subdivisions of roughly 256^3 each. I'm doing this as a homeschool project for my kids who love to destroy each other's work, so I plan to integrate one of the protection mods so each kid can only dig/build in their own subdivision. The stone walls are placeholders for custom color-coded nodes I intend to add as indicators to help them understand their respective boundaries:

subdivisions.jpg
subdivisions.jpg (157.55 KiB) Viewed 1979 times

I will probably create a copy of the mapgen and strip all these extraneous features before sharing the code, or I might just add these to the MapgenParams so they can be toggled on and off along with other settings via minetest.conf just in case someone else would find these features useful:

settings.jpg
settings.jpg (36.11 KiB) Viewed 1979 times

The observation chamber is a big square "tube" made of glass (intend to replace with a clear, indestructible variant) that goes all the way straight down the center of the map to allow them to explore the various layers which I built to somewhat resemble earth, from the surface down:

  • dirt
  • sand
  • gravel
  • stone
  • aquifer
  • stone
  • obsidian
  • lava
observation-chamber.jpg
observation-chamber.jpg (109.47 KiB) Viewed 1979 times

I built all this right into the mapgen because it's faster than lua and, since it's part of the mapgen itself, it's all baked into the map as new blocks emerge without any additional overhead. 🤷🏻‍♂️

User avatar
Blockabilly
Member
Posts: 10
Joined: Sun Mar 05, 2023 04:49
GitHub: Blockabilly
IRC: Blockabilly
In-game: Blockabilly
Location: United States
Contact:

Re: Custom c++ mapgen using 3D simplex noise

by Blockabilly » Post

Oh, and in case anyone is now wondering what the AirGap/Sandbox is, I made it so the mapgen only generates the defined mgsimplex_map_size, regardless of the mapgen_limit setting. Everything outside this area is simply filled with air so players can fly beyond the ends of the map and actually see the sides rather than the CONTENT_IGNORE mirror/abyss. The "sandbox" is just the stone walls and floor that the map and all of its content sit inside to prevent the water from the lakes and aquifer or the lava at the bottom of the "world" from "leaking" out into the surrounding air, causing ABMs to run wild:

airgap-sandbox.jpg
airgap-sandbox.jpg (90.03 KiB) Viewed 1973 times

wheat8
Member
Posts: 41
Joined: Sat Jul 20, 2024 13:06
Location: France

Re: Custom c++ mapgen using 3D simplex noise

by wheat8 » Post

That's very good to see that it is possible to have a faster map generation !
Is there any other advantage or characterisic of 3D noise compared to 2D noise ? Differences in the terrain generation ?

User avatar
Blockabilly
Member
Posts: 10
Joined: Sun Mar 05, 2023 04:49
GitHub: Blockabilly
IRC: Blockabilly
In-game: Blockabilly
Location: United States
Contact:

Re: Custom c++ mapgen using 3D simplex noise

by Blockabilly » Post

I had to take a step back to handle some other things, but I'm back playing with it some more this weekend and thought I'd share some previews from my experiments.

Some Earth-like simulations:
map-1.jpg
map-1.jpg (252.71 KiB) Viewed 1432 times
map-2.jpg
map-2.jpg (382.81 KiB) Viewed 1432 times
map-3.jpg
map-3.jpg (491.76 KiB) Viewed 1432 times

User avatar
Blockabilly
Member
Posts: 10
Joined: Sun Mar 05, 2023 04:49
GitHub: Blockabilly
IRC: Blockabilly
In-game: Blockabilly
Location: United States
Contact:

Re: Custom c++ mapgen using 3D simplex noise

by Blockabilly » Post

Using a single 2D Simplex noise map with feature classification by subdivided value ranges, I've managed to generate a beautiful terrain with a nice balance of lakes and land. I then started playing with targeted value ranges for specific features (lakes, hills, etc.) and accidentally created this strange (but really interesting) landscape with grassy hills embedded in the ground, and due to the way I'm processing/handling the noise values, some of them are hollow like a volcano:

embedded-hills.jpg
embedded-hills.jpg (280.95 KiB) Viewed 1348 times

It then occurred to me that I could use this to create real volcanos filled with lava:

volcanos.jpg
volcanos.jpg (348.24 KiB) Viewed 1348 times

Oh... P.S. each chunk (80^3) is now rendering in 75-150ms. Some take a little longer (pretty sure it's due to sqlite latency), with a max of ~300ms.

User avatar
Blockabilly
Member
Posts: 10
Joined: Sun Mar 05, 2023 04:49
GitHub: Blockabilly
IRC: Blockabilly
In-game: Blockabilly
Location: United States
Contact:

Re: Custom c++ mapgen using 3D simplex noise

by Blockabilly » Post

Playing with 3D noise again, generating only 1 node for any given x/z coordinate with y = noise value. Really interesting results so far:
simplex3d1.jpg
simplex3d1.jpg (449.6 KiB) Viewed 1310 times
simplex3d1.jpg
simplex3d1.jpg (449.6 KiB) Viewed 1310 times
simplex3d1.jpg
simplex3d1.jpg (449.6 KiB) Viewed 1310 times
Attachments
simplex3d2.jpg
simplex3d2.jpg (323.1 KiB) Viewed 1310 times
simplex3d3.jpg
simplex3d3.jpg (411.37 KiB) Viewed 1310 times

User avatar
Blockabilly
Member
Posts: 10
Joined: Sun Mar 05, 2023 04:49
GitHub: Blockabilly
IRC: Blockabilly
In-game: Blockabilly
Location: United States
Contact:

Re: Custom c++ mapgen using 3D simplex noise

by Blockabilly » Post

Finally making progress with my realistic map generation:
n-s.jpg
n-s.jpg (174.83 KiB) Viewed 1212 times
w-e.jpg
w-e.jpg (206.44 KiB) Viewed 1212 times
Very pleased with the generation times, too:
console.jpg
console.jpg (384.98 KiB) Viewed 1212 times

User avatar
freshreplicant
Member
Posts: 238
Joined: Sun Aug 09, 2020 10:37
In-game: freshreplicant

Re: Custom c++ mapgen using 3D simplex noise

by freshreplicant » Post

Wow, this looks pretty promising.

User avatar
Skamiz Kazzarch
Member
Posts: 656
Joined: Fri Mar 09, 2018 20:34
GitHub: Skamiz
In-game: Skamiz
Location: la lojbaugag.

Re: Custom c++ mapgen using 3D simplex noise

by Skamiz Kazzarch » Post

Just FYI, there exists a dedicated terrain screenshot thread: viewtopic.php?t=20782
I and several others have been dumping pictures of our various mapgen experiments there.

Post Reply