OpenCubicChunks / CubicChunks2

Infinite* height mod for Minecraft - rewrite for versions above 1.12
MIT License
77 stars 18 forks source link

Carvers are missing noise data from above #4

Open Cyclonit opened 3 years ago

Cyclonit commented 3 years ago

Issue

World generation is split into multiple stages. These include determining biomes, generating noise for the terrain, carving caves and rivers, or placing structures. In general each cube is generated by itself and moves through the different stages. However, some stages require information from neighbouring cubes to produce satisfying results. A simple example is placing structures across multiple cubes.

Vanilla Minecraft already has a dependency system in place to deal with this problem along the horizontal axis. Each stage has a well defined task margin. This margin defines the radius of cubes around the current cube, that are needed to progress the current cube to the next stage. For example, generating features has a task margin of 8, meaning that in a radius of 8 cubes around the current cube, all cubes must exist and be in the stage prior to features. This way, the feature generator can reference the neighbouring cubes and rely on their data.

Surface and liquid carvers do not have a task margin in Vanilla Minecraft as they do not depend on neighbouring chunks horizontally. They do however depend on information above the current cube. When a carver is executed it references noise up to 8 blocks above the current cube to determine if there exists a cave or some other carved feature that needs to be extended downwards. We thus need a system to provide these additional 8 block layers to the carvers.

Possible Solutions

Increasing the task margin for carvers

Increasing the task margin for carvers would result in all neighbouring cubes being present and containing block information. However, the cube above the current cube could be in a later stage. Thus blocks might have changed since the noise stage. This could lead to carvers using information different to what they expect from Vanilla Minecraft.

Generating noise on demand

Whenever a carver is being executed, we can generate the necessary 8 block layers of noise just in time and present them to the carver. This approach does work, but it results in some noise being generated twice. Given a cube size of 32³ blocks, it results in a 25% increase of noise to be generated, as the bottom 8 layers of each cube are calculated twice.

Caching noise and generating it on demand

To avoid the 25% computational penalty from generating noise on demand, we could cache the required noise data from the original noise calculation. When a new cube is generated, its block array is filled with noise information. We could stash the bottom 8 layers of this information separately. This copy would not be affected by the cube reaching later stages of generation and could thus safely be used for running carvers for the cube underneath it. The cache would effectively duplicate the bottom 8 block layers of each cube. Thus we must ensure that this cache is removed as soon as possible. This could happen as soon as the cube underneath has finished its carver stages.