From fb2bc956b18bd70a47bff00d5726d4754867856a Mon Sep 17 00:00:00 2001 From: kwolekr Date: Wed, 10 Dec 2014 00:37:09 -0500 Subject: [PATCH] Noise: Create a deep copy of NoiseParams --- src/mapgen_v5.cpp | 6 ++-- src/mapgen_v6.cpp | 36 ++++++++++---------- src/mapgen_v7.cpp | 26 +++++++-------- src/mg_ore.cpp | 20 +++--------- src/mg_ore.h | 17 ++++++---- src/noise.cpp | 58 ++++++++++++++++----------------- src/noise.h | 2 +- src/script/lua_api/l_mapgen.cpp | 9 ++++- src/script/lua_api/l_noise.cpp | 8 ++--- 9 files changed, 91 insertions(+), 91 deletions(-) diff --git a/src/mapgen_v5.cpp b/src/mapgen_v5.cpp index 04e9d8c95..f2cb79179 100644 --- a/src/mapgen_v5.cpp +++ b/src/mapgen_v5.cpp @@ -187,12 +187,12 @@ void MapgenV5Params::writeParams(Settings *settings) { int MapgenV5::getGroundLevelAtPoint(v2s16 p) { //TimeTaker t("getGroundLevelAtPoint", NULL, PRECISION_MICRO); - float f = 0.55 + NoisePerlin2D(noise_factor->np, p.X, p.Y, seed); + float f = 0.55 + NoisePerlin2D(&noise_factor->np, p.X, p.Y, seed); if(f < 0.01) f = 0.01; else if(f >= 1.0) f *= 1.6; - float h = water_level + NoisePerlin2D(noise_height->np, p.X, p.Y, seed); + float h = water_level + NoisePerlin2D(&noise_height->np, p.X, p.Y, seed); s16 search_top = water_level + 15; s16 search_base = water_level; @@ -202,7 +202,7 @@ int MapgenV5::getGroundLevelAtPoint(v2s16 p) { s16 level = -31000; for (s16 y = search_top; y >= search_base; y--) { - float n_ground = NoisePerlin3DEased(noise_ground->np, p.X, y, p.Y, seed); + float n_ground = NoisePerlin3DEased(&noise_ground->np, p.X, y, p.Y, seed); if(n_ground * f > y - h) { if(y >= search_top - 7) break; diff --git a/src/mapgen_v6.cpp b/src/mapgen_v6.cpp index b8474cb53..04c3b147e 100644 --- a/src/mapgen_v6.cpp +++ b/src/mapgen_v6.cpp @@ -246,13 +246,13 @@ float MapgenV6::baseTerrainLevelFromNoise(v2s16 p) { if (flags & MG_FLAT) return water_level; - float terrain_base = NoisePerlin2DPosOffset(noise_terrain_base->np, + float terrain_base = NoisePerlin2DPosOffset(&noise_terrain_base->np, p.X, 0.5, p.Y, 0.5, seed); - float terrain_higher = NoisePerlin2DPosOffset(noise_terrain_higher->np, + float terrain_higher = NoisePerlin2DPosOffset(&noise_terrain_higher->np, p.X, 0.5, p.Y, 0.5, seed); - float steepness = NoisePerlin2DPosOffset(noise_steepness->np, + float steepness = NoisePerlin2DPosOffset(&noise_steepness->np, p.X, 0.5, p.Y, 0.5, seed); - float height_select = NoisePerlin2DNoTxfmPosOffset(noise_height_select->np, + float height_select = NoisePerlin2DNoTxfmPosOffset(&noise_height_select->np, p.X, 0.5, p.Y, 0.5, seed); return baseTerrainLevel(terrain_base, terrain_higher, @@ -550,37 +550,37 @@ void MapgenV6::calculateNoise() { // Need to adjust for the original implementation's +.5 offset... if (!(flags & MG_FLAT)) { noise_terrain_base->perlinMap2D( - x + 0.5 * noise_terrain_base->np->spread.X, - z + 0.5 * noise_terrain_base->np->spread.Z); + x + 0.5 * noise_terrain_base->np.spread.X, + z + 0.5 * noise_terrain_base->np.spread.Z); noise_terrain_base->transformNoiseMap(); noise_terrain_higher->perlinMap2D( - x + 0.5 * noise_terrain_higher->np->spread.X, - z + 0.5 * noise_terrain_higher->np->spread.Z); + x + 0.5 * noise_terrain_higher->np.spread.X, + z + 0.5 * noise_terrain_higher->np.spread.Z); noise_terrain_higher->transformNoiseMap(); noise_steepness->perlinMap2D( - x + 0.5 * noise_steepness->np->spread.X, - z + 0.5 * noise_steepness->np->spread.Z); + x + 0.5 * noise_steepness->np.spread.X, + z + 0.5 * noise_steepness->np.spread.Z); noise_steepness->transformNoiseMap(); noise_height_select->perlinMap2D( - x + 0.5 * noise_height_select->np->spread.X, - z + 0.5 * noise_height_select->np->spread.Z); + x + 0.5 * noise_height_select->np.spread.X, + z + 0.5 * noise_height_select->np.spread.Z); noise_mud->perlinMap2D( - x + 0.5 * noise_mud->np->spread.X, - z + 0.5 * noise_mud->np->spread.Z); + x + 0.5 * noise_mud->np.spread.X, + z + 0.5 * noise_mud->np.spread.Z); noise_mud->transformNoiseMap(); } noise_beach->perlinMap2D( - x + 0.2 * noise_beach->np->spread.X, - z + 0.7 * noise_beach->np->spread.Z); + x + 0.2 * noise_beach->np.spread.X, + z + 0.7 * noise_beach->np.spread.Z); noise_biome->perlinMap2D( - x + 0.6 * noise_biome->np->spread.X, - z + 0.2 * noise_biome->np->spread.Z); + x + 0.6 * noise_biome->np.spread.X, + z + 0.2 * noise_biome->np.spread.Z); } diff --git a/src/mapgen_v7.cpp b/src/mapgen_v7.cpp index 739efadd8..be60a2c98 100644 --- a/src/mapgen_v7.cpp +++ b/src/mapgen_v7.cpp @@ -173,7 +173,7 @@ int MapgenV7::getGroundLevelAtPoint(v2s16 p) { // Ridge/river terrain calculation float width = 0.3; - float uwatern = NoisePerlin2DNoTxfm(noise_ridge_uwater->np, p.X, p.Y, seed) * 2; + float uwatern = NoisePerlin2DNoTxfm(&noise_ridge_uwater->np, p.X, p.Y, seed) * 2; // actually computing the depth of the ridge is much more expensive; // if inside a river, simply guess if (uwatern >= -width && uwatern <= width) @@ -305,8 +305,8 @@ void MapgenV7::calculateNoise() { Biome *MapgenV7::getBiomeAtPoint(v3s16 p) { - float heat = NoisePerlin2D(noise_heat->np, p.X, p.Z, seed); - float humidity = NoisePerlin2D(noise_humidity->np, p.X, p.Z, seed); + float heat = NoisePerlin2D(&noise_heat->np, p.X, p.Z, seed); + float humidity = NoisePerlin2D(&noise_humidity->np, p.X, p.Z, seed); s16 groundlevel = baseTerrainLevelAtPoint(p.X, p.Z); return bmgr->getBiome(heat, humidity, groundlevel); @@ -314,17 +314,17 @@ Biome *MapgenV7::getBiomeAtPoint(v3s16 p) { //needs to be updated float MapgenV7::baseTerrainLevelAtPoint(int x, int z) { - float hselect = NoisePerlin2D(noise_height_select->np, x, z, seed); + float hselect = NoisePerlin2D(&noise_height_select->np, x, z, seed); hselect = rangelim(hselect, 0.0, 1.0); - float persist = NoisePerlin2D(noise_terrain_persist->np, x, z, seed); + float persist = NoisePerlin2D(&noise_terrain_persist->np, x, z, seed); persist = rangelim(persist, 0.4, 0.9); - noise_terrain_base->np->persist = persist; - float height_base = NoisePerlin2D(noise_terrain_base->np, x, z, seed); + noise_terrain_base->np.persist = persist; + float height_base = NoisePerlin2D(&noise_terrain_base->np, x, z, seed); - noise_terrain_alt->np->persist = persist; - float height_alt = NoisePerlin2D(noise_terrain_alt->np, x, z, seed); + noise_terrain_alt->np.persist = persist; + float height_alt = NoisePerlin2D(&noise_terrain_alt->np, x, z, seed); if (height_alt > height_base) return height_alt; @@ -346,9 +346,9 @@ float MapgenV7::baseTerrainLevelFromMap(int index) { bool MapgenV7::getMountainTerrainAtPoint(int x, int y, int z) { - float mnt_h_n = NoisePerlin2D(noise_mount_height->np, x, z, seed); + float mnt_h_n = NoisePerlin2D(&noise_mount_height->np, x, z, seed); float height_modifier = -((float)y / rangelim(mnt_h_n, 80.0, 150.0)); - float mnt_n = NoisePerlin3D(noise_mountain->np, x, y, z, seed); + float mnt_n = NoisePerlin3D(&noise_mountain->np, x, y, z, seed); return mnt_n + height_modifier >= 0.6; } @@ -373,10 +373,10 @@ void MapgenV7::carveRivers() { for (s16 x = node_min.X; x <= node_max.X; x++, index++) { float terrain_mod = noise_terrain_mod->result[index]; NoiseParams *np = noise_terrain_river->np; - np->persist = noise_terrain_persist->result[index]; + np.persist = noise_terrain_persist->result[index]; float terrain_river = NoisePerlin2DNoTxfm(np, x, z, seed); float height = terrain_river * (1 - abs(terrain_mod)) * - noise_terrain_river->np->scale; + noise_terrain_river->np.scale; height = log(height * height); //log(h^3) is pretty interesting for terrain s16 y = heightmap[index]; diff --git a/src/mg_ore.cpp b/src/mg_ore.cpp index 80e86130a..1aac59ddb 100644 --- a/src/mg_ore.cpp +++ b/src/mg_ore.cpp @@ -56,19 +56,6 @@ size_t OreManager::placeAllOres(Mapgen *mg, u32 seed, v3s16 nmin, v3s16 nmax) /////////////////////////////////////////////////////////////////////////////// -Ore::Ore() -{ - c_ore = CONTENT_IGNORE; - np = NULL; - noise = NULL; -} - -Ore::~Ore() -{ - delete np; - delete noise; -} - size_t Ore::placeOre(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax) { @@ -117,7 +104,8 @@ void OreScatter::generate(ManualMapVoxelManipulator *vm, int seed, int y0 = pr.range(nmin.Y, nmax.Y - csize + 1); int z0 = pr.range(nmin.Z, nmax.Z - csize + 1); - if (np && (NoisePerlin3D(np, x0, y0, z0, seed) < nthresh)) + if ((flags & OREFLAG_USE_NOISE) && + (NoisePerlin3D(&np, x0, y0, z0, seed) < nthresh)) continue; for (int z1 = 0; z1 != csize; z1++) @@ -148,7 +136,7 @@ void OreSheet::generate(ManualMapVoxelManipulator *vm, int seed, if (!noise) { int sx = nmax.X - nmin.X + 1; int sz = nmax.Z - nmin.Z + 1; - noise = new Noise(np, 0, sx, sz); + noise = new Noise(&np, seed, sx, sz); } noise->seed = seed + y_start; noise->perlinMap2D(nmin.X, nmin.Z); @@ -161,7 +149,7 @@ void OreSheet::generate(ManualMapVoxelManipulator *vm, int seed, continue; int height = max_height * (1. / pr.range(1, 3)); - int y0 = y_start + np->scale * noiseval; //pr.range(1, 3) - 1; + int y0 = y_start + np.scale * noiseval; //pr.range(1, 3) - 1; int y1 = y0 + height; for (int y = y0; y != y1; y++) { u32 i = vm->m_area.index(x, y, z); diff --git a/src/mg_ore.h b/src/mg_ore.h index 16fb50cd5..f3a565050 100644 --- a/src/mg_ore.h +++ b/src/mg_ore.h @@ -40,6 +40,8 @@ class ManualMapVoxelManipulator; // nodes isn't the specified node #define OREFLAG_NODEISNT 0x04 // not yet implemented +#define OREFLAG_USE_NOISE 0x08 + #define ORE_RANGE_ACTUAL 1 #define ORE_RANGE_MIRROR 2 @@ -54,6 +56,8 @@ extern FlagDesc flagdesc_ore[]; class Ore : public GenElement { public: + static const bool NEEDS_NOISE = false; + content_t c_ore; // the node to place std::vector c_wherein; // the nodes to be placed in u32 clust_scarcity; // ore cluster has a 1-in-clust_scarcity chance of appearing at a node @@ -64,25 +68,26 @@ public: u8 ore_param2; // to set node-specific attributes u32 flags; // attributes for this ore float nthresh; // threshhold for noise at which an ore is placed - NoiseParams *np; // noise for distribution of clusters (NULL for uniform scattering) + NoiseParams np; // noise for distribution of clusters (NULL for uniform scattering) Noise *noise; - Ore(); - virtual ~Ore(); - size_t placeOre(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax); virtual void generate(ManualMapVoxelManipulator *vm, int seed, u32 blockseed, v3s16 nmin, v3s16 nmax) = 0; }; class OreScatter : public Ore { - virtual ~OreScatter() {} +public: + static const bool NEEDS_NOISE = false; + virtual void generate(ManualMapVoxelManipulator *vm, int seed, u32 blockseed, v3s16 nmin, v3s16 nmax); }; class OreSheet : public Ore { - virtual ~OreSheet() {} +public: + static const bool NEEDS_NOISE = true; + virtual void generate(ManualMapVoxelManipulator *vm, int seed, u32 blockseed, v3s16 nmin, v3s16 nmax); }; diff --git a/src/noise.cpp b/src/noise.cpp index 57938bd06..0d8b118aa 100644 --- a/src/noise.cpp +++ b/src/noise.cpp @@ -317,9 +317,9 @@ float contour(float v) ///////////////////////// [ New perlin stuff ] //////////////////////////// -Noise::Noise(NoiseParams *np, int seed, int sx, int sy, int sz) +Noise::Noise(NoiseParams *np_, int seed, int sx, int sy, int sz) { - this->np = np; + memcpy(&np, np_, sizeof(np)); this->seed = seed; this->sx = sx; this->sy = sy; @@ -329,10 +329,10 @@ Noise::Noise(NoiseParams *np, int seed, int sx, int sy, int sz) this->gradient_buf = NULL; this->result = NULL; - if (np->flags & NOISE_FLAG_DEFAULTS) { + if (np.flags & NOISE_FLAG_DEFAULTS) { // By default, only 2d noise is eased. if (sz <= 1) - np->flags |= NOISE_FLAG_EASED; + np.flags |= NOISE_FLAG_EASED; } allocBuffers(); @@ -380,7 +380,7 @@ void Noise::setSize(int sx, int sy, int sz) void Noise::setSpreadFactor(v3f spread) { - this->np->spread = spread; + this->np.spread = spread; resizeNoiseBuf(sz > 1); } @@ -388,7 +388,7 @@ void Noise::setSpreadFactor(v3f spread) void Noise::setOctaves(int octaves) { - this->np->octaves = octaves; + this->np.octaves = octaves; resizeNoiseBuf(sz > 1); } @@ -400,15 +400,15 @@ void Noise::resizeNoiseBuf(bool is3d) float ofactor; //maximum possible spread value factor - ofactor = pow(np->lacunarity, np->octaves - 1); + ofactor = pow(np.lacunarity, np.octaves - 1); //noise lattice point count //(int)(sz * spread * ofactor) is # of lattice points crossed due to length // + 2 for the two initial endpoints // + 1 for potentially crossing a boundary due to offset - nlx = (int)ceil(sx * ofactor / np->spread.X) + 3; - nly = (int)ceil(sy * ofactor / np->spread.Y) + 3; - nlz = is3d ? (int)ceil(sz * ofactor / np->spread.Z) + 3 : 1; + nlx = (int)ceil(sx * ofactor / np.spread.X) + 3; + nly = (int)ceil(sy * ofactor / np.spread.Y) + 3; + nlz = is3d ? (int)ceil(sz * ofactor / np.spread.Z) + 3 : 1; delete[] noise_buf; try { @@ -440,7 +440,7 @@ void Noise::gradientMap2D( int index, i, j, x0, y0, noisex, noisey; int nlx, nly; - Interp2dFxn interpolate = (np->flags & NOISE_FLAG_EASED) ? + Interp2dFxn interpolate = (np.flags & NOISE_FLAG_EASED) ? biLinearInterpolation : biLinearInterpolationNoEase; x0 = floor(x); @@ -504,7 +504,7 @@ void Noise::gradientMap3D( int index, i, j, k, x0, y0, z0, noisex, noisey, noisez; int nlx, nly, nlz; - Interp3dFxn interpolate = (np->flags & NOISE_FLAG_EASED) ? + Interp3dFxn interpolate = (np.flags & NOISE_FLAG_EASED) ? triLinearInterpolation : triLinearInterpolationNoEase; x0 = floor(x); @@ -588,8 +588,8 @@ float *Noise::perlinMap2D(float x, float y, float *persistence_map) float f = 1.0, g = 1.0; size_t bufsize = sx * sy; - x /= np->spread.X; - y /= np->spread.Y; + x /= np.spread.X; + y /= np.spread.Y; memset(result, 0, sizeof(float) * bufsize); @@ -600,15 +600,15 @@ float *Noise::perlinMap2D(float x, float y, float *persistence_map) persist_buf[i] = 1.0; } - for (size_t oct = 0; oct < np->octaves; oct++) { + for (size_t oct = 0; oct < np.octaves; oct++) { gradientMap2D(x * f, y * f, - f / np->spread.X, f / np->spread.Y, - seed + np->seed + oct); + f / np.spread.X, f / np.spread.Y, + seed + np.seed + oct); updateResults(g, persist_buf, persistence_map, bufsize); - f *= np->lacunarity; - g *= np->persist; + f *= np.lacunarity; + g *= np.persist; } return result; @@ -620,9 +620,9 @@ float *Noise::perlinMap3D(float x, float y, float z, float *persistence_map) float f = 1.0, g = 1.0; size_t bufsize = sx * sy * sz; - x /= np->spread.X; - y /= np->spread.Y; - z /= np->spread.Z; + x /= np.spread.X; + y /= np.spread.Y; + z /= np.spread.Z; memset(result, 0, sizeof(float) * bufsize); @@ -633,15 +633,15 @@ float *Noise::perlinMap3D(float x, float y, float z, float *persistence_map) persist_buf[i] = 1.0; } - for (size_t oct = 0; oct < np->octaves; oct++) { + for (size_t oct = 0; oct < np.octaves; oct++) { gradientMap3D(x * f, y * f, z * f, - f / np->spread.X, f / np->spread.Y, f / np->spread.Z, - seed + np->seed + oct); + f / np.spread.X, f / np.spread.Y, f / np.spread.Z, + seed + np.seed + oct); updateResults(g, persist_buf, persistence_map, bufsize); - f *= np->lacunarity; - g *= np->persist; + f *= np.lacunarity; + g *= np.persist; } return result; @@ -653,7 +653,7 @@ void Noise::updateResults(float g, float *gmap, { // This looks very ugly, but it is 50-70% faster than having // conditional statements inside the loop - if (np->flags & NOISE_FLAG_ABSVALUE) { + if (np.flags & NOISE_FLAG_ABSVALUE) { if (persistence_map) { for (size_t i = 0; i != bufsize; i++) { result[i] += gmap[i] * fabs(gradient_buf[i]); @@ -685,6 +685,6 @@ void Noise::transformNoiseMap() // slowdown even with -O2. To prevent this, store the value in a local. size_t bufsize = sx * sy * sz; for (size_t i = 0; i != bufsize; i++) - result[i] = result[i] * np->scale + np->offset; + result[i] = result[i] * np.scale + np.offset; } diff --git a/src/noise.h b/src/noise.h index a7212a298..66be8db93 100644 --- a/src/noise.h +++ b/src/noise.h @@ -122,7 +122,7 @@ struct NoiseParams { class Noise { public: - NoiseParams *np; + NoiseParams np; int seed; int sx; int sy; diff --git a/src/script/lua_api/l_mapgen.cpp b/src/script/lua_api/l_mapgen.cpp index 0e3d219a4..3176b920c 100644 --- a/src/script/lua_api/l_mapgen.cpp +++ b/src/script/lua_api/l_mapgen.cpp @@ -546,7 +546,14 @@ int ModApiMapgen::l_register_ore(lua_State *L) getflagsfield(L, index, "flags", flagdesc_ore, &ore->flags, NULL); lua_getfield(L, index, "noise_params"); - ore->np = get_noiseparams(L, -1); + if (read_noiseparams(L, -1, &ore->np)) { + ore->flags |= OREFLAG_USE_NOISE; + } else if (ore->NEEDS_NOISE) { + errorstream << "register_ore: specified ore type requires valid " + "noise parameters" << std::endl; + delete ore; + return 0; + } lua_pop(L, 1); u32 id = oremgr->add(ore); diff --git a/src/script/lua_api/l_noise.cpp b/src/script/lua_api/l_noise.cpp index 2a57df0f6..c66f54e6f 100644 --- a/src/script/lua_api/l_noise.cpp +++ b/src/script/lua_api/l_noise.cpp @@ -161,7 +161,7 @@ int LuaPerlinNoiseMap::l_get2dMap(lua_State *L) for (int y = 0; y != n->sy; y++) { lua_newtable(L); for (int x = 0; x != n->sx; x++) { - float noiseval = n->np->offset + n->np->scale * n->result[i++]; + float noiseval = n->np.offset + n->np.scale * n->result[i++]; lua_pushnumber(L, noiseval); lua_rawseti(L, -2, x + 1); } @@ -185,7 +185,7 @@ int LuaPerlinNoiseMap::l_get2dMap_flat(lua_State *L) lua_newtable(L); for (int i = 0; i != maplen; i++) { - float noiseval = n->np->offset + n->np->scale * n->result[i]; + float noiseval = n->np.offset + n->np.scale * n->result[i]; lua_pushnumber(L, noiseval); lua_rawseti(L, -2, i + 1); } @@ -210,7 +210,7 @@ int LuaPerlinNoiseMap::l_get3dMap(lua_State *L) for (int y = 0; y != n->sy; y++) { lua_newtable(L); for (int x = 0; x != n->sx; x++) { - lua_pushnumber(L, n->np->offset + n->np->scale * n->result[i++]); + lua_pushnumber(L, n->np.offset + n->np.scale * n->result[i++]); lua_rawseti(L, -2, x + 1); } lua_rawseti(L, -2, y + 1); @@ -236,7 +236,7 @@ int LuaPerlinNoiseMap::l_get3dMap_flat(lua_State *L) lua_newtable(L); for (int i = 0; i != maplen; i++) { - float noiseval = n->np->offset + n->np->scale * n->result[i]; + float noiseval = n->np.offset + n->np.scale * n->result[i]; lua_pushnumber(L, noiseval); lua_rawseti(L, -2, i + 1); }