aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorparamat <mat.gregory@virginmedia.com>2015-12-08 05:40:36 +0000
committerparamat <mat.gregory@virginmedia.com>2015-12-15 04:18:19 +0000
commitc26eb87aec7438d167fa2f460a3f412db09c0ac5 (patch)
tree0dfafc32c1f82da3b136283f09bc37239b75c56f /src
parentaed10765f208aedf324128972c74ecc033bb5035 (diff)
downloadminetest-c26eb87aec7438d167fa2f460a3f412db09c0ac5.tar.gz
minetest-c26eb87aec7438d167fa2f460a3f412db09c0ac5.tar.bz2
minetest-c26eb87aec7438d167fa2f460a3f412db09c0ac5.zip
Mgfractal: Add 3D and 4D fractals
3D Mandelbrot/Mandelbar 3D Christmas Tree 3D Mandelbulb 3D Cosine Mandelbulb 4D Mandelbulb Plus corresponding julia set for each Add credits for formulas Rename parameter 'formula' to 'fractal' Speed optimisations
Diffstat (limited to 'src')
-rw-r--r--src/mapgen_fractal.cpp86
-rw-r--r--src/mapgen_fractal.h12
2 files changed, 81 insertions, 17 deletions
diff --git a/src/mapgen_fractal.cpp b/src/mapgen_fractal.cpp
index 14dfe5c85..6c03c4ca9 100644
--- a/src/mapgen_fractal.cpp
+++ b/src/mapgen_fractal.cpp
@@ -66,7 +66,7 @@ MapgenFractal::MapgenFractal(int mapgenid, MapgenParams *params, EmergeManager *
MapgenFractalParams *sp = (MapgenFractalParams *)params->sparams;
this->spflags = sp->spflags;
- this->formula = sp->formula;
+ this->fractal = sp->fractal;
this->iterations = sp->iterations;
this->scale = sp->scale;
this->offset = sp->offset;
@@ -77,6 +77,9 @@ MapgenFractal::MapgenFractal(int mapgenid, MapgenParams *params, EmergeManager *
this->julia_z = sp->julia_z;
this->julia_w = sp->julia_w;
+ this->formula = fractal / 2 + fractal % 2;
+ this->julia = fractal % 2 == 0;
+
//// 2D terrain noise
noise_seabed = new Noise(&sp->np_seabed, seed, csize.X, csize.Z);
noise_filler_depth = new Noise(&sp->np_filler_depth, seed, csize.X, csize.Z);
@@ -141,7 +144,7 @@ MapgenFractalParams::MapgenFractalParams()
{
spflags = 0;
- formula = 1;
+ fractal = 1;
iterations = 11;
scale = v3f(4096.0, 1024.0, 4096.0);
offset = v3f(1.79, 0.0, 0.0);
@@ -163,7 +166,7 @@ void MapgenFractalParams::readParams(const Settings *settings)
{
settings->getFlagStrNoEx("mgfractal_spflags", spflags, flagdesc_mapgen_fractal);
- settings->getU16NoEx("mgfractal_formula", formula);
+ settings->getU16NoEx("mgfractal_fractal", fractal);
settings->getU16NoEx("mgfractal_iterations", iterations);
settings->getV3FNoEx("mgfractal_scale", scale);
settings->getV3FNoEx("mgfractal_offset", offset);
@@ -185,7 +188,7 @@ void MapgenFractalParams::writeParams(Settings *settings) const
{
settings->setFlagStr("mgfractal_spflags", spflags, flagdesc_mapgen_fractal, U32_MAX);
- settings->setU16("mgfractal_formula", formula);
+ settings->setU16("mgfractal_fractal", fractal);
settings->setU16("mgfractal_iterations", iterations);
settings->setV3F("mgfractal_scale", scale);
settings->setV3F("mgfractal_offset", offset);
@@ -368,7 +371,7 @@ bool MapgenFractal::getFractalAtPoint(s16 x, s16 y, s16 z)
{
float cx, cy, cz, cw, ox, oy, oz, ow;
- if (formula % 2 == 0) { // Julia sets, formula = 2, 4, 6, 8
+ if (julia) { // Julia set
cx = julia_x;
cy = julia_y;
cz = julia_z;
@@ -377,7 +380,7 @@ bool MapgenFractal::getFractalAtPoint(s16 x, s16 y, s16 z)
oy = (float)y / scale.Y - offset.Y;
oz = (float)z / scale.Z - offset.Z;
ow = slice_w;
- } else { // Mandelbrot sets, formula = 1, 3, 5, 7
+ } else { // Mandelbrot set
cx = (float)x / scale.X - offset.X;
cy = (float)y / scale.Y - offset.Y;
cz = (float)z / scale.Z - offset.Z;
@@ -388,32 +391,87 @@ bool MapgenFractal::getFractalAtPoint(s16 x, s16 y, s16 z)
ow = 0.0f;
}
+ float nx = 0.0f;
+ float ny = 0.0f;
+ float nz = 0.0f;
+ float nw = 0.0f;
+
for (u16 iter = 0; iter < iterations; iter++) {
- float nx = 0.0f;
- float ny = 0.0f;
- float nz = 0.0f;
- float nw = 0.0f;
- if (formula == 1 || formula == 2) { // 4D "Roundy" Mandelbrot/Julia Set
+ if (formula == 1) { // 4D "Roundy"
nx = ox * ox - oy * oy - oz * oz - ow * ow + cx;
ny = 2.0f * (ox * oy + oz * ow) + cy;
nz = 2.0f * (ox * oz + oy * ow) + cz;
nw = 2.0f * (ox * ow + oy * oz) + cw;
- } else if (formula == 3 || formula == 4) { // 4D "Squarry" Mandelbrot/Julia Set
+ } else if (formula == 2) { // 4D "Squarry"
nx = ox * ox - oy * oy - oz * oz - ow * ow + cx;
ny = 2.0f * (ox * oy + oz * ow) + cy;
nz = 2.0f * (ox * oz + oy * ow) + cz;
nw = 2.0f * (ox * ow - oy * oz) + cw;
- } else if (formula == 5 || formula == 6) { // 4D "Mandy Cousin" Mandelbrot/Julia Set
+ } else if (formula == 3) { // 4D "Mandy Cousin"
nx = ox * ox - oy * oy - oz * oz + ow * ow + cx;
ny = 2.0f * (ox * oy + oz * ow) + cy;
nz = 2.0f * (ox * oz + oy * ow) + cz;
nw = 2.0f * (ox * ow + oy * oz) + cw;
- } else if (formula == 7 || formula == 8) { // 4D "Variation" Mandelbrot/Julia Set
+ } else if (formula == 4) { // 4D "Variation"
nx = ox * ox - oy * oy - oz * oz - ow * ow + cx;
ny = 2.0f * (ox * oy + oz * ow) + cy;
nz = 2.0f * (ox * oz - oy * ow) + cz;
nw = 2.0f * (ox * ow + oy * oz) + cw;
+ } else if (formula == 5) { // 3D "Mandelbrot/Mandelbar"
+ nx = ox * ox - oy * oy - oz * oz + cx;
+ ny = 2.0f * ox * oy + cy;
+ nz = -2.0f * ox * oz + cz;
+ } else if (formula == 6) { // 3D "Christmas Tree"
+ // Altering the formula here is necessary to avoid division by zero
+ if (fabs(oz) < 0.000000001f) {
+ nx = ox * ox - oy * oy - oz * oz + cx;
+ ny = 2.0f * oy * ox + cy;
+ nz = 4.0f * oz * ox + cz;
+ } else {
+ float a = (2.0f * ox) / (sqrt(oy * oy + oz * oz));
+ nx = ox * ox - oy * oy - oz * oz + cx;
+ ny = a * (oy * oy - oz * oz) + cy;
+ nz = a * 2.0f * oy * oz + cz;
+ }
+ } else if (formula == 7) { // 3D "Mandelbulb"
+ if (fabs(oy) < 0.000000001f) {
+ nx = ox * ox - oz * oz + cx;
+ ny = cy;
+ nz = -2.0f * oz * sqrt(ox * ox) + cz;
+ } else {
+ float a = 1.0f - (oz * oz) / (ox * ox + oy * oy);
+ nx = (ox * ox - oy * oy) * a + cx;
+ ny = 2.0f * ox * oy * a + cy;
+ nz = -2.0f * oz * sqrt(ox * ox + oy * oy) + cz;
+ }
+ } else if (formula == 8) { // 3D "Cosine Mandelbulb"
+ if (fabs(oy) < 0.000000001f) {
+ nx = 2.0f * ox * oz + cx;
+ ny = 4.0f * oy * oz + cy;
+ nz = oz * oz - ox * ox - oy * oy + cz;
+ } else {
+ float a = (2.0f * oz) / sqrt(ox * ox + oy * oy);
+ nx = (ox * ox - oy * oy) * a + cx;
+ ny = 2.0f * ox * oy * a + cy;
+ nz = oz * oz - ox * ox - oy * oy + cz;
+ }
+ } else if (formula == 9) { // 4D "Mandelbulb"
+ float rxy = sqrt(ox * ox + oy * oy);
+ float rxyz = sqrt(ox * ox + oy * oy + oz * oz);
+ if (fabs(ow) < 0.000000001f && fabs(oz) < 0.000000001f) {
+ nx = (ox * ox - oy * oy) + cx;
+ ny = 2.0f * ox * oy + cy;
+ nz = -2.0f * rxy * oz + cz;
+ nw = 2.0f * rxyz * ow + cw;
+ } else {
+ float a = 1.0f - (ow * ow) / (rxyz * rxyz);
+ float b = a * (1.0f - (oz * oz) / (rxy * rxy));
+ nx = (ox * ox - oy * oy) * b + cx;
+ ny = 2.0f * ox * oy * b + cy;
+ nz = -2.0f * rxy * oz * a + cz;
+ nw = 2.0f * rxyz * ow + cw;
+ }
}
if (nx * nx + ny * ny + nz * nz + nw * nw > 4.0f)
diff --git a/src/mapgen_fractal.h b/src/mapgen_fractal.h
index 7d31a43b8..3d4f7ee8f 100644
--- a/src/mapgen_fractal.h
+++ b/src/mapgen_fractal.h
@@ -3,6 +3,9 @@ Minetest
Copyright (C) 2010-2015 kwolekr, Ryan Kwolek <kwolekr@minetest.net>
Copyright (C) 2010-2015 paramat, Matt Gregory
+Fractal formulas from http://www.bugman123.com/Hypercomplex/index.html
+by Paul Nylander, and from http://www.fractalforums.com, thank you.
+
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
@@ -33,7 +36,7 @@ extern FlagDesc flagdesc_mapgen_fractal[];
struct MapgenFractalParams : public MapgenSpecificParams {
u32 spflags;
- u16 formula;
+ u16 fractal;
u16 iterations;
v3f scale;
v3f offset;
@@ -63,14 +66,17 @@ public:
int ystride;
int zstride;
- u32 spflags;
+ u16 formula;
+ bool julia;
v3s16 node_min;
v3s16 node_max;
v3s16 full_node_min;
v3s16 full_node_max;
- u16 formula;
+ u32 spflags;
+
+ u16 fractal;
u16 iterations;
v3f scale;
v3f offset;