From 61dfa912f5f37f435e41b3c7d8cdb6244562e597 Mon Sep 17 00:00:00 2001 From: kwolekr Date: Sun, 28 Dec 2014 21:17:12 -0500 Subject: [PATCH] Ore: Add Vein ore type --- doc/lua_api.txt | 28 +++++++++++++-- src/mg_ore.cpp | 60 ++++++++++++++++++++++++++++++--- src/mg_ore.h | 24 ++++++++----- src/script/lua_api/l_mapgen.cpp | 13 +++++-- 4 files changed, 106 insertions(+), 19 deletions(-) diff --git a/doc/lua_api.txt b/doc/lua_api.txt index 8f491f5a..7474c2bf 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -563,9 +563,27 @@ All default ores are of the uniformly-distributed scatter type. clust_scarcity and clust_num_ores are ignored. This is essentially an improved version of the so-called "stratus" ore seen in some unofficial mods. - blob - Creates a roundish blob of ore according to 3d perlin noise described by noise_params. The maximum - size of the blob is clust_size, and clust_scarcity has the same meaning as with scatter type. - + Creates a deformed sphere blobs of ore according to 3d perlin noise described by noise_params. The + maximum size of the blob is clust_size, and clust_scarcity has the same meaning as with scatter type. + - vein + Creates veins of ore varying in density by according to the intersection of two instances 3d perlin + noise with diffferent seeds both described by noise_params. random_factor varies the influence random + chance has on placement of an ore inside the vein, which is 1 by default. Note that modifying this + parameter may require adjusting noise_threshhold. The parameters clust_scarcity, clust_num_ores, and + clust_size are ignored by this ore type. This ore type is difficult to control since it is sensitive + to small changes. The following is a decent set of parameters to work from: + noise_params = { + offset = 0, + scale = 3, + spread = {x=200, y=200, z=200}, + seed = 5390, + octaves = 4, + persist = 0.5, + flags = "eased", + }, + noise_threshhold = 1.6 + WARNING: Use this ore type *very* sparingly since it is ~200x more computationally expensive than + any other ore. Ore attributes ------------------- @@ -2717,6 +2735,10 @@ Ore definition (register_ore) noise_params = {offset=0, scale=1, spread={x=100, y=100, z=100}, seed=23, octaves=3, persist=0.70} ^ NoiseParams structure describing the perlin noise used for ore distribution. ^ Needed for sheet ore_type. Omit from scatter ore_type for a uniform ore distribution + random_factor = 1.0, + ^ Multiplier of the randomness contribution to the noise value at any given point to + ^ decide if ore should be placed. Set to 0 for solid veins. This parameter is only valid + ^ for ore_type == "vein". } Decoration definition (register_decoration) diff --git a/src/mg_ore.cpp b/src/mg_ore.cpp index 2c5712da..95bc02f4 100644 --- a/src/mg_ore.cpp +++ b/src/mg_ore.cpp @@ -27,10 +27,8 @@ with this program; if not, write to the Free Software Foundation, Inc., const char *OreManager::ELEMENT_TITLE = "ore"; FlagDesc flagdesc_ore[] = { - {"absheight", OREFLAG_ABSHEIGHT}, - {"scatter_noisedensity", OREFLAG_DENSITY}, - {"claylike_nodeisnt", OREFLAG_NODEISNT}, - {NULL, 0} + {"absheight", OREFLAG_ABSHEIGHT}, + {NULL, 0} }; @@ -217,7 +215,7 @@ void OreBlob::generate(ManualMapVoxelManipulator *vm, int seed, u32 blockseed, int volume = (nmax.X - nmin.X + 1) * (nmax.Y - nmin.Y + 1) * (nmax.Z - nmin.Z + 1); - int csize = clust_size; + int csize = clust_size; int nblobs = volume / clust_scarcity; if (!noise) @@ -261,3 +259,55 @@ void OreBlob::generate(ManualMapVoxelManipulator *vm, int seed, u32 blockseed, } } } + + +/////////////////////////////////////////////////////////////////////////////// + +OreVein::~OreVein() +{ + delete noise2; +} + + +void OreVein::generate(ManualMapVoxelManipulator *vm, int seed, u32 blockseed, + v3s16 nmin, v3s16 nmax) +{ + PseudoRandom pr(blockseed + 520); + MapNode n_ore(c_ore, 0, ore_param2); + + if (!noise) { + int sx = nmax.X - nmin.X + 1; + int sy = nmax.Y - nmin.Y + 1; + int sz = nmax.Z - nmin.Z + 1; + noise = new Noise(&np, seed, sx, sy, sz); + noise2 = new Noise(&np, seed + 436, sx, sy, sz); + } + bool noise_generated = false; + + size_t index = 0; + for (int z = nmin.Z; z <= nmax.Z; z++) + for (int y = nmin.Y; y <= nmax.Y; y++) + for (int x = nmin.X; x <= nmax.X; x++, index++) { + u32 i = vm->m_area.index(x, y, z); + if (!vm->m_area.contains(i)) + continue; + if (!CONTAINS(c_wherein, vm->m_data[i].getContent())) + continue; + + // Same lazy generation optimization as in OreBlob + if (!noise_generated) { + noise_generated = true; + noise->perlinMap3D(nmin.X, nmin.Y, nmin.Z); + noise2->perlinMap3D(nmin.X, nmin.Y, nmin.Z); + } + + // randval ranges from -1..1 + float randval = (float)pr.next() / (PSEUDORANDOM_MAX / 2) - 1.f; + float noiseval = contour(noise->result[index]); + float noiseval2 = contour(noise2->result[index]); + if (noiseval * noiseval2 + randval * random_factor < nthresh) + continue; + + vm->m_data[i] = n_ore; + } +} diff --git a/src/mg_ore.h b/src/mg_ore.h index a20aeefe..bd81a63f 100644 --- a/src/mg_ore.h +++ b/src/mg_ore.h @@ -32,14 +32,6 @@ class ManualMapVoxelManipulator; // Use absolute value of height to determine ore placement #define OREFLAG_ABSHEIGHT 0x01 - -// Use 3d noise to get density of ore placement, instead of just the position -#define OREFLAG_DENSITY 0x02 // not yet implemented - -// For claylike ore types, place ore if the number of surrounding -// nodes isn't the specified node -#define OREFLAG_NODEISNT 0x04 // not yet implemented - #define OREFLAG_USE_NOISE 0x08 #define ORE_RANGE_ACTUAL 1 @@ -50,6 +42,7 @@ enum OreType { ORE_TYPE_SCATTER, ORE_TYPE_SHEET, ORE_TYPE_BLOB, + ORE_TYPE_VEIN, }; extern FlagDesc flagdesc_ore[]; @@ -105,6 +98,19 @@ class OreBlob : public Ore { u32 blockseed, v3s16 nmin, v3s16 nmax); }; +class OreVein : public Ore { +public: + static const bool NEEDS_NOISE = true; + + float random_factor; + Noise *noise2; + + virtual ~OreVein(); + + virtual void generate(ManualMapVoxelManipulator *vm, int seed, + u32 blockseed, v3s16 nmin, v3s16 nmax); +}; + class OreManager : public GenElementManager { public: static const char *ELEMENT_TITLE; @@ -122,6 +128,8 @@ class OreManager : public GenElementManager { return new OreSheet; case ORE_TYPE_BLOB: return new OreBlob; + case ORE_TYPE_VEIN: + return new OreVein; default: return NULL; } diff --git a/src/script/lua_api/l_mapgen.cpp b/src/script/lua_api/l_mapgen.cpp index 8c81412b..c0a58305 100644 --- a/src/script/lua_api/l_mapgen.cpp +++ b/src/script/lua_api/l_mapgen.cpp @@ -68,9 +68,10 @@ struct EnumString ModApiMapgen::es_MapgenObject[] = struct EnumString ModApiMapgen::es_OreType[] = { - {ORE_TYPE_SCATTER, "scatter"}, - {ORE_TYPE_SHEET, "sheet"}, - {ORE_TYPE_BLOB, "blob"}, + {ORE_TYPE_SCATTER, "scatter"}, + {ORE_TYPE_SHEET, "sheet"}, + {ORE_TYPE_BLOB, "blob"}, + {ORE_TYPE_VEIN, "vein"}, {0, NULL}, }; @@ -680,6 +681,12 @@ int ModApiMapgen::l_register_ore(lua_State *L) } lua_pop(L, 1); + if (oretype == ORE_TYPE_VEIN) { + OreVein *orevein = (OreVein *)ore; + orevein->random_factor = getfloatfield_default(L, index, + "random_factor", 1.f); + } + u32 id = oremgr->add(ore); if (id == (u32)-1) { delete ore;