From 75b8c13b0042678a909becbde8f1f82400f2d8ac Mon Sep 17 00:00:00 2001 From: proller Date: Sun, 23 Jun 2013 18:07:10 +0400 Subject: [PATCH] New math mapgen with fractal based worlds --- minetest.conf.example | 5 +- src/CMakeLists.txt | 1 + src/defaultsettings.cpp | 4 +- src/emerge.cpp | 2 + src/mapgen_math.cpp | 366 ++++++++++++++++++++++++++++++++++++++++ src/mapgen_math.h | 70 ++++++++ src/mapgen_v7.h | 4 +- 7 files changed, 448 insertions(+), 4 deletions(-) create mode 100644 src/mapgen_math.cpp create mode 100644 src/mapgen_math.h diff --git a/minetest.conf.example b/minetest.conf.example index 8ec65403d..07063b913 100644 --- a/minetest.conf.example +++ b/minetest.conf.example @@ -325,7 +325,7 @@ # Mapgen stuff # -# Name of map generator to be used. Currently v6, indev and singlenode are supported. +# Name of map generator to be used. Currently supported: v6, indev, singlenode, math #mg_name = v6 # Water level of map. #water_level = 1 @@ -368,6 +368,9 @@ # Float islands starts from height, 0 to disable #mgindev_float_islands = 500 +# Math mapgen generator: sphere, mandelbox, mengersponge dont forget to lower water_level = -30000 +#mgmath_generator = mandelbox + # Enable/disable IPv6 #enable_ipv6 = true # Enable/disable running an IPv6 server. An IPv6 server may be restricted diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 51ed27837..bcd265858 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -233,6 +233,7 @@ set(common_SRCS mapgen_v7.cpp mapgen_indev.cpp mapgen_singlenode.cpp + mapgen_math.cpp treegen.cpp dungeongen.cpp cavegen.cpp diff --git a/src/defaultsettings.cpp b/src/defaultsettings.cpp index 2802d33f5..501a04f51 100644 --- a/src/defaultsettings.cpp +++ b/src/defaultsettings.cpp @@ -251,7 +251,9 @@ void set_default_settings(Settings *settings) settings->setDefault("mgindev_np_float_islands3", "0, 1, (256, 256, 256), 6412, 2, 0.5, 1, 0.5"); settings->setDefault("mgindev_np_biome", "0, 1, (250, 250, 250), 9130, 3, 0.50, 1, 10"); settings->setDefault("mgindev_float_islands", "500"); - + + settings->setDefault("mgmath_generator", "mandelbox"); + // IPv6 settings->setDefault("enable_ipv6", "true"); settings->setDefault("ipv6_server", "false"); diff --git a/src/emerge.cpp b/src/emerge.cpp index 9edc42b7b..aed9af7b5 100644 --- a/src/emerge.cpp +++ b/src/emerge.cpp @@ -42,6 +42,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "mapgen_v7.h" #include "mapgen_indev.h" #include "mapgen_singlenode.h" +#include "mapgen_math.h" /////////////////////////////// Emerge Manager //////////////////////////////// @@ -52,6 +53,7 @@ EmergeManager::EmergeManager(IGameDef *gamedef) { registerMapgen("v7", new MapgenFactoryV7()); registerMapgen("indev", new MapgenFactoryIndev()); registerMapgen("singlenode", new MapgenFactorySinglenode()); + registerMapgen("math", new MapgenFactoryMath()); this->ndef = gamedef->getNodeDefManager(); this->biomedef = new BiomeDefManager(); diff --git a/src/mapgen_math.cpp b/src/mapgen_math.cpp new file mode 100644 index 000000000..775d0523d --- /dev/null +++ b/src/mapgen_math.cpp @@ -0,0 +1,366 @@ +/* +Minetest +Copyright (C) 2010-2013 celeron55, Perttu Ahola + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation; either version 2.1 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include +#include "mapgen_math.h" +#include "voxel.h" +#include "mapblock.h" +#include "mapnode.h" +#include "map.h" +#include "nodedef.h" +#include "voxelalgorithms.h" +#include "profiler.h" +#include "settings.h" // For g_settings +#include "main.h" // For g_profiler +#include "emerge.h" +#include "biome.h" + +// can use ported lib from http://mandelbulber.googlecode.com/svn/trunk/src +//#include "mandelbulber/fractal.h" +//#include "mandelbulber/fractal.cpp" + +double mandelbox(double x, double y, double z, double d, int nn = 10) { + int s = 7; + x *= s; + y *= s; + z *= s; + d *= s; + + double posX = x; + double posY = y; + double posZ = z; + + double dr = 1.0; + double r = 0.0; + + double scale = 2; + + double minRadius2 = 0.25; + double fixedRadius2 = 1; + + for (int n = 0; n < nn; n++) { + // Reflect + if (x > 1.0) + x = 2.0 - x; + else if (x < -1.0) + x = -2.0 - x; + if (y > 1.0) + y = 2.0 - y; + else if (y < -1.0) + y = -2.0 - y; + if (z > 1.0) + z = 2.0 - z; + else if (z < -1.0) + z = -2.0 - z; + + // Sphere Inversion + double r2 = x * x + y * y + z * z; + + if (r2 < minRadius2) { + x = x * fixedRadius2 / minRadius2; + y = y * fixedRadius2 / minRadius2; + z = z * fixedRadius2 / minRadius2; + dr = dr * fixedRadius2 / minRadius2; + } else if (r2 < fixedRadius2) { + x = x * fixedRadius2 / r2; + y = y * fixedRadius2 / r2; + z = z * fixedRadius2 / r2; + fixedRadius2 *= fixedRadius2 / r2; + } + + x = x * scale + posX; + y = y * scale + posY; + z = z * scale + posZ; + dr *= scale; + } + r = sqrt(x * x + y * y + z * z); + return ((r / fabs(dr)) < d); + +} + +double mengersponge(double x, double y, double z, double d, int MI = 10) { + + double r = x * x + y * y + z * z; + double scale = 3; + int i = 0; + + + for (i = 0; i < MI && r < 9; i++) { + + + x = fabs(x); + y = fabs(y); + z = fabs(z); + + + if (x - y < 0) { + double x1 = y; + y = x; + x = x1; + } + if (x - z < 0) { + double x1 = z; + z = x; + x = x1; + } + if (y - z < 0) { + double y1 = z; + z = y; + y = y1; + } + + + x = scale * x - 1 * (scale - 1); + y = scale * y - 1 * (scale - 1); + z = scale * z; + + + if (z > 0.5 * 1 * (scale - 1)) + z -= 1 * (scale - 1); + + + r = x * x + y * y + z * z; + } + return ((sqrt(r)) * pow(scale, (-i)) < d); +} + +double sphere(double x, double y, double z, double d, int ITR = 1) { + return v3f(x, y, z).getLength() < d; +} + + +//////////////////////// Mapgen Singlenode parameter read/write + +bool MapgenMathParams::readParams(Settings *settings) { + //params = settings->getJson("mg_math"); + // can be counfigured from here. + std::string value = "{}"; + Json::Reader reader; + if (!reader.parse( value, params ) ) { + errorstream << "Failed to parse json conf var ='" << value << "' : " << reader.getFormattedErrorMessages(); + } + + if (params["generator"].empty()) params["generator"] = settings->get("mgmath_generator"); + + return true; +} + + +void MapgenMathParams::writeParams(Settings *settings) { + //settings->setJson("mg_math", params); + settings->set("mgmath_generator", params["generator"].asString()); +} + +/////////////////////////////////////////////////////////////////////////////// + +MapgenMath::MapgenMath(int mapgenid, MapgenMathParams *params_, EmergeManager *emerge) : MapgenV7(mapgenid, params_, emerge) { + mg_params = params_; + + Json::Value & params = mg_params->params; + invert = params["invert"].empty() ? 1 : params["invert"].asBool(); //params["invert"].empty()?1:params["invert"].asBool(); + size = params["size"].empty() ? 0 : params["size"].asDouble(); // = max_r + scale = params["scale"].empty() ? 0 : params["scale"].asDouble(); //(double)1 / size; + if(!params["center"].empty()) center = v3f(params["center"]["x"].asFloat(), params["center"]["y"].asFloat(), params["center"]["z"].asFloat()); //v3f(5, -size - 5, 5); + iterations = params["iterations"].empty() ? 0 : params["iterations"].asInt(); //10; + distance = params["distance"].empty() ? 0 : params["distance"].asDouble(); // = 1/size; + + func = &sphere; + + if (params["generator"].empty()) params["generator"] = "mandelbox"; + if (params["generator"].asString() == "mengersponge") { + if (!size) size = (MAP_GENERATION_LIMIT - 1000) / 2; + if (!iterations) iterations = 10; + if (!distance) distance = 0.0003; + //if (!scale) scale = (double)0.1 / size; + //if (!distance) distance = 0.01; //10/size;//sqrt3 * bd4; + //if (!scale) scale = 0.01; //10/size;//sqrt3 * bd4; + //center=v3f(-size/3,-size/3+(-2*-invert),2); + center = v3f(-size, -size, -size); + func = &mengersponge; + } else if (params["generator"].asString() == "mandelbox") { + /* + size = MAP_GENERATION_LIMIT - 1000; + //size = 1000; + distance = 0.01; //100/size; //0.01; + iterations = 10; + center = v3f(1, 1, 1); // *size/6; + */ + + //mandelbox + if (!size) size = 1000; + if (!distance) distance = 0.01; + if(params["invert"].empty()) invert = 0; + //center=v3f(2,-size/4,2); + //size = 10000; + //center=v3f(size/2,-size*0.9,size/2); + if(params["center"].empty())center = v3f(size * 0.3, -size * 0.6, size * 0.5); + func = &mandelbox; + } else if (params["generator"].asString() == "sphere") { + if(params["invert"].empty()) invert = 0; + if (!size) size = 100; + if (!distance) distance = size; + func = &sphere; + if (!scale) scale = 1; + //sphere + //size = 1000;scale = 1;center = v3f(2,-size-2,2); + } + + if (!iterations) iterations = 10; + if (!size) size = 1000; + if (!scale) scale = (double)1 / size; + if (!distance) distance = scale; + if (params["center"].empty() && !center.getLength()) center = v3f(3, -size + (-5 - (-invert * 10)), 3); + //size ||= params["size"].empty()?1000:params["size"].asDouble(); // = max_r + +} + + +MapgenMath::~MapgenMath() { +} + +//////////////////////// Map generator + +void MapgenMath::generateTerrain() { + + MapNode n_air(CONTENT_AIR), n_water_source(c_water_source, LIGHT_SUN); + MapNode n_stone(c_stone, LIGHT_SUN); + u32 index = 0; + v3s16 em = vm->m_area.getExtent(); + +#if 1 + + /* debug + v3f vec0 = (v3f(node_min.X, node_min.Y, node_min.Z) - center) * scale ; + errorstream << " X=" << node_min.X << " Y=" << node_min.Y << " Z=" << node_min.Z + //<< " N="<< mengersponge(vec0.X, vec0.Y, vec0.Z, distance, iterations) + << " N=" << (*func)(vec0.X, vec0.Y, vec0.Z, distance, iterations) + << " Sc=" << scale << " gen=" << params["generator"].asString() << " J=" << Json::FastWriter().write(params) << std::endl; + */ + for (s16 z = node_min.Z; z <= node_max.Z; z++) { + for (s16 x = node_min.X; x <= node_max.X; x++, index++) { + Biome *biome = bmgr->biomes[biomemap[index]]; + u32 i = vm->m_area.index(x, node_min.Y, z); + for (s16 y = node_min.Y; y <= node_max.Y; y++) { + v3f vec = (v3f(x, y, z) - center) * scale ; + double d = (*func)(vec.X, vec.Y, vec.Z, distance, iterations); + if ((!invert && d > 0) || (invert && d == 0) ) { + if (vm->m_data[i].getContent() == CONTENT_IGNORE) + vm->m_data[i] = (y > water_level + biome->filler_height) ? + MapNode(biome->c_filler) : n_stone; + } else if (y <= water_level) { + vm->m_data[i] = n_water_source; + } else { + vm->m_data[i] = n_air; + } + vm->m_area.add_y(em, i, 1); + } + } + } +#endif + + +#if 0 +// mandelbulber, unfinished but works + sFractal par; + par.doubles.N = 10; + + par.doubles.power = 9.0; + par.doubles.foldingSphericalFixed = 1.0; + par.doubles.foldingSphericalMin = 0.5; + //no par.formula = smoothMandelbox; par.doubles.N = 40; invert = 0;//no + par.mandelbox.doubles.sharpness = 3.0; + par.mandelbox.doubles.scale = 1; + par.mandelbox.doubles.sharpness = 2; + par.mandelbox.doubles.foldingLimit = 1.0; + par.mandelbox.doubles.foldingValue = 2; + +//ok par.formula = mandelboxVaryScale4D; par.doubles.N = 50; scale = 5; invert = 1; //ok + par.mandelbox.doubles.vary4D.scaleVary = 0.1; + par.mandelbox.doubles.vary4D.fold = 1; + par.mandelbox.doubles.vary4D.rPower = 1; + par.mandelbox.doubles.vary4D.minR = 0.5; + par.mandelbox.doubles.vary4D.wadd = 0; + par.doubles.constantFactor = 1.0; + + par.formula = menger_sponge; par.doubles.N = 15; invert = 0; size = 30000; center = v3f(-size / 2, -size + (-2 * -invert), 2); scale = (double)1 / size; //ok + + //double tresh = 1.5; + //par.formula = mandelbulb2; par.doubles.N = 10; scale = (double)1/size; invert=1; center = v3f(5,-size-5,0); //ok + //par.formula = hypercomplex; par.doubles.N = 20; scale = 0.0001; invert=1; center = v3f(0,-10001,0); //(double)50 / max_r; + + //no par.formula = trig_DE; par.doubles.N = 5; scale = (double)10; invert=1; + + //no par.formula = trig_optim; scale = (double)10; par.doubles.N = 4; + + //par.formula = mandelbulb2; scale = (double)1/10000; par.doubles.N = 10; invert = 1; center = v3f(1,-4201,1); //ok + // no par.formula = tglad; + + //par.formula = xenodreambuie; par.juliaMode = 1; par.doubles.julia.x = -1; par.doubles.power = 2.0; center=v3f(-size/2,-size/2-5,5); //ok + + par.mandelbox.doubles.vary4D.scaleVary = 0.1; + par.mandelbox.doubles.vary4D.fold = 1; + par.mandelbox.doubles.vary4D.minR = 0.5; + par.mandelbox.doubles.vary4D.rPower = 1; + par.mandelbox.doubles.vary4D.wadd = 0; + //no par.formula = mandelboxVaryScale4D; + par.doubles.cadd = -1.3; + //par.formula = aexion; // ok but center + //par.formula = benesi; par.doubles.N = 10; center = v3f(0,0,0); invert = 0; //ok + + // par.formula = bristorbrot; //ok + + v3f vec0(node_min.X, node_min.Y, node_min.Z); + vec0 = (vec0 - center) * scale ; + errorstream << " X=" << node_min.X << " Y=" << node_min.Y << " Z=" << node_min.Z + << " N=" << Compute(CVector3(vec0.X, vec0.Y, vec0.Z), par) + //<<" F="<< Compute(CVector3(node_min.X,node_min.Y,node_min.Z), par) + //<<" L="<