Decoration API: Add lightweight ability to have complete coverage (#7456)
authorParamat <paramat@users.noreply.github.com>
Sun, 24 Jun 2018 16:14:18 +0000 (17:14 +0100)
committerGitHub <noreply@github.com>
Sun, 24 Jun 2018 16:14:18 +0000 (17:14 +0100)
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.

doc/lua_api.txt
src/mapgen/mg_decoration.cpp

index db340e415d550dc3280dce3e1f56ed34d665a30f..743cca47df01e9b89e0b960b1063c3d6190b97e7 100644 (file)
@@ -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
index 6daa8216eb07bb0dd14ebb9dfe10884824be519c..28dde0209250421e2a1b8a9bbfcce728facf7972 100644 (file)
@@ -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) ||