Decoration API: Add lightweight ability to have complete coverage (#7456)

When the noise value or fill_ratio >= 10.0 complete coverage is enabled.
This disables random placement to avoid redundant multiple placements
at one position. Instead, 1 decoration per surface node is placed by
looping across each division.

'10' was chosen as this is the fill_ratio that previously created
very near complete coverage. The complete coverage feature therefore
integrates smoothly when noise is used for variable decoration density.

'fill_ratio = 10' should be used by modders who want a decoration
placed on every surface node. Compared to before such a decoration
placement will be 10 times faster.
This commit is contained in:
Paramat 2018-06-24 17:14:18 +01:00 committed by GitHub
parent 1d1cf000c0
commit de621d5d4b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 33 additions and 9 deletions

@ -5769,6 +5769,8 @@ Definition tables
fill_ratio = 0.02,
-- ^ The value determines 'decorations per surface node'.
-- ^ Used only if noise_params is not specified.
-- ^ If >= 10.0 complete coverage is enabled and decoration placement uses
-- ^ a different and much faster method.
noise_params = {
offset = 0,
scale = 0.45,
@ -5783,6 +5785,8 @@ Definition tables
-- ^ distribution.
-- ^ A noise value is calculated for each square division and determines
-- ^ 'decorations per surface node' within each division.
-- ^ If the noise value >= 10.0 complete coverage is enabled and decoration
-- ^ placement uses a different and much faster method.
biomes = {"Oceanside", "Hills", "Plains"},
-- ^ List of biomes in which this decoration occurs. Occurs in all biomes
-- ^ if this is omitted, and ignored if the Mapgen being used does not

@ -155,23 +155,43 @@ size_t Decoration::placeDeco(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax)
nmin.Z + sidelen + sidelen * z0 - 1
);
bool cover = false;
// Amount of decorations
float nval = (flags & DECO_USE_NOISE) ?
NoisePerlin2D(&np, p2d_center.X, p2d_center.Y, mapseed) :
fill_ratio;
u32 deco_count = 0;
float deco_count_f = (float)area * nval;
if (deco_count_f >= 1.f) {
deco_count = deco_count_f;
} else if (deco_count_f > 0.f) {
// For low density decorations calculate a chance for 1 decoration
if (ps.range(1000) <= deco_count_f * 1000.f)
deco_count = 1;
if (nval >= 10.0f) {
// Complete coverage. Disable random placement to avoid
// redundant multiple placements at one position.
cover = true;
deco_count = area;
} else {
float deco_count_f = (float)area * nval;
if (deco_count_f >= 1.0f) {
deco_count = deco_count_f;
} else if (deco_count_f > 0.0f) {
// For very low density calculate a chance for 1 decoration
if (ps.range(1000) <= deco_count_f * 1000.0f)
deco_count = 1;
}
}
s16 x = p2d_min.X - 1;
s16 z = p2d_min.Y;
for (u32 i = 0; i < deco_count; i++) {
s16 x = ps.range(p2d_min.X, p2d_max.X);
s16 z = ps.range(p2d_min.Y, p2d_max.Y);
if (!cover) {
x = ps.range(p2d_min.X, p2d_max.X);
z = ps.range(p2d_min.Y, p2d_max.Y);
} else {
x++;
if (x == p2d_max.X + 1) {
z++;
x = p2d_min.X;
}
}
int mapindex = carea_size * (z - nmin.Z) + (x - nmin.X);
if ((flags & DECO_ALL_FLOORS) ||