|
| 1 | +/* |
| 2 | +Minetest |
| 3 | +Copyright (C) 2010-2013 celeron55, Perttu Ahola <celeron55@gmail.com> |
| 4 | +
|
| 5 | +This program is free software; you can redistribute it and/or modify |
| 6 | +it under the terms of the GNU Lesser General Public License as published by |
| 7 | +the Free Software Foundation; either version 2.1 of the License, or |
| 8 | +(at your option) any later version. |
| 9 | +
|
| 10 | +This program is distributed in the hope that it will be useful, |
| 11 | +but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 12 | +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 13 | +GNU Lesser General Public License for more details. |
| 14 | +
|
| 15 | +You should have received a copy of the GNU Lesser General Public License along |
| 16 | +with this program; if not, write to the Free Software Foundation, Inc., |
| 17 | +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
| 18 | +*/ |
| 19 | + |
| 20 | +#include <cmath> |
| 21 | +#include "mapgen_math.h" |
| 22 | +#include "voxel.h" |
| 23 | +#include "mapblock.h" |
| 24 | +#include "mapnode.h" |
| 25 | +#include "map.h" |
| 26 | +#include "nodedef.h" |
| 27 | +#include "voxelalgorithms.h" |
| 28 | +#include "profiler.h" |
| 29 | +#include "settings.h" // For g_settings |
| 30 | +#include "main.h" // For g_profiler |
| 31 | +#include "emerge.h" |
| 32 | +#include "biome.h" |
| 33 | + |
| 34 | +// can use ported lib from http://mandelbulber.googlecode.com/svn/trunk/src |
| 35 | +//#include "mandelbulber/fractal.h" |
| 36 | +//#include "mandelbulber/fractal.cpp" |
| 37 | + |
| 38 | +double mandelbox(double x, double y, double z, double d, int nn = 10) { |
| 39 | + int s = 7; |
| 40 | + x *= s; |
| 41 | + y *= s; |
| 42 | + z *= s; |
| 43 | + d *= s; |
| 44 | + |
| 45 | + double posX = x; |
| 46 | + double posY = y; |
| 47 | + double posZ = z; |
| 48 | + |
| 49 | + double dr = 1.0; |
| 50 | + double r = 0.0; |
| 51 | + |
| 52 | + double scale = 2; |
| 53 | + |
| 54 | + double minRadius2 = 0.25; |
| 55 | + double fixedRadius2 = 1; |
| 56 | + |
| 57 | + for (int n = 0; n < nn; n++) { |
| 58 | + // Reflect |
| 59 | + if (x > 1.0) |
| 60 | + x = 2.0 - x; |
| 61 | + else if (x < -1.0) |
| 62 | + x = -2.0 - x; |
| 63 | + if (y > 1.0) |
| 64 | + y = 2.0 - y; |
| 65 | + else if (y < -1.0) |
| 66 | + y = -2.0 - y; |
| 67 | + if (z > 1.0) |
| 68 | + z = 2.0 - z; |
| 69 | + else if (z < -1.0) |
| 70 | + z = -2.0 - z; |
| 71 | + |
| 72 | + // Sphere Inversion |
| 73 | + double r2 = x * x + y * y + z * z; |
| 74 | + |
| 75 | + if (r2 < minRadius2) { |
| 76 | + x = x * fixedRadius2 / minRadius2; |
| 77 | + y = y * fixedRadius2 / minRadius2; |
| 78 | + z = z * fixedRadius2 / minRadius2; |
| 79 | + dr = dr * fixedRadius2 / minRadius2; |
| 80 | + } else if (r2 < fixedRadius2) { |
| 81 | + x = x * fixedRadius2 / r2; |
| 82 | + y = y * fixedRadius2 / r2; |
| 83 | + z = z * fixedRadius2 / r2; |
| 84 | + fixedRadius2 *= fixedRadius2 / r2; |
| 85 | + } |
| 86 | + |
| 87 | + x = x * scale + posX; |
| 88 | + y = y * scale + posY; |
| 89 | + z = z * scale + posZ; |
| 90 | + dr *= scale; |
| 91 | + } |
| 92 | + r = sqrt(x * x + y * y + z * z); |
| 93 | + return ((r / fabs(dr)) < d); |
| 94 | + |
| 95 | +} |
| 96 | + |
| 97 | +double mengersponge(double x, double y, double z, double d, int MI = 10) { |
| 98 | + |
| 99 | + double r = x * x + y * y + z * z; |
| 100 | + double scale = 3; |
| 101 | + int i = 0; |
| 102 | + |
| 103 | + |
| 104 | + for (i = 0; i < MI && r < 9; i++) { |
| 105 | + |
| 106 | + |
| 107 | + x = fabs(x); |
| 108 | + y = fabs(y); |
| 109 | + z = fabs(z); |
| 110 | + |
| 111 | + |
| 112 | + if (x - y < 0) { |
| 113 | + double x1 = y; |
| 114 | + y = x; |
| 115 | + x = x1; |
| 116 | + } |
| 117 | + if (x - z < 0) { |
| 118 | + double x1 = z; |
| 119 | + z = x; |
| 120 | + x = x1; |
| 121 | + } |
| 122 | + if (y - z < 0) { |
| 123 | + double y1 = z; |
| 124 | + z = y; |
| 125 | + y = y1; |
| 126 | + } |
| 127 | + |
| 128 | + |
| 129 | + x = scale * x - 1 * (scale - 1); |
| 130 | + y = scale * y - 1 * (scale - 1); |
| 131 | + z = scale * z; |
| 132 | + |
| 133 | + |
| 134 | + if (z > 0.5 * 1 * (scale - 1)) |
| 135 | + z -= 1 * (scale - 1); |
| 136 | + |
| 137 | + |
| 138 | + r = x * x + y * y + z * z; |
| 139 | + } |
| 140 | + return ((sqrt(r)) * pow(scale, (-i)) < d); |
| 141 | +} |
| 142 | + |
| 143 | +double sphere(double x, double y, double z, double d, int ITR = 1) { |
| 144 | + return v3f(x, y, z).getLength() < d; |
| 145 | +} |
| 146 | + |
| 147 | + |
| 148 | +//////////////////////// Mapgen Singlenode parameter read/write |
| 149 | + |
| 150 | +bool MapgenMathParams::readParams(Settings *settings) { |
| 151 | + //params = settings->getJson("mg_math"); |
| 152 | + // can be counfigured from here. |
| 153 | + std::string value = "{}"; |
| 154 | + Json::Reader reader; |
| 155 | + if (!reader.parse( value, params ) ) { |
| 156 | + errorstream << "Failed to parse json conf var ='" << value << "' : " << reader.getFormattedErrorMessages(); |
| 157 | + } |
| 158 | + |
| 159 | + if (params["generator"].empty()) params["generator"] = settings->get("mgmath_generator"); |
| 160 | + |
| 161 | + return true; |
| 162 | +} |
| 163 | + |
| 164 | + |
| 165 | +void MapgenMathParams::writeParams(Settings *settings) { |
| 166 | + //settings->setJson("mg_math", params); |
| 167 | + settings->set("mgmath_generator", params["generator"].asString()); |
| 168 | +} |
| 169 | + |
| 170 | +/////////////////////////////////////////////////////////////////////////////// |
| 171 | + |
| 172 | +MapgenMath::MapgenMath(int mapgenid, MapgenMathParams *params_, EmergeManager *emerge) : MapgenV7(mapgenid, params_, emerge) { |
| 173 | + mg_params = params_; |
| 174 | + |
| 175 | + Json::Value & params = mg_params->params; |
| 176 | + invert = params["invert"].empty() ? 1 : params["invert"].asBool(); //params["invert"].empty()?1:params["invert"].asBool(); |
| 177 | + size = params["size"].empty() ? 0 : params["size"].asDouble(); // = max_r |
| 178 | + scale = params["scale"].empty() ? 0 : params["scale"].asDouble(); //(double)1 / size; |
| 179 | + if(!params["center"].empty()) center = v3f(params["center"]["x"].asFloat(), params["center"]["y"].asFloat(), params["center"]["z"].asFloat()); //v3f(5, -size - 5, 5); |
| 180 | + iterations = params["iterations"].empty() ? 0 : params["iterations"].asInt(); //10; |
| 181 | + distance = params["distance"].empty() ? 0 : params["distance"].asDouble(); // = 1/size; |
| 182 | + |
| 183 | + func = &sphere; |
| 184 | + |
| 185 | + if (params["generator"].empty()) params["generator"] = "mandelbox"; |
| 186 | + if (params["generator"].asString() == "mengersponge") { |
| 187 | + if (!size) size = (MAP_GENERATION_LIMIT - 1000) / 2; |
| 188 | + if (!iterations) iterations = 10; |
| 189 | + if (!distance) distance = 0.0003; |
| 190 | + //if (!scale) scale = (double)0.1 / size; |
| 191 | + //if (!distance) distance = 0.01; //10/size;//sqrt3 * bd4; |
| 192 | + //if (!scale) scale = 0.01; //10/size;//sqrt3 * bd4; |
| 193 | + //center=v3f(-size/3,-size/3+(-2*-invert),2); |
| 194 | + center = v3f(-size, -size, -size); |
| 195 | + func = &mengersponge; |
| 196 | + } else if (params["generator"].asString() == "mandelbox") { |
| 197 | + /* |
| 198 | + size = MAP_GENERATION_LIMIT - 1000; |
| 199 | + //size = 1000; |
| 200 | + distance = 0.01; //100/size; //0.01; |
| 201 | + iterations = 10; |
| 202 | + center = v3f(1, 1, 1); // *size/6; |
| 203 | + */ |
| 204 | + |
| 205 | + //mandelbox |
| 206 | + if (!size) size = 1000; |
| 207 | + if (!distance) distance = 0.01; |
| 208 | + if(params["invert"].empty()) invert = 0; |
| 209 | + //center=v3f(2,-size/4,2); |
| 210 | + //size = 10000; |
| 211 | + //center=v3f(size/2,-size*0.9,size/2); |
| 212 | + if(params["center"].empty())center = v3f(size * 0.3, -size * 0.6, size * 0.5); |
| 213 | + func = &mandelbox; |
| 214 | + } else if (params["generator"].asString() == "sphere") { |
| 215 | + if(params["invert"].empty()) invert = 0; |
| 216 | + if (!size) size = 100; |
| 217 | + if (!distance) distance = size; |
| 218 | + func = &sphere; |
| 219 | + if (!scale) scale = 1; |
| 220 | + //sphere |
| 221 | + //size = 1000;scale = 1;center = v3f(2,-size-2,2); |
| 222 | + } |
| 223 | + |
| 224 | + if (!iterations) iterations = 10; |
| 225 | + if (!size) size = 1000; |
| 226 | + if (!scale) scale = (double)1 / size; |
| 227 | + if (!distance) distance = scale; |
| 228 | + if (params["center"].empty() && !center.getLength()) center = v3f(3, -size + (-5 - (-invert * 10)), 3); |
| 229 | + //size ||= params["size"].empty()?1000:params["size"].asDouble(); // = max_r |
| 230 | + |
| 231 | +} |
| 232 | + |
| 233 | + |
| 234 | +MapgenMath::~MapgenMath() { |
| 235 | +} |
| 236 | + |
| 237 | +//////////////////////// Map generator |
| 238 | + |
| 239 | +void MapgenMath::generateTerrain() { |
| 240 | + |
| 241 | + MapNode n_air(CONTENT_AIR), n_water_source(c_water_source, LIGHT_SUN); |
| 242 | + MapNode n_stone(c_stone, LIGHT_SUN); |
| 243 | + u32 index = 0; |
| 244 | + v3s16 em = vm->m_area.getExtent(); |
| 245 | + |
| 246 | +#if 1 |
| 247 | + |
| 248 | + /* debug |
| 249 | + v3f vec0 = (v3f(node_min.X, node_min.Y, node_min.Z) - center) * scale ; |
| 250 | + errorstream << " X=" << node_min.X << " Y=" << node_min.Y << " Z=" << node_min.Z |
| 251 | + //<< " N="<< mengersponge(vec0.X, vec0.Y, vec0.Z, distance, iterations) |
| 252 | + << " N=" << (*func)(vec0.X, vec0.Y, vec0.Z, distance, iterations) |
| 253 | + << " Sc=" << scale << " gen=" << params["generator"].asString() << " J=" << Json::FastWriter().write(params) << std::endl; |
| 254 | + */ |
| 255 | + for (s16 z = node_min.Z; z <= node_max.Z; z++) { |
| 256 | + for (s16 x = node_min.X; x <= node_max.X; x++, index++) { |
| 257 | + Biome *biome = bmgr->biomes[biomemap[index]]; |
| 258 | + u32 i = vm->m_area.index(x, node_min.Y, z); |
| 259 | + for (s16 y = node_min.Y; y <= node_max.Y; y++) { |
| 260 | + v3f vec = (v3f(x, y, z) - center) * scale ; |
| 261 | + double d = (*func)(vec.X, vec.Y, vec.Z, distance, iterations); |
| 262 | + if ((!invert && d > 0) || (invert && d == 0) ) { |
| 263 | + if (vm->m_data[i].getContent() == CONTENT_IGNORE) |
| 264 | + vm->m_data[i] = (y > water_level + biome->filler_height) ? |
| 265 | + MapNode(biome->c_filler) : n_stone; |
| 266 | + } else if (y <= water_level) { |
| 267 | + vm->m_data[i] = n_water_source; |
| 268 | + } else { |
| 269 | + vm->m_data[i] = n_air; |
| 270 | + } |
| 271 | + vm->m_area.add_y(em, i, 1); |
| 272 | + } |
| 273 | + } |
| 274 | + } |
| 275 | +#endif |
| 276 | + |
| 277 | + |
| 278 | +#if 0 |
| 279 | +// mandelbulber, unfinished but works |
| 280 | + sFractal par; |
| 281 | + par.doubles.N = 10; |
| 282 | + |
| 283 | + par.doubles.power = 9.0; |
| 284 | + par.doubles.foldingSphericalFixed = 1.0; |
| 285 | + par.doubles.foldingSphericalMin = 0.5; |
| 286 | + //no par.formula = smoothMandelbox; par.doubles.N = 40; invert = 0;//no |
| 287 | + par.mandelbox.doubles.sharpness = 3.0; |
| 288 | + par.mandelbox.doubles.scale = 1; |
| 289 | + par.mandelbox.doubles.sharpness = 2; |
| 290 | + par.mandelbox.doubles.foldingLimit = 1.0; |
| 291 | + par.mandelbox.doubles.foldingValue = 2; |
| 292 | + |
| 293 | +//ok par.formula = mandelboxVaryScale4D; par.doubles.N = 50; scale = 5; invert = 1; //ok |
| 294 | + par.mandelbox.doubles.vary4D.scaleVary = 0.1; |
| 295 | + par.mandelbox.doubles.vary4D.fold = 1; |
| 296 | + par.mandelbox.doubles.vary4D.rPower = 1; |
| 297 | + par.mandelbox.doubles.vary4D.minR = 0.5; |
| 298 | + par.mandelbox.doubles.vary4D.wadd = 0; |
| 299 | + par.doubles.constantFactor = 1.0; |
| 300 | + |
| 301 | + 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 |
| 302 | + |
| 303 | + //double tresh = 1.5; |
| 304 | + //par.formula = mandelbulb2; par.doubles.N = 10; scale = (double)1/size; invert=1; center = v3f(5,-size-5,0); //ok |
| 305 | + //par.formula = hypercomplex; par.doubles.N = 20; scale = 0.0001; invert=1; center = v3f(0,-10001,0); //(double)50 / max_r; |
| 306 | + |
| 307 | + //no par.formula = trig_DE; par.doubles.N = 5; scale = (double)10; invert=1; |
| 308 | + |
| 309 | + //no par.formula = trig_optim; scale = (double)10; par.doubles.N = 4; |
| 310 | + |
| 311 | + //par.formula = mandelbulb2; scale = (double)1/10000; par.doubles.N = 10; invert = 1; center = v3f(1,-4201,1); //ok |
| 312 | + // no par.formula = tglad; |
| 313 | + |
| 314 | + //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 |
| 315 | + |
| 316 | + par.mandelbox.doubles.vary4D.scaleVary = 0.1; |
| 317 | + par.mandelbox.doubles.vary4D.fold = 1; |
| 318 | + par.mandelbox.doubles.vary4D.minR = 0.5; |
| 319 | + par.mandelbox.doubles.vary4D.rPower = 1; |
| 320 | + par.mandelbox.doubles.vary4D.wadd = 0; |
| 321 | + //no par.formula = mandelboxVaryScale4D; |
| 322 | + par.doubles.cadd = -1.3; |
| 323 | + //par.formula = aexion; // ok but center |
| 324 | + //par.formula = benesi; par.doubles.N = 10; center = v3f(0,0,0); invert = 0; //ok |
| 325 | + |
| 326 | + // par.formula = bristorbrot; //ok |
| 327 | + |
| 328 | + v3f vec0(node_min.X, node_min.Y, node_min.Z); |
| 329 | + vec0 = (vec0 - center) * scale ; |
| 330 | + errorstream << " X=" << node_min.X << " Y=" << node_min.Y << " Z=" << node_min.Z |
| 331 | + << " N=" << Compute<normal>(CVector3(vec0.X, vec0.Y, vec0.Z), par) |
| 332 | + //<<" F="<< Compute<fake_AO>(CVector3(node_min.X,node_min.Y,node_min.Z), par) |
| 333 | + //<<" L="<<node_min.getLength()<< " -="<<node_min.getLength() - Compute<normal>(CVector3(node_min.X,node_min.Y,node_min.Z), par) |
| 334 | + << " Sc=" << scale |
| 335 | + << std::endl; |
| 336 | + |
| 337 | + for (s16 z = node_min.Z; z <= node_max.Z; z++) |
| 338 | + for (s16 y = node_min.Y; y <= node_max.Y; y++) { |
| 339 | + u32 i = vm->m_area.index(node_min.X, y, z); |
| 340 | + for (s16 x = node_min.X; x <= node_max.X; x++) { |
| 341 | + v3f vec(x, y, z); |
| 342 | + vec = (vec - center) * scale ; |
| 343 | + //double d = Compute<fake_AO>(CVector3(x,y,z), par); |
| 344 | + double d = Compute<normal>(CVector3(vec.X, vec.Y, vec.Z), par); |
| 345 | + //if (d>0) |
| 346 | + // errorstream << " d=" << d <<" v="<< vec.getLength()<< " -="<< vec.getLength() - d <<" yad=" |
| 347 | + //<< Compute<normal>(CVector3(x,y,z), par) |
| 348 | + //<< std::endl; |
| 349 | + if ((!invert && d > 0) || (invert && d == 0)/*&& vec.getLength() - d > tresh*/ ) { |
| 350 | + if (vm->m_data[i].getContent() == CONTENT_IGNORE) |
| 351 | + vm->m_data[i] = n_stone; |
| 352 | + } else { |
| 353 | + vm->m_data[i] = n_air; |
| 354 | + } |
| 355 | + i++; |
| 356 | + } |
| 357 | + } |
| 358 | + |
| 359 | + |
| 360 | +#endif |
| 361 | + |
| 362 | +} |
| 363 | + |
| 364 | +int MapgenMath::getGroundLevelAtPoint(v2s16 p) { |
| 365 | + return 0; |
| 366 | +} |
0 commit comments