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

Basic Overworld world generation #120

Merged
merged 49 commits into from Sep 14, 2019
Merged

Conversation

caelunshun
Copy link
Member

@caelunshun caelunshun commented Sep 7, 2019

The aim is to implement a basic generator with Perlin noise and biome support. Caves, trees, etc. will be added in a later PR.

  • Lay groundwork for world generation with a ComposableGenerator based on http://cuberite.xoft.cz/docs/Generator.html
  • Implement a basic height map generator
  • Implement a basic composition generator
  • Implement a biome grid generator
  • Generate composition based on biomes
  • Implement a density map generator using 3D noise instead of 2D
  • Generate height based on biomes
  • Interpolate between biome height values to prevent sharp cutoffs
  • Implement basic "finishers," e.g. shrubs, grass, snow
  • Add tests where possible

@codecov
Copy link

codecov bot commented Sep 7, 2019

Codecov Report

Merging #120 into develop will increase coverage by 2.13%.
The diff coverage is 86.57%.

Impacted file tree graph

@@             Coverage Diff             @@
##           develop     #120      +/-   ##
===========================================
+ Coverage    58.54%   60.68%   +2.13%     
===========================================
  Files           64       76      +12     
  Lines         8492     9197     +705     
===========================================
+ Hits          4972     5581     +609     
- Misses        3520     3616      +96
Impacted Files Coverage Δ
server/src/physics/entity.rs 71.73% <ø> (ø) ⬆️
server/src/worldgen/superflat.rs 89.18% <ø> (ø)
core/src/save/level.rs 30.92% <0%> (ø) ⬆️
server/src/worldgen/density_map/height.rs 0% <0%> (ø)
core/src/world/chunk.rs 87.76% <0%> (-1.54%) ⬇️
server/src/worldgen/util.rs 100% <100%> (ø)
server/src/worldgen/finishers/snow.rs 100% <100%> (ø)
server/src/main.rs 42.99% <100%> (-0.21%) ⬇️
server/src/worldgen/biomes/two_level.rs 100% <100%> (ø)
server/src/worldgen/composition.rs 79.77% <79.77%> (ø)
... and 19 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 0bc8b03...878d346. Read the comment docs.

@caelunshun caelunshun mentioned this pull request Sep 7, 2019
15 tasks
@caelunshun
Copy link
Member Author

First steps!
failed worldgen

@caelunshun caelunshun modified the milestone: 0.7 Sep 7, 2019
@caelunshun
Copy link
Member Author

Height map generator is a bit messed up at the moment. Hope to figure out what's causing this problem.

@NiLSPACE
Copy link

NiLSPACE commented Sep 8, 2019

In Cuberite we moved away from heightmap generators in favor of shape generators cuberite/cuberite#1604. Basically, a shape represents if a block should be empty (air) or filled. The reason for this is because it was much harder to create proper overhangs if we're generating heights.

@madmaxoft
Copy link

Feel free to contact me with questions about terrain generation (I'm the author of most of the Cuberite Composable generator docs you mentioned).

@caelunshun
Copy link
Member Author

caelunshun commented Sep 8, 2019

Yes, that's what I plan to switch to—the height map generator is just temporary. The issue, though, is that the noise function doesn't appear to produce smooth results, and there are visible lines between chunks. So switching to a density map will still cause issues.

This image is a visualization of what the noise function outputs when called in chunks:
output

See verpeteren/rust-simd-noise#9.

Also, thanks for the excellent documentation—it's helping a lot.

@caelunshun
Copy link
Member Author

caelunshun commented Sep 12, 2019

@madmaxoft so I have a question about the biome height interpolation method mentioned in the Cuberite docs. I can see how you could interpolate between heights by averaging when using a 2D height map, but the same doesn't apply when using 3D noise to generate a density map rather than a height map. What's your method for doing this?

I see that Glowstone uses a 2D height noise with added 3D detail and roughness noises to add overhangs and such. They then use the 2D height noise to calculate interpolation between biomes. Is this a method you would recommend?

@madmaxoft
Copy link

madmaxoft commented Sep 12, 2019

We use a bit different method.
For the base, we have two 3D noises that are used for the density, another low-frequency 3D noise is used to switch between them (this allows for sudden "walls", overhangs etc.)
Then biomes averaged across 9 * 9 columns are used to select two "parameters" for each point, the ideal height and the ideal amplitude of the terrain. Each biome has those two hard-coded. The ideal height and the amplitude are then turned into a vertical "gradient" (height -> gradient midpoint, amplitude -> gradient slope) which is added to the 3D noise. The gradient is slightly modified to account for some shaping - at the top of the chunk, the gradient makes the terrain disappear faster, and underground the gradient is 4 times "steeper" than above ground to make the ground have fewer holes. Finally, yet another 2D noise, added to each Y column, is used to modify the ground height.

Of course calculating all this would be too much for the CPU, so these noises are all linearly upscaled by a factor of 4 horizontally and 8 vertically, so that only a 5 * 33 * 5 values from each are needed for a single chunk.

Here's the C++ code:
https://github.com/cuberite/cuberite/blob/7678d5e6ed6fcc9361416ef41c43fa09a1d49f6f/src/Generating/Noise3DGenerator.cpp#L585-L772

@caelunshun
Copy link
Member Author

caelunshun commented Sep 12, 2019

For the base, we have two 3D noises that are used for the density, another low-frequency 3D noise is used to switch between them (this allows for sudden "walls", overhangs etc.)
Then biomes averaged across 9 * 9 columns are used to select two "parameters" for each point, the ideal height and the ideal amplitude of the terrain. Each biome has those two hard-coded. The ideal height and the amplitude are then turned into a vertical "gradient" (height -> gradient midpoint, amplitude -> gradient slope) which is added to the 3D noise. The gradient is slightly modified to account for some shaping - at the top of the chunk, the gradient makes the terrain disappear faster, and underground the gradient is 4 times "steeper" than above ground to make the ground have fewer holes. Finally, yet another 2D noise, added to each Y column, is used to modify the ground height.

Thanks, that makes sense. So from what I can tell, the amplitude for a biome indicates the impact of the Y coordinate on the density values, so lower amplitudes would mean higher terrain, e.g. mountains.

This definitely seems like a better approach than the 2D heightmap + 3D roughness noises. I think we'll go with something like this.

@caelunshun
Copy link
Member Author

2019-09-12_21 56 44

@caelunshun
Copy link
Member Author

caelunshun commented Sep 14, 2019

worldgen

I plan to merge this PR within the next day and make incremental improvements to worldgen over time. @Momothereal any thoughts?

@caelunshun caelunshun marked this pull request as ready for review September 14, 2019 05:01
@caelunshun caelunshun changed the title [WIP] Overworld world generation Basic Overworld world generation Sep 14, 2019
@aramperes
Copy link
Contributor

Just tested the PR. Very impressive work!

Sounds good to me

@caelunshun caelunshun merged commit 8187341 into develop Sep 14, 2019
@caelunshun caelunshun deleted the feature/world-generation branch October 2, 2019 18:54
cheako pushed a commit to cheako/feather that referenced this pull request Jan 4, 2020
This is a sad squashing of 49 laborious commits into one:

* Lay groundwork for a true world generator

* Implement basic height map and composition generators

* more work

* Initialize light values to 15

* Implement basic biome grid generator + visualization

* Initialize biome values in chunks

* Implement basic changing of topsoil blocks depending on column biome

* Load seed from world save

* Don't generate invalid biomes, such as TheEnd

* Adjust some parameters and fix biome composition for certain biomes

* Various fixes and tweaks

* Implement basic two-level biome generator

* Rename HeightMapGenerator -> DensityMapGenerator

* Add basic ocean support

* Correctly set water level below ocean surface

* Refactor biome generators into separate files

* Fix height map noise - don't use generate_scaled

* Refactor density_map into multiple files

* Begin work on linear interpolation for noise

* More work on trilinear interpolation

* Get tests to pass for trilinear interpolation

* Initiial implementation of density map generator

* Work more on linear interpolation

* Rewrite linear interpolation algorithm using different approach

* Fix bug with linear interpolation

* Fix another bug with interpolation (no, it still doesn't work)

* And another one

* Sigh... nothing works.

* Get density generation to work, after four days of painful debugging

* Remove physics debug message which was accidentally added in this branch

* Generate density based on biome

* Composition fixes

* Interpolate between biome parameter values

* Minor Voronoi fix: don't use generate_scaled

* Biome changes

* Add snow finisher

* Add shrub and lily pad generator

* Fix Voronoi implementation

* Add additional height noise to density generator

* Add grass finisher

* Fix NearbyBiomes impl, which caused cutoffs at biome boundaries

* Add reproducability test
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants