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
This commit is contained in:
paramat 2015-12-08 05:40:36 +00:00
parent aed10765f2
commit c26eb87aec
4 changed files with 145 additions and 59 deletions

@ -970,49 +970,60 @@ mgflat_np_cave2 (Mapgen flat cave2 noise parameters) noise_params 0, 12, (128, 1
[***Mapgen fractal] [***Mapgen fractal]
# Choice of 8 4-dimensional fractals. # Choice of 18 fractals from 9 formulas.
# 1 = "Roundy" mandelbrot set. # 1 = 4D "Roundy" mandelbrot set.
# 2 = "Roundy" julia set. # 2 = 4D "Roundy" julia set.
# 3 = "Squarry" mandelbrot set. # 3 = 4D "Squarry" mandelbrot set.
# 4 = "Squarry" julia set. # 4 = 4D "Squarry" julia set.
# 5 = "Mandy Cousin" mandelbrot set. # 5 = 4D "Mandy Cousin" mandelbrot set.
# 6 = "Mandy Cousin" julia set. # 6 = 4D "Mandy Cousin" julia set.
# 7 = "Variation" mandelbrot set. # 7 = 4D "Variation" mandelbrot set.
# 8 = "Variation" julia set. # 8 = 4D "Variation" julia set.
mgfractal_formula (Mapgen fractal formula) int 1 1 8 # 9 = 3D "Mandelbrot/Mandelbar" mandelbrot set.
# 10 = 3D "Mandelbrot/Mandelbar" julia set.
# 11 = 3D "Christmas Tree" mandelbrot set.
# 12 = 3D "Christmas Tree" julia set.
# 13 = 3D "Mandelbulb" mandelbrot set.
# 14 = 3D "Mandelbulb" julia set.
# 15 = 3D "Cosine Mandelbulb" mandelbrot set.
# 16 = 3D "Cosine Mandelbulb" julia set.
# 17 = 4D "Mandelbulb" mandelbrot set.
# 18 = 4D "Mandelbulb" julia set.
mgfractal_fractal (Mapgen fractal fractal) int 1 1 18
# Iterations of the recursive function. # Iterations of the recursive function.
# Controls scale of finest detail. # Controls the amount of fine detail.
mgfractal_iterations (Mapgen fractal iterations) int 11 mgfractal_iterations (Mapgen fractal iterations) int 11
# Approximate (X,Y,Z) scale of fractal in nodes. # Approximate (X,Y,Z) scale of fractal in nodes.
mgfractal_scale (Mapgen fractal scale) v3f (4096.0, 1024.0, 4096.0) mgfractal_scale (Mapgen fractal scale) v3f (4096.0, 1024.0, 4096.0)
# (X,Y,Z) offset of fractal from world centre. # (X,Y,Z) offset of fractal from world centre in units of 'scale'.
# Used to move a suitable spawn area of low land close to (0, 0). # Used to move a suitable spawn area of low land close to (0, 0).
# The default is suitable for mandelbrot sets, it needs to be edited for julia sets, # The default is suitable for mandelbrot sets, it needs to be edited for julia sets.
# do this by greatly reducing 'scale' and setting 'offset' initially to (0, 0, 0).
# Range roughly -2 to 2. Multiply by 'scale' for offset in nodes. # Range roughly -2 to 2. Multiply by 'scale' for offset in nodes.
mgfractal_offset (Mapgen fractal offset) v3f (1.79, 0.0, 0.0) mgfractal_offset (Mapgen fractal offset) v3f (1.79, 0.0, 0.0)
# W co-ordinate of the generated 3D slice of the 4D shape. # W co-ordinate of the generated 3D slice of a 4D fractal.
# Alters the generated 3D shape. # Determines which 3D slice of the 4D shape is generated.
# Has no effect on 3D fractals.
# Range roughly -2 to 2. # Range roughly -2 to 2.
mgfractal_slice_w (Mapgen fractal slice w) float 0.0 mgfractal_slice_w (Mapgen fractal slice w) float 0.0
# Julia set only: X value determining the 4D shape. # Julia set only: X component of hypercomplex constant determining julia shape.
# Range roughly -2 to 2. # Range roughly -2 to 2.
mgfractal_julia_x (Mapgen fractal julia x) float 0.33 mgfractal_julia_x (Mapgen fractal julia x) float 0.33
# Julia set only: Y value determining the 4D shape. # Julia set only: Y component of hypercomplex constant determining julia shape.
# Range roughly -2 to 2. # Range roughly -2 to 2.
mgfractal_julia_y (Mapgen fractal julia y) float 0.33 mgfractal_julia_y (Mapgen fractal julia y) float 0.33
# Julia set only: Z value determining the 4D shape. # Julia set only: Z component of hypercomplex constant determining julia shape.
# Range roughly -2 to 2. # Range roughly -2 to 2.
mgfractal_julia_z (Mapgen fractal julia z) float 0.33 mgfractal_julia_z (Mapgen fractal julia z) float 0.33
# Julia set only: W value determining the 4D shape. # Julia set only: W component of hypercomplex constant determining julia shape.
# Has no effect on 3D fractals.
# Range roughly -2 to 2. # Range roughly -2 to 2.
mgfractal_julia_w (Mapgen fractal julia w) float 0.33 mgfractal_julia_w (Mapgen fractal julia w) float 0.33

@ -1234,20 +1234,30 @@
#### Mapgen fractal #### Mapgen fractal
# Choice of 8 4-dimensional fractals. # Choice of 18 fractals from 9 formulas.
# 1 = "Roundy" mandelbrot set. # 1 = 4D "Roundy" mandelbrot set.
# 2 = "Roundy" julia set. # 2 = 4D "Roundy" julia set.
# 3 = "Squarry" mandelbrot set. # 3 = 4D "Squarry" mandelbrot set.
# 4 = "Squarry" julia set. # 4 = 4D "Squarry" julia set.
# 5 = "Mandy Cousin" mandelbrot set. # 5 = 4D "Mandy Cousin" mandelbrot set.
# 6 = "Mandy Cousin" julia set. # 6 = 4D "Mandy Cousin" julia set.
# 7 = "Variation" mandelbrot set. # 7 = 4D "Variation" mandelbrot set.
# 8 = "Variation" julia set. # 8 = 4D "Variation" julia set.
# type: int min: 1 max: 8 # 9 = 3D "Mandelbrot/Mandelbar" mandelbrot set.
# mgfractal_formula = 1 # 10 = 3D "Mandelbrot/Mandelbar" julia set.
# 11 = 3D "Christmas Tree" mandelbrot set.
# 12 = 3D "Christmas Tree" julia set.
# 13 = 3D "Mandelbulb" mandelbrot set.
# 14 = 3D "Mandelbulb" julia set.
# 15 = 3D "Cosine Mandelbulb" mandelbrot set.
# 16 = 3D "Cosine Mandelbulb" julia set.
# 17 = 4D "Mandelbulb" mandelbrot set.
# 18 = 4D "Mandelbulb" julia set.
# type: int min: 1 max: 18
# mgfractal_fractal = 1
# Iterations of the recursive function. # Iterations of the recursive function.
# Controls scale of finest detail. # Controls the amount of fine detail.
# type: int # type: int
# mgfractal_iterations = 11 # mgfractal_iterations = 11
@ -1255,36 +1265,37 @@
# type: v3f # type: v3f
# mgfractal_scale = (4096.0, 1024.0, 4096.0) # mgfractal_scale = (4096.0, 1024.0, 4096.0)
# (X,Y,Z) offset of fractal from world centre. # (X,Y,Z) offset of fractal from world centre in units of 'scale'.
# Used to move a suitable spawn area of low land close to (0, 0). # Used to move a suitable spawn area of low land close to (0, 0).
# The default is suitable for mandelbrot sets, it needs to be edited for julia sets, # The default is suitable for mandelbrot sets, it needs to be edited for julia sets.
# do this by greatly reducing 'scale' and setting 'offset' initially to (0, 0, 0).
# Range roughly -2 to 2. Multiply by 'scale' for offset in nodes. # Range roughly -2 to 2. Multiply by 'scale' for offset in nodes.
# type: v3f # type: v3f
# mgfractal_offset = (1.79, 0.0, 0.0) # mgfractal_offset = (1.79, 0.0, 0.0)
# W co-ordinate of the generated 3D slice of the 4D shape. # W co-ordinate of the generated 3D slice of a 4D fractal.
# Alters the generated 3D shape. # Determines which 3D slice of the 4D shape is generated.
# Has no effect on 3D fractals.
# Range roughly -2 to 2. # Range roughly -2 to 2.
# type: float # type: float
# mgfractal_slice_w = 0.0 # mgfractal_slice_w = 0.0
# Julia set only: X value determining the 4D shape. # Julia set only: X component of hypercomplex constant determining julia shape.
# Range roughly -2 to 2. # Range roughly -2 to 2.
# type: float # type: float
# mgfractal_julia_x = 0.33 # mgfractal_julia_x = 0.33
# Julia set only: Y value determining the 4D shape. # Julia set only: Y component of hypercomplex constant determining julia shape.
# Range roughly -2 to 2. # Range roughly -2 to 2.
# type: float # type: float
# mgfractal_julia_y = 0.33 # mgfractal_julia_y = 0.33
# Julia set only: Z value determining the 4D shape. # Julia set only: Z component of hypercomplex constant determining julia shape.
# Range roughly -2 to 2. # Range roughly -2 to 2.
# type: float # type: float
# mgfractal_julia_z = 0.33 # mgfractal_julia_z = 0.33
# Julia set only: W value determining the 4D shape. # Julia set only: W component of hypercomplex constant determining julia shape.
# Has no effect on 3D fractals.
# Range roughly -2 to 2. # Range roughly -2 to 2.
# type: float # type: float
# mgfractal_julia_w = 0.33 # mgfractal_julia_w = 0.33

@ -66,7 +66,7 @@ MapgenFractal::MapgenFractal(int mapgenid, MapgenParams *params, EmergeManager *
MapgenFractalParams *sp = (MapgenFractalParams *)params->sparams; MapgenFractalParams *sp = (MapgenFractalParams *)params->sparams;
this->spflags = sp->spflags; this->spflags = sp->spflags;
this->formula = sp->formula; this->fractal = sp->fractal;
this->iterations = sp->iterations; this->iterations = sp->iterations;
this->scale = sp->scale; this->scale = sp->scale;
this->offset = sp->offset; this->offset = sp->offset;
@ -77,6 +77,9 @@ MapgenFractal::MapgenFractal(int mapgenid, MapgenParams *params, EmergeManager *
this->julia_z = sp->julia_z; this->julia_z = sp->julia_z;
this->julia_w = sp->julia_w; this->julia_w = sp->julia_w;
this->formula = fractal / 2 + fractal % 2;
this->julia = fractal % 2 == 0;
//// 2D terrain noise //// 2D terrain noise
noise_seabed = new Noise(&sp->np_seabed, seed, csize.X, csize.Z); 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); noise_filler_depth = new Noise(&sp->np_filler_depth, seed, csize.X, csize.Z);
@ -141,7 +144,7 @@ MapgenFractalParams::MapgenFractalParams()
{ {
spflags = 0; spflags = 0;
formula = 1; fractal = 1;
iterations = 11; iterations = 11;
scale = v3f(4096.0, 1024.0, 4096.0); scale = v3f(4096.0, 1024.0, 4096.0);
offset = v3f(1.79, 0.0, 0.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->getFlagStrNoEx("mgfractal_spflags", spflags, flagdesc_mapgen_fractal);
settings->getU16NoEx("mgfractal_formula", formula); settings->getU16NoEx("mgfractal_fractal", fractal);
settings->getU16NoEx("mgfractal_iterations", iterations); settings->getU16NoEx("mgfractal_iterations", iterations);
settings->getV3FNoEx("mgfractal_scale", scale); settings->getV3FNoEx("mgfractal_scale", scale);
settings->getV3FNoEx("mgfractal_offset", offset); 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->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->setU16("mgfractal_iterations", iterations);
settings->setV3F("mgfractal_scale", scale); settings->setV3F("mgfractal_scale", scale);
settings->setV3F("mgfractal_offset", offset); 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; 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; cx = julia_x;
cy = julia_y; cy = julia_y;
cz = julia_z; cz = julia_z;
@ -377,7 +380,7 @@ bool MapgenFractal::getFractalAtPoint(s16 x, s16 y, s16 z)
oy = (float)y / scale.Y - offset.Y; oy = (float)y / scale.Y - offset.Y;
oz = (float)z / scale.Z - offset.Z; oz = (float)z / scale.Z - offset.Z;
ow = slice_w; ow = slice_w;
} else { // Mandelbrot sets, formula = 1, 3, 5, 7 } else { // Mandelbrot set
cx = (float)x / scale.X - offset.X; cx = (float)x / scale.X - offset.X;
cy = (float)y / scale.Y - offset.Y; cy = (float)y / scale.Y - offset.Y;
cz = (float)z / scale.Z - offset.Z; cz = (float)z / scale.Z - offset.Z;
@ -388,32 +391,87 @@ bool MapgenFractal::getFractalAtPoint(s16 x, s16 y, s16 z)
ow = 0.0f; ow = 0.0f;
} }
for (u16 iter = 0; iter < iterations; iter++) { float nx = 0.0f;
float nx = 0.0f; float ny = 0.0f;
float ny = 0.0f; float nz = 0.0f;
float nz = 0.0f; float nw = 0.0f;
float nw = 0.0f;
if (formula == 1 || formula == 2) { // 4D "Roundy" Mandelbrot/Julia Set for (u16 iter = 0; iter < iterations; iter++) {
if (formula == 1) { // 4D "Roundy"
nx = ox * ox - oy * oy - oz * oz - ow * ow + cx; nx = ox * ox - oy * oy - oz * oz - ow * ow + cx;
ny = 2.0f * (ox * oy + oz * ow) + cy; ny = 2.0f * (ox * oy + oz * ow) + cy;
nz = 2.0f * (ox * oz + oy * ow) + cz; nz = 2.0f * (ox * oz + oy * ow) + cz;
nw = 2.0f * (ox * ow + oy * oz) + cw; 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; nx = ox * ox - oy * oy - oz * oz - ow * ow + cx;
ny = 2.0f * (ox * oy + oz * ow) + cy; ny = 2.0f * (ox * oy + oz * ow) + cy;
nz = 2.0f * (ox * oz + oy * ow) + cz; nz = 2.0f * (ox * oz + oy * ow) + cz;
nw = 2.0f * (ox * ow - oy * oz) + cw; 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; nx = ox * ox - oy * oy - oz * oz + ow * ow + cx;
ny = 2.0f * (ox * oy + oz * ow) + cy; ny = 2.0f * (ox * oy + oz * ow) + cy;
nz = 2.0f * (ox * oz + oy * ow) + cz; nz = 2.0f * (ox * oz + oy * ow) + cz;
nw = 2.0f * (ox * ow + oy * oz) + cw; 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; nx = ox * ox - oy * oy - oz * oz - ow * ow + cx;
ny = 2.0f * (ox * oy + oz * ow) + cy; ny = 2.0f * (ox * oy + oz * ow) + cy;
nz = 2.0f * (ox * oz - oy * ow) + cz; nz = 2.0f * (ox * oz - oy * ow) + cz;
nw = 2.0f * (ox * ow + oy * oz) + cw; 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) if (nx * nx + ny * ny + nz * nz + nw * nw > 4.0f)

@ -3,6 +3,9 @@ Minetest
Copyright (C) 2010-2015 kwolekr, Ryan Kwolek <kwolekr@minetest.net> Copyright (C) 2010-2015 kwolekr, Ryan Kwolek <kwolekr@minetest.net>
Copyright (C) 2010-2015 paramat, Matt Gregory 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 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 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 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 { struct MapgenFractalParams : public MapgenSpecificParams {
u32 spflags; u32 spflags;
u16 formula; u16 fractal;
u16 iterations; u16 iterations;
v3f scale; v3f scale;
v3f offset; v3f offset;
@ -63,14 +66,17 @@ public:
int ystride; int ystride;
int zstride; int zstride;
u32 spflags; u16 formula;
bool julia;
v3s16 node_min; v3s16 node_min;
v3s16 node_max; v3s16 node_max;
v3s16 full_node_min; v3s16 full_node_min;
v3s16 full_node_max; v3s16 full_node_max;
u16 formula; u32 spflags;
u16 fractal;
u16 iterations; u16 iterations;
v3f scale; v3f scale;
v3f offset; v3f offset;