Permalink
Fetching contributors…
Cannot retrieve contributors at this time
14609 lines (13220 sloc) 468 KB
/**
* Mandelbulber v2, a 3D fractal generator ,=#MKNmMMKmmßMNWy,
* ,B" ]L,,p%%%,,,§;, "K
* Copyright (C) 2014-18 Mandelbulber Team §R-==%w["'~5]m%=L.=~5N
* ,=mm=§M ]=4 yJKA"/-Nsaj "Bw,==,,
* This file is part of Mandelbulber. §R.r= jw",M Km .mM FW ",§=ß., ,TN
* ,4R =%["w[N=7]J '"5=],""]]M,w,-; T=]M
* Mandelbulber is free software: §R.ß~-Q/M=,=5"v"]=Qf,'§"M= =,M.§ Rz]M"Kw
* you can redistribute it and/or §w "xDY.J ' -"m=====WeC=\ ""%""y=%"]"" §
* modify it under the terms of the "§M=M =D=4"N #"%==A%p M§ M6 R' #"=~.4M
* GNU General Public License as §W =, ][T"]C § § '§ e===~ U !§[Z ]N
* published by the 4M",,Jm=,"=e~ § § j]]""N BmM"py=ßM
* Free Software Foundation, ]§ T,M=& 'YmMMpM9MMM%=w=,,=MT]M m§;'§,
* either version 3 of the License, TWw [.j"5=~N[=§%=%W,T ]R,"=="Y[LFT ]N
* or (at your option) TW=,-#"%=;[ =Q:["V"" ],,M.m == ]N
* any later version. J§"mr"] ,=,," =="""J]= M"M"]==ß"
* §= "=C=4 §"eM "=B:m|4"]#F,§~
* Mandelbulber is distributed in "9w=,,]w em%wJ '"~" ,=,,ß"
* the hope that it will be useful, . "K= ,=RMMMßM"""
* but WITHOUT ANY WARRANTY; .'''
* without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*
* See the GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with Mandelbulber. If not, see <http://www.gnu.org/licenses/>.
*
* ###########################################################################
*
* Authors: Krzysztof Marczak (buddhi1980@gmail.com), Graeme McLaren,
* Sebastian Jennen (jenzebas@gmail.com)
*
* functions for calculation single fractal iterations
*/
#include "fractal_formulas.hpp"
#include "common_math.h"
#include "common_params.hpp"
#include "fractal.h"
using namespace fractal;
using std::swap;
/**
* Classic Mandelbulb fractal.
* @reference http://www.fractalforums.com/3d-fractal-generation/true-3d-mandlebrot-type-fractal/
*/
void MandelbulbIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
// if (aux.r < 1e-21) aux.r = 1e-21;
const double th0 = asin(z.z / aux.r) + fractal->bulb.betaAngleOffset;
const double ph0 = atan2(z.y, z.x) + fractal->bulb.alphaAngleOffset;
double rp = pow(aux.r, fractal->bulb.power - 1.0);
const double th = th0 * fractal->bulb.power;
const double ph = ph0 * fractal->bulb.power;
const double cth = cos(th);
aux.DE = (rp * aux.DE) * fractal->bulb.power + 1.0;
rp *= aux.r;
z.x = cth * cos(ph) * rp;
z.y = cth * sin(ph) * rp;
z.z = sin(th) * rp;
}
/**
* Mandelbox fractal known as AmazingBox or ABox, invented by Tom Lowe in 2010
* @reference
* http://www.fractalforums.com/ifs-iterated-function-systems/amazing-fractal/msg12467/#msg12467
* This formula contains aux.color
*/
void MandelboxIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
if (fractal->mandelbox.rotationsEnabled)
{
CVector4 zRot;
// cast vector to array pointer for address taking of components in opencl
double *zRotP = reinterpret_cast<double *>(&zRot);
const double *colP = reinterpret_cast<const double *>(&fractal->mandelbox.color.factor);
for (int dim = 0; dim < 3; dim++)
{
// handle each dimension x, y and z sequentially in pointer var dim
double *rotDim = (dim == 0) ? &zRotP[0] : ((dim == 1) ? &zRotP[1] : &zRotP[2]);
const double *colorFactor = (dim == 0) ? &colP[0] : ((dim == 1) ? &colP[1] : &colP[2]);
zRot = fractal->mandelbox.rot[0][dim].RotateVector(z);
if (*rotDim > fractal->mandelbox.foldingLimit)
{
*rotDim = fractal->mandelbox.foldingValue - *rotDim;
z = fractal->mandelbox.rotinv[0][dim].RotateVector(zRot);
aux.color += *colorFactor;
}
else
{
zRot = fractal->mandelbox.rot[1][dim].RotateVector(z);
if (*rotDim < -fractal->mandelbox.foldingLimit)
{
*rotDim = -fractal->mandelbox.foldingValue - *rotDim;
z = fractal->mandelbox.rotinv[1][dim].RotateVector(zRot);
aux.color += *colorFactor;
}
}
}
}
else
{
if (fabs(z.x) > fractal->mandelbox.foldingLimit)
{
z.x = sign(z.x) * fractal->mandelbox.foldingValue - z.x;
aux.color += fractal->mandelbox.color.factor.x;
}
if (fabs(z.y) > fractal->mandelbox.foldingLimit)
{
z.y = sign(z.y) * fractal->mandelbox.foldingValue - z.y;
aux.color += fractal->mandelbox.color.factor.y;
}
if (fabs(z.z) > fractal->mandelbox.foldingLimit)
{
z.z = sign(z.z) * fractal->mandelbox.foldingValue - z.z;
aux.color += fractal->mandelbox.color.factor.z;
}
}
const double r2 = z.Dot(z);
z += fractal->mandelbox.offset;
if (r2 < fractal->mandelbox.mR2)
{
z *= fractal->mandelbox.mboxFactor1;
aux.DE *= fractal->mandelbox.mboxFactor1;
aux.color += fractal->mandelbox.color.factorSp1;
}
else if (r2 < fractal->mandelbox.fR2)
{
const double tglad_factor2 = fractal->mandelbox.fR2 / r2;
z *= tglad_factor2;
aux.DE *= tglad_factor2;
aux.color += fractal->mandelbox.color.factorSp2;
}
z -= fractal->mandelbox.offset;
if (fractal->mandelbox.mainRotationEnabled) z = fractal->mandelbox.mainRot.RotateVector(z);
z = z * fractal->mandelbox.scale;
aux.DE = aux.DE * fabs(fractal->mandelbox.scale) + 1.0;
}
/**
* Fractal formula created by Buddhi
*/
void Mandelbulb2Iteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
Q_UNUSED(fractal);
aux.DE = aux.DE * 2.0 * aux.r;
double tempR = sqrt(z.x * z.x + z.y * z.y); //+ 1e-061
z *= 1.0 / tempR;
double temp = z.x * z.x - z.y * z.y;
z.y = 2.0 * z.x * z.y;
z.x = temp;
z *= tempR;
tempR = sqrt(z.y * z.y + z.z * z.z); //+ 1e-061
z *= 1.0 / tempR;
temp = z.y * z.y - z.z * z.z;
z.z = 2.0 * z.y * z.z;
z.y = temp;
z *= tempR;
tempR = sqrt(z.x * z.x + z.z * z.z); //+ 1e-061
z *= 1.0 / tempR;
temp = z.x * z.x - z.z * z.z;
z.z = 2.0 * z.x * z.z;
z.x = temp;
z *= tempR;
z *= aux.r;
}
/**
* Fractal formula created by Buddhi
*/
void Mandelbulb3Iteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
Q_UNUSED(fractal);
aux.DE = aux.DE * 2.0 * aux.r;
double temp, tempR;
double sign = 1.0;
double sign2 = 1.0;
if (z.x < 0.0) sign2 = -1.0;
tempR = sqrt(z.x * z.x + z.y * z.y); //+ 1e-061
z *= 1.0 / tempR;
temp = z.x * z.x - z.y * z.y;
z.y = 2.0 * z.x * z.y;
z.x = temp;
z *= tempR;
if (z.x < 0.0) sign = -1.0;
tempR = sqrt(z.x * z.x + z.z * z.z); //+ 1e-061
z *= 1.0 / tempR;
temp = z.x * z.x - z.z * z.z;
z.z = 2.0 * z.x * z.z * sign2;
z.x = temp * sign;
z *= tempR;
z *= aux.r;
}
/**
* Fractal formula created by Buddhi
*/
void Mandelbulb4Iteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
double rp = pow(aux.r, fractal->bulb.power - 1.0);
aux.DE = rp * aux.DE * fractal->bulb.power + 1.0;
double angZ = atan2(z.y, z.x) + fractal->bulb.alphaAngleOffset;
double angY = atan2(z.z, z.x) + fractal->bulb.betaAngleOffset;
double angX = atan2(z.z, z.y) + fractal->bulb.gammaAngleOffset;
CRotationMatrix rotM;
rotM.RotateX(angX * (fractal->bulb.power - 1.0));
rotM.RotateY(angY * (fractal->bulb.power - 1.0));
rotM.RotateZ(angZ * (fractal->bulb.power - 1.0));
z = rotM.RotateVector(z) * rp;
}
/**
* Classic Mandelbulb Power 2 fractal
* @reference http://www.fractalforums.com/3d-fractal-generation/true-3d-mandlebrot-type-fractal/
*/
void MandelbulbPower2Iteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
Q_UNUSED(fractal);
aux.DE = aux.DE * 2.0 * aux.r;
double x2 = z.x * z.x;
double y2 = z.y * z.y;
double z2 = z.z * z.z;
double temp = 1.0 - z2 / (x2 + y2);
double newx = (x2 - y2) * temp;
double newy = 2.0 * z.x * z.y * temp;
double newz = -2.0 * z.z * sqrt(x2 + y2);
z.x = newx;
z.y = newy;
z.z = newz;
}
/**
* Xenodreambuie
* @reference
* http://www.fractalforums.com/3d-fractal-generation/true-3d-mandlebrot-type-fractal/273/
*/
void XenodreambuieIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
double rp = pow(aux.r, fractal->bulb.power - 1.0);
aux.DE = rp * aux.DE * fractal->bulb.power + 1.0;
rp *= aux.r;
double th = atan2(z.y, z.x) + fractal->bulb.betaAngleOffset;
double ph = acos(z.z / aux.r) + fractal->bulb.alphaAngleOffset;
if (fabs(ph) > 0.5 * M_PI) ph = sign(ph) * M_PI - ph;
z.x = rp * cos(th * fractal->bulb.power) * sin(ph * fractal->bulb.power);
z.y = rp * sin(th * fractal->bulb.power) * sin(ph * fractal->bulb.power);
z.z = rp * cos(ph * fractal->bulb.power);
}
/**
* Menger Sponge formula created by Knighty
* @reference
* http://www.fractalforums.com/ifs-iterated-function-systems/kaleidoscopic-(escape-time-ifs)/
*/
void MengerSpongeIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
Q_UNUSED(fractal);
z.x = fabs(z.x);
z.y = fabs(z.y);
z.z = fabs(z.z);
if (z.x - z.y < 0.0) swap(z.x, z.y);
if (z.x - z.z < 0.0) swap(z.x, z.z);
if (z.y - z.z < 0.0) swap(z.y, z.z);
z *= 3.0;
z.x -= 2.0;
z.y -= 2.0;
if (z.z > 1.0) z.z -= 2.0;
aux.DE *= 3.0;
}
/**
* Menger Sponge formula created by Knighty,
* Modulus Operation applied by mancoast
* @reference
* http://www.fractalforums.com/new-theories-and-research/escape-time-algorithm-defined-using-the-quotient-and-remainder-functions/
*/
void ModulusMengerSpongeIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
Q_UNUSED(fractal);
z.x = fabs(z.x);
z.y = fabs(z.y);
z.z = fabs(z.z);
if (z.x - z.y < 0.0) swap(z.x, z.y);
if (z.x - z.z < 0.0) swap(z.x, z.z);
if (z.y - z.z < 0.0) swap(z.y, z.z);
z *= 3.0;
z.x -= 2.0;
z.y -= 2.0;
if (fmod(z.z, M_PI) > 2.0) z.z -= 2.0;
aux.DE *= 3.0;
}
/**
* Classic Mandelbulb fractal with a Modulus Operation applied by mancoast
* @reference
* http://www.fractalforums.com/new-theories-and-research/escape-time-algorithm-defined-using-the-quotient-and-remainder-functions/
*/
void ModulusMandelbulbIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
// if (aux.r < 1e-21) aux.r = 1e-21;
const double th0 = asin(z.z / aux.r) + fractal->bulb.betaAngleOffset;
const double ph0 = atan2(z.y, z.x) + fractal->bulb.alphaAngleOffset;
double rp = pow(aux.r, fractal->bulb.power - 1.0);
const double th = th0 * fractal->bulb.power;
const double ph = ph0 * fractal->bulb.power;
const double cth = cos(th);
aux.DE = (rp * aux.DE) * fractal->bulb.power + 1.0;
rp *= aux.r;
z.x = cth * cos(ph) * rp;
z.y = fmod(cth * sin(ph) * rp, 2.0);
z.z = sin(th) * rp;
}
/**
* Smooth Mandelbox created by Buddhi
* @reference http://www.fractalforums.com/3d-fractal-generation/mandelbox-with-'smooth'-conditions/
* This formula contains aux.color
*/
void MandelboxSmoothIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
double sm = fractal->mandelbox.sharpness;
double zk1 = SmoothConditionAGreaterB(z.x, fractal->mandelbox.foldingLimit, sm);
double zk2 = SmoothConditionALessB(z.x, -fractal->mandelbox.foldingLimit, sm);
z.x = z.x * (1.0 - zk1) + (fractal->mandelbox.foldingValue - z.x) * zk1;
z.x = z.x * (1.0 - zk2) + (-fractal->mandelbox.foldingValue - z.x) * zk2;
aux.color += (zk1 + zk2) * fractal->mandelbox.color.factor.x;
double zk3 = SmoothConditionAGreaterB(z.y, fractal->mandelbox.foldingLimit, sm);
double zk4 = SmoothConditionALessB(z.y, -fractal->mandelbox.foldingLimit, sm);
z.y = z.y * (1.0 - zk3) + (fractal->mandelbox.foldingValue - z.y) * zk3;
z.y = z.y * (1.0 - zk4) + (-fractal->mandelbox.foldingValue - z.y) * zk4;
aux.color += (zk3 + zk4) * fractal->mandelbox.color.factor.y;
double zk5 = SmoothConditionAGreaterB(z.z, fractal->mandelbox.foldingLimit, sm);
double zk6 = SmoothConditionALessB(z.z, -fractal->mandelbox.foldingLimit, sm);
z.z = z.z * (1.0 - zk5) + (fractal->mandelbox.foldingValue - z.z) * zk5;
z.z = z.z * (1.0 - zk6) + (-fractal->mandelbox.foldingValue - z.z) * zk6;
aux.color += (zk5 + zk6) * fractal->mandelbox.color.factor.z;
double r2 = z.Dot(z);
double tglad_factor2 = fractal->mandelbox.fR2 / r2;
double rk1 = SmoothConditionALessB(r2, fractal->mandelbox.mR2, sm);
double rk2 = SmoothConditionALessB(r2, fractal->mandelbox.fR2, sm);
double rk21 = (1.0 - rk1) * rk2;
z = z * (1.0 - rk1) + z * (fractal->mandelbox.mboxFactor1 * rk1);
z = z * (1.0 - rk21) + z * (tglad_factor2 * rk21);
aux.DE = aux.DE * (1.0 - rk1) + aux.DE * (fractal->mandelbox.mboxFactor1 * rk1);
aux.DE = aux.DE * (1.0 - rk21) + aux.DE * (tglad_factor2 * rk21);
aux.color += rk1 * fractal->mandelbox.color.factorSp1;
aux.color += rk21 * fractal->mandelbox.color.factorSp2;
z = fractal->mandelbox.mainRot.RotateVector(z);
z = z * fractal->mandelbox.scale;
aux.DE = aux.DE * fabs(fractal->mandelbox.scale) + 1.0;
}
/**
* Hybrid of Mandelbox and Mandelbulb power 2 with scaling of z axis
*/
void BoxFoldBulbPow2Iteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
(void)aux;
if (fabs(z.x) > fractal->foldingIntPow.foldFactor)
z.x = sign(z.x) * fractal->foldingIntPow.foldFactor * 2.0 - z.x;
if (fabs(z.y) > fractal->foldingIntPow.foldFactor)
z.y = sign(z.y) * fractal->foldingIntPow.foldFactor * 2.0 - z.y;
if (fabs(z.z) > fractal->foldingIntPow.foldFactor)
z.z = sign(z.z) * fractal->foldingIntPow.foldFactor * 2.0 - z.z;
double fR2_2 = 1.0;
double mR2_2 = 0.25;
double r2_2 = z.Dot(z);
double tglad_factor1_2 = fR2_2 / mR2_2;
if (r2_2 < mR2_2)
{
z = z * tglad_factor1_2;
}
else if (r2_2 < fR2_2)
{
double tglad_factor2_2 = fR2_2 / r2_2;
z = z * tglad_factor2_2;
}
z = z * 2.0;
double x2 = z.x * z.x;
double y2 = z.y * z.y;
double z2 = z.z * z.z;
double temp = 1.0 - z2 / (x2 + y2);
CVector4 zTemp;
zTemp.x = (x2 - y2) * temp;
zTemp.y = 2.0 * z.x * z.y * temp;
zTemp.z = -2.0 * z.z * sqrt(x2 + y2);
zTemp.w = z.w;
z = zTemp;
z.z *= fractal->foldingIntPow.zFactor;
// INFO remark: changed sequence of operation.
// adding of C constant was before multiplying by z-factor
}
/**
* Kaleidoscopic Iterated Function Systems (IFS)
* @reference
* http://www.fractalforums.com/ifs-iterated-function-systems/kaleidoscopic-(escape-time-ifs)/
*/
void KaleidoscopicIfsIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
if (fractal->IFS.absX) z.x = fabs(z.x);
if (fractal->IFS.absY) z.y = fabs(z.y);
if (fractal->IFS.absZ) z.z = fabs(z.z);
for (int i = 0; i < IFS_VECTOR_COUNT; i++)
{
if (fractal->IFS.enabled[i])
{
z = fractal->IFS.rot[i].RotateVector(z);
double length = z.Dot(fractal->IFS.direction[i]);
if (length < fractal->IFS.distance[i])
{
z -= fractal->IFS.direction[i]
* (2.0 * (length - fractal->IFS.distance[i]) * fractal->IFS.intensity[i]);
}
}
}
if (fractal->IFS.rotationEnabled)
z = fractal->IFS.mainRot.RotateVector(z - fractal->IFS.offset) + fractal->IFS.offset;
if (fractal->IFS.edge.x > 0.0) z.x = fractal->IFS.edge.x - fabs(fractal->IFS.edge.x - z.x);
if (fractal->IFS.edge.y > 0.0) z.y = fractal->IFS.edge.y - fabs(fractal->IFS.edge.y - z.y);
if (fractal->IFS.edge.z > 0.0) z.z = fractal->IFS.edge.z - fabs(fractal->IFS.edge.z - z.z);
z *= fractal->IFS.scale;
if (fractal->IFS.mengerSpongeMode)
{
z.x -= fractal->IFS.offset.x * (fractal->IFS.scale - 1.0);
z.y -= fractal->IFS.offset.y * (fractal->IFS.scale - 1.0);
if (z.z > 0.5 * fractal->IFS.offset.z * (fractal->IFS.scale - 1.0))
z.z -= fractal->IFS.offset.z * (fractal->IFS.scale - 1.0);
}
else
{
z -= fractal->IFS.offset * (fractal->IFS.scale - 1.0);
}
aux.DE *= fractal->IFS.scale;
}
/**
* Aexion's Quadray Sets from FractalForums
* @reference http://www.fractalforums.com/the-3d-mandelbulb/quadray-sets/msg31458/#msg31458
*/
void AexionIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
if (aux.i == 0)
{
double cx = fabs(aux.c.x + aux.c.y + aux.c.z) + fractal->aexion.cadd;
double cy = fabs(-aux.c.x - aux.c.y + aux.c.z) + fractal->aexion.cadd;
double cz = fabs(-aux.c.x + aux.c.y - aux.c.z) + fractal->aexion.cadd;
double cw = fabs(aux.c.x - aux.c.y - aux.c.z) + fractal->aexion.cadd;
aux.c.x = cx;
aux.c.y = cy;
aux.c.z = cz;
aux.cw = cw;
double tempX = fabs(z.x + z.y + z.z) + fractal->aexion.cadd;
double tempY = fabs(-z.x - z.y + z.z) + fractal->aexion.cadd;
double tempZ = fabs(-z.x + z.y - z.z) + fractal->aexion.cadd;
double tempW = fabs(z.x - z.y - z.z) + fractal->aexion.cadd;
z.x = tempX;
z.y = tempY;
z.z = tempZ;
z.w = tempW;
}
double tempX = z.x * z.x - z.y * z.y + 2.0 * z.w * z.z + aux.c.x;
double tempY = z.y * z.y - z.x * z.x + 2.0 * z.w * z.z + aux.c.y;
double tempZ = z.z * z.z - z.w * z.w + 2.0 * z.x * z.y + aux.c.z;
double tempW = z.w * z.w - z.z * z.z + 2.0 * z.x * z.y + aux.cw;
z.x = tempX;
z.y = tempY;
z.z = tempZ;
z.w = tempW;
}
/**
* 3D Mandelbrot formula invented by David Makin
* @reference
* http://www.fractalforums.com/3d-fractal-generation/true-3d-mandlebrot-type-fractal/msg7235/#msg7235
*/
void HypercomplexIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
Q_UNUSED(fractal);
aux.DE = aux.DE * 2.0 * aux.r;
double newx = z.x * z.x - z.y * z.y - z.z * z.z - z.w * z.w;
double newy = 2.0 * z.x * z.y - 2.0 * z.w * z.z;
double newz = 2.0 * z.x * z.z - 2.0 * z.y * z.w;
double neww = 2.0 * z.x * z.w - 2.0 * z.y * z.z;
z.x = newx;
z.y = newy;
z.z = newz;
z.w = neww;
}
/**
* Quaternion fractal
* @reference http://www.fractalforums.com/3d-fractal-generation/true-3d-mandlebrot-type-fractal/
*/
void QuaternionIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
Q_UNUSED(fractal);
aux.DE = aux.DE * 2.0 * aux.r;
double newx = z.x * z.x - z.y * z.y - z.z * z.z - z.w * z.w;
double newy = 2.0 * z.x * z.y;
double newz = 2.0 * z.x * z.z;
double neww = 2.0 * z.x * z.w;
z.x = newx;
z.y = newy;
z.z = newz;
z.w = neww;
}
/**
* Formula invented by Benesi
* @reference http://www.fractalforums.com/index.php?action=profile;u=1170
*/
void BenesiIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
Q_UNUSED(fractal);
CVector4 c = aux.const_c;
aux.DE = aux.DE * 2.0 * aux.r;
double r1 = z.y * z.y + z.z * z.z;
double newx;
if (c.x < 0.0 || z.x < sqrt(r1))
{
newx = z.x * z.x - r1;
}
else
{
newx = -z.x * z.x + r1;
}
r1 = -1.0 / sqrt(r1) * 2.0 * fabs(z.x);
double newy = r1 * (z.y * z.y - z.z * z.z);
double newz = r1 * 2.0 * z.y * z.z;
z.x = newx;
z.y = newy;
z.z = newz;
}
/**
* Bristorbrot formula
* @reference http://www.fractalforums.com/theory/bristorbrot-3d/
* by Doug Bristor
*/
void BristorbrotIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
Q_UNUSED(fractal);
aux.DE = aux.DE * 2.0 * aux.r;
double newx = z.x * z.x - z.y * z.y - z.z * z.z;
double newy = z.y * (2.0 * z.x - z.z);
double newz = z.z * (2.0 * z.x + z.y);
z.x = newx;
z.y = newy;
z.z = newz;
}
/**
* From M3D. A formula made by Trafassel, the original Ide's Formula thread
* @reference http://www.fractalforums.com/videos/formula-21-%28julia-set-interpretation%29/
*/
void IdesIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
Q_UNUSED(aux);
if (fabs(z.x) < 2.5) z.x = z.x * .9;
if (fabs(z.z) < 2.5) z.z = z.z * .9;
CVector4 z2 = z * z;
CVector4 newZ;
newZ.x = fractal->transformCommon.constantMultiplier121.x * z2.x
- fractal->transformCommon.additionConstant0555.x * (z2.y + z2.z);
newZ.y = fractal->transformCommon.constantMultiplier121.y * z.x * z.y * z.z;
newZ.z = fractal->transformCommon.constantMultiplier121.z * z2.z
- fractal->transformCommon.additionConstant0555.z * (z2.x + z2.y);
newZ.w = z.w;
z = newZ;
}
/**
* From M3D. A formula made by Trafassel, the original Ide's Formula thread
* @reference http://www.fractalforums.com/videos/formula-21-%28julia-set-interpretation%29/
*/
void Ides2Iteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
Q_UNUSED(aux);
CVector4 z2 = z * z;
CVector4 newZ;
newZ.x = fractal->transformCommon.constantMultiplier121.x * z2.x
- fractal->transformCommon.additionConstant0555.x * (z2.y + z2.z);
newZ.y = fractal->transformCommon.constantMultiplier121.y * z.x * z.y * z.z;
newZ.z = fractal->transformCommon.constantMultiplier121.z * z2.z
- fractal->transformCommon.additionConstant0555.z * (z2.x + z2.y);
newZ.w = z.w;
z = newZ + z;
}
/**
* Buffalo fractal
*/
void BuffaloIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
aux.DE = aux.DE * 2.0 * aux.r;
if (fractal->buffalo.preabsx) z.x = fabs(z.x);
if (fractal->buffalo.preabsy) z.y = fabs(z.y);
if (fractal->buffalo.preabsz) z.z = fabs(z.z);
double x2 = z.x * z.x;
double y2 = z.y * z.y;
double z2 = z.z * z.z;
double temp = 1.0 - z2 / (x2 + y2);
double newx = (x2 - y2) * temp;
double newy = 2.0 * z.x * z.y * temp;
double newz = (fractal->buffalo.posz ? 2.0 : -2.0) * z.z * sqrt(x2 + y2);
z.x = fractal->buffalo.absx ? fabs(newx) : newx;
z.y = fractal->buffalo.absy ? fabs(newy) : newy;
z.z = fractal->buffalo.absz ? fabs(newz) : newz;
}
/**
* Fractal formula created by Robert Pancoast
*/
void CoastalbrotIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
Q_UNUSED(fractal);
double temp = aux.r;
temp = pow(temp, 7.7);
aux.DE = temp * aux.DE * 7.7;
temp *= aux.r;
z.x = sin(sin(sin(M_PI / 3 + z.x * M_PI)));
z.y = sin(sin(sin(M_PI / 3 + z.y * M_PI)));
z.z = sin(sin(sin(M_PI / 3 + z.z * M_PI)));
z *= temp;
}
/**
* From M3D
* @reference http://www.fractalforums.com/3d-fractal-generation/another-shot-at-the-holy-grail/
*/
void QuickDudleyIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
Q_UNUSED(fractal);
Q_UNUSED(aux);
double x2 = z.x * z.x;
double y2 = z.y * z.y;
double z2 = z.z * z.z;
double newx = x2 - 2.0 * z.y * z.z;
double newy = z2 + 2.0 * z.x * z.y;
double newz = y2 + 2.0 * z.x * z.z;
z.x = newx;
z.y = newy;
z.z = newz;
}
/**
* From M3D
* @reference http://www.fractalforums.com/3d-fractal-generation/another-shot-at-the-holy-grail/
*/
void QuickDudleyModIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
Q_UNUSED(aux);
double x2 = z.x * z.x;
double y2 = z.y * z.y;
double z2 = z.z * z.z;
double newx = x2 * fractal->transformCommon.constantMultiplier111.x
- fractal->transformCommon.constantMultiplier222.x * z.y * z.z;
double newy = z2 * fractal->transformCommon.constantMultiplier111.y
+ fractal->transformCommon.constantMultiplier222.y * z.x * z.y;
double newz = y2 * fractal->transformCommon.constantMultiplier111.z
+ fractal->transformCommon.constantMultiplier222.z * z.z * z.x;
z.x = newx;
z.y = newy;
z.z = newz;
}
/**
* LkmitchIteration
* @reference http://www.fractalforums.com/3d-fractal-generation/another-shot-at-the-holy-grail/
*/
void LkmitchIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
Q_UNUSED(fractal);
Q_UNUSED(aux);
double x2 = z.x * z.x;
double y2 = z.y * z.y;
double z2 = z.z * z.z;
double newx = x2 - 2.0 * z.y * z.z;
double newy = z2 + 2.0 * z.x * z.y;
double newz = y2 - 2.0 * z.x * z.z;
z.x = newx;
z.y = newy;
z.z = newz;
}
/**
* Makin3D-2 found through the another shot at the holy grail topic at ff
* @reference http://www.fractalforums.com/3d-fractal-generation/another-shot-at-the-holy-grail/
*/
void Makin3d2Iteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
Q_UNUSED(fractal);
Q_UNUSED(aux);
double x2 = z.x * z.x;
double y2 = z.y * z.y;
double z2 = z.z * z.z;
double newx = x2 + 2.0 * z.y * z.z;
double newy = -y2 - 2.0 * z.x * z.z;
double newz = -z2 + 2.0 * z.x * z.y;
z.x = newx;
z.y = newy;
z.z = newz;
}
// NEW FORMULAS-----------------------------------------------------------------
/**
* aBoxMod1, a variation of Mandelbox fractal known as AmazingBox or ABox,
* invented by Tom Lowe in 2010, the variation by DarkBeam
*
* This formula has a different box fold to the standard Tglad fold
* This formula has a c.x c.y SWAP (in compute_fractals.cpp)
* In V2.11 minimum radius is MinimumR2, for settings made in
* older versions, you need to use the square root of the old parameter.
*
* based on DarkBeam's Mandelbulb3D code
*
* @reference
* http://www.fractalforums.com/ifs-iterated-function-systems/amazing-fractal/msg12467/#msg12467
* This formula contains aux.color and aux.actualScale
*/
void AboxMod1Iteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
aux.actualScale =
fractal->mandelbox.scale + fractal->mandelboxVary4D.scaleVary * (fabs(aux.actualScale) - 1.0);
CVector4 c = aux.const_c;
CVector4 oldZ = z;
z.x = fractal->mandelbox.foldingValue
- fabs(fabs(z.x + fractal->transformCommon.additionConstant000.x)
- fractal->mandelbox.foldingValue)
- fabs(fractal->transformCommon.additionConstant000.x);
z.y = fractal->mandelbox.foldingValue
- fabs(fabs(z.y + fractal->transformCommon.additionConstant000.y)
- fractal->mandelbox.foldingValue)
- fabs(fractal->transformCommon.additionConstant000.y);
if (fractal->transformCommon.functionEnabledz)
{
z.z = fractal->mandelbox.foldingValue * fractal->transformCommon.scale1
- fabs(fabs(z.z + fractal->transformCommon.additionConstant000.z)
- fractal->mandelbox.foldingValue * fractal->transformCommon.scale1)
- fabs(fractal->transformCommon.additionConstant000.z);
if (z.z != oldZ.z) aux.color += fractal->mandelbox.color.factor.z;
}
if (z.x != oldZ.x) aux.color += fractal->mandelbox.color.factor.x;
if (z.y != oldZ.y) aux.color += fractal->mandelbox.color.factor.y;
double rr = (z.x * z.x + z.y * z.y + z.z * z.z);
if (fractal->transformCommon.functionEnabledFalse)
{
rr = pow(rr, fractal->mandelboxVary4D.rPower);
}
if (rr < fractal->transformCommon.minR0)
{
double tglad_factor1 = fractal->transformCommon.maxR2d1 / fractal->transformCommon.minR0;
z *= tglad_factor1;
aux.DE *= tglad_factor1;
aux.color += fractal->mandelbox.color.factorSp1;
}
else if (rr < fractal->transformCommon.maxR2d1)
{
double tglad_factor2 = fractal->transformCommon.maxR2d1 / rr;
z *= tglad_factor2;
aux.DE *= tglad_factor2;
aux.color += fractal->mandelbox.color.factorSp2;
}
z *= aux.actualScale;
aux.DE = aux.DE * fabs(aux.actualScale) + 1.0;
if (fractal->transformCommon.addCpixelEnabledFalse
&& aux.i >= fractal->transformCommon.startIterationsE
&& aux.i < fractal->transformCommon.stopIterationsE)
{
CVector4 tempC = c;
if (fractal->transformCommon.alternateEnabledFalse) // alternate
{
tempC = aux.c;
switch (fractal->mandelbulbMulti.orderOfXYZ)
{
case multi_OrderOfXYZ_xyz:
default: tempC = CVector4(tempC.x, tempC.y, tempC.z, tempC.w); break;
case multi_OrderOfXYZ_xzy: tempC = CVector4(tempC.x, tempC.z, tempC.y, tempC.w); break;
case multi_OrderOfXYZ_yxz: tempC = CVector4(tempC.y, tempC.x, tempC.z, tempC.w); break;
case multi_OrderOfXYZ_yzx: tempC = CVector4(tempC.y, tempC.z, tempC.x, tempC.w); break;
case multi_OrderOfXYZ_zxy: tempC = CVector4(tempC.z, tempC.x, tempC.y, tempC.w); break;
case multi_OrderOfXYZ_zyx: tempC = CVector4(tempC.z, tempC.y, tempC.x, tempC.w); break;
}
aux.c = tempC;
}
else
{
switch (fractal->mandelbulbMulti.orderOfXYZ)
{
case multi_OrderOfXYZ_xyz:
default: tempC = CVector4(c.x, c.y, c.z, c.w); break;
case multi_OrderOfXYZ_xzy: tempC = CVector4(c.x, c.z, c.y, c.w); break;
case multi_OrderOfXYZ_yxz: tempC = CVector4(c.y, c.x, c.z, c.w); break;
case multi_OrderOfXYZ_yzx: tempC = CVector4(c.y, c.z, c.x, c.w); break;
case multi_OrderOfXYZ_zxy: tempC = CVector4(c.z, c.x, c.y, c.w); break;
case multi_OrderOfXYZ_zyx: tempC = CVector4(c.z, c.y, c.x, c.w); break;
}
}
z += tempC * fractal->transformCommon.constantMultiplier111;
}
if (fractal->transformCommon.rotationEnabled && aux.i >= fractal->transformCommon.startIterationsR
&& aux.i < fractal->transformCommon.stopIterationsR)
{
z = fractal->transformCommon.rotationMatrix.RotateVector(z);
}
}
/**
* aBoxMod2, a variation of the Mandelbox fractal known as AmazingBox or ABox,
* invented by Tom Lowe in 2010, this variation by DarkBeam
*
* The formula Cylinder Half Size transform changes the spherical fold
* In V2.11 minimum radius is MinimumR2, for settings made in
* older versions, you need to use the square root of the old parameter.
* V.12 added full Mbox color controls
*
* based on DarkBeam's Mandelbulb3D code
*
* @reference
* http://www.fractalforums.com/ifs-iterated-function-systems/amazing-fractal/msg12467/#msg12467
* This formula contains aux.color and aux.actualScale
*/
void AboxMod2Iteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
CVector4 c = aux.const_c;
double colorAdd = 0.0;
aux.actualScale =
fractal->mandelbox.scale + fractal->mandelboxVary4D.scaleVary * (fabs(aux.actualScale) - 1.0);
// Tglad Fold
CVector4 oldZ = z;
z.x = fabs(z.x + fractal->transformCommon.additionConstant111.x)
- fabs(z.x - fractal->transformCommon.additionConstant111.x) - z.x;
z.y = fabs(z.y + fractal->transformCommon.additionConstant111.y)
- fabs(z.y - fractal->transformCommon.additionConstant111.y) - z.y;
if (fractal->transformCommon.functionEnabledM)
{
z.z = fabs(z.z + fractal->transformCommon.additionConstant111.z)
- fabs(z.z - fractal->transformCommon.additionConstant111.z) - z.z;
}
if (z.x != oldZ.x) colorAdd += fractal->mandelbox.color.factor.x;
if (z.y != oldZ.y) colorAdd += fractal->mandelbox.color.factor.y;
if (z.z != oldZ.z) colorAdd += fractal->mandelbox.color.factor.z;
/* double rr;
if (temp > 0.0)
rr = z.x * z.x + z.y * z.y + z.z * z.z; // on top & bottom of cyl. z.z should be tempZ
else
rr = z.x * z.x + z.y * z.y; // on cyl body*/
// cylinder half size
double tempZ = fabs(z.z) - fractal->transformCommon.offset05;
double rr = z.x * z.x + z.y * z.y;
if (tempZ > 0.0) rr = rr + (tempZ * tempZ * fractal->transformCommon.scale1);
// rPower
if (fractal->transformCommon.functionEnabledFalse)
{
rr = pow(rr, fractal->mandelboxVary4D.rPower);
}
// Spherical Fold
if (rr < fractal->transformCommon.minR2p25)
{
z *= fractal->transformCommon.maxMinR2factor;
aux.DE *= fractal->transformCommon.maxMinR2factor;
colorAdd += fractal->mandelbox.color.factorSp1;
}
else if (rr < fractal->transformCommon.maxR2d1)
{
double tglad_factor2 = fractal->transformCommon.maxR2d1 / rr;
z *= tglad_factor2;
aux.DE *= tglad_factor2;
colorAdd += fractal->mandelbox.color.factorSp2;
}
// Scale
z *= aux.actualScale;
aux.DE = aux.DE * fabs(aux.actualScale) + 1.0;
// addCpixel
if (fractal->transformCommon.addCpixelEnabledFalse
&& aux.i >= fractal->transformCommon.startIterationsE
&& aux.i < fractal->transformCommon.stopIterationsE)
{
CVector4 tempC = c;
if (fractal->transformCommon.alternateEnabledFalse) // alternate
{
tempC = aux.c;
switch (fractal->mandelbulbMulti.orderOfXYZ)
{
case multi_OrderOfXYZ_xyz:
default: tempC = CVector4(tempC.x, tempC.y, tempC.z, tempC.w); break;
case multi_OrderOfXYZ_xzy: tempC = CVector4(tempC.x, tempC.z, tempC.y, tempC.w); break;
case multi_OrderOfXYZ_yxz: tempC = CVector4(tempC.y, tempC.x, tempC.z, tempC.w); break;
case multi_OrderOfXYZ_yzx: tempC = CVector4(tempC.y, tempC.z, tempC.x, tempC.w); break;
case multi_OrderOfXYZ_zxy: tempC = CVector4(tempC.z, tempC.x, tempC.y, tempC.w); break;
case multi_OrderOfXYZ_zyx: tempC = CVector4(tempC.z, tempC.y, tempC.x, tempC.w); break;
}
aux.c = tempC;
}
else
{
switch (fractal->mandelbulbMulti.orderOfXYZ)
{
case multi_OrderOfXYZ_xyz:
default: tempC = CVector4(c.x, c.y, c.z, c.w); break;
case multi_OrderOfXYZ_xzy: tempC = CVector4(c.x, c.z, c.y, c.w); break;
case multi_OrderOfXYZ_yxz: tempC = CVector4(c.y, c.x, c.z, c.w); break;
case multi_OrderOfXYZ_yzx: tempC = CVector4(c.y, c.z, c.x, c.w); break;
case multi_OrderOfXYZ_zxy: tempC = CVector4(c.z, c.x, c.y, c.w); break;
case multi_OrderOfXYZ_zyx: tempC = CVector4(c.z, c.y, c.x, c.w); break;
}
}
z += tempC * fractal->transformCommon.constantMultiplier111;
}
// rotation
if (fractal->transformCommon.rotationEnabled && aux.i >= fractal->transformCommon.startIterationsR
&& aux.i < fractal->transformCommon.stopIterationsR)
{
z = fractal->transformCommon.rotationMatrix.RotateVector(z);
}
// color updated v2.14
if (fractal->foldColor.auxColorEnabled)
{
aux.color += colorAdd;
}
}
/**
* ABoxMod11,
* The Mandelbox fractal known as AmazingBox or ABox, invented by Tom Lowe in 2010
* Variations from DarkBeam, Buddhi, Eiffie and mclarekin
* based on DarkBeam's Mandelbulb3D code
* @reference
* http://www.fractalforums.com/ifs-iterated-function-systems/amazing-fractal/msg12467/#msg12467
* This formula contains aux.color and aux.actualScale
*/
void AboxMod11Iteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
double colorAdd = 0.0;
aux.actualScale =
fractal->mandelbox.scale + fractal->mandelboxVary4D.scaleVary * (fabs(aux.actualScale) - 1.0);
CVector4 c = aux.const_c;
// tglad fold
CVector4 oldZ = z;
if (aux.i >= fractal->transformCommon.startIterationsB
&& aux.i < fractal->transformCommon.stopIterationsB)
{
z.x = fabs(z.x + fractal->transformCommon.additionConstant111.x)
- fabs(z.x - fractal->transformCommon.additionConstant111.x) - z.x;
z.y = fabs(z.y + fractal->transformCommon.additionConstant111.y)
- fabs(z.y - fractal->transformCommon.additionConstant111.y) - z.y;
if (fractal->transformCommon.functionEnabled)
{
z.z = fabs(z.z + fractal->transformCommon.additionConstant111.z)
- fabs(z.z - fractal->transformCommon.additionConstant111.z) - z.z;
}
if (z.x != oldZ.x) colorAdd += fractal->mandelbox.color.factor.x;
if (z.y != oldZ.y) colorAdd += fractal->mandelbox.color.factor.y;
if (z.z != oldZ.z) colorAdd += fractal->mandelbox.color.factor.z;
}
if (fractal->transformCommon.functionEnabledFalse
&& aux.i >= fractal->transformCommon.startIterationsD
&& aux.i < fractal->transformCommon.stopIterationsD1)
{
CVector4 limit = fractal->transformCommon.additionConstant111;
CVector4 length = 2.0 * limit;
CVector4 tgladS = 1.0 / length;
CVector4 Add;
Add.w = 0.0;
if (fabs(z.x) < limit.x) Add.x = z.x * z.x * tgladS.x;
if (fabs(z.y) < limit.y) Add.y = z.y * z.y * tgladS.y;
if (fabs(z.z) < limit.z) Add.z = z.z * z.z * tgladS.z;
if (fabs(z.x) > limit.x && fabs(z.x) < length.x)
Add.x = (length.x - fabs(z.x)) * (length.x - fabs(z.x)) * tgladS.x;
if (fabs(z.y) > limit.y && fabs(z.y) < length.y)
Add.y = (length.y - fabs(z.y)) * (length.y - fabs(z.y)) * tgladS.y;
if (fabs(z.z) > limit.z && fabs(z.z) < length.z)
Add.z = (length.z - fabs(z.z)) * (length.z - fabs(z.z)) * tgladS.z;
Add *= fractal->transformCommon.scale3D000;
z.x = (z.x - (sign(z.x) * (Add.x)));
z.y = (z.y - (sign(z.y) * (Add.y)));
z.z = (z.z - (sign(z.z) * (Add.z)));
}
// swap
if (fractal->transformCommon.functionEnabledSwFalse)
{
z = CVector4(z.z, z.y, z.x, z.w);
}
// spherical fold
if (aux.i >= fractal->transformCommon.startIterationsS
&& aux.i < fractal->transformCommon.stopIterationsS)
{
double para = 0.0;
double paraAddP0 = 0.0;
if (fractal->transformCommon.functionEnabledyFalse)
{
// para += paraAddP0 + fractal->transformCommon.minR2p25;
if (fractal->Cpara.enabledLinear)
{
para = fractal->Cpara.para00; // parameter value at iter 0
double temp0 = para;
double tempA = fractal->Cpara.paraA;
double tempB = fractal->Cpara.paraB;
double tempC = fractal->Cpara.paraC;
double lengthAB = fractal->Cpara.iterB - fractal->Cpara.iterA;
double lengthBC = fractal->Cpara.iterC - fractal->Cpara.iterB;
double grade1 = (tempA - temp0) / fractal->Cpara.iterA;
double grade2 = (tempB - tempA) / lengthAB;
double grade3 = (tempC - tempB) / lengthBC;
// slopes
if (aux.i < fractal->Cpara.iterA)
{
para = temp0 + (aux.i * grade1);
}
if (aux.i < fractal->Cpara.iterB && aux.i >= fractal->Cpara.iterA)
{
para = tempA + (aux.i - fractal->Cpara.iterA) * grade2;
}
if (aux.i >= fractal->Cpara.iterB)
{
para = tempB + (aux.i - fractal->Cpara.iterB) * grade3;
}
// Curvi part on "true"
if (fractal->Cpara.enabledCurves)
{
double paraAdd = 0.0;
double paraIt;
if (lengthAB > 2.0 * fractal->Cpara.iterA) // stop error, todo fix.
{
double curve1 = (grade2 - grade1) / (4.0 * fractal->Cpara.iterA);
double tempL = lengthAB - fractal->Cpara.iterA;
double curve2 = (grade3 - grade2) / (4.0 * tempL);
if (aux.i < 2 * fractal->Cpara.iterA)
{
paraIt = tempA - fabs(tempA - aux.i);
paraAdd = paraIt * paraIt * curve1;
}
if (aux.i >= 2 * fractal->Cpara.iterA && aux.i < fractal->Cpara.iterB + tempL)
{
paraIt = tempB - fabs(tempB * aux.i);
paraAdd = paraIt * paraIt * curve2;
}
para += paraAdd;
}
}
}
paraAddP0 = 0.0;
if (fractal->Cpara.enabledParabFalse)
{ // parabolic = paraOffset + iter *slope + (iter *iter *scale)
paraAddP0 = fractal->Cpara.parabOffset0 + (aux.i * fractal->Cpara.parabSlope)
+ (aux.i * aux.i * 0.001 * fractal->Cpara.parabScale);
}
}
para += paraAddP0 + fractal->transformCommon.minR2p25;
// spherical fold
double rr = z.Dot(z);
z += fractal->mandelbox.offset;
// if (r2 < 1e-21) r2 = 1e-21;
if (rr < para)
{
double tglad_factor1 = fractal->transformCommon.maxR2d1 / para;
z *= tglad_factor1;
aux.DE *= tglad_factor1;
colorAdd += fractal->mandelbox.color.factorSp1;
}
else if (rr < fractal->transformCommon.maxR2d1)
{
double tglad_factor2 = fractal->transformCommon.maxR2d1 / rr;
z *= tglad_factor2;
aux.DE *= tglad_factor2;
colorAdd += fractal->mandelbox.color.factorSp2;
}
z -= fractal->mandelbox.offset;
}
// scale, incl DarkBeam's Scale vary
if (aux.i >= fractal->transformCommon.startIterationsA
&& aux.i < fractal->transformCommon.stopIterationsA)
{
z *= aux.actualScale;
if (!fractal->analyticDE.enabledFalse)
aux.DE = aux.DE * fabs(aux.actualScale) + 1.0;
else
aux.DE =
aux.DE * fabs(aux.actualScale) * fractal->analyticDE.scale1 + fractal->analyticDE.offset1;
}
// offset
z += fractal->transformCommon.additionConstant000;
// addCpixel
if (fractal->transformCommon.addCpixelEnabledFalse
&& aux.i >= fractal->transformCommon.startIterationsE
&& aux.i < fractal->transformCommon.stopIterationsE)
{
CVector4 tempC = c;
if (fractal->transformCommon.alternateEnabledFalse) // alternate
{
tempC = aux.c;
switch (fractal->mandelbulbMulti.orderOfXYZ)
{
case multi_OrderOfXYZ_xyz:
default: tempC = CVector4(tempC.x, tempC.y, tempC.z, tempC.w); break;
case multi_OrderOfXYZ_xzy: tempC = CVector4(tempC.x, tempC.z, tempC.y, tempC.w); break;
case multi_OrderOfXYZ_yxz: tempC = CVector4(tempC.y, tempC.x, tempC.z, tempC.w); break;
case multi_OrderOfXYZ_yzx: tempC = CVector4(tempC.y, tempC.z, tempC.x, tempC.w); break;
case multi_OrderOfXYZ_zxy: tempC = CVector4(tempC.z, tempC.x, tempC.y, tempC.w); break;
case multi_OrderOfXYZ_zyx: tempC = CVector4(tempC.z, tempC.y, tempC.x, tempC.w); break;
}
aux.c = tempC;
}
else
{
switch (fractal->mandelbulbMulti.orderOfXYZ)
{
case multi_OrderOfXYZ_xyz:
default: tempC = CVector4(c.x, c.y, c.z, c.w); break;
case multi_OrderOfXYZ_xzy: tempC = CVector4(c.x, c.z, c.y, c.w); break;
case multi_OrderOfXYZ_yxz: tempC = CVector4(c.y, c.x, c.z, c.w); break;
case multi_OrderOfXYZ_yzx: tempC = CVector4(c.y, c.z, c.x, c.w); break;
case multi_OrderOfXYZ_zxy: tempC = CVector4(c.z, c.x, c.y, c.w); break;
case multi_OrderOfXYZ_zyx: tempC = CVector4(c.z, c.y, c.x, c.w); break;
}
}
z += tempC * fractal->transformCommon.constantMultiplier111;
}
// rotation
if (fractal->transformCommon.rotationEnabled && aux.i >= fractal->transformCommon.startIterationsR
&& aux.i < fractal->transformCommon.stopIterationsR)
{
z = fractal->transformCommon.rotationMatrix.RotateVector(z);
}
// tweak scale
if (aux.i >= fractal->transformCommon.startIterationsC
&& aux.i < fractal->transformCommon.stopIterationsC1)
{
z *= fractal->transformCommon.scaleG1;
aux.DE = aux.DE * fabs(fractal->transformCommon.scaleG1);
}
// color updated v2.14
if (fractal->foldColor.auxColorEnabled)
{
aux.color += colorAdd;
}
}
/**
* ABoxMod12,
* The Mandelbox fractal known as AmazingBox or ABox, invented by Tom Lowe in 2010
* Variations from DarkBeam, Buddhi, Eiffie and mclarekin
* based on DarkBeam's Mandelbulb3D code
* @reference
* http://www.fractalforums.com/ifs-iterated-function-systems/amazing-fractal/msg12467/#msg12467
* This formula contains aux.color and aux.actualScaleA
*/
void AboxMod12Iteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
CVector4 c = aux.const_c;
double colorAdd = 0.0;
// tglad fold
CVector4 oldZ = z;
if (aux.i >= fractal->transformCommon.startIterationsA
&& aux.i < fractal->transformCommon.stopIterationsA)
{
z.x = fabs(z.x + fractal->transformCommon.additionConstant111.x)
- fabs(z.x - fractal->transformCommon.additionConstant111.x) - z.x;
z.y = fabs(z.y + fractal->transformCommon.additionConstant111.y)
- fabs(z.y - fractal->transformCommon.additionConstant111.y) - z.y;
if (fractal->transformCommon.functionEnabled)
{
z.z = fabs(z.z + fractal->transformCommon.additionConstant111.z)
- fabs(z.z - fractal->transformCommon.additionConstant111.z) - z.z;
}
if (fractal->foldColor.auxColorEnabledFalse)
{
if (z.x != oldZ.x) colorAdd += fractal->mandelbox.color.factor.x;
if (z.y != oldZ.y) colorAdd += fractal->mandelbox.color.factor.y;
if (z.z != oldZ.z) colorAdd += fractal->mandelbox.color.factor.z;
}
}
if (fractal->transformCommon.functionEnabledFalse
&& aux.i >= fractal->transformCommon.startIterationsD
&& aux.i < fractal->transformCommon.stopIterationsD1)
{
CVector4 limit = fractal->transformCommon.additionConstant111;
CVector4 length = 2.0 * limit;
CVector4 tgladS = 1.0 / length;
CVector4 Add;
Add.w = 0.0;
if (fabs(z.x) < limit.x) Add.x = z.x * z.x * tgladS.x;
if (fabs(z.y) < limit.y) Add.y = z.y * z.y * tgladS.y;
if (fabs(z.z) < limit.z) Add.z = z.z * z.z * tgladS.z;
if (fabs(z.x) > limit.x && fabs(z.x) < length.x)
Add.x = (length.x - fabs(z.x)) * (length.x - fabs(z.x)) * tgladS.x;
if (fabs(z.y) > limit.y && fabs(z.y) < length.y)
Add.y = (length.y - fabs(z.y)) * (length.y - fabs(z.y)) * tgladS.y;
if (fabs(z.z) > limit.z && fabs(z.z) < length.z)
Add.z = (length.z - fabs(z.z)) * (length.z - fabs(z.z)) * tgladS.z;
Add *= fractal->transformCommon.scale3D000;
z.x = (z.x - (sign(z.x) * (Add.x)));
z.y = (z.y - (sign(z.y) * (Add.y)));
z.z = (z.z - (sign(z.z) * (Add.z)));
}
// swap
if (fractal->transformCommon.functionEnabledSwFalse)
{
z = CVector4(z.z, z.y, z.x, z.w);
}
// spherical folds
if (aux.i >= fractal->transformCommon.startIterationsS
&& aux.i < fractal->transformCommon.stopIterationsS)
{
double minR2 = fractal->transformCommon.minR2p25;
double addR = 0.0;
double m = 1.0;
oldZ = z;
// spherical fold with xyz bias option
if (fractal->transformCommon.functionEnabledAx)
{
if (aux.i >= fractal->transformCommon.startIterationsE
&& aux.i < fractal->transformCommon.stopIterationsE)
{
CVector4 xyzBias = fractal->transformCommon.constantMultiplier000;
if (fractal->transformCommon.functionEnabledAzFalse)
{
xyzBias *= aux.c * aux.c;
}
else
{
xyzBias *= fabs(aux.c);
}
addR = (xyzBias.x + xyzBias.y + xyzBias.z);
minR2 += addR;
if (fractal->transformCommon.functionEnabledAz && minR2 > fractal->transformCommon.maxR2d1)
{ // stop overlapping potential
minR2 = fractal->transformCommon.maxR2d1;
}
}
double rr = z.Dot(z);
z += fractal->transformCommon.offset000;
if (rr < minR2)
{
m *= fractal->transformCommon.maxR2d1 / minR2;
colorAdd += fractal->mandelbox.color.factorSp1;
}
else if (rr < fractal->transformCommon.maxR2d1)
{
m *= fractal->transformCommon.maxR2d1 / rr;
colorAdd += fractal->mandelbox.color.factorSp2;
}
z -= fractal->transformCommon.offset000;
// scale
z *= m;
aux.DE *= fabs(m);
}
// cuboid
if (fractal->transformCommon.functionEnabledAyFalse
&& aux.i >= fractal->transformCommon.startIterationsB
&& aux.i < fractal->transformCommon.stopIterationsB)
{
CVector4 temp3;
CVector4 R2;
double MinR2 = fractal->transformCommon.minR2p25;
CVector4 limitMinR2 = fractal->transformCommon.scaleP222;
double rr = z.Dot(z);
z += fractal->transformCommon.offset000;
// if (aux.i >= fractal->transformCommon.startIterationsD
// && aux.i < fractal->transformCommon.stopIterationsD)
//{
if (fractal->transformCommon.functionEnabledAxFalse)
temp3 = z * z;
else
temp3 = fabs(z);
if (temp3.x < limitMinR2.x && temp3.y < limitMinR2.y && temp3.z < limitMinR2.z)
{ // if inside cuboid
R2.x = limitMinR2.x / temp3.x;
R2.y = limitMinR2.y / temp3.y;
R2.z = limitMinR2.z / temp3.z;
double First = min(R2.x, min(R2.y, R2.z));
MinR2 = rr * First;
// if (fractal->transformCommon.functionEnabled && MinR2 > fractal->transformCommon.maxR2d1)
if (MinR2 > fractal->transformCommon.maxR2d1)
{ // stop overlapping potential
MinR2 = fractal->transformCommon.maxR2d1;
}
m *= fractal->transformCommon.maxR2d1 / MinR2;
aux.color += fractal->mandelbox.color.factorSp1;
}
else if (rr < fractal->transformCommon.maxR2d1)
{
m *= fractal->transformCommon.maxR2d1 / rr;
aux.color += fractal->mandelbox.color.factorSp2;
}
z -= fractal->transformCommon.offset000;
// scale
z *= m;
aux.DE *= fabs(m);
}
// if not use standard Mbox sphere fold
if (z.x == oldZ.x && z.y == oldZ.y && z.z == oldZ.z && z.w == oldZ.w)
{
double MinR2 = fractal->transformCommon.minR2p25;
double rr = z.Dot(z);
z += fractal->transformCommon.offset000;
if (rr < MinR2)
{
m *= fractal->transformCommon.maxR2d1 / MinR2;
aux.color += fractal->mandelbox.color.factorSp1;
}
else if (rr < fractal->transformCommon.maxR2d1)
{
m *= fractal->transformCommon.maxR2d1 / rr;
aux.color += fractal->mandelbox.color.factorSp2;
}
z -= fractal->transformCommon.offset000;
// scale
z *= m;
aux.DE *= fabs(m);
}
}
double useScale = fractal->mandelbox.scale;
if (fractal->transformCommon.functionEnabledXFalse
&& aux.i >= fractal->transformCommon.startIterationsX
&& aux.i < fractal->transformCommon.stopIterationsX)
{
useScale += aux.actualScaleA;
z *= useScale;
aux.DE = aux.DE * fabs(useScale) + 1.0;
// update actualScale for next iteration
double vary = fractal->transformCommon.scaleVary0
* (fabs(aux.actualScaleA) - fractal->transformCommon.scaleB1);
if (fractal->transformCommon.functionEnabledMFalse)
aux.actualScaleA = -vary;
else
aux.actualScaleA = aux.actualScaleA - vary;
}
else
{
z *= useScale;
aux.DE = aux.DE * fabs(useScale) + 1.0;
}
// offset
z += fractal->transformCommon.additionConstant000;
// addCpixel
if (fractal->transformCommon.addCpixelEnabledFalse
&& aux.i >= fractal->transformCommon.startIterationsC
&& aux.i < fractal->transformCommon.stopIterationsC)
{
CVector4 tempC = c;
if (fractal->transformCommon.alternateEnabledFalse) // alternate
{
tempC = aux.c;
switch (fractal->mandelbulbMulti.orderOfXYZ)
{
case multi_OrderOfXYZ_xyz:
default: tempC = CVector4(tempC.x, tempC.y, tempC.z, tempC.w); break;
case multi_OrderOfXYZ_xzy: tempC = CVector4(tempC.x, tempC.z, tempC.y, tempC.w); break;
case multi_OrderOfXYZ_yxz: tempC = CVector4(tempC.y, tempC.x, tempC.z, tempC.w); break;
case multi_OrderOfXYZ_yzx: tempC = CVector4(tempC.y, tempC.z, tempC.x, tempC.w); break;
case multi_OrderOfXYZ_zxy: tempC = CVector4(tempC.z, tempC.x, tempC.y, tempC.w); break;
case multi_OrderOfXYZ_zyx: tempC = CVector4(tempC.z, tempC.y, tempC.x, tempC.w); break;
}
aux.c = tempC;
}
else
{
switch (fractal->mandelbulbMulti.orderOfXYZ)
{
case multi_OrderOfXYZ_xyz:
default: tempC = CVector4(c.x, c.y, c.z, c.w); break;
case multi_OrderOfXYZ_xzy: tempC = CVector4(c.x, c.z, c.y, c.w); break;
case multi_OrderOfXYZ_yxz: tempC = CVector4(c.y, c.x, c.z, c.w); break;
case multi_OrderOfXYZ_yzx: tempC = CVector4(c.y, c.z, c.x, c.w); break;
case multi_OrderOfXYZ_zxy: tempC = CVector4(c.z, c.x, c.y, c.w); break;
case multi_OrderOfXYZ_zyx: tempC = CVector4(c.z, c.y, c.x, c.w); break;
}
}
z += tempC * fractal->transformCommon.constantMultiplier111;
}
// rotation
if (fractal->transformCommon.rotationEnabled && aux.i >= fractal->transformCommon.startIterationsR
&& aux.i < fractal->transformCommon.stopIterationsR)
{
z = fractal->transformCommon.rotationMatrix.RotateVector(z);
}
// color updated v2.13
if (fractal->foldColor.auxColorEnabled)
{
aux.color += colorAdd;
}
}
/**
* ABoxMod13,
* The Mandelbox fractal known as AmazingBox or ABox, invented by Tom Lowe in 2010
* Variations from DarkBeam, Buddhi, Eiffie and mclarekin
* based on DarkBeam's Mandelbulb3D code
* @reference
* http://www.fractalforums.com/ifs-iterated-function-systems/amazing-fractal/msg12467/#msg12467
* This formula contains aux.color, aux.pos_neg and aux.actualScaleA
*/
void AboxMod13Iteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
CVector4 c = aux.const_c;
double colorAdd = 0.0;
// invert c
if (fractal->transformCommon.functionEnabledAzFalse
&& aux.i >= fractal->transformCommon.startIterationsE
&& aux.i < fractal->transformCommon.stopIterationsE)
{
if (fractal->transformCommon.functionEnabledAyFalse)
{
aux.c *= fractal->transformCommon.scale3D111;
double rSqrL = aux.c.Dot(aux.c);
rSqrL = 1.0 / rSqrL;
aux.c *= rSqrL;
z += aux.c;
}
else
{
c *= fractal->transformCommon.scale3D111;
double rSqrL = c.Dot(c);
rSqrL = 1.0 / rSqrL;
z += c * rSqrL;
}
}
// tglad fold
CVector4 oldZ = z;
if (aux.i >= fractal->transformCommon.startIterationsA
&& aux.i < fractal->transformCommon.stopIterationsA)
{
z.x = fabs(z.x + fractal->transformCommon.additionConstant111.x)
- fabs(z.x - fractal->transformCommon.additionConstant111.x) - z.x;
z.y = fabs(z.y + fractal->transformCommon.additionConstant111.y)
- fabs(z.y - fractal->transformCommon.additionConstant111.y) - z.y;
if (fractal->transformCommon.functionEnabled)
{
z.z = fabs(z.z + fractal->transformCommon.additionConstant111.z)
- fabs(z.z - fractal->transformCommon.additionConstant111.z) - z.z;
}
if (fractal->foldColor.auxColorEnabledFalse)
{
if (z.x != oldZ.x) colorAdd += fractal->mandelbox.color.factor.x;
if (z.y != oldZ.y) colorAdd += fractal->mandelbox.color.factor.y;
if (z.z != oldZ.z) colorAdd += fractal->mandelbox.color.factor.z;
}
}
if (fractal->transformCommon.functionEnabledFalse
&& aux.i >= fractal->transformCommon.startIterationsD
&& aux.i < fractal->transformCommon.stopIterationsD1)
{
CVector4 limit = fractal->transformCommon.additionConstant111;
CVector4 length = 2.0 * limit;
CVector4 tgladS = 1.0 / length;
CVector4 Add = CVector4(0.0, 0.0, 0.0, 0.0);
Add.w = 0.0;
if (fabs(z.x) < limit.x) Add.x = z.x * z.x * tgladS.x;
if (fabs(z.y) < limit.y) Add.y = z.y * z.y * tgladS.y;
if (fabs(z.z) < limit.z) Add.z = z.z * z.z * tgladS.z;
if (fabs(z.x) > limit.x && fabs(z.x) < length.x)
Add.x = (length.x - fabs(z.x)) * (length.x - fabs(z.x)) * tgladS.x;
if (fabs(z.y) > limit.y && fabs(z.y) < length.y)
Add.y = (length.y - fabs(z.y)) * (length.y - fabs(z.y)) * tgladS.y;
if (fabs(z.z) > limit.z && fabs(z.z) < length.z)
Add.z = (length.z - fabs(z.z)) * (length.z - fabs(z.z)) * tgladS.z;
Add *= fractal->transformCommon.scale3D000;
z.x = (z.x - (sign(z.x) * (Add.x)));
z.y = (z.y - (sign(z.y) * (Add.y)));
z.z = (z.z - (sign(z.z) * (Add.z)));
}
// swap
if (fractal->transformCommon.functionEnabledSwFalse)
{
z = CVector4(z.z, z.y, z.x, z.w);
}
// spherical fold
double rr = z.Dot(z);
z += fractal->mandelbox.offset;
// if (r2 < 1e-21) r2 = 1e-21;
if (rr < fractal->transformCommon.minR2p25)
{
double tglad_factor1 = fractal->transformCommon.maxR2d1 / fractal->transformCommon.minR2p25;
z *= tglad_factor1;
aux.DE *= tglad_factor1;
colorAdd += fractal->mandelbox.color.factorSp1;
}
else if (rr < fractal->transformCommon.maxR2d1)
{
double tglad_factor2 = fractal->transformCommon.maxR2d1 / rr;
z *= tglad_factor2;
aux.DE *= tglad_factor2;
colorAdd += fractal->mandelbox.color.factorSp2;
}
z -= fractal->mandelbox.offset;
double useScale = fractal->mandelbox.scale;
if (fractal->transformCommon.functionEnabledXFalse
&& aux.i >= fractal->transformCommon.startIterationsX
&& aux.i < fractal->transformCommon.stopIterationsX)
{
useScale += aux.actualScaleA;
z *= useScale;
aux.DE = aux.DE * fabs(useScale) + 1.0;
// update actualScale for next iteration
double vary = fractal->transformCommon.scaleVary0
* (fabs(aux.actualScaleA) - fractal->transformCommon.scaleB1);
if (fractal->transformCommon.functionEnabledMFalse)
aux.actualScaleA = -vary;
else
aux.actualScaleA = aux.actualScaleA - vary;
}
else
{
z *= useScale;
aux.DE = aux.DE * fabs(useScale) + 1.0;
}
// offset
if (aux.i >= fractal->transformCommon.startIterationsB
&& aux.i < fractal->transformCommon.stopIterationsB)
{
if (fractal->transformCommon.functionEnabledAxFalse)
{
CVector4 offsetAlt = aux.pos_neg * fractal->transformCommon.additionConstant000;
z += offsetAlt;
aux.pos_neg *= -1.0 * fractal->transformCommon.scale1;
}
else
{
z += fractal->transformCommon.additionConstant000;
}
}
// addCpixel
if (fractal->transformCommon.addCpixelEnabledFalse
&& aux.i >= fractal->transformCommon.startIterationsC
&& aux.i < fractal->transformCommon.stopIterationsC)
{
CVector4 tempC = c;
if (fractal->transformCommon.alternateEnabledFalse) // alternate
{
tempC = aux.c;
switch (fractal->mandelbulbMulti.orderOfXYZ)
{
case multi_OrderOfXYZ_xyz:
default: tempC = CVector4(tempC.x, tempC.y, tempC.z, tempC.w); break;
case multi_OrderOfXYZ_xzy: tempC = CVector4(tempC.x, tempC.z, tempC.y, tempC.w); break;
case multi_OrderOfXYZ_yxz: tempC = CVector4(tempC.y, tempC.x, tempC.z, tempC.w); break;
case multi_OrderOfXYZ_yzx: tempC = CVector4(tempC.y, tempC.z, tempC.x, tempC.w); break;
case multi_OrderOfXYZ_zxy: tempC = CVector4(tempC.z, tempC.x, tempC.y, tempC.w); break;
case multi_OrderOfXYZ_zyx: tempC = CVector4(tempC.z, tempC.y, tempC.x, tempC.w); break;
}
aux.c = tempC;
}
else
{
switch (fractal->mandelbulbMulti.orderOfXYZ)
{
case multi_OrderOfXYZ_xyz:
default: tempC = CVector4(c.x, c.y, c.z, c.w); break;
case multi_OrderOfXYZ_xzy: tempC = CVector4(c.x, c.z, c.y, c.w); break;
case multi_OrderOfXYZ_yxz: tempC = CVector4(c.y, c.x, c.z, c.w); break;
case multi_OrderOfXYZ_yzx: tempC = CVector4(c.y, c.z, c.x, c.w); break;
case multi_OrderOfXYZ_zxy: tempC = CVector4(c.z, c.x, c.y, c.w); break;
case multi_OrderOfXYZ_zyx: tempC = CVector4(c.z, c.y, c.x, c.w); break;
}
}
z += tempC * fractal->transformCommon.constantMultiplier111;
}
// rotation
if (fractal->transformCommon.rotationEnabled && aux.i >= fractal->transformCommon.startIterationsR
&& aux.i < fractal->transformCommon.stopIterationsR)
{
z = fractal->transformCommon.rotationMatrix.RotateVector(z);
}
// color updated v2.13
if (fractal->foldColor.auxColorEnabled)
{
aux.color += colorAdd;
}
}
/**
* ABoxModKali, a formula from Mandelbulb3D
* @reference http://www.fractalforums.com/new-theories-and-research/aboxmodkali-the-2d-version/
*/
void AboxModKaliIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
z = fractal->transformCommon.additionConstant0555 - fabs(z);
double rr = z.Dot(z);
double MinR = fractal->transformCommon.minR06;
double dividend = rr < MinR ? MinR : min(rr, 1.0);
double m = fractal->transformCommon.scale015 / dividend;
z = z * m;
aux.DE = aux.DE * fabs(m) + 1.0;
}
/**
* ABoxModKaliEiffie, modified formula from Mandelbulb3D
* @reference http://www.fractalforums.com/new-theories-and-research/aboxmodkali-the-2d-version/
* This formula contains aux.color
*/
void AboxModKaliEiffieIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
CVector4 c = aux.const_c;
double colorAdd = 0.0;
CVector4 oldZ = z;
z.x = fabs(z.x + fractal->transformCommon.additionConstant111.x)
- fabs(z.x - fractal->transformCommon.additionConstant111.x) - z.x;
z.y = fabs(z.y + fractal->transformCommon.additionConstant111.y)
- fabs(z.y - fractal->transformCommon.additionConstant111.y) - z.y;
if (fractal->transformCommon.functionEnabledM)
{
z.z = fabs(z.z + fractal->transformCommon.additionConstant111.z)
- fabs(z.z - fractal->transformCommon.additionConstant111.z) - z.z;
}
if (z.x != oldZ.x) colorAdd += fractal->mandelbox.color.factor.x;
if (z.y != oldZ.y) colorAdd += fractal->mandelbox.color.factor.y;
if (z.z != oldZ.z) colorAdd += fractal->mandelbox.color.factor.z;
if (fractal->transformCommon.functionEnabledxFalse
&& aux.i >= fractal->transformCommon.startIterationsA
&& aux.i < fractal->transformCommon.stopIterationsA) // box fold z.z
{
double zLimit =
fractal->transformCommon.additionConstant111.z * fractal->transformCommon.scale1;
double zValue = fractal->mandelbox.foldingValue * fractal->transformCommon.scale1;
if (fabs(z.z) > zLimit)
{
z.z = sign(z.z) * zValue - z.z;
colorAdd += fractal->mandelbox.color.factor.z;
}
}
if (fractal->transformCommon.functionEnabled)
{
z = CVector4(z.z, z.y, z.x, z.w); // swap
}
if (z.y > z.x) z = CVector4(z.y, z.x, z.z, z.w); // conditional
double rr = z.Dot(z);
double MinR = fractal->transformCommon.minR05;
double m = fractal->transformCommon.scale015;
if (rr < MinR)
{
m = m / MinR;
colorAdd += fractal->mandelbox.color.factorSp1;
}
else
{
if (rr < 1.0)
{
m = m / rr;
colorAdd += fractal->mandelbox.color.factorSp2;
}
}
z = z * m;
aux.DE = aux.DE * fabs(m) + 1.0;
z += fractal->transformCommon.additionConstant000;
if (fractal->transformCommon.addCpixelEnabledFalse)
{
CVector4 tempC = c;
if (fractal->transformCommon.alternateEnabledFalse) // alternate
{
tempC = aux.c;
switch (fractal->mandelbulbMulti.orderOfXYZ)
{
case multi_OrderOfXYZ_xyz:
default: tempC = CVector4(tempC.x, tempC.y, tempC.z, tempC.w); break;
case multi_OrderOfXYZ_xzy: tempC = CVector4(tempC.x, tempC.z, tempC.y, tempC.w); break;
case multi_OrderOfXYZ_yxz: tempC = CVector4(tempC.y, tempC.x, tempC.z, tempC.w); break;
case multi_OrderOfXYZ_yzx: tempC = CVector4(tempC.y, tempC.z, tempC.x, tempC.w); break;
case multi_OrderOfXYZ_zxy: tempC = CVector4(tempC.z, tempC.x, tempC.y, tempC.w); break;
case multi_OrderOfXYZ_zyx: tempC = CVector4(tempC.z, tempC.y, tempC.x, tempC.w); break;
}
aux.c = tempC;
}
else
{
switch (fractal->mandelbulbMulti.orderOfXYZ)
{
case multi_OrderOfXYZ_xyz:
default: tempC = CVector4(c.x, c.y, c.z, c.w); break;
case multi_OrderOfXYZ_xzy: tempC = CVector4(c.x, c.z, c.y, c.w); break;
case multi_OrderOfXYZ_yxz: tempC = CVector4(c.y, c.x, c.z, c.w); break;
case multi_OrderOfXYZ_yzx: tempC = CVector4(c.y, c.z, c.x, c.w); break;
case multi_OrderOfXYZ_zxy: tempC = CVector4(c.z, c.x, c.y, c.w); break;
case multi_OrderOfXYZ_zyx: tempC = CVector4(c.z, c.y, c.x, c.w); break;
}
}
z += tempC * fractal->transformCommon.constantMultiplier111;
}
if (fractal->transformCommon.rotationEnabled && aux.i >= fractal->transformCommon.startIterations
&& aux.i < fractal->transformCommon.stopIterations)
{
z = fractal->transformCommon.rotationMatrix.RotateVector(z);
}
if (fractal->foldColor.auxColorEnabled)
{
aux.color += colorAdd;
}
}
/**
* ABoxModKaliV2, a formula from Mandelbulb3D
* @reference http://www.fractalforums.com/new-theories-and-research/aboxmodkali-the-2d-version/
*/
void AboxModKaliV2Iteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
CVector4 c = aux.const_c;
double colorAdd = 0.0;
// fold
CVector4 oldZ = z;
z.x = fractal->transformCommon.additionConstant0555.x - fabs(z.x);
z.y = fractal->transformCommon.additionConstant0555.y - fabs(z.y);
if (fractal->transformCommon.functionEnabledM)
{
z.z = fractal->transformCommon.additionConstant0555.z - fabs(z.z);
}
CVector4 postZ = z;
// spherical fold & scaling
double rr = z.Dot(z);
// z += fractal->transformCommon.additionConstant000;
double m = fractal->transformCommon.scale015;
if (rr < fractal->transformCommon.minR2p25)
{
m *= fractal->transformCommon.maxR2d1 / fractal->transformCommon.minR2p25;
colorAdd += fractal->mandelbox.color.factorSp1;
}
else if (rr < fractal->transformCommon.maxR2d1)
{
m *= fractal->transformCommon.maxR2d1 / rr;
colorAdd += fractal->mandelbox.color.factorSp2;
}
// z -= fractal->transformCommon.additionConstant000;
z = z * m;
aux.DE = aux.DE * fabs(m) + 1.0;
z += fractal->transformCommon.additionConstant000;
// rotation
if (fractal->transformCommon.rotationEnabled && aux.i >= fractal->transformCommon.startIterations
&& aux.i < fractal->transformCommon.stopIterations)
{
z = fractal->transformCommon.rotationMatrix.RotateVector(z);
}
z += fractal->transformCommon.additionConstant000;
// add cpixel symmetrical
if (fractal->transformCommon.addCpixelEnabledFalse
&& aux.i >= fractal->transformCommon.startIterationsC
&& aux.i < fractal->transformCommon.stopIterationsC)
{
CVector4 tempFAB = c;
if (fractal->transformCommon.functionEnabledx) tempFAB.x = fabs(tempFAB.x);
if (fractal->transformCommon.functionEnabledy) tempFAB.y = fabs(tempFAB.y);
if (fractal->transformCommon.functionEnabledz) tempFAB.z = fabs(tempFAB.z);
tempFAB *= fractal->transformCommon.constantMultiplier000;
z.x += sign(z.x) * tempFAB.x;
z.y += sign(z.y) * tempFAB.y;
z.z += sign(z.z) * tempFAB.z;
}
// aux.color controls
if (fractal->foldColor.auxColorEnabledFalse)
{
postZ -= oldZ;
if (postZ.x < 1.0) aux.color += fractal->mandelbox.color.factor.x;
if (postZ.y < 1.0) aux.color += fractal->mandelbox.color.factor.y;
if (postZ.z < 1.0) aux.color += fractal->mandelbox.color.factor.z;
aux.color += colorAdd;
}
}
/**
* ABoxModKali V3, a formula from Mandelbulb3D
* @reference http://www.fractalforums.com/new-theories-and-research/aboxmodkali-the-2d-version/
*/
void AboxModKaliV3Iteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
if (aux.i >= fractal->transformCommon.startIterationsA
&& aux.i < fractal->transformCommon.stopIterations15)
{
z = fractal->transformCommon.offset111 - fabs(z);
double rr = z.Dot(z);
double MinR = fractal->transformCommon.minR0;
double dividend = rr < MinR ? MinR : min(rr, 1.0);
double m = -fractal->transformCommon.scale015 / dividend;
z = z * m;
aux.DE = aux.DE * fabs(m) + 1.0;
}
if (aux.i >= fractal->transformCommon.startIterationsB
&& aux.i < fractal->transformCommon.stopIterationsB)
{
z += fractal->transformCommon.offsetA111;
}
// TODO add the options
}
/**
* ABoxVS_icen1, a formula from Mandelbulb3D.
* Inspired from a 2D formula proposed by Kali at Fractal Forums
* @reference
* http://www.fractalforums.com/new-theories-and-research/kaliset-plus-boxfold-nice-new-2d-fractal/msg33670/#new
* This formula contains aux.color and aux.actualScale
*/
void AboxVSIcen1Iteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
aux.actualScale =
fractal->mandelbox.scale + fractal->mandelboxVary4D.scaleVary * (fabs(aux.actualScale) - 1.0);
CVector4 c = aux.const_c;
CVector4 oldZ = z;
z.x = fabs(z.x + fractal->transformCommon.additionConstant111.x)
- fabs(z.x - fractal->transformCommon.additionConstant111.x) - z.x;
z.y = fabs(z.y + fractal->transformCommon.additionConstant111.y)
- fabs(z.y - fractal->transformCommon.additionConstant111.y) - z.y;
z.z = fabs(z.z + fractal->transformCommon.additionConstant111.z)
- fabs(z.z - fractal->transformCommon.additionConstant111.z) - z.z;
if (z.x != oldZ.x) aux.color += fractal->mandelbox.color.factor.x;
if (z.y != oldZ.y) aux.color += fractal->mandelbox.color.factor.y;
if (z.z != oldZ.z) aux.color += fractal->mandelbox.color.factor.z;
if (fractal->transformCommon.juliaMode)
{
z += c * fractal->transformCommon.constantMultiplier111;
}
else
{
z += fractal->transformCommon.juliaC;
}
double r2 = z.Dot(z);
// if (r2 < 1e-21 && r2 > -1e-21)
// r2 = (r2 > 0) ? 1e-21 : -1e-21;
if (r2 < fractal->mandelbox.mR2)
{
z *= fractal->mandelbox.mboxFactor1;
aux.DE *= fractal->mandelbox.mboxFactor1;
aux.color += fractal->mandelbox.color.factorSp1;
}
else if (r2 < fractal->mandelbox.fR2)
{
double tglad_factor2 = fractal->mandelbox.fR2 / r2;
z *= tglad_factor2;
aux.DE *= tglad_factor2;
aux.color += fractal->mandelbox.color.factorSp2;
}
z *= aux.actualScale; // aux.actualScale;
aux.DE = aux.DE * fabs(aux.actualScale) + 1.0;
if (fractal->transformCommon.rotationEnabled && aux.i >= fractal->transformCommon.startIterations
&& aux.i < fractal->transformCommon.stopIterations)
{
z = fractal->transformCommon.rotationMatrix.RotateVector(z);
}
if (fractal->transformCommon.juliaMode)
{
z += fractal->transformCommon.juliaC - c * fractal->transformCommon.constantMultiplier111;
}
else
{
z += c * fractal->transformCommon.constantMultiplier111 + fractal->transformCommon.juliaC;
}
}
/**
* aexion octopus. Based on Aex_Octo from Mandelbulber3D
* @reference
* http://www.fractalforums.com/mandelbulb-3d/custom-formulas-and-transforms-release-t17106/
*/
void AexionOctopusModIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
CVector4 c = aux.const_c;
CVector4 tempN;
tempN.x = z.x * z.z * fractal->transformCommon.scale3D111.x;
tempN.y = (z.x * z.x - z.z * z.z) * fractal->transformCommon.scale3D111.y;
tempN.z = z.y;
tempN.w = z.w;
if (fractal->transformCommon.functionEnabledAx) tempN.x = fabs(tempN.x);
if (fractal->transformCommon.functionEnabledAy) tempN.y = fabs(tempN.y);
if (fractal->transformCommon.functionEnabledAz) tempN.z = fabs(tempN.z);
z = tempN;
if (fractal->transformCommon.rotationEnabled)
z = fractal->transformCommon.rotationMatrix.RotateVector(z);
z += fractal->transformCommon.additionConstant000;
if (fractal->transformCommon.addCpixelEnabledFalse)
{
CVector4 tempFAB = c;
if (fractal->transformCommon.functionEnabledx) tempFAB.x = fabs(tempFAB.x);
if (fractal->transformCommon.functionEnabledy) tempFAB.y = fabs(tempFAB.y);
if (fractal->transformCommon.functionEnabledz) tempFAB.z = fabs(tempFAB.z);
tempFAB *= fractal->transformCommon.constantMultiplier000;
z.x += sign(z.x) * tempFAB.x;
z.y += sign(z.y) * tempFAB.y;
z.z += sign(z.z) * tempFAB.z;
}
}
/**
* amazing surf from Mandelbulber3D. Formula proposed by Kali, with features added by DarkBeam
*
* This formula has a c.x c.y SWAP
*
* @reference
* http://www.fractalforums.com/mandelbulb-3d/custom-formulas-and-transforms-release-t17106/
*/
void AmazingSurfIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
// update aux.actualScale
aux.actualScale =
fractal->mandelbox.scale + fractal->mandelboxVary4D.scaleVary * (fabs(aux.actualScale) - 1.0);
CVector4 c = aux.const_c;
z.x = fabs(z.x + fractal->transformCommon.additionConstant111.x)
- fabs(z.x - fractal->transformCommon.additionConstant111.x) - z.x;
z.y = fabs(z.y + fractal->transformCommon.additionConstant111.y)
- fabs(z.y - fractal->transformCommon.additionConstant111.y) - z.y;
// no z fold
double rr = z.Dot(z);
if (fractal->transformCommon.functionEnabledFalse) // force cylinder fold
rr -= z.z * z.z;
double sqrtMinR = sqrt(fractal->transformCommon.minR05);
double dividend = rr < sqrtMinR ? sqrtMinR : min(rr, 1.0);
/*if (rr < sqrtMinR)
{
aux.color += fractal->mandelbox.color.factorSp1;
}
else if (rr < 1.0)
{
aux.color += fractal->mandelbox.color.factorSp2;
}*/
// use aux.actualScale
double m = aux.actualScale / dividend;
z *= (m - 1.0) * fractal->transformCommon.scale1 + 1.0;
// z *= m * fractal->transformCommon.scale1 + 1.0 * (1.0 - fractal->transformCommon.scale1);
aux.DE = aux.DE * fabs(m) + 1.0;
if (fractal->transformCommon.addCpixelEnabledFalse)
z += CVector4(c.y, c.x, c.z, c.w) * fractal->transformCommon.constantMultiplier111;
z = fractal->transformCommon.rotationMatrix.RotateVector(z);
}
/**
* Based on Amazing Surf Mod 1 from Mandelbulber3D, a formula proposed by Kali,
* with features added by DarkBeam
* @reference
* http://www.fractalforums.com/mandelbulb-3d/custom-formulas-and-transforms-release-t17106/
* This formula contains aux.color and aux.actualScale
*/
void AmazingSurfMod1Iteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
double colorAdd = 0.0;
aux.actualScale =
fractal->mandelbox.scale + fractal->mandelboxVary4D.scaleVary * (fabs(aux.actualScale) - 1.0);
CVector4 oldZ = z;
if (fractal->transformCommon.functionEnabledAx)
{
z.x = fabs(z.x + fractal->transformCommon.additionConstant111.x)
- fabs(z.x - fractal->transformCommon.additionConstant111.x) - z.x;
z.y = fabs(z.y + fractal->transformCommon.additionConstant111.y)
- fabs(z.y - fractal->transformCommon.additionConstant111.y) - z.y;
if (z.x != oldZ.x) colorAdd += fractal->mandelbox.color.factor.x;
if (z.y != oldZ.y) colorAdd += fractal->mandelbox.color.factor.y;
}
// z = fold - fabs( fabs(z) - fold)
if (fractal->transformCommon.functionEnabledAyFalse)
{
z.x = fractal->transformCommon.additionConstant111.x
- fabs(fabs(z.x) - fractal->transformCommon.additionConstant111.x);
z.y = fractal->transformCommon.additionConstant111.y
- fabs(fabs(z.y) - fractal->transformCommon.additionConstant111.y);
if (z.x != oldZ.x) colorAdd += fractal->mandelbox.color.factor.x;
if (z.y != oldZ.y) colorAdd += fractal->mandelbox.color.factor.y;
}
if (fractal->transformCommon.functionEnabledAzFalse)
{
z.x = fabs(z.x + fractal->transformCommon.additionConstant111.x);
z.y = fabs(z.y + fractal->transformCommon.additionConstant111.y);
if (z.x != oldZ.x) colorAdd += fractal->mandelbox.color.factor.x;
if (z.y != oldZ.y) colorAdd += fractal->mandelbox.color.factor.y;
}
// if z > limit) z = Value -z, else if z < limit) z = - Value - z,
if (fractal->transformCommon.functionEnabledxFalse)
{
if (fabs(z.x) > fractal->transformCommon.additionConstant111.x)
{
z.x = sign(z.x) * fractal->mandelbox.foldingValue - z.x;
}
if (fabs(z.y) > fractal->transformCommon.additionConstant111.y)
{
z.y = sign(z.y) * fractal->mandelbox.foldingValue - z.y;
}
if (z.x != oldZ.x) colorAdd += fractal->mandelbox.color.factor.x;
if (z.y != oldZ.y) colorAdd += fractal->mandelbox.color.factor.y;
}
// z = fold2 - fabs( fabs(z + fold) - fold2) - fabs(fold)
if (fractal->transformCommon.functionEnabledyFalse)
{
z.x = fractal->transformCommon.offset2
- fabs(fabs(z.x + fractal->transformCommon.additionConstant111.x)
- fractal->transformCommon.offset2)
- fractal->transformCommon.additionConstant111.x;
z.y = fractal->transformCommon.offset2
- fabs(fabs(z.y + fractal->transformCommon.additionConstant111.y)
- fractal->transformCommon.offset2)
- fractal->transformCommon.additionConstant111.y;
if (z.x != oldZ.x) colorAdd += fractal->mandelbox.color.factor.x;
if (z.y != oldZ.y) colorAdd += fractal->mandelbox.color.factor.y;
}
z += fractal->transformCommon.additionConstant000;
double r2;
r2 = z.Dot(z);
if (fractal->transformCommon.functionEnabledFalse) // force cylinder fold
r2 -= z.z * z.z;
// if (r2 < 1e-21)
// r2 = 1e-21;
double sqrtMinR = fractal->transformCommon.sqtR;
if (r2 < sqrtMinR)
{
z *= fractal->transformCommon.mboxFactor1;
aux.DE *= fractal->transformCommon.mboxFactor1;
colorAdd += fractal->mandelbox.color.factorSp1;
}
else if (r2 < 1.0)
{
z *= 1.0 / r2;
aux.DE *= 1.0 / r2;
colorAdd += fractal->mandelbox.color.factorSp2;
}
z *= aux.actualScale * fractal->transformCommon.scale1
+ 1.0 * (1.0 - fractal->transformCommon.scale1);
aux.DE = aux.DE * fabs(aux.actualScale) + 1.0;
z = fractal->transformCommon.rotationMatrix.RotateVector(z);
aux.color += colorAdd;
}
/**
* asurf mod2
* modification of amazing surf from M3D. Formula proposed by Kali, with features added by DarkBeam
*
* Note for the original version apply a c.x c.y SWAP
*
* @reference
* http://www.fractalforums.com/mandelbulb-3d/custom-formulas-and-transforms-release-t17106/
*
* This formula contains aux.color and aux.actualScale
*/
void AmazingSurfMod2Iteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
double colorAdd = 0.0;
double rrCol = 0.0;
CVector4 zCol = z;
CVector4 oldZ = z;
CVector4 c = aux.const_c;
if (fractal->transformCommon.addCpixelEnabledFalse
&& aux.i >= fractal->transformCommon.startIterationsH
&& aux.i < fractal->transformCommon.stopIterationsH)
{
CVector4 tempC = aux.const_c;
if (fractal->transformCommon.alternateEnabledFalse) // alternate
{
tempC = aux.c;
switch (fractal->mandelbulbMulti.orderOfXYZ)
{
case multi_OrderOfXYZ_xyz:
default: tempC = CVector4(tempC.x, tempC.y, tempC.z, tempC.w); break;
case multi_OrderOfXYZ_xzy: tempC = CVector4(tempC.x, tempC.z, tempC.y, tempC.w); break;
case multi_OrderOfXYZ_yxz: tempC = CVector4(tempC.y, tempC.x, tempC.z, tempC.w); break;
case multi_OrderOfXYZ_yzx: tempC = CVector4(tempC.y, tempC.z, tempC.x, tempC.w); break;
case multi_OrderOfXYZ_zxy: tempC = CVector4(tempC.z, tempC.x, tempC.y, tempC.w); break;
case multi_OrderOfXYZ_zyx: tempC = CVector4(tempC.z, tempC.y, tempC.x, tempC.w); break;
}
aux.c = tempC;
}
else
{
switch (fractal->mandelbulbMulti.orderOfXYZ)
{
case multi_OrderOfXYZ_xyz:
default: tempC = CVector4(c.x, c.y, c.z, c.w); break;
case multi_OrderOfXYZ_xzy: tempC = CVector4(c.x, c.z, c.y, c.w); break;
case multi_OrderOfXYZ_yxz: tempC = CVector4(c.y, c.x, c.z, c.w); break;
case multi_OrderOfXYZ_yzx: tempC = CVector4(c.y, c.z, c.x, c.w); break;
case multi_OrderOfXYZ_zxy: tempC = CVector4(c.z, c.x, c.y, c.w); break;
case multi_OrderOfXYZ_zyx: tempC = CVector4(c.z, c.y, c.x, c.w); break;
}
}
if (fractal->transformCommon.rotationEnabled
&& aux.i >= fractal->transformCommon.startIterationsG
&& aux.i < fractal->transformCommon.stopIterationsG)
{
tempC = fractal->transformCommon.rotationMatrix.RotateVector(tempC);
}
z += tempC * fractal->transformCommon.constantMultiplier111;
}
// invert c
if (fractal->transformCommon.functionEnabledCxFalse
&& aux.i >= fractal->transformCommon.startIterationsF
&& aux.i < fractal->transformCommon.stopIterationsF)
{
if (fractal->transformCommon.functionEnabledCyFalse)
{
aux.c *= fractal->transformCommon.scale3D111;
double rSqrL = aux.c.Dot(aux.c);
rSqrL = 1.0 / rSqrL;
aux.c *= rSqrL;
z += aux.c;
}
else
{
c *= fractal->transformCommon.scale3D111;
double rSqrL = c.Dot(c);
rSqrL = 1.0 / rSqrL;
z += c * rSqrL;
}
}
oldZ = z;
/*bool functionEnabledN[5] = {fractal->transformCommon.functionEnabledAx,
fractal->transformCommon.functionEnabledAyFalse,
fractal->transformCommon.functionEnabledAzFalse};
// fractal->transformCommon.functionEnabledBxFalse,
// fractal->transformCommon.functionEnabledByFalse};
int startIterationN[5] = {fractal->transformCommon.startIterationsA,
fractal->transformCommon.startIterationsB, fractal->transformCommon.startIterationsC,
fractal->transformCommon.startIterationsD, fractal->transformCommon.startIterationsE};
int stopIterationN[5] = {fractal->transformCommon.stopIterationsA,
fractal->transformCommon.stopIterationsB, fractal->transformCommon.stopIterationsC,
fractal->transformCommon.stopIterationsD, fractal->transformCommon.stopIterationsE};
enumMulti_orderOfFolds foldN[5] = {fractal->surfFolds.orderOfFolds1,
fractal->surfFolds.orderOfFolds2, fractal->surfFolds.orderOfFolds3,
fractal->surfFolds.orderOfFolds4, fractal->surfFolds.orderOfFolds5};
for (int f = 0; f < 5; f++)*/
bool functionEnabledN[3] = {fractal->transformCommon.functionEnabledAx,
fractal->transformCommon.functionEnabledAyFalse,
fractal->transformCommon.functionEnabledAzFalse};
int startIterationN[3] = {fractal->transformCommon.startIterationsA,
fractal->transformCommon.startIterationsB, fractal->transformCommon.startIterationsC};
int stopIterationN[3] = {fractal->transformCommon.stopIterationsA,
fractal->transformCommon.stopIterationsB, fractal->transformCommon.stopIterationsC};
enumMulti_orderOf3Folds foldN[3] = {fractal->aSurf3Folds.orderOf3Folds1,
fractal->aSurf3Folds.orderOf3Folds2, fractal->aSurf3Folds.orderOf3Folds3};
for (int f = 0; f < 3; f++)
{
if (functionEnabledN[f] && aux.i >= startIterationN[f] && aux.i < stopIterationN[f])
{
switch (foldN[f])
{
case multi_orderOf3Folds_type1: // tglad fold
default:
z.x = fabs(z.x + fractal->transformCommon.additionConstant111.x)
- fabs(z.x - fractal->transformCommon.additionConstant111.x) - z.x;
z.y = fabs(z.y + fractal->transformCommon.additionConstant111.y)
- fabs(z.y - fractal->transformCommon.additionConstant111.y) - z.y;
if (fractal->transformCommon.functionEnabledCzFalse
&& aux.i >= fractal->transformCommon.startIterationsT
&& aux.i < fractal->transformCommon.stopIterationsT1)
{
CVector4 limit = fractal->transformCommon.additionConstant111;
CVector4 length = 2.0 * limit;
CVector4 tgladS = 1.0 / length;
CVector4 Add;
Add.w = 0.0;
if (fabs(z.x) < limit.x) Add.x = z.x * z.x * tgladS.x;
if (fabs(z.y) < limit.y) Add.y = z.y * z.y * tgladS.y;
if (fabs(z.x) > limit.x && fabs(z.x) < length.x)
Add.x = (length.x - fabs(z.x)) * (length.x - fabs(z.x)) * tgladS.x;
if (fabs(z.y) > limit.y && fabs(z.y) < length.y)
Add.y = (length.y - fabs(z.y)) * (length.y - fabs(z.y)) * tgladS.y;
Add *= fractal->transformCommon.scale3D000;
z.x = (z.x - (sign(z.x) * (Add.x)));
z.y = (z.y - (sign(z.y) * (Add.y)));
}
zCol = z;
break;
case multi_orderOf3Folds_type2: // z = fold - fabs( fabs(z) - fold)
z.x = fractal->transformCommon.additionConstant111.x
- fabs(fabs(z.x) - fractal->transformCommon.offset111.x);
z.y = fractal->transformCommon.additionConstant111.y
- fabs(fabs(z.y) - fractal->transformCommon.offset111.y);
zCol = z;
break;
case multi_orderOf3Folds_type3:
// z = fold2 - fabs( fabs(z + fold) - fold2) - fabs(fold), darkbeam's
z.x = fractal->transformCommon.offset2
- fabs(fabs(z.x + fractal->transformCommon.offsetA111.x)
- fractal->transformCommon.offset2)
- fractal->transformCommon.offsetA111.x;
z.y = fractal->transformCommon.offset2
- fabs(fabs(z.y + fractal->transformCommon.offsetA111.y)
- fractal->transformCommon.offset2)
- fractal->transformCommon.offsetA111.y;
zCol = z;
break;
}
}
}
// enable z axis
if (fractal->transformCommon.functionEnabledAxFalse)
{
z.z = fabs(z.z + fractal->transformCommon.additionConstant111.z)
- fabs(z.z - fractal->transformCommon.additionConstant111.z) - z.z;
zCol.z = z.z;
}
// swap
if (fractal->transformCommon.functionEnabledSwFalse)
{
z = CVector4(z.y, z.x, z.z, z.w);
}
// offset
if (fractal->transformCommon.functionEnabledBzFalse
&& aux.i >= fractal->transformCommon.startIterationsX
&& aux.i < fractal->transformCommon.stopIterationsX)
{
if (fractal->transformCommon.functionEnabledBxFalse)
{
CVector4 temp = fractal->transformCommon.additionConstant000;
CVector4 temp2 = temp * temp;
z.x -= ((temp.x * temp2.x) / ((z.x * z.x) + (temp2.x)) - 2.0 * temp.x)
* fractal->transformCommon.scale1;
z.y -= ((temp.y * temp2.y) / ((z.y * z.y) + (temp2.y)) - 2.0 * temp.y)
* fractal->transformCommon.scale1;
z.z -= ((temp.z * temp2.z) / ((z.z * z.z) + (temp2.z)) - 2.0 * temp.z)
* fractal->transformCommon.scale1;
}
else if (fractal->transformCommon.functionEnabledByFalse)
{
CVector4 temp = fractal->transformCommon.additionConstant000;
CVector4 temp2 = temp * temp;
z.x -= ((temp2.x) / ((z.x * z.x) + (temp2.x)) - 2.0 * temp.x)
* fractal->transformCommon.scale1; // * sign(z.x);
z.y -= ((temp2.y) / ((z.y * z.y) + (temp2.y)) - 2.0 * temp.y)
* fractal->transformCommon.scale1; // * sign(z.y);
z.z -= ((temp2.z) / ((z.z * z.z) + (temp2.z)) - 2.0 * temp.z)
* fractal->transformCommon.scale1; // * sign(z.z);
}
}
else
z += fractal->transformCommon.additionConstant000;
// standard functions
if (fractal->transformCommon.functionEnabledAy)
{
double rr = z.Dot(z);
rrCol = rr;
if (fractal->transformCommon.functionEnabledFalse) // force cylinder fold
rr -= z.z * z.z * fractal->transformCommon.scaleB1; // fold weight
// Mandelbox Spherical fold
if (aux.i >= fractal->transformCommon.startIterationsM
&& aux.i < fractal->transformCommon.stopIterationsM)
{
z += fractal->mandelbox.offset;
// if (r2 < 1e-21) r2 = 1e-21;
if (rr < fractal->transformCommon.minR2p25)
{
double tglad_factor1 = fractal->transformCommon.maxR2d1 / fractal->transformCommon.minR2p25;
z *= tglad_factor1;
aux.DE *= tglad_factor1;
}
else if (rr < fractal->transformCommon.maxR2d1)
{
double tglad_factor2 = fractal->transformCommon.maxR2d1 / rr;
z *= tglad_factor2;
aux.DE *= tglad_factor2;
}
z -= fractal->mandelbox.offset;
}
// scale
double useScale = 1.0;
if (aux.i >= fractal->transformCommon.startIterationsS
&& aux.i < fractal->transformCommon.stopIterationsS)
{
useScale = aux.actualScaleA + fractal->mandelbox.scale;
z *= useScale;
if (!fractal->analyticDE.enabledFalse)
aux.DE = aux.DE * fabs(useScale) + 1.0;
else // testing for log
aux.DE = aux.DE * fabs(useScale) * fractal->analyticDE.scale1 + fractal->analyticDE.offset1;
if (fractal->transformCommon.functionEnabledFFalse
&& aux.i >= fractal->transformCommon.startIterationsY
&& aux.i < fractal->transformCommon.stopIterationsY)
{
// update actualScaleA for next iteration
double vary = fractal->transformCommon.scaleVary0
* (fabs(aux.actualScaleA) - fractal->transformCommon.scaleC1);
if (fractal->transformCommon.functionEnabledMFalse)
aux.actualScaleA = -vary;
else
aux.actualScaleA = aux.actualScaleA - vary;
}
}
}
if (fractal->mandelbox.mainRotationEnabled && aux.i >= fractal->transformCommon.startIterationsR
&& aux.i < fractal->transformCommon.stopIterationsR)
z = fractal->mandelbox.mainRot.RotateVector(z);
if (fractal->foldColor.auxColorEnabledFalse)
{
if (zCol.x != oldZ.x)
colorAdd += fractal->mandelbox.color.factor.x
* (fabs(zCol.x) - fractal->transformCommon.additionConstant111.x);
if (zCol.y != oldZ.y)
colorAdd += fractal->mandelbox.color.factor.y
* (fabs(zCol.y) - fractal->transformCommon.additionConstant111.y);
if (zCol.z != oldZ.z)
colorAdd += fractal->mandelbox.color.factor.z
* (fabs(zCol.z) - fractal->transformCommon.additionConstant111.z);
if (rrCol < fractal->transformCommon.maxR2d1)
{
/*if (rrCol < fractal->transformCommon.minR2p25)
colorAdd += fractal->mandelbox.color.factorSp1 * (fractal->transformCommon.minR2p25 - rrCol)
+ fractal->mandelbox.color.factorSp2
* (fractal->transformCommon.maxR2d1 - fractal->transformCommon.minR2p25);
else
colorAdd += fractal->mandelbox.color.factorSp2 * (fractal->transformCommon.maxR2d1 -
rrCol);*/
colorAdd += fractal->mandelbox.color.factorSp2 * (fractal->transformCommon.maxR2d1 - rrCol);
if (rrCol < fractal->transformCommon.minR2p25)
colorAdd += fractal->mandelbox.color.factorSp1 * (fractal->transformCommon.minR2p25 - rrCol)
+ fractal->mandelbox.color.factorSp2
* (fractal->transformCommon.maxR2d1 - fractal->transformCommon.minR2p25);
}
aux.color += colorAdd;
}
}
/**
* Amazing Surface Multi
* Based on Amazing Surf Mod 1 from Mandelbulber3D, a formula proposed by Kali,
* with features added by DarkBeam
* This formula contains aux.color
*/
void AmazingSurfMultiIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
CVector4 c = aux.const_c;
double colorAdd = 0.0;
CVector4 oldZ = z;
bool functionEnabledN[5] = {fractal->transformCommon.functionEnabledAx,
fractal->transformCommon.functionEnabledAyFalse,
fractal->transformCommon.functionEnabledAzFalse,
fractal->transformCommon.functionEnabledBxFalse,
fractal->transformCommon.functionEnabledByFalse};
int startIterationN[5] = {fractal->transformCommon.startIterationsA,
fractal->transformCommon.startIterationsB, fractal->transformCommon.startIterationsC,
fractal->transformCommon.startIterationsD, fractal->transformCommon.startIterationsE};
int stopIterationN[5] = {fractal->transformCommon.stopIterationsA,
fractal->transformCommon.stopIterationsB, fractal->transformCommon.stopIterationsC,
fractal->transformCommon.stopIterationsD, fractal->transformCommon.stopIterationsE};
enumMulti_orderOfFolds foldN[5] = {fractal->surfFolds.orderOfFolds1,
fractal->surfFolds.orderOfFolds2, fractal->surfFolds.orderOfFolds3,
fractal->surfFolds.orderOfFolds4, fractal->surfFolds.orderOfFolds5};
for (int f = 0; f < 5; f++)
{
if (functionEnabledN[f] && aux.i >= startIterationN[f] && aux.i < stopIterationN[f])
{
switch (foldN[f])
{
case multi_orderOfFolds_type1: // tglad fold
default:
z.x = fabs(z.x + fractal->transformCommon.additionConstant111.x)
- fabs(z.x - fractal->transformCommon.additionConstant111.x) - z.x;
z.y = fabs(z.y + fractal->transformCommon.additionConstant111.y)
- fabs(z.y - fractal->transformCommon.additionConstant111.y) - z.y;
if (z.x != oldZ.x) colorAdd += fractal->mandelbox.color.factor.x;
if (z.y != oldZ.y) colorAdd += fractal->mandelbox.color.factor.y;
break;
case multi_orderOfFolds_type2: // z = fold - fabs( fabs(z) - fold)
z.x = fractal->transformCommon.additionConstant111.x
- fabs(fabs(z.x) - fractal->transformCommon.additionConstant111.x);
z.y = fractal->transformCommon.additionConstant111.y
- fabs(fabs(z.y) - fractal->transformCommon.additionConstant111.y);
if (z.x != oldZ.x) colorAdd += fractal->mandelbox.color.factor.x;
if (z.y != oldZ.y) colorAdd += fractal->mandelbox.color.factor.y;
break;
case multi_orderOfFolds_type3:
z.x = fabs(z.x + fractal->transformCommon.additionConstant111.x);
z.y = fabs(z.y + fractal->transformCommon.additionConstant111.y);
break;
case multi_orderOfFolds_type4:
// if z > limit) z = Value -z, else if z < limit) z = - Value - z,
if (fabs(z.x) > fractal->transformCommon.additionConstant111.x)
{
z.x = sign(z.x) * fractal->mandelbox.foldingValue - z.x;
colorAdd += fractal->mandelbox.color.factor.x;
}
if (fabs(z.y) > fractal->transformCommon.additionConstant111.y)
{
z.y = sign(z.y) * fractal->mandelbox.foldingValue - z.y;
colorAdd += fractal->mandelbox.color.factor.y;
}
break;
case multi_orderOfFolds_type5:
// z = fold2 - fabs( fabs(z + fold) - fold2) - fabs(fold)
z.x = fractal->transformCommon.offset2
- fabs(fabs(z.x + fractal->transformCommon.additionConstant111.x)
- fractal->transformCommon.offset2)
- fractal->transformCommon.additionConstant111.x;
z.y = fractal->transformCommon.offset2
- fabs(fabs(z.y + fractal->transformCommon.additionConstant111.y)
- fractal->transformCommon.offset2)
- fractal->transformCommon.additionConstant111.y;
if (z.x != oldZ.x) colorAdd += fractal->mandelbox.color.factor.x;
if (z.y != oldZ.y) colorAdd += fractal->mandelbox.color.factor.y;
break;
}
}
}
if (fractal->transformCommon.functionEnabledAxFalse)
{ // enable z scale
double zLimit = fractal->transformCommon.foldingLimit * fractal->transformCommon.scale0;
double zValue = fractal->transformCommon.foldingValue * fractal->transformCommon.scale0;
if (fabs(z.z) > zLimit)
{
z.z = sign(z.z) * zValue - z.z;
}
}
z += fractal->transformCommon.additionConstant000;
// standard functions
if (fractal->transformCommon.functionEnabledAy)
{
double rr;
rr = z.Dot(z);
if (fractal->transformCommon.functionEnabledFalse) // force cylinder fold
rr -= z.z * z.z * fractal->transformCommon.scaleB1; // fold weight ;
if (fractal->transformCommon.functionEnabledAz
&& aux.i >= fractal->transformCommon.startIterationsT
&& aux.i < fractal->transformCommon.stopIterationsT)
{
// Abox Spherical fold
z += fractal->mandelbox.offset;
double sqrtMinR = fractal->transformCommon.sqtR;
if (rr < sqrtMinR)
{
z *= fractal->transformCommon.mboxFactor1;
aux.DE *= fractal->transformCommon.mboxFactor1;
colorAdd += fractal->mandelbox.color.factorSp1;
}
else if (rr < 1.0)
{
z *= 1.0 / rr;
aux.DE *= 1.0 / rr;
colorAdd += fractal->mandelbox.color.factorSp2;
}
z -= fractal->mandelbox.offset;
}
// Mandelbox Spherical fold
if (fractal->transformCommon.functionEnabledzFalse
&& aux.i >= fractal->transformCommon.startIterationsM
&& aux.i < fractal->transformCommon.stopIterationsM)
{
// r2 = z.Dot(z);
z += fractal->mandelbox.offset;
if (rr < fractal->mandelbox.mR2) // mR2 = minR^2
{
z *= fractal->mandelbox.mboxFactor1; // fR2/mR2
aux.DE *= fractal->mandelbox.mboxFactor1;
colorAdd += fractal->mandelbox.color.factorSp1;
}
else if (rr < fractal->mandelbox.fR2)
{
double tglad_factor2 = fractal->mandelbox.fR2 / rr;
z *= tglad_factor2;
aux.DE *= tglad_factor2;
colorAdd += fractal->mandelbox.color.factorSp2;
}
z -= fractal->mandelbox.offset;
}
if (aux.i >= fractal->transformCommon.startIterationsS
&& aux.i < fractal->transformCommon.stopIterationsS)
{ // scale
z *= fractal->mandelbox.scale * fractal->transformCommon.scale1
+ 1.0 * (1.0 - fractal->transformCommon.scale1);
aux.DE = aux.DE * fabs(fractal->mandelbox.scale) + 1.0;
}
}
if (fractal->transformCommon.addCpixelEnabledFalse)
{
CVector4 tempC = c;
if (fractal->transformCommon.alternateEnabledFalse) // alternate
{
tempC = aux.c;
switch (fractal->mandelbulbMulti.orderOfXYZ)
{
case multi_OrderOfXYZ_xyz:
default: tempC = CVector4(tempC.x, tempC.y, tempC.z, tempC.w); break;
case multi_OrderOfXYZ_xzy: tempC = CVector4(tempC.x, tempC.z, tempC.y, tempC.w); break;
case multi_OrderOfXYZ_yxz: tempC = CVector4(tempC.y, tempC.x, tempC.z, tempC.w); break;
case multi_OrderOfXYZ_yzx: tempC = CVector4(tempC.y, tempC.z, tempC.x, tempC.w); break;
case multi_OrderOfXYZ_zxy: tempC = CVector4(tempC.z, tempC.x, tempC.y, tempC.w); break;
case multi_OrderOfXYZ_zyx: tempC = CVector4(tempC.z, tempC.y, tempC.x, tempC.w); break;
}
aux.c = tempC;
}
else
{
switch (fractal->mandelbulbMulti.orderOfXYZ)
{
case multi_OrderOfXYZ_xyz:
default: tempC = CVector4(c.x, c.y, c.z, c.w); break;
case multi_OrderOfXYZ_xzy: tempC = CVector4(c.x, c.z, c.y, c.w); break;
case multi_OrderOfXYZ_yxz: tempC = CVector4(c.y, c.x, c.z, c.w); break;
case multi_OrderOfXYZ_yzx: tempC = CVector4(c.y, c.z, c.x, c.w); break;
case multi_OrderOfXYZ_zxy: tempC = CVector4(c.z, c.x, c.y, c.w); break;
case multi_OrderOfXYZ_zyx: tempC = CVector4(c.z, c.y, c.x, c.w); break;
}
}
z += tempC * fractal->transformCommon.constantMultiplier111;
}
if (fractal->mandelbox.mainRotationEnabled && aux.i >= fractal->transformCommon.startIterationsR
&& aux.i < fractal->transformCommon.stopIterationsR)
z = fractal->mandelbox.mainRot.RotateVector(z);
aux.color += colorAdd;
}
/**
* benesiFastPwr2PineTree 3D
* @reference
* http://www.fractalforums.com/new-theories-and-research/
* do-m3d-formula-have-to-be-distance-estimation-formulas/
*/
void BenesiPineTreeIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
aux.DE = aux.r * aux.DE * 2.0 + 1.0;
CVector4 c = aux.const_c;
CVector4 temp = z;
z *= z;
double t = 2.0 * temp.x;
if (z.y + z.z > 0.0)
t = t / sqrt(z.y + z.z);
else
t = 1.0;
z.x = (z.x - z.y - z.z) + c.x * fractal->transformCommon.constantMultiplier100.x;
z.z = (t * (z.y - z.z)) + c.y * fractal->transformCommon.constantMultiplier100.y;
z.y = (2.0 * t * temp.y * temp.z) + c.z * fractal->transformCommon.constantMultiplier100.z;
if (fractal->transformCommon.angle0 != 0)
{
double tempY = z.y;
double beta = fractal->transformCommon.angle0 * M_PI_180;
z.y = z.y * cos(beta) + z.z * sin(beta);
z.z = tempY * -sin(beta) + z.z * cos(beta);
}
}
/**
* benesiT1PineTree 3D
* @reference
* http://www.fractalforums.com/new-theories-and-research/
* do-m3d-formula-have-to-be-distance-estimation-formulas/
*/
void BenesiT1PineTreeIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
CVector4 c = aux.const_c;
if (fractal->transformCommon.benesiT1Enabled && aux.i >= fractal->transformCommon.startIterations
&& aux.i < fractal->transformCommon.stopIterations)
{
double tempXZ = z.x * SQRT_2_3 - z.z * SQRT_1_3;
z = CVector4(
(tempXZ - z.y) * SQRT_1_2, (tempXZ + z.y) * SQRT_1_2, z.x * SQRT_1_3 + z.z * SQRT_2_3, z.w);
CVector4 temp = z;
double tempL = temp.Length();
z = fabs(z) * fractal->transformCommon.scale3D222;
// if (tempL < 1e-21) tempL = 1e-21;
double avgScale = z.Length() / tempL;
aux.DE *= avgScale; // pos
if (fractal->transformCommon.rotationEnabled)
{
z = fractal->transformCommon.rotationMatrix.RotateVector(z);
}
tempXZ = (z.y + z.x) * SQRT_1_2;
z = CVector4(z.z * SQRT_1_3 + tempXZ * SQRT_2_3, (z.y - z.x) * SQRT_1_2,
z.z * SQRT_2_3 - tempXZ * SQRT_1_3, z.w);
z = z - fractal->transformCommon.offset200;
}
if (fractal->transformCommon.addCpixelEnabled
&& aux.i >= fractal->transformCommon.startIterationsC
&& aux.i < fractal->transformCommon.stopIterationsC)
{
CVector4 temp = z;
aux.r = z.Length();
z *= z;
double t = 2.0 * temp.x;
if (z.y + z.z > 0.0)
t = t / sqrt(z.y + z.z);
else
t = 1.0;
CVector4 tempC = c;
if (fractal->transformCommon.alternateEnabledFalse) // alternate
{
tempC = CVector4(aux.c.x, aux.c.z, aux.c.y, aux.c.w);
aux.c = tempC;
}
else
{
tempC = CVector4(c.x, c.z, c.y, c.w);
}
z.x = (z.x - z.y - z.z) + tempC.x * fractal->transformCommon.constantMultiplier100.x;
z.z = (t * (z.y - z.z)) + tempC.z * fractal->transformCommon.constantMultiplier100.y;
z.y = (2.0 * t * temp.y * temp.z) + tempC.y * fractal->transformCommon.constantMultiplier100.z;
aux.DE = aux.r * aux.DE * 2.0 + 1.0;
}
if (fractal->transformCommon.functionEnabledBxFalse
&& aux.i >= fractal->transformCommon.startIterationsD
&& aux.i < fractal->transformCommon.stopIterationsD)
{
z = CVector4(z.x * cos(z.y * fractal->transformCommon.scale1),
z.x * sin(z.y * fractal->transformCommon.scale1), z.z * fractal->transformCommon.scaleC1,
z.w)
* fractal->transformCommon.scaleA1;
aux.DE *= fabs(fractal->transformCommon.scaleA1);
}
if (fractal->transformCommon.juliaMode)
{
z.x += fractal->transformCommon.offset000.x;
z.y += fractal->transformCommon.offset000.y;
z.z += fractal->transformCommon.offset000.z;
}
if (fractal->transformCommon.rotation2EnabledFalse)
{
z = fractal->transformCommon.rotationMatrix2.RotateVector(z);
}
}
/**
* benesiMagTransforms
* @reference
* http://www.fractalforums.com/new-theories-and-research/
* do-m3d-formula-have-to-be-distance-estimation-formulas/
*/
void BenesiMagTransformsIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
CVector4 c = aux.const_c;
if (fractal->transformCommon.benesiT1Enabled && aux.i >= fractal->transformCommon.startIterations
&& aux.i < fractal->transformCommon.stopIterations)
{
double tempXZ = z.x * SQRT_2_3 - z.z * SQRT_1_3;
z = CVector4(
(tempXZ - z.y) * SQRT_1_2, (tempXZ + z.y) * SQRT_1_2, z.x * SQRT_1_3 + z.z * SQRT_2_3, z.w);
CVector4 temp = z;
double tempL = temp.Length();
z = fabs(z) * fractal->transformCommon.scale3D222;
// if (tempL < 1e-21) tempL = 1e-21;
double avgScale = z.Length() / tempL; // pos
aux.DE = aux.DE * avgScale + 1.0;
tempXZ = (z.y + z.x) * SQRT_1_2;
z = CVector4(z.z * SQRT_1_3 + tempXZ * SQRT_2_3, (z.y - z.x) * SQRT_1_2,
z.z * SQRT_2_3 - tempXZ * SQRT_1_3, z.w);
z = z - fractal->transformCommon.offset200;
}
if (fractal->transformCommon.rotationEnabled)
z = fractal->transformCommon.rotationMatrix.RotateVector(z);
if (fractal->transformCommon.addCpixelEnabled
&& aux.i >= fractal->transformCommon.startIterationsT
&& aux.i < fractal->transformCommon.stopIterationsT)
{
CVector4 temp = z;
aux.r = z.Length();
z *= z;
double t = 2.0 * temp.x;
if (z.y + z.z > 0.0)
t = t / sqrt(z.y + z.z);
else
t = 1.0;
if (fractal->transformCommon.addCpixelEnabled)
{
CVector4 tempC = c;
if (fractal->transformCommon.alternateEnabledFalse) // alternate
{
tempC = CVector4(aux.c.x, aux.c.z, aux.c.y, aux.c.w);
aux.c = tempC;
}
else
{
tempC = CVector4(c.x, c.z, c.y, c.w);
}
z.x = (z.x - z.y - z.z) + tempC.x * fractal->transformCommon.constantMultiplier100.x;
z.z = (t * (z.y - z.z)) + tempC.z * fractal->transformCommon.constantMultiplier100.y;
z.y =
(2.0 * t * temp.y * temp.z) + tempC.y * fractal->transformCommon.constantMultiplier100.z;
}
aux.DE = aux.r * aux.DE * 2.0 + 1.0;
}
if (fractal->transformCommon.juliaMode)
{
z.x += fractal->transformCommon.juliaC.x * fractal->transformCommon.constantMultiplier100.x;
z.z += fractal->transformCommon.juliaC.y * fractal->transformCommon.constantMultiplier100.y;
z.y += fractal->transformCommon.juliaC.z * fractal->transformCommon.constantMultiplier100.z;
}
// additional transform slot controls
bool functionEnabledN[5] = {fractal->transformCommon.functionEnabledAxFalse,
fractal->transformCommon.functionEnabledAyFalse,
fractal->transformCommon.functionEnabledAzFalse,
fractal->transformCommon.functionEnabledBxFalse,
fractal->transformCommon.functionEnabledByFalse};
int startIterationN[5] = {fractal->transformCommon.startIterationsA,
fractal->transformCommon.startIterationsB, fractal->transformCommon.startIterationsC,
fractal->transformCommon.startIterationsD, fractal->transformCommon.startIterationsE};
int stopIterationN[5] = {fractal->transformCommon.stopIterationsA,
fractal->transformCommon.stopIterationsB, fractal->transformCommon.stopIterationsC,
fractal->transformCommon.stopIterationsD, fractal->transformCommon.stopIterationsE};
enumMulti_orderOfTransf transfN[5] = {fractal->magTransf.orderOfTransf1,
fractal->magTransf.orderOfTransf2, fractal->magTransf.orderOfTransf3,
fractal->magTransf.orderOfTransf4, fractal->magTransf.orderOfTransf5};
for (int f = 0; f < 5; f++)
{
if (functionEnabledN[f] && aux.i >= startIterationN[f] && aux.i < stopIterationN[f])
{
double tempXZ;
double tempL;
CVector4 temp;
double avgScale;
CVector4 tempV2;
switch (transfN[f])
{
case multi_orderOfTransf_typeT1:
default:
tempXZ = z.x * SQRT_2_3 - z.z * SQRT_1_3;
z = CVector4((tempXZ - z.y) * SQRT_1_2, (tempXZ + z.y) * SQRT_1_2,
z.x * SQRT_1_3 + z.z * SQRT_2_3, z.w);
z = fabs(z) * fractal->transformCommon.scale3Da222;
tempL = temp.Length();
// if (tempL < 1e-21) tempL = 1e-21;
avgScale = z.Length() / tempL;
aux.DE = aux.DE * avgScale + 1.0;
tempXZ = (z.y + z.x) * SQRT_1_2;
z = CVector4(z.z * SQRT_1_3 + tempXZ * SQRT_2_3, (z.y - z.x) * SQRT_1_2,
z.z * SQRT_2_3 - tempXZ * SQRT_1_3, z.w);
z = z - fractal->transformCommon.offsetA200;
break;
case multi_orderOfTransf_typeT1Mod:
tempXZ = z.x * SQRT_2_3 - z.z * SQRT_1_3;
z = CVector4((tempXZ - z.y) * SQRT_1_2, (tempXZ + z.y) * SQRT_1_2,
z.x * SQRT_1_3 + z.z * SQRT_2_3, z.w);
z = fabs(z) * fractal->transformCommon.scale3D333;
tempL = temp.Length();
// if (tempL < 1e-21) tempL = 1e-21;
avgScale = z.Length() / tempL;
aux.DE = aux.DE * avgScale + 1.0;
z = (fabs(z + fractal->transformCommon.offset111)
- fabs(z - fractal->transformCommon.offset111) - z);
tempXZ = (z.y + z.x) * SQRT_1_2;
z = CVector4(z.z * SQRT_1_3 + tempXZ * SQRT_2_3, (z.y - z.x) * SQRT_1_2,
z.z * SQRT_2_3 - tempXZ * SQRT_1_3, z.w);
break;
case multi_orderOfTransf_typeT2:
tempXZ = z.x * SQRT_2_3 - z.z * SQRT_1_3;
z = CVector4((tempXZ - z.y) * SQRT_1_2, (tempXZ + z.y) * SQRT_1_2,
z.x * SQRT_1_3 + z.z * SQRT_2_3, z.w);
tempV2 = z;
tempV2.x = sqrt(z.y * z.y + z.z * z.z);
tempV2.y = sqrt(z.x * z.x + z.z * z.z); // switching, squared, sqrt
tempV2.z = sqrt(z.x * z.x + z.y * z.y);
z = fabs(tempV2 - fractal->transformCommon.offsetA111);
temp = z;
tempL = temp.Length();
z = fabs(z) * fractal->transformCommon.scale3D444;
// if (tempL < 1e-21) tempL = 1e-21;
avgScale = z.Length() / tempL;
aux.DE = aux.DE * avgScale + 1.0;
tempXZ = (z.y + z.x) * SQRT_1_2;
z = CVector4(z.z * SQRT_1_3 + tempXZ * SQRT_2_3, (z.y - z.x) * SQRT_1_2,
z.z * SQRT_2_3 - tempXZ * SQRT_1_3, z.w);
break;
case multi_orderOfTransf_typeT3:
tempXZ = z.x * SQRT_2_3 - z.z * SQRT_1_3;
z = CVector4((tempXZ - z.y) * SQRT_1_2, (tempXZ + z.y) * SQRT_1_2,
z.x * SQRT_1_3 + z.z * SQRT_2_3, z.w);
tempV2 = z;
tempV2.x = (z.y + z.z);
tempV2.y = (z.x + z.z); // switching
tempV2.z = (z.x + z.y);
z = (fabs(tempV2 - fractal->transformCommon.offset222))
* fractal->transformCommon.scale3Db222;
tempXZ = (z.y + z.x) * SQRT_1_2;
z = CVector4(z.z * SQRT_1_3 + tempXZ * SQRT_2_3, (z.y - z.x) * SQRT_1_2,
z.z * SQRT_2_3 - tempXZ * SQRT_1_3, z.w);
break;
case multi_orderOfTransf_typeT4:
tempXZ = z.x * SQRT_2_3 - z.z * SQRT_1_3;
z = CVector4((tempXZ - z.y) * SQRT_1_2, (tempXZ + z.y) * SQRT_1_2,
z.x * SQRT_1_3 + z.z * SQRT_2_3, z.w);
tempV2 = z;
tempV2.x = (z.y * z.y + z.z * z.z);
tempV2.y = (z.x * z.x + z.z * z.z); // switching, squared,
tempV2.z = (z.x * z.x + z.y * z.y);
z = (fabs(tempV2 - fractal->transformCommon.offsetB111))
* fractal->transformCommon.scale3Dc222;
tempXZ = (z.y + z.x) * SQRT_1_2;
z = CVector4(z.z * SQRT_1_3 + tempXZ * SQRT_2_3, (z.y - z.x) * SQRT_1_2,
z.z * SQRT_2_3 - tempXZ * SQRT_1_3, z.w);
break;
case multi_orderOfTransf_typeT5b:
tempXZ = z.x * SQRT_2_3 - z.z * SQRT_1_3;
z = CVector4((tempXZ - z.y) * SQRT_1_2, (tempXZ + z.y) * SQRT_1_2,
z.x * SQRT_1_3 + z.z * SQRT_2_3, z.w);
// if (z.x > -1e-21 && z.x < 1e-21)
// z.x = (z.x > 0) ? 1e-21 : -1e-21;
// if (z.y > -1e-21 && z.y < 1e-21)
// z.y = (z.y > 0) ? 1e-21 : -1e-21;
// if (z.z > -1e-21 && z.z < 1e-21)
// z.z = (z.z > 0) ? 1e-21 : -1e-21;
tempV2 = z;
tempV2.x = fabs(
pow(pow(z.y, fractal->transformCommon.int8X) + pow(z.z, fractal->transformCommon.int8X),
fractal->transformCommon.power025.x));
tempV2.y = fabs(
pow(pow(z.x, fractal->transformCommon.int8Y) + pow(z.z, fractal->transformCommon.int8Y),
fractal->transformCommon.power025.y));
tempV2.z = fabs(
pow(pow(z.x, fractal->transformCommon.int8Z) + pow(z.y, fractal->transformCommon.int8Z),
fractal->transformCommon.power025.z));
z = (fabs(tempV2 - fractal->transformCommon.offsetC111))
* fractal->transformCommon.scale3Dd222;
tempXZ = (z.y + z.x) * SQRT_1_2;
z = CVector4(z.z * SQRT_1_3 + tempXZ * SQRT_2_3, (z.y - z.x) * SQRT_1_2,
z.z * SQRT_2_3 - tempXZ * SQRT_1_3, z.w);
break;
}
}
}
}
/**
* benesiPwr2 mandelbulb
* @reference
* http://www.fractalforums.com/new-theories-and-research/
* do-m3d-formula-have-to-be-distance-estimation-formulas/
*/
void BenesiPwr2MandelbulbIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
CVector4 c = aux.const_c;
{
CVector4 gap = fractal->transformCommon.constantMultiplier000;
double t;
double dot1;
if (fractal->transformCommon.functionEnabledPFalse
&& aux.i >= fractal->transformCommon.startIterationsP
&& aux.i < fractal->transformCommon.stopIterationsP1)
{
z.y = fabs(z.y);
z.z = fabs(z.z);
dot1 = (z.x * -SQRT_3_4 + z.y * 0.5) * fractal->transformCommon.scale;
t = max(0.0, dot1);
z.x -= t * -SQRT_3;
z.y = fabs(z.y - t);
if (z.y > z.z) swap(z.y, z.z);
z -= gap * CVector4(SQRT_3_4, 1.5, 1.5, 0.0);
if (z.z > z.x) swap(z.z, z.x);
if (z.x > 0.0)
{
z.y = max(0.0, z.y);
z.z = max(0.0, z.z);
}
}
}
if (fractal->transformCommon.benesiT1Enabled && aux.i >= fractal->transformCommon.startIterations
&& aux.i < fractal->transformCommon.stopIterations)
{
double tempXZ = z.x * SQRT_2_3 - z.z * SQRT_1_3;
z = CVector4(
(tempXZ - z.y) * SQRT_1_2, (tempXZ + z.y) * SQRT_1_2, z.x * SQRT_1_3 + z.z * SQRT_2_3, z.w);
CVector4 temp = z;
double tempL = temp.Length();
z = fabs(z) * fractal->transformCommon.scale3D222;
// if (tempL < 1e-21) tempL = 1e-21;
double avgScale = z.Length() / tempL;
aux.DE = aux.DE * avgScale + 1.0;
if (fractal->transformCommon.rotationEnabled)
{ // rotation inside T1
z = fractal->transformCommon.rotationMatrix.RotateVector(z);
}
tempXZ = (z.y + z.x) * SQRT_1_2;
z = CVector4(z.z * SQRT_1_3 + tempXZ * SQRT_2_3, (z.y - z.x) * SQRT_1_2,
z.z * SQRT_2_3 - tempXZ * SQRT_1_3, z.w);
z = z - fractal->transformCommon.offset200;
}
if (fractal->transformCommon.addCpixelEnabled
&& aux.i >= fractal->transformCommon.startIterationsF
&& aux.i < fractal->transformCommon.stopIterationsF)
{ // Benesi original pwr2
aux.r = z.Length(); // needed when alternating pwr2s
aux.DE = aux.DE * 2.0 * aux.r;
double r1 = z.y * z.y + z.z * z.z;
CVector4 newZ = CVector4(0.0, 0.0, 0.0, z.w);
if (c.x < 0.0 || z.x < sqrt(r1))
{
newZ.x = z.x * z.x - r1;
}
else
{
newZ.x = -z.x * z.x + r1;
}
r1 = -1.0 / sqrt(r1) * 2.0 * fabs(z.x);
newZ.y = r1 * (z.y * z.y - z.z * z.z);
newZ.z = r1 * 2.0 * z.y * z.z;
z = newZ + (c * fractal->transformCommon.constantMultiplierA100);
}
if (fractal->transformCommon.addCpixelEnabledFalse
&& aux.i >= fractal->transformCommon.startIterationsC
&& aux.i < fractal->transformCommon.stopIterationsC)
{ // pine tree
CVector4 temp = z;
aux.r = z.Length(); // needed when alternating pwr2s
z *= z;
double t = 2.0 * temp.x;
if (z.y + z.z > 0.0)
t = t / sqrt(z.y + z.z);
else
t = 1.0;
CVector4 tempC = c;
if (fractal->transformCommon.alternateEnabledFalse) // alternate
{
tempC = aux.c;
tempC = CVector4(tempC.x, tempC.z, tempC.y, tempC.w);
aux.c = tempC;
}
else
{
tempC = CVector4(c.x, c.z, c.y, c.w);
}
z.x = (z.x - z.y - z.z) + tempC.x * fractal->transformCommon.constantMultiplier100.x;
z.z = (t * (z.y - z.z)) + tempC.z * fractal->transformCommon.constantMultiplier100.y;
z.y = (2.0 * t * temp.y * temp.z) + tempC.y * fractal->transformCommon.constantMultiplier100.z;
aux.DE = aux.r * aux.DE * 2.0 + 1.0;
}
if (fractal->transformCommon.functionEnabledBxFalse
&& aux.i >= fractal->transformCommon.startIterationsD
&& aux.i < fractal->transformCommon.stopIterationsD)
{
z = CVector4(z.x * cos(z.y * fractal->transformCommon.scale1),
z.x * sin(z.y * fractal->transformCommon.scale1), z.z * fractal->transformCommon.scaleC1,
z.w)
* fractal->transformCommon.scaleA1;
aux.DE *= fabs(fractal->transformCommon.scaleA1);
}
if (fractal->transformCommon.juliaMode)
{
z.x += fractal->transformCommon.offset000.x;
z.y += fractal->transformCommon.offset000.y;
z.z += fractal->transformCommon.offset000.z;
}
if (fractal->transformCommon.rotation2EnabledFalse)
{
z = fractal->transformCommon.rotationMatrix2.RotateVector(z);
}
}
/**
* BoxBulb power 2 V2 with scaling of z axis
* This formula contains aux.color and aux.actualScaleA
*/
void BoxFoldBulbPow2V2Iteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
double colorAdd = 0.0;
double rrCol = 0.0;
CVector4 zCol = z;
CVector4 oldZ = z;
// tglad fold
if (aux.i >= fractal->transformCommon.startIterationsB
&& aux.i < fractal->transformCommon.stopIterationsB)
{
z.x = fabs(z.x + fractal->transformCommon.additionConstant111.x)
- fabs(z.x - fractal->transformCommon.additionConstant111.x) - z.x;
z.y = fabs(z.y + fractal->transformCommon.additionConstant111.y)
- fabs(z.y - fractal->transformCommon.additionConstant111.y) - z.y;
z.z = fabs(z.z + fractal->transformCommon.additionConstant111.z)
- fabs(z.z - fractal->transformCommon.additionConstant111.z) - z.z;
zCol = z;
}
// spherical fold
if (aux.i >= fractal->transformCommon.startIterationsS
&& aux.i < fractal->transformCommon.stopIterationsS)
{
double rr = z.Dot(z);
rrCol = rr;
z += fractal->mandelbox.offset;
// if (r2 < 1e-21) r2 = 1e-21;
if (rr < fractal->transformCommon.minR2p25)
{
double tglad_factor1 = fractal->transformCommon.maxR2d1 / fractal->transformCommon.minR2p25;
z *= tglad_factor1;
aux.DE *= tglad_factor1;
}
else if (rr < fractal->transformCommon.maxR2d1)
{
double tglad_factor2 = fractal->transformCommon.maxR2d1 / rr;
z *= tglad_factor2;
aux.DE *= tglad_factor2;
}
z -= fractal->mandelbox.offset;
}
// scale
double useScale = 1.0;
if (aux.i >= fractal->transformCommon.startIterationsC
&& aux.i < fractal->transformCommon.stopIterationsC)
{
useScale = aux.actualScaleA + fractal->transformCommon.scale;
z *= useScale;
aux.DE = aux.DE * fabs(useScale);
if (aux.i >= fractal->transformCommon.startIterationsX
&& aux.i < fractal->transformCommon.stopIterationsX)
{
// update actualScale for next iteration
double vary = fractal->transformCommon.scaleVary0
* (fabs(aux.actualScaleA) - fractal->transformCommon.scaleB1);
if (fractal->transformCommon.functionEnabledMFalse)
aux.actualScaleA = -vary;
else
aux.actualScaleA = aux.actualScaleA - vary;
}
}
if (aux.i >= fractal->transformCommon.startIterationsA
&& aux.i < fractal->transformCommon.stopIterationsA)
{
aux.r = z.Length();
aux.DE = aux.r * aux.DE * 16.0 * fractal->analyticDE.scale1
* sqrt(fractal->foldingIntPow.zFactor * fractal->foldingIntPow.zFactor + 2.0
+ fractal->analyticDE.offset2)
/ SQRT_3
+ fractal->analyticDE.offset1;
z = z * 2.0;
double x2 = z.x * z.x;
double y2 = z.y * z.y;
double z2 = z.z * z.z;
double temp = 1.0 - z2 / (x2 + y2);
CVector4 zTemp;
zTemp.x = (x2 - y2) * temp;
zTemp.y = 2.0 * z.x * z.y * temp;
zTemp.z = -2.0 * z.z * sqrt(x2 + y2);
zTemp.w = z.w;
z = zTemp;
z.z *= fractal->foldingIntPow.zFactor;
}
if (fractal->foldColor.auxColorEnabledFalse)
{
if (zCol.x != oldZ.x)
colorAdd += fractal->mandelbox.color.factor.x
* (fabs(zCol.x) - fractal->transformCommon.additionConstant111.x);
if (zCol.y != oldZ.y)
colorAdd += fractal->mandelbox.color.factor.y
* (fabs(zCol.y) - fractal->transformCommon.additionConstant111.y);
if (zCol.z != oldZ.z)
colorAdd += fractal->mandelbox.color.factor.z
* (fabs(zCol.z) - fractal->transformCommon.additionConstant111.z);
if (rrCol < fractal->transformCommon.maxR2d1)
{
if (rrCol < fractal->transformCommon.minR2p25)
colorAdd += fractal->mandelbox.color.factorSp1 * (fractal->transformCommon.minR2p25 - rrCol)
+ fractal->mandelbox.color.factorSp2
* (fractal->transformCommon.maxR2d1 - fractal->transformCommon.minR2p25);
else
colorAdd += fractal->mandelbox.color.factorSp2 * (fractal->transformCommon.maxR2d1 - rrCol);
}
aux.color += colorAdd;
}
}
/**
* BoxBulb power 2 V3 with scaling of z axis
* This formula contains aux.color and aux.actualScaleA
*/
void BoxFoldBulbPow2V3Iteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
// CVector4 c = aux.const_c;
double colorAdd = 0.0;
double rrCol = 0.0;
CVector4 zCol = z;
CVector4 oldZ = z;
// tglad fold
if (aux.i >= fractal->transformCommon.startIterationsB
&& aux.i < fractal->transformCommon.stopIterationsB)
{
z.x = fabs(z.x + fractal->transformCommon.additionConstant111.x)
- fabs(z.x - fractal->transformCommon.additionConstant111.x) - z.x;
z.y = fabs(z.y + fractal->transformCommon.additionConstant111.y)
- fabs(z.y - fractal->transformCommon.additionConstant111.y) - z.y;
z.z = fabs(z.z + fractal->transformCommon.additionConstant111.z)
- fabs(z.z - fractal->transformCommon.additionConstant111.z) - z.z;
zCol = z;
}
// spherical fold
if (aux.i >= fractal->transformCommon.startIterationsS
&& aux.i < fractal->transformCommon.stopIterationsS)
{
double rr = z.Dot(z);
rrCol = rr;
z += fractal->mandelbox.offset;
// if (r2 < 1e-21) r2 = 1e-21;
if (rr < fractal->transformCommon.minR2p25)
{
double tglad_factor1 = fractal->transformCommon.maxR2d1 / fractal->transformCommon.minR2p25;
z *= tglad_factor1;
aux.DE *= tglad_factor1;
}
else if (rr < fractal->transformCommon.maxR2d1)
{
double tglad_factor2 = fractal->transformCommon.maxR2d1 / rr;
z *= tglad_factor2;
aux.DE *= tglad_factor2;
}
z -= fractal->mandelbox.offset;
}
// scale
if (aux.i >= fractal->transformCommon.startIterationsC
&& aux.i < fractal->transformCommon.stopIterationsC)
{
double useScale = aux.actualScaleA + fractal->transformCommon.scale;
z *= useScale;
aux.DE = aux.DE * fabs(useScale);
if (aux.i >= fractal->transformCommon.startIterationsX
&& aux.i < fractal->transformCommon.stopIterationsX)
{
// update actualScale for next iteration
double vary = fractal->transformCommon.scaleVary0
* (fabs(aux.actualScaleA) - fractal->transformCommon.scaleB1);
if (fractal->transformCommon.functionEnabledMFalse)
aux.actualScaleA = -vary;
else
aux.actualScaleA = aux.actualScaleA - vary;
}
}
if (fractal->transformCommon.functionEnabledXFalse
&& aux.i >= fractal->transformCommon.startIterationsTM
&& aux.i < fractal->transformCommon.stopIterationsTM1)
{
double tempXZ = z.x * SQRT_2_3 - z.z * SQRT_1_3;
z = CVector4(
(tempXZ - z.y) * SQRT_1_2, (tempXZ + z.y) * SQRT_1_2, z.x * SQRT_1_3 + z.z * SQRT_2_3, z.w);
CVector4 temp = z;
double tempL = temp.Length();
z = fabs(z) * fractal->transformCommon.scale3D333;
// if (tempL < 1e-21) tempL = 1e-21;
double avgScale = z.Length() / tempL;
aux.DE = aux.DE * avgScale;
z = (fabs(z + fractal->transformCommon.additionConstantA111)
- fabs(z - fractal->transformCommon.additionConstantA111) - z);
tempXZ = (z.y + z.x) * SQRT_1_2;
z = CVector4(z.z * SQRT_1_3 + tempXZ * SQRT_2_3, (z.y - z.x) * SQRT_1_2,
z.z * SQRT_2_3 - tempXZ * SQRT_1_3, z.w);
}
// octo
if (fractal->transformCommon.functionEnabledDFalse
&& aux.i >= fractal->transformCommon.startIterationsD
&& aux.i < fractal->transformCommon.stopIterationsD)
{
if (z.x + z.y < 0.0) z = CVector4(-z.y, -z.x, z.z, z.w);
if (z.x + z.z < 0.0) // z.xz = -z.zx;
z = CVector4(-z.z, z.y, -z.x, z.w);
if (z.x - z.y < 0.0) // z.xy = z.yx;
z = CVector4(z.y, z.x, z.z, z.w);
if (z.x - z.z < 0.0) // z.xz = z.zx;
z = CVector4(z.z, z.y, z.x, z.w);
z.x = fabs(z.x);
z = z * fractal->transformCommon.scaleA2
- fractal->transformCommon.offset100 * (fractal->transformCommon.scaleA2 - 1.0);
aux.DE *= fabs(fractal->transformCommon.scaleA2);
}
if (fractal->transformCommon.functionEnabledRFalse
&& aux.i >= fractal->transformCommon.startIterationsR
&& aux.i < fractal->transformCommon.stopIterationsR)
z = fractal->transformCommon.rotationMatrix.RotateVector(z);
if (fractal->transformCommon.functionEnabledFFalse
&& aux.i >= fractal->transformCommon.startIterationsM
&& aux.i < fractal->transformCommon.stopIterationsM)
{ // fabs() and menger fold
z = fabs(z + fractal->transformCommon.additionConstantA000);
if (z.x - z.y < 0.0) swap(z.y, z.x);
if (z.x - z.z < 0.0) swap(z.z, z.x);
if (z.y - z.z < 0.0) swap(z.z, z.y);
// menger scales and offsets
z *= fractal->transformCommon.scale3;
z.x -= 2.0 * fractal->transformCommon.constantMultiplier111.x;
z.y -= 2.0 * fractal->transformCommon.constantMultiplier111.y;
if (fractal->transformCommon.functionEnabled)
{
if (z.z > 1.0) z.z -= 2.0 * fractal->transformCommon.constantMultiplier111.z;
}
else
{
z.z -= 2.0 * fractal->transformCommon.constantMultiplier111.z;
}
aux.DE *= fractal->transformCommon.scale3;
}
if (aux.i >= fractal->transformCommon.startIterationsA
&& aux.i < fractal->transformCommon.stopIterationsA)
{
aux.r = z.Length();
if (fractal->analyticDE.enabledFalse)
{
aux.DE = aux.r * aux.DE * 10.0 * fractal->analyticDE.scale1
* sqrt(fractal->foldingIntPow.zFactor * fractal->foldingIntPow.zFactor + 2.0
+ fractal->analyticDE.offset2)
+ fractal->analyticDE.offset1;
}
else
{
aux.DE = aux.r * aux.DE * 16.0 * fractal->analyticDE.scale1
* sqrt(fractal->foldingIntPow.zFactor * fractal->foldingIntPow.zFactor + 2.0
+ fractal->analyticDE.offset2)
/ SQRT_3
+ fractal->analyticDE.offset1;
}
z = z * 2.0;
double x2 = z.x * z.x;
double y2 = z.y * z.y;
double z2 = z.z * z.z;
double temp = 1.0 - z2 / (x2 + y2);
CVector4 zTemp;
zTemp.x = (x2 - y2) * temp;
zTemp.y = 2.0 * z.x * z.y * temp;
zTemp.z = -2.0 * z.z * sqrt(x2 + y2);
zTemp.w = z.w;
z = zTemp;
z.z *= fractal->foldingIntPow.zFactor;
}
if (fractal->foldColor.auxColorEnabledFalse)
{
if (zCol.x != oldZ.x)
colorAdd += fractal->mandelbox.color.factor.x
* (fabs(zCol.x) - fractal->transformCommon.additionConstant111.x);
if (zCol.y != oldZ.y)
colorAdd += fractal->mandelbox.color.factor.y
* (fabs(zCol.y) - fractal->transformCommon.additionConstant111.y);
if (zCol.z != oldZ.z)
colorAdd += fractal->mandelbox.color.factor.z
* (fabs(zCol.z) - fractal->transformCommon.additionConstant111.z);
if (rrCol < fractal->transformCommon.maxR2d1)
{
if (rrCol < fractal->transformCommon.minR2p25)
colorAdd += fractal->mandelbox.color.factorSp1 * (fractal->transformCommon.minR2p25 - rrCol)
+ fractal->mandelbox.color.factorSp2
* (fractal->transformCommon.maxR2d1 - fractal->transformCommon.minR2p25);
else
colorAdd += fractal->mandelbox.color.factorSp2 * (fractal->transformCommon.maxR2d1 - rrCol);
}
aux.color += colorAdd;
}
}
/**
* BoxFold Quaternion
* This formula contains aux.color and aux.actualScale
* Sometimes Delta DE Linear works best.
*/
void BoxFoldQuatIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
// CVector4 c = aux.const_c;
double colorAdd = 0.0;
double rrCol = 0.0;
CVector4 zCol = z;
CVector4 oldZ = z;
// tglad fold
if (aux.i >= fractal->transformCommon.startIterationsB
&& aux.i < fractal->transformCommon.stopIterationsB)
{
z.x = fabs(z.x + fractal->transformCommon.additionConstant111.x)
- fabs(z.x - fractal->transformCommon.additionConstant111.x) - z.x;
z.y = fabs(z.y + fractal->transformCommon.additionConstant111.y)
- fabs(z.y - fractal->transformCommon.additionConstant111.y) - z.y;
z.z = fabs(z.z + fractal->transformCommon.additionConstant111.z)
- fabs(z.z - fractal->transformCommon.additionConstant111.z) - z.z;
zCol = z;
}
// spherical fold
if (aux.i >= fractal->transformCommon.startIterationsS
&& aux.i < fractal->transformCommon.stopIterationsS)
{
double rr = z.Dot(z);
rrCol = rr;
z += fractal->mandelbox.offset;
// if (r2 < 1e-21) r2 = 1e-21;
if (rr < fractal->transformCommon.minR2p25)
{
double tglad_factor1 = fractal->transformCommon.maxR2d1 / fractal->transformCommon.minR2p25;
z *= tglad_factor1;
aux.DE *= tglad_factor1;
}
else if (rr < fractal->transformCommon.maxR2d1)
{
double tglad_factor2 = fractal->transformCommon.maxR2d1 / rr;
z *= tglad_factor2;
aux.DE *= tglad_factor2;
}
z -= fractal->mandelbox.offset;
}
// scale
if (aux.i >= fractal->transformCommon.startIterationsC
&& aux.i < fractal->transformCommon.stopIterationsC)
{
double useScale = aux.actualScaleA + fractal->transformCommon.scale;
z *= useScale;
aux.DE = aux.DE * fabs(useScale);
if (aux.i >= fractal->transformCommon.startIterationsX
&& aux.i < fractal->transformCommon.stopIterationsX)
{
// update actualScale for next iteration
double vary = fractal->transformCommon.scaleVary0
* (fabs(aux.actualScaleA) - fractal->transformCommon.scaleB1);
if (fractal->transformCommon.functionEnabledMFalse)
aux.actualScaleA = -vary;
else
aux.actualScaleA = aux.actualScaleA - vary;
}
}
if (fractal->transformCommon.functionEnabledXFalse
&& aux.i >= fractal->transformCommon.startIterationsTM
&& aux.i < fractal->transformCommon.stopIterationsTM1)
{
double tempXZ = z.x * SQRT_2_3 - z.z * SQRT_1_3;
z = CVector4(
(tempXZ - z.y) * SQRT_1_2, (tempXZ + z.y) * SQRT_1_2, z.x * SQRT_1_3 + z.z * SQRT_2_3, z.w);
CVector4 temp = z;
double tempL = temp.Length();
z = fabs(z) * fractal->transformCommon.scale3D333;
// if (tempL < 1e-21) tempL = 1e-21;
double avgScale = z.Length() / tempL;
aux.DE = aux.DE * avgScale;
z = (fabs(z + fractal->transformCommon.additionConstantA111)
- fabs(z - fractal->transformCommon.additionConstantA111) - z);
tempXZ = (z.y + z.x) * SQRT_1_2;
z = CVector4(z.z * SQRT_1_3 + tempXZ * SQRT_2_3, (z.y - z.x) * SQRT_1_2,
z.z * SQRT_2_3 - tempXZ * SQRT_1_3, z.w);
}
// octo
if (fractal->transformCommon.functionEnabledDFalse
&& aux.i >= fractal->transformCommon.startIterationsD
&& aux.i < fractal->transformCommon.stopIterationsD)
{
if (z.x + z.y < 0.0) z = CVector4(-z.y, -z.x, z.z, z.w);
if (z.x + z.z < 0.0) // z.xz = -z.zx;
z = CVector4(-z.z, z.y, -z.x, z.w);
if (z.x - z.y < 0.0) // z.xy = z.yx;
z = CVector4(z.y, z.x, z.z, z.w);
if (z.x - z.z < 0.0) // z.xz = z.zx;
z = CVector4(z.z, z.y, z.x, z.w);
z.x = fabs(z.x);
z = z * fractal->transformCommon.scaleA2
- fractal->transformCommon.offset100 * (fractal->transformCommon.scaleA2 - 1.0);
aux.DE *= fabs(fractal->transformCommon.scaleA2);
}
if (fractal->transformCommon.functionEnabledRFalse
&& aux.i >= fractal->transformCommon.startIterationsR
&& aux.i < fractal->transformCommon.stopIterationsR)
z = fractal->transformCommon.rotationMatrix.RotateVector(z);
if (fractal->transformCommon.functionEnabledFFalse
&& aux.i >= fractal->transformCommon.startIterationsM
&& aux.i < fractal->transformCommon.stopIterationsM)
{ // fabs() and menger fold
z = fabs(z + fractal->transformCommon.additionConstantA000);
if (z.x - z.y < 0.0) swap(z.y, z.x);
if (z.x - z.z < 0.0) swap(z.z, z.x);
if (z.y - z.z < 0.0) swap(z.z, z.y);
// menger scales and offsets
z *= fractal->transformCommon.scale2;
z.x -= 2.0 * fractal->transformCommon.constantMultiplier111.x;
z.y -= 2.0 * fractal->transformCommon.constantMultiplier111.y;
z.z -= 2.0 * fractal->transformCommon.constantMultiplier111.z;
aux.DE *= fractal->transformCommon.scale2;
}
if (aux.i >= fractal->transformCommon.startIterationsA
&& aux.i < fractal->transformCommon.stopIterationsA)
{
aux.r = z.Length();
aux.DE = aux.DE * 2.0 * aux.r;
if (fractal->analyticDE.enabledFalse)
{
aux.DE = aux.DE * fractal->analyticDE.scale1 + fractal->analyticDE.offset1;
}
z = CVector4(z.x * z.x - z.y * z.y - z.z * z.z, z.x * z.y, z.x * z.z, z.w);
double tempL = z.Length();
z *= fractal->transformCommon.constantMultiplier122;
// if (tempL < 1e-21) tempL = 1e-21;
CVector4 tempAvgScale = CVector4(z.x, z.y / 2.0, z.z / 2.0, z.w);
double avgScale = tempAvgScale.Length() / tempL;
double tempAux = aux.DE * avgScale;
aux.DE = aux.DE + (tempAux - aux.DE) * fractal->transformCommon.scaleA1;
if (fractal->transformCommon.functionEnabledAxFalse)
{
CVector4 offsetAlt = aux.pos_neg * fractal->transformCommon.additionConstant000;
z += offsetAlt;
aux.pos_neg *= -fractal->transformCommon.scale1;
}
else
{
z += fractal->transformCommon.additionConstant000;
}
}
if (fractal->foldColor.auxColorEnabledFalse)
{
if (zCol.x != oldZ.x)
colorAdd += fractal->mandelbox.color.factor.x
* (fabs(zCol.x) - fractal->transformCommon.additionConstant111.x);
if (zCol.y != oldZ.y)
colorAdd += fractal->mandelbox.color.factor.y
* (fabs(zCol.y) - fractal->transformCommon.additionConstant111.y);
if (zCol.z != oldZ.z)
colorAdd += fractal->mandelbox.color.factor.z
* (fabs(zCol.z) - fractal->transformCommon.additionConstant111.z);
if (rrCol < fractal->transformCommon.maxR2d1)
{
if (rrCol < fractal->transformCommon.minR2p25)
colorAdd += fractal->mandelbox.color.factorSp1 * (fractal->transformCommon.minR2p25 - rrCol)
+ fractal->mandelbox.color.factorSp2
* (fractal->transformCommon.maxR2d1 - fractal->transformCommon.minR2p25);
else
colorAdd += fractal->mandelbox.color.factorSp2 * (fractal->transformCommon.maxR2d1 - rrCol);
}
aux.color += colorAdd;
}
}
/**
* CollatzIteration formula
* @reference https://mathr.co.uk/blog/2016-04-10_collatz_fractal.html
* https://en.wikipedia.org/wiki/Collatz_conjecture#Iterating_on_real_or_complex_numbers
*/
void CollatzIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
Q_UNUSED(fractal);
CVector4 xV = CVector4(1.0, 1.0, 1.0, 0.0);
CVector4 temp = xV + z * 2.0;
temp *= z.RotateAroundVectorByAngle(xV.GetXYZ(), M_PI);
z = xV + z * 4.0 - temp;
z /= 4.0;
aux.DE = aux.DE * 4.0 + 1.0;
}
/**
* CollatzModIteration formula
* @reference https://mathr.co.uk/blog/2016-04-10_collatz_fractal.html
* https://en.wikipedia.org/wiki/Collatz_conjecture#Iterating_on_real_or_complex_numbers
*/
void CollatzModIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
CVector4 c = aux.const_c;
CVector4 constantMult = CVector4(fractal->transformCommon.constantMultiplierB111.x,
fractal->transformCommon.constantMultiplierB111.y,
fractal->transformCommon.constantMultiplierB111.z, 0.0);
z = constantMult + fractal->transformCommon.scale4 * z
- (fractal->transformCommon.constantMultiplier111 + fractal->transformCommon.scale2 * z)
* z.RotateAroundVectorByAngle(fractal->transformCommon.constantMultiplier111.GetXYZ(),
M_PI * fractal->transformCommon.scale1); // * cPI ;
z *= fractal->transformCommon.scale025;
aux.DE = aux.DE * 4.0 * fractal->analyticDE.scale1 + 1.0;
if (fractal->transformCommon.addCpixelEnabledFalse)
{
c = CVector4(c.z, c.y, c.x, c.w);
z += c * fractal->transformCommon.constantMultiplierA111;
}
}
/**
* Modified Mandelbox (ABox) formula
* This formula contains aux.color and aux.actualScaleA
*/
void FoldBoxMod1Iteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
double colorAdd = 0.0;
if (aux.i >= fractal->transformCommon.startIterations
&& aux.i < fractal->transformCommon.stopIterations)
{
CVector4 tempA, tempB;
CVector4 oldZ = z;
if (fractal->transformCommon.functionEnabledx)
tempA.x = fabs(z.x + fractal->transformCommon.additionConstant111.x);
if (fractal->transformCommon.functionEnabledAx)
tempB.x = fabs(z.x - fractal->transformCommon.additionConstantA111.x);
z.x = tempA.x - tempB.x - (z.x * fractal->transformCommon.scale3D111.x);
if (fractal->transformCommon.functionEnabledy)
tempA.y = fabs(z.y + fractal->transformCommon.additionConstant111.y);
if (fractal->transformCommon.functionEnabledAy)
tempB.y = fabs(z.y - fractal->transformCommon.additionConstantA111.y);
z.y = tempA.y - tempB.y - (z.y * fractal->transformCommon.scale3D111.y);
if (fractal->transformCommon.functionEnabledz)
tempA.z = fabs(z.z + fractal->transformCommon.additionConstant111.z);
if (fractal->transformCommon.functionEnabledAz)
tempB.z = fabs(z.z - fractal->transformCommon.additionConstantA111.z);
z.z = tempA.z - tempB.z - (z.z * fractal->transformCommon.scale3D111.z);
if (z.x != oldZ.x) colorAdd += fractal->mandelbox.color.factor.x;
if (z.y != oldZ.y) colorAdd += fractal->mandelbox.color.factor.y;
if (z.z != oldZ.z) colorAdd += fractal->mandelbox.color.factor.z;
}
if (fractal->transformCommon.functionEnabledFalse
&& aux.i >= fractal->transformCommon.startIterationsA
&& aux.i < fractal->transformCommon.stopIterationsA) // box fold
{
if (fabs(z.x) > fractal->mandelbox.foldingLimit)
{
z.x = sign(z.x) * fractal->mandelbox.foldingValue - z.x;
colorAdd += fractal->mandelbox.color.factor.x;
}
if (fabs(z.y) > fractal->mandelbox.foldingLimit)
{
z.y = sign(z.y) * fractal->mandelbox.foldingValue - z.y;
colorAdd += fractal->mandelbox.color.factor.y;
}
double zLimit = fractal->mandelbox.foldingLimit * fractal->transformCommon.scale1;
double zValue = fractal->mandelbox.foldingValue * fractal->transformCommon.scale1;
if (fabs(z.z) > zLimit)
{
z.z = sign(z.z) * zValue - z.z;
colorAdd += fractal->mandelbox.color.factor.z;
}
}
if (aux.i >= fractal->transformCommon.startIterationsB
&& aux.i < fractal->transformCommon.stopIterationsB) // spherical fold
{
double r2 = z.Dot(z);
// if (r2 < 1e-21 && r2 > -1e-21)
// r2 = (r2 > 0) ? 1e-21 : -1e-21;
if (r2 < fractal->mandelbox.mR2)
{
z *= fractal->mandelbox.mboxFactor1;
aux.DE *= fractal->mandelbox.mboxFactor1;
colorAdd += fractal->mandelbox.color.factorSp1;
}
else if (r2 < fractal->mandelbox.fR2)
{
double tglad_factor2 = fractal->mandelbox.fR2 / r2;
z *= tglad_factor2;
aux.DE *= tglad_factor2;
colorAdd += fractal->mandelbox.color.factorSp2;
}
}
// scale
if (fractal->transformCommon.functionEnabledXFalse
&& aux.i >= fractal->transformCommon.startIterationsD
&& aux.i < fractal->transformCommon.stopIterationsD)
{
double useScale = aux.actualScaleA + fractal->mandelbox.scale;
z *= useScale;
aux.DE = aux.DE * fabs(useScale) + 1.0;
// update actualScale for next iteration
double vary = fractal->transformCommon.scaleVary0
* (fabs(aux.actualScaleA) - fractal->transformCommon.scaleB1);
if (fractal->transformCommon.functionEnabledMFalse)
aux.actualScaleA = -vary;
else
aux.actualScaleA = aux.actualScaleA - vary;
}
else
{
z *= fractal->mandelbox.scale;
aux.DE = aux.DE * fabs(fractal->mandelbox.scale) + 1.0;
}
if (fractal->mandelbox.mainRotationEnabled && aux.i >= fractal->transformCommon.startIterationsC
&& aux.i < fractal->transformCommon.stopIterationsC)
z = fractal->mandelbox.mainRot.RotateVector(z);
// color updated v2.14
if (fractal->foldColor.auxColorEnabled)
{
aux.color += colorAdd;
}
}
/**
* IQ-Bulb from Mandelbulb 3D and Inigo Quilez
* @reference http://iquilezles.org/www/articles/mandelbulb/mandelbulb.htm
*/
void IqBulbIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
// extract polar coordinates
double wr = aux.r;
double wo = acos(z.y / wr);
double wi = atan2(z.x, z.z);
// scale and rotate the point
wr = pow(wr, fractal->transformCommon.pwr8 - 1.0);
aux.DE = wr * aux.DE * fractal->transformCommon.pwr8 + 1.0;
wr *= aux.r;
wo *= fractal->transformCommon.pwr8;
wi *= fractal->transformCommon.pwr8a;
// convert back to cartesian coordinates
z.x = sin(wo) * sin(wi);
z.y = cos(wo);
z.z = sin(wo) * cos(wi);
z *= wr; // then add Cpixel constant
}
/**
* JosLeys-Kleinian formula
* @reference
* http://www.fractalforums.com/3d-fractal-generation/an-escape-tim-algorithm-for-kleinian-group-limit-sets/msg98248/#msg98248
* This formula contains aux.color
*/
void JosKleinianIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
double a = fractal->transformCommon.foldingValue;
double b = fractal->transformCommon.offset;
double f = sign(b);
CVector4 box_size = fractal->transformCommon.offset111;
CVector3 box1 = CVector3(2.0 * box_size.x, a * box_size.y, 2.0 * box_size.z);
CVector3 box2 = CVector3(-box_size.x, -box_size.y + 1.0, -box_size.z);
CVector3 wrapped = wrap(z.GetXYZ(), box1, box2);
z = CVector4(wrapped.x, wrapped.y, wrapped.z, z.w);
// If above the separation line, rotate by 180deg about (-b/2, a/2)
if (z.y >= a * (0.5 + 0.2 * sin(f * M_PI * (z.x + b * 0.5) / box_size.x)))
z = CVector4(-b, a, 0., z.w) - z; // z.xy = vec2(-b, a) - z.xy;
double z2 = z.Dot(z);
CVector4 colorVector = CVector4(z.x, z.y, z.z, z2);
aux.color = min(aux.color, colorVector.Length()); // For coloring
double iR = 1.0 / z2;
z *= -iR;
z.x = -b - z.x;
z.y = a + z.y;
aux.pseudoKleinianDE *= iR;
}
/**
* Based on Kalisets1 and KaliDucks, from Mandelbulb 3D, and refer Formula proposed by Kali, with
* features added by DarkBeam.
*
* <b>M3D notes:</b>
* Try out julia and low R_bailout values of 2 down to 1!
* You might have to cutoff at z=0 or so, to see something.
* @reference
* http://www.fractalforums.com/new-theories-and-research/very-simple-formula-for-fractal-patterns
*/
void Kalisets1Iteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
CVector4 c = aux.const_c;
z = fabs(z);
double sqs = (z.x * z.x + z.y * z.y + z.z * z.z + 1e-21); // sph inv
double m;
double minR = fractal->transformCommon.minR0; // KaliDucks
if (sqs < minR)
m = 1.0 / sqrt(minR);
else
m = fractal->transformCommon.scale / sqs; // kalisets
z = z * m;
aux.DE = aux.DE * fabs(m) + 1.0;
if (fractal->transformCommon.addCpixelEnabledFalse)
z += c * fractal->transformCommon.constantMultiplier111;
if (fractal->transformCommon.juliaMode) z += fractal->transformCommon.juliaC;
if (fractal->transformCommon.rotationEnabled)
z = fractal->transformCommon.rotationMatrix.RotateVector(z);
}
/**
* Mandelbox Menger Sponge Hybrid
* @reference
* http://www.fractalforums.com/ifs-iterated-function-systems/amazing-fractal/msg12467/#msg12467
* This formula contains aux.color
*/
void MandelboxMengerIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
CVector4 c = aux.const_c;
double colorAdd = 0.0;
if (fractal->mandelbox.rotationsEnabled)
{
CVector4 zRot;
// cast vector to array pointer for address taking of components in opencl
double *zRotP = (double *)&zRot;
const double *colP = (const double *)&fractal->mandelbox.color.factor;
for (int dim = 0; dim < 3; dim++)
{
// handle each dimension x, y and z sequentially in pointer var dim
double *rotDim = (dim == 0) ? &zRotP[0] : ((dim == 1) ? &zRotP[1] : &zRotP[2]);
const double *colorFactor = (dim == 0) ? &colP[0] : ((dim == 1) ? &colP[1] : &colP[2]);
zRot = fractal->mandelbox.rot[0][dim].RotateVector(z);
if (*rotDim > fractal->mandelbox.foldingLimit)
{
*rotDim = fractal->mandelbox.foldingValue - *rotDim;
z = fractal->mandelbox.rotinv[0][dim].RotateVector(zRot);
colorAdd += *colorFactor;
}
else
{
zRot = fractal->mandelbox.rot[1][dim].RotateVector(z);
if (*rotDim < -fractal->mandelbox.foldingLimit)
{
*rotDim = -fractal->mandelbox.foldingValue - *rotDim;
z = fractal->mandelbox.rotinv[1][dim].RotateVector(zRot);
colorAdd += *colorFactor;
}
}
}
}
else
{
if (aux.i >= fractal->transformCommon.startIterationsA
&& aux.i < fractal->transformCommon.stopIterationsA)
{
if (fabs(z.x) > fractal->mandelbox.foldingLimit)
{
z.x = sign(z.x) * fractal->mandelbox.foldingValue - z.x;
colorAdd += fractal->mandelbox.color.factor.x;
}
if (fabs(z.y) > fractal->mandelbox.foldingLimit)
{
z.y = sign(z.y) * fractal->mandelbox.foldingValue - z.y;
colorAdd += fractal->mandelbox.color.factor.y;
}
double zLimit = fractal->mandelbox.foldingLimit * fractal->transformCommon.scale1;
double zValue = fractal->mandelbox.foldingValue * fractal->transformCommon.scale1;
if (fabs(z.z) > zLimit)
{
z.z = sign(z.z) * zValue - z.z;
colorAdd += fractal->mandelbox.color.factor.z;
}
}
}
if (aux.i >= fractal->transformCommon.startIterationsB
&& aux.i < fractal->transformCommon.stopIterationsB)
{
double r2 = z.Dot(z);
z += fractal->mandelbox.offset;
if (r2 < fractal->mandelbox.mR2)
{
z *= fractal->mandelbox.mboxFactor1;
aux.DE *= fractal->mandelbox.mboxFactor1;
colorAdd += fractal->mandelbox.color.factorSp1;
}
else if (r2 < fractal->mandelbox.fR2)
{
double tglad_factor2 = fractal->mandelbox.fR2 / r2;
z *= tglad_factor2;
aux.DE *= tglad_factor2;
colorAdd += fractal->mandelbox.color.factorSp2;
}
z -= fractal->mandelbox.offset;
}
if (fractal->mandelbox.mainRotationEnabled && aux.i >= fractal->transformCommon.startIterationsR
&& aux.i < fractal->transformCommon.stopIterationsR)
z = fractal->mandelbox.mainRot.RotateVector(z);
if (aux.i >= fractal->transformCommon.startIterationsS
&& aux.i < fractal->transformCommon.stopIterationsS)
{
z = z * fractal->mandelbox.scale;
aux.DE = aux.DE * fabs(fractal->mandelbox.scale) + 1.0;
}
if (fractal->transformCommon.addCpixelEnabledFalse)
{
CVector4 tempC = c;
if (fractal->transformCommon.alternateEnabledFalse) // alternate
{
tempC = aux.c;
switch (fractal->mandelbulbMulti.orderOfXYZ)
{
case multi_OrderOfXYZ_xyz:
default: tempC = CVector4(tempC.x, tempC.y, tempC.z, tempC.w); break;
case multi_OrderOfXYZ_xzy: tempC = CVector4(tempC.x, tempC.z, tempC.y, tempC.w); break;
case multi_OrderOfXYZ_yxz: tempC = CVector4(tempC.y, tempC.x, tempC.z, tempC.w); break;
case multi_OrderOfXYZ_yzx: tempC = CVector4(tempC.y, tempC.z, tempC.x, tempC.w); break;
case multi_OrderOfXYZ_zxy: tempC = CVector4(tempC.z, tempC.x, tempC.y, tempC.w); break;
case multi_OrderOfXYZ_zyx: tempC = CVector4(tempC.z, tempC.y, tempC.x, tempC.w); break;
}
aux.c = tempC;
}
else
{
switch (fractal->mandelbulbMulti.orderOfXYZ)
{
case multi_OrderOfXYZ_xyz:
default: tempC = CVector4(c.x, c.y, c.z, c.w); break;
case multi_OrderOfXYZ_xzy: tempC = CVector4(c.x, c.z, c.y, c.w); break;
case multi_OrderOfXYZ_yxz: tempC = CVector4(c.y, c.x, c.z, c.w); break;
case multi_OrderOfXYZ_yzx: tempC = CVector4(c.y, c.z, c.x, c.w); break;
case multi_OrderOfXYZ_zxy: tempC = CVector4(c.z, c.x, c.y, c.w); break;
case multi_OrderOfXYZ_zyx: tempC = CVector4(c.z, c.y, c.x, c.w); break;
}
}
z += tempC * fractal->transformCommon.constantMultiplier111;
}
if (fractal->transformCommon.functionEnabled && aux.i >= fractal->transformCommon.startIterationsM
&& aux.i < fractal->transformCommon.stopIterationsM)
{
int count = fractal->transformCommon.int1; // Menger Sponge
int k;
for (k = 0; k < count; k++)
{
z = fabs(z);
if (z.x - z.y < 0.0) swap(z.y, z.x);
if (z.x - z.z < 0.0) swap(z.z, z.x);
if (z.y - z.z < 0.0) swap(z.z, z.y);
z *= fractal->transformCommon.scale3;
z.x -= 2.0 * fractal->transformCommon.constantMultiplierA111.x;
z.y -= 2.0 * fractal->transformCommon.constantMultiplierA111.y;
if (z.z > 1.0) z.z -= 2.0 * fractal->transformCommon.constantMultiplierA111.z;
aux.DE *= fabs(fractal->transformCommon.scale3 * fractal->transformCommon.scaleA1);
z += fractal->transformCommon.additionConstantA000;
if (fractal->transformCommon.functionEnabledxFalse) // addCpixel options
{
switch (fractal->mandelbulbMulti.orderOfXYZC)
{
case multi_OrderOfXYZ_xyz:
default: c = CVector4(c.x, c.y, c.z, c.w); break;
case multi_OrderOfXYZ_xzy: c = CVector4(c.x, c.z, c.y, c.w); break;
case multi_OrderOfXYZ_yxz: c = CVector4(c.y, c.x, c.z, c.w); break;
case multi_OrderOfXYZ_yzx: c = CVector4(c.y, c.z, c.x, c.w); break;
case multi_OrderOfXYZ_zxy: c = CVector4(c.z, c.x, c.y, c.w); break;
case multi_OrderOfXYZ_zyx: c = CVector4(c.z, c.y, c.x, c.w); break;
}
z += c * fractal->transformCommon.constantMultiplierB111;
}
}
}
if (fractal->analyticDE.enabledFalse)
aux.DE = aux.DE * fractal->analyticDE.scale1 + fractal->analyticDE.offset0;
aux.color += colorAdd;
}
/**
* Mandelbox fractal known as AmazingBox or ABox, invented by Tom Lowe in 2010
* Variable parameters over iteration time
* Based on work by Tglad, Buddhi, DarkBeam
* @reference
* http://www.fractalforums.com/ifs-iterated-function-systems/amazing-fractal/msg12467/#msg12467
* This formula contains aux.color and aux.actualScaleA
*/
void MandelboxVariableIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
double colorAdd = 0.0;
double rrCol = 0.0;
CVector4 zCol = z;
CVector4 oldZ = z;
CVector4 limit4 = fractal->transformCommon.additionConstant111;
CVector4 value4 = 2.0 * fractal->transformCommon.additionConstant111;
if (fractal->transformCommon.functionEnabledFalse)
value4 = fractal->transformCommon.additionConstant222;
if (fractal->mandelbox.rotationsEnabled)
{ // TODO evaluate implementation of vec3 limit and value
/* CVector4 zRot;
// cast vector to array pointer for address taking of components in opencl
double *zRotP = reinterpret_cast<double *>(&zRot);
const double *colP = reinterpret_cast<const double *>(&fractal->mandelbox.color.factor);
for (int dim = 0; dim < 3; dim++)
{
// handle each dimension x, y and z sequentially in pointer var dim
double *rotDim = (dim == 0) ? &zRotP[0] : ((dim == 1) ? &zRotP[1] : &zRotP[2]);
const double *colorFactor = (dim == 0) ? &colP[0] : ((dim == 1) ? &colP[1] : &colP[2]);
zRot = fractal->mandelbox.rot[0][dim].RotateVector(z);
if (*rotDim > fractal->mandelbox.foldingLimit)
{
*rotDim = fractal->mandelbox.foldingValue - *rotDim;
z = fractal->mandelbox.rotinv[0][dim].RotateVector(zRot);
aux.color += *colorFactor;
}
else
{
zRot = fractal->mandelbox.rot[1][dim].RotateVector(z);
if (*rotDim < -fractal->mandelbox.foldingLimit)
{
*rotDim = -fractal->mandelbox.foldingValue - *rotDim;
z = fractal->mandelbox.rotinv[1][dim].RotateVector(zRot);
aux.color += *colorFactor;
}
}
}*/
}
else
{
if (z.x > limit4.x)
{
z.x = value4.x - z.x;
}
else if (z.x < -limit4.x)
{
z.x = -value4.x - z.x;
}
if (z.y > limit4.y)
{
z.y = value4.y - z.y;
}
else if (z.y < -limit4.y)
{
z.y = -value4.y - z.y;
}
if (z.z > limit4.z)
{
z.z = value4.z - z.z;
}
else if (z.z < -limit4.z)
{
z.z = -value4.z - z.z;
}
zCol = z;
}
// spherical folding
double maxR2use = fractal->transformCommon.maxR2d1;
double minR2use = fractal->transformCommon.minR2p25;
// vary maxR2
if (fractal->transformCommon.functionEnabledEFalse)
{
if (aux.i > fractal->transformCommon.startIterationsA)
{
maxR2use *= (1.0
- 1.0 / (1.0
+ (aux.i - fractal->transformCommon.startIterationsB)
/ fractal->transformCommon.offsetA0))
* fractal->transformCommon.scaleA1;
}
}
// vary minR2
if (fractal->transformCommon.functionEnabledDFalse)
{
if (aux.i > fractal->transformCommon.startIterationsA)
{
minR2use *= (1.0
- 1.0 / (1.0
+ (aux.i - fractal->transformCommon.startIterationsA)
/ fractal->transformCommon.offset0))
* fractal->transformCommon.scale1;
}
}
const double rr = z.Dot(z);
rrCol = rr;
// Mandelbox Spherical fold
z += fractal->mandelbox.offset;
// if (r2 < 1e-21) r2 = 1e-21;
if (rr < minR2use)
{
double tglad_factor1 = maxR2use / minR2use;
z *= tglad_factor1;
aux.DE *= tglad_factor1;
}
else if (rr < maxR2use)
{
double tglad_factor2 = maxR2use / rr;
z *= tglad_factor2;
aux.DE *= tglad_factor2;
}
z -= fractal->mandelbox.offset;
// 3D Rotation
if (fractal->mandelbox.mainRotationEnabled) // z = fractal->mandelbox.mainRot.RotateVector(z);
{
CVector4 tempVC = CVector4(fractal->mandelbox.rotationMain, 0.0); // constant to be varied
if (fractal->transformCommon.functionEnabledPFalse)
{
if (aux.i >= fractal->transformCommon.startIterations
&& aux.i < fractal->transformCommon.stopIterations
&& (fractal->transformCommon.stopIterations - fractal->transformCommon.startIterations
!= 0))
{
double iterationRange =
fractal->transformCommon.stopIterations - fractal->transformCommon.startIterations;
double currentIteration = (aux.i - fractal->transformCommon.startIterations);
tempVC += fractal->transformCommon.offset000 * currentIteration / iterationRange;
}
if (aux.i >= fractal->transformCommon.stopIterations)
{
tempVC += tempVC + fractal->transformCommon.offset000;
}
}
tempVC *= M_PI_180;
z = z.RotateAroundVectorByAngle(CVector3(1.0, 0.0, 0.0), tempVC.x);
z = z.RotateAroundVectorByAngle(CVector3(0.0, 1.0, 0.0), tempVC.y);
z = z.RotateAroundVectorByAngle(CVector3(0.0, 0.0, 1.0), tempVC.z);
}
// scale
double useScale = 1.0;
{
useScale = aux.actualScaleA + fractal->mandelbox.scale;
z *= useScale;
aux.DE = aux.DE * fabs(useScale) + 1.0;
if (fractal->transformCommon.functionEnabledFFalse
&& aux.i >= fractal->transformCommon.startIterationsX
&& aux.i < fractal->transformCommon.stopIterationsX)
{
// update actualScaleA for next iteration
double vary = fractal->transformCommon.scaleVary0
* (fabs(aux.actualScaleA) - fractal->transformCommon.scaleB1);
if (fractal->transformCommon.functionEnabledMFalse)
aux.actualScaleA = -vary;
else
aux.actualScaleA = aux.actualScaleA - vary;
}
}
CVector4 c = aux.const_c;
if (fractal->transformCommon.addCpixelEnabledFalse
&& aux.i >= fractal->transformCommon.startIterationsH
&& aux.i < fractal->transformCommon.stopIterationsH)
{
CVector4 tempC = aux.const_c;
if (fractal->transformCommon.alternateEnabledFalse) // alternate
{
tempC = aux.c;
switch (fractal->mandelbulbMulti.orderOfXYZ)
{
case multi_OrderOfXYZ_xyz:
default: tempC = CVector4(tempC.x, tempC.y, tempC.z, tempC.w); break;
case multi_OrderOfXYZ_xzy: tempC = CVector4(tempC.x, tempC.z, tempC.y, tempC.w); break;
case multi_OrderOfXYZ_yxz: tempC = CVector4(tempC.y, tempC.x, tempC.z, tempC.w); break;
case multi_OrderOfXYZ_yzx: tempC = CVector4(tempC.y, tempC.z, tempC.x, tempC.w); break;
case multi_OrderOfXYZ_zxy: tempC = CVector4(tempC.z, tempC.x, tempC.y, tempC.w); break;
case multi_OrderOfXYZ_zyx: tempC = CVector4(tempC.z, tempC.y, tempC.x, tempC.w); break;
}
aux.c = tempC;
}
else
{
switch (fractal->mandelbulbMulti.orderOfXYZ)
{
case multi_OrderOfXYZ_xyz:
default: tempC = CVector4(c.x, c.y, c.z, c.w); break;
case multi_OrderOfXYZ_xzy: tempC = CVector4(c.x, c.z, c.y, c.w); break;
case multi_OrderOfXYZ_yxz: tempC = CVector4(c.y, c.x, c.z, c.w); break;
case multi_OrderOfXYZ_yzx: tempC = CVector4(c.y, c.z, c.x, c.w); break;
case multi_OrderOfXYZ_zxy: tempC = CVector4(c.z, c.x, c.y, c.w); break;
case multi_OrderOfXYZ_zyx: tempC = CVector4(c.z, c.y, c.x, c.w); break;
}
}
if (fractal->transformCommon.rotationEnabled
&& aux.i >= fractal->transformCommon.startIterationsG
&& aux.i < fractal->transformCommon.stopIterationsG)
{
tempC = fractal->transformCommon.rotationMatrix.RotateVector(tempC);
}
z += tempC * fractal->transformCommon.constantMultiplier111;
}
// color updated v2.13 & mode2 v2.14
if (fractal->foldColor.auxColorEnabledFalse)
{
if (fractal->transformCommon.functionEnabledCxFalse)
{
if (zCol.x != oldZ.x)
colorAdd += fractal->mandelbox.color.factor.x
* (fabs(zCol.x) - fractal->transformCommon.additionConstant111.x);
if (zCol.y != oldZ.y)
colorAdd += fractal->mandelbox.color.factor.y
* (fabs(zCol.y) - fractal->transformCommon.additionConstant111.y);
if (zCol.z != oldZ.z)
colorAdd += fractal->mandelbox.color.factor.z
* (fabs(zCol.z) - fractal->transformCommon.additionConstant111.z);
if (rrCol < fractal->transformCommon.maxR2d1)
{
if (rrCol < fractal->transformCommon.minR2p25)
colorAdd +=
fractal->mandelbox.color.factorSp1 * (fractal->transformCommon.minR2p25 - rrCol)
+ fractal->mandelbox.color.factorSp2
* (fractal->transformCommon.maxR2d1 - fractal->transformCommon.minR2p25);
else
colorAdd +=
fractal->mandelbox.color.factorSp2 * (fractal->transformCommon.maxR2d1 - rrCol);
}
}
else
{
if (zCol.x != oldZ.x) colorAdd += fractal->mandelbox.color.factor.x;
if (zCol.y != oldZ.y) colorAdd += fractal->mandelbox.color.factor.y;
if (zCol.z != oldZ.z) colorAdd += fractal->mandelbox.color.factor.z;
if (rrCol < fractal->transformCommon.minR2p25)
colorAdd += fractal->mandelbox.color.factorSp1;
else if (rrCol < fractal->transformCommon.maxR2d1)
colorAdd += fractal->mandelbox.color.factorSp2;
}
aux.color += colorAdd;
}
}
/**
* mandelbulbBermarte
*
* abs() version of Mandelbulb Kali modified by visual.bermarte
* @reference http://www.fractalforums.com/theory/mandelbulb-variant/
*/
void MandelbulbBermarteIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
if (fractal->transformCommon.functionEnabledAxFalse) z.x = fabs(z.x);
if (fractal->transformCommon.functionEnabledAyFalse) z.y = fabs(z.y);
if (fractal->transformCommon.functionEnabledAzFalse) z.z = fabs(z.z);
double th0;
double ph0;
double costh;
double sinth;
double zp;
if (fractal->transformCommon.functionEnabledFalse)
{
th0 = acos(z.z / aux.r) + fractal->bulb.betaAngleOffset + 1e-061; // MUST keep exception catch
ph0 = atan(z.y / z.x) + fractal->bulb.alphaAngleOffset;
th0 *= fractal->transformCommon.pwr8 * fractal->transformCommon.scaleA1;
sinth = sin(th0);
z = aux.r * CVector4(sinth * cos(ph0), sin(ph0) * sinth, cos(th0), 0.0);
}
else
{
th0 = asin(z.z / aux.r) + fractal->bulb.betaAngleOffset + 1e-061; // MUST keep exception catch
ph0 = atan2(z.y, z.x) + fractal->bulb.alphaAngleOffset;
th0 *= fractal->transformCommon.pwr8 * fractal->transformCommon.scaleA1;
costh = cos(th0);
z = aux.r * CVector4(costh * sin(ph0), cos(ph0) * costh, sin(th0), 0.0);
}
if (fractal->transformCommon.functionEnabledAx) z.x = fabs(z.x);
if (fractal->transformCommon.functionEnabledAy) z.y = fabs(z.y);
if (fractal->transformCommon.functionEnabledAz) z.z = fabs(z.z);
if (fractal->transformCommon.functionEnabledxFalse)
{
th0 = acos(z.z / aux.r) + fractal->transformCommon.betaAngleOffset
+ 1e-061; // MUST keep exception catch ??;
ph0 = atan(z.y / z.x);
ph0 *= fractal->transformCommon.pwr8 * fractal->transformCommon.scaleB1;
zp = pow(aux.r, fractal->transformCommon.pwr8);
sinth = sin(th0);
z = zp * CVector4(sinth * cos(ph0), sin(ph0) * sinth, cos(th0), 0.0);
}
else
{
th0 = asin(z.z / aux.r) + fractal->transformCommon.betaAngleOffset
+ 1e-061; // MUST keep exception catch ??;
ph0 = atan2(z.y, z.x);
ph0 *= fractal->transformCommon.pwr8 * fractal->transformCommon.scaleB1;
zp = pow(aux.r, fractal->transformCommon.pwr8);
costh = cos(th0);
z = zp * CVector4(costh * sin(ph0), cos(ph0) * costh, sin(th0), 0.0);
}
if (fractal->transformCommon.functionEnabledBxFalse) z.x = fabs(z.x);
if (fractal->transformCommon.functionEnabledByFalse) z.y = fabs(z.y);
if (fractal->analyticDE.enabledFalse)
{ // analytic log DE adjustment
aux.DE = pow(aux.r, fractal->transformCommon.pwr8 - fractal->analyticDE.offset1) * aux.DE
* fractal->transformCommon.pwr8 * fractal->analyticDE.scale1
+ fractal->analyticDE.offset2;
}
else // default, i.e. scale1 & offset1 & offset2 = 1.0
{
aux.DE =
pow(aux.r, fractal->transformCommon.pwr8 - 1.0) * fractal->transformCommon.pwr8 * aux.DE
+ 1.0;
}
}
/**
* mandelbulb juliabulb hybrid 3D
* constructed from Mandelbulb, Msltoe - Julia Bulb Eiffie & Msltoe - Sym4 Mod formulas.
* note: an Offset Radius of 0.1 can sometimes improve the DE statistic
*/
void MandelbulbJuliabulbIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
// mandelbulb multi
if (aux.i >= fractal->transformCommon.startIterationsM
&& aux.i < fractal->transformCommon.stopIterationsM)
{
aux.r = z.Length();
if (fractal->transformCommon.functionEnabledFalse)
{
if (fractal->transformCommon.functionEnabledAxFalse
&& aux.i >= fractal->transformCommon.startIterationsX
&& aux.i < fractal->transformCommon.stopIterationsX)
z.x = fabs(z.x);
if (fractal->transformCommon.functionEnabledAyFalse
&& aux.i >= fractal->transformCommon.startIterationsY
&& aux.i < fractal->transformCommon.stopIterationsY)
z.y = fabs(z.y);
if (fractal->transformCommon.functionEnabledAzFalse
&& aux.i >= fractal->transformCommon.startIterationsZ
&& aux.i < fractal->transformCommon.stopIterationsZ)
z.z = fabs(z.z);
}
double th0 = fractal->bulb.betaAngleOffset;
double ph0 = fractal->bulb.alphaAngleOffset;
CVector3 v;
switch (fractal->sinTan2Trig.orderOfZYX)
{
case multi_OrderOfZYX_zyx:
default: v = CVector3(z.z, z.y, z.x); break;
case multi_OrderOfZYX_zxy: v = CVector3(z.z, z.x, z.y); break;
case multi_OrderOfZYX_yzx: v = CVector3(z.y, z.z, z.x); break;
case multi_OrderOfZYX_yxz: v = CVector3(z.y, z.x, z.z); break;
case multi_OrderOfZYX_xzy: v = CVector3(z.x, z.z, z.y); break;
case multi_OrderOfZYX_xyz: v = CVector3(z.x, z.y, z.z); break;
}
if (fractal->sinTan2Trig.asinOrAcos == multi_asinOrAcos_asin)
th0 += asin(v.x / aux.r);
else
th0 += acos(v.x / aux.r);
if (fractal->sinTan2Trig.atan2OrAtan == multi_atan2OrAtan_atan2)
ph0 += atan2(v.y, v.z);
else
ph0 += atan(v.y / v.z);
double rp = pow(aux.r, fractal->bulb.power - 1.0);
double th = th0 * fractal->bulb.power * fractal->transformCommon.scaleA1;
double ph = ph0 * fractal->bulb.power * fractal->transformCommon.scaleB1;
aux.DE = rp * aux.DE * fractal->bulb.power + 1.0;
rp *= aux.r;
if (fractal->transformCommon.functionEnabledxFalse)
{ // cosine mode
double sinth = th;
if (fractal->transformCommon.functionEnabledyFalse) sinth = th0;
sinth = sin(sinth);
z = rp * CVector4(sinth * sin(ph), cos(ph) * sinth, cos(th), 0.0);
}
else
{ // sine mode
double costh = th;
if (fractal->transformCommon.functionEnabledzFalse) costh = th0;
costh = cos(costh);
z = rp * CVector4(costh * cos(ph), sin(ph) * costh, sin(th), 0.0);
}
}
// sym4
if (fractal->transformCommon.functionEnabled && aux.i >= fractal->transformCommon.startIterationsD
&& aux.i < fractal->transformCommon.stopIterationsD)
{
aux.r = z.Length();
aux.DE = aux.DE * 2.0 * aux.r;
CVector4 temp = z;
double tempL = temp.Length();
// if (tempL < 1e-21)
// tempL = 1e-21;
z *= fractal->transformCommon.scale3D111;
aux.DE *= fabs(z.Length() / tempL);
if (fabs(z.x) < fabs(z.z)) swap(z.x, z.z);
if (fabs(z.x) < fabs(z.y)) swap(z.x, z.y);
if (fabs(z.y) < fabs(z.z)) swap(z.y, z.z);
if (z.x * z.z < 0.0) z.z = -z.z;
if (z.x * z.y < 0.0) z.y = -z.y;
temp.x = z.x * z.x - z.y * z.y - z.z * z.z;
temp.y = 2.0 * z.x * z.y;
temp.z = 2.0 * z.x * z.z;
z = temp + fractal->transformCommon.offsetF000;
}
// sym3 msltoe eiffie
if (fractal->transformCommon.functionEnabledEFalse
&& aux.i >= fractal->transformCommon.startIterationsE
&& aux.i < fractal->transformCommon.stopIterationsE)
{
aux.r = z.Length();
double psi = fabs(fmod(atan2(z.z, z.y) + M_PI + M_PI_8, M_PI_4) - M_PI_8);
double lengthYZ = sqrt(z.y * z.y + z.z * z.z);
z.y = cos(psi) * lengthYZ;
z.z = sin(psi) * lengthYZ;
aux.DE = aux.DE * 2.0 * aux.r;
CVector4 z2 = z * z;
double rr = z2.x + z2.y + z2.z;
double m = 1.0 - z2.z / rr;
CVector4 temp;
temp.x = (z2.x - z2.y) * m;
temp.y = 2.0 * z.x * z.y * m * fractal->transformCommon.scale; // scaling y;;
temp.z = 2.0 * z.z * sqrt(z2.x + z2.y);
temp.w = z.w;
z = temp + fractal->transformCommon.additionConstant000;
}
if (fractal->transformCommon.addCpixelEnabledFalse)
{
CVector4 c = aux.const_c;
CVector4 tempC = c;
if (fractal->transformCommon.alternateEnabledFalse) // alternate
{
tempC = aux.c;
switch (fractal->mandelbulbMulti.orderOfXYZC)
{
case multi_OrderOfXYZ_xyz:
default: tempC = CVector4(tempC.x, tempC.y, tempC.z, tempC.w); break;
case multi_OrderOfXYZ_xzy: tempC = CVector4(tempC.x, tempC.z, tempC.y, tempC.w); break;
case multi_OrderOfXYZ_yxz: tempC = CVector4(tempC.y, tempC.x, tempC.z, tempC.w); break;
case multi_OrderOfXYZ_yzx: tempC = CVector4(tempC.y, tempC.z, tempC.x, tempC.w); break;
case multi_OrderOfXYZ_zxy: tempC = CVector4(tempC.z, tempC.x, tempC.y, tempC.w); break;
case multi_OrderOfXYZ_zyx: tempC = CVector4(tempC.z, tempC.y, tempC.x, tempC.w); break;
}
aux.c = tempC;
}
else
{
switch (fractal->mandelbulbMulti.orderOfXYZC)
{
case multi_OrderOfXYZ_xyz:
default: tempC = CVector4(c.x, c.y, c.z, c.w); break;
case multi_OrderOfXYZ_xzy: tempC = CVector4(c.x, c.z, c.y, c.w); break;
case multi_OrderOfXYZ_yxz: tempC = CVector4(c.y, c.x, c.z, c.w); break;
case multi_OrderOfXYZ_yzx: tempC = CVector4(c.y, c.z, c.x, c.w); break;
case multi_OrderOfXYZ_zxy: tempC = CVector4(c.z, c.x, c.y, c.w); break;
case multi_OrderOfXYZ_zyx: tempC = CVector4(c.z, c.y, c.x, c.w); break;
}
}
z += tempC * fractal->transformCommon.constantMultiplierC111;
}
// radial offset
double lengthTempZ = -z.Length();
// if (lengthTempZ > -1e-21)
// lengthTempZ = -1e-21; // z is neg.)
z *= 1.0 + fractal->transformCommon.offset / lengthTempZ;
// scale
z *= fractal->transformCommon.scale1;
aux.DE *= fabs(fractal->transformCommon.scale1);
}
/**
* mandelbulb Kali modification
* @reference http://www.fractalforums.com/theory/mandelbulb-variant/
*/
void MandelbulbKaliIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
if (fractal->transformCommon.functionEnabledFalse)
{
if (fractal->transformCommon.functionEnabledAxFalse) z.x = fabs(z.x);
if (fractal->transformCommon.functionEnabledAyFalse) z.y = fabs(z.y);
if (fractal->transformCommon.functionEnabledAzFalse) z.z = fabs(z.z);
}
double th0 =
acos(z.z / aux.r) + fractal->bulb.betaAngleOffset + 1e-061; // MUST keep exception catch
double ph0 = atan(z.y / z.x) + fractal->bulb.alphaAngleOffset;
th0 *= fractal->transformCommon.pwr8 * fractal->transformCommon.scaleA1;
double sinth = sin(th0);
z = aux.r * CVector4(sinth * cos(ph0), sin(ph0) * sinth, cos(th0), 0.0);
th0 = acos(z.z / aux.r) + fractal->transformCommon.betaAngleOffset
+ 1e-061; // MUST keep exception catch ??;
ph0 = atan(z.y / z.x);
ph0 *= fractal->transformCommon.pwr8 * fractal->transformCommon.scaleB1;
double zp = pow(aux.r, fractal->transformCommon.pwr8);
sinth = sin(th0);
z = zp * CVector4(sinth * cos(ph0), sin(ph0) * sinth, cos(th0), 0.0);
if (fractal->analyticDE.enabledFalse)
{ // analytic log DE adjustment
aux.DE = pow(aux.r, fractal->transformCommon.pwr8 - fractal->analyticDE.offset1) * aux.DE
* fractal->transformCommon.pwr8 * fractal->analyticDE.scale1
+ fractal->analyticDE.offset2;
}
else // default, i.e. scale1 & offset1 & offset2 = 1.0
{
aux.DE =
pow(aux.r, fractal->transformCommon.pwr8 - 1.0) * fractal->transformCommon.pwr8 * aux.DE
+ 1.0;
}
}
/**
* based on mandelbulb Kali multi
* @reference http://www.fractalforums.com/theory/mandelbulb-variant/
*/
void MandelbulbKaliMultiIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
CVector4 c = aux.const_c;
if (fractal->transformCommon.functionEnabledFalse)
{
if (fractal->transformCommon.functionEnabledAxFalse) z.x = fabs(z.x);
if (fractal->transformCommon.functionEnabledAyFalse) z.y = fabs(z.y);
if (fractal->transformCommon.functionEnabledAzFalse) z.z = fabs(z.z);
}
double costh;
double sinth;
double th0 = fractal->bulb.betaAngleOffset + 1e-061; // MUST keep exception catch
double ph0 = fractal->bulb.alphaAngleOffset;
CVector4 v;
switch (fractal->mandelbulbMulti.orderOfXYZ)
{
case multi_OrderOfXYZ_xyz:
default: v = CVector4(z.x, z.y, z.z, z.w); break;
case multi_OrderOfXYZ_xzy: v = CVector4(z.x, z.z, z.y, z.w); break;
case multi_OrderOfXYZ_yxz: v = CVector4(z.y, z.x, z.z, z.w); break;
case multi_OrderOfXYZ_yzx: v = CVector4(z.y, z.z, z.x, z.w); break;
case multi_OrderOfXYZ_zxy: v = CVector4(z.z, z.x, z.y, z.w); break;
case multi_OrderOfXYZ_zyx: v = CVector4(z.z, z.y, z.x, z.w); break;
}
if (fractal->mandelbulbMulti.acosOrAsin == multi_acosOrAsin_acos)
th0 += acos(v.x / aux.r);
else
th0 += asin(v.x / aux.r);
if (fractal->mandelbulbMulti.atanOrAtan2 == multi_atanOrAtan2_atan)
ph0 += atan(v.y / v.z);
else
ph0 += atan2(v.y, v.z);
th0 *= fractal->transformCommon.pwr8 * fractal->transformCommon.scaleA1;
if (fractal->transformCommon.functionEnabledBxFalse)
{
costh = cos(th0);
z = aux.r * CVector4(costh * sin(ph0), cos(ph0) * costh, sin(th0), 0.0);
}
else
{ // cosine mode default
sinth = sin(th0);
z = aux.r * CVector4(sinth * cos(ph0), sin(ph0) * sinth, cos(th0), 0.0);
}
if (fractal->transformCommon.functionEnabledxFalse)
{
switch (fractal->mandelbulbMulti.orderOfXYZ2)
{
case multi_OrderOfXYZ_xyz:
default: v = CVector4(z.x, z.y, z.z, z.w); break;
case multi_OrderOfXYZ_xzy: v = CVector4(z.x, z.z, z.y, z.w); break;
case multi_OrderOfXYZ_yxz: v = CVector4(z.y, z.x, z.z, z.w); break;
case multi_OrderOfXYZ_yzx: v = CVector4(z.y, z.z, z.x, z.w); break;
case multi_OrderOfXYZ_zxy: v = CVector4(z.z, z.x, z.y, z.w); break;
case multi_OrderOfXYZ_zyx: v = CVector4(z.z, z.y, z.x, z.w); break;
}
if (fractal->mandelbulbMulti.acosOrAsinA == multi_acosOrAsin_acos)
th0 = acos(v.x / aux.r) + fractal->transformCommon.betaAngleOffset
+ 1e-061; // MUST keep exception catch
else
th0 += asin(v.x / aux.r) + fractal->transformCommon.betaAngleOffset
+ 1e-061; // MUST keep exception catch;
if (fractal->mandelbulbMulti.atanOrAtan2A == multi_atanOrAtan2_atan)
ph0 += atan(v.y / v.z);
else
ph0 += atan2(v.y, v.z);
}
else
{
switch (fractal->mandelbulbMulti.orderOfXYZ)
{
case multi_OrderOfXYZ_xyz:
default: v = CVector4(z.x, z.y, z.z, z.w); break;
case multi_OrderOfXYZ_xzy: v = CVector4(z.x, z.z, z.y, z.w); break;
case multi_OrderOfXYZ_yxz: v = CVector4(z.y, z.x, z.z, z.w); break;
case multi_OrderOfXYZ_yzx: v = CVector4(z.y, z.z, z.x, z.w); break;
case multi_OrderOfXYZ_zxy: v = CVector4(z.z, z.x, z.y, z.w); break;
case multi_OrderOfXYZ_zyx: v = CVector4(z.z, z.y, z.x, z.w); break;
}
if (fractal->mandelbulbMulti.acosOrAsin == multi_acosOrAsin_acos)
th0 = acos(v.x / aux.r) + fractal->transformCommon.betaAngleOffset
+ 1e-061; // MUST keep exception catch ??;
else
th0 += asin(v.x / aux.r) + fractal->transformCommon.betaAngleOffset
+ 1e-061; // MUST keep exception catch ??;
if (fractal->mandelbulbMulti.atanOrAtan2 == multi_atanOrAtan2_atan)
ph0 += atan(v.y / v.z);
else
ph0 += atan2(v.y, v.z);
}
ph0 *= fractal->transformCommon.pwr8 * fractal->transformCommon.scaleB1 * 0.5; // 0.5 retain
double zp = pow(aux.r, fractal->transformCommon.pwr8);
if (fractal->transformCommon.functionEnabledzFalse)
{ // sine mode
costh = cos(th0);
z = zp * CVector4(costh * sin(ph0), cos(ph0) * costh, sin(th0), 0.0);
}
else
{ // cosine mode default
sinth = sin(th0);
z = zp * CVector4(sinth * cos(ph0), sin(ph0) * sinth, cos(th0), 0.0);
}
if (fractal->analyticDE.enabledFalse)
{ // analytic log DE adjustment
aux.DE = pow(aux.r, fractal->transformCommon.pwr8 - fractal->analyticDE.offset1) * aux.DE
* fractal->transformCommon.pwr8 * fractal->analyticDE.scale1
+ fractal->analyticDE.offset2;
}
else // default, i.e. scale1 & offset1 & offset2 = 1.0
{
aux.DE =
pow(aux.r, fractal->transformCommon.pwr8 - 1.0) * fractal->transformCommon.pwr8 * aux.DE
+ 1.0;
}
if (fractal->transformCommon.addCpixelEnabledFalse)
{
CVector4 tempC = c;
if (fractal->transformCommon.alternateEnabledFalse) // alternate
{
tempC = aux.c;
switch (fractal->mandelbulbMulti.orderOfXYZC)
{
case multi_OrderOfXYZ_xyz:
default: tempC = CVector4(tempC.x, tempC.y, tempC.z, tempC.w); break;
case multi_OrderOfXYZ_xzy: tempC = CVector4(tempC.x, tempC.z, tempC.y, tempC.w); break;
case multi_OrderOfXYZ_yxz: tempC = CVector4(tempC.y, tempC.x, tempC.z, tempC.w); break;
case multi_OrderOfXYZ_yzx: tempC = CVector4(tempC.y, tempC.z, tempC.x, tempC.w); break;
case multi_OrderOfXYZ_zxy: tempC = CVector4(tempC.z, tempC.x, tempC.y, tempC.w); break;
case multi_OrderOfXYZ_zyx: tempC = CVector4(tempC.z, tempC.y, tempC.x, tempC.w); break;
}
aux.c = tempC;
}
else
{
switch (fractal->mandelbulbMulti.orderOfXYZC)
{
case multi_OrderOfXYZ_xyz:
default: tempC = CVector4(c.x, c.y, c.z, c.w); break;
case multi_OrderOfXYZ_xzy: tempC = CVector4(c.x, c.z, c.y, c.w); break;
case multi_OrderOfXYZ_yxz: tempC = CVector4(c.y, c.x, c.z, c.w); break;
case multi_OrderOfXYZ_yzx: tempC = CVector4(c.y, c.z, c.x, c.w); break;
case multi_OrderOfXYZ_zxy: tempC = CVector4(c.z, c.x, c.y, c.w); break;
case multi_OrderOfXYZ_zyx: tempC = CVector4(c.z, c.y, c.x, c.w); break;
}
}
z += tempC * fractal->transformCommon.constantMultiplierC111;
}
}
/**
* mandelbulbMulti 3D
*/
void MandelbulbMultiIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
CVector4 c = aux.const_c;
if (fractal->transformCommon.functionEnabledFalse)
{
if (fractal->transformCommon.functionEnabledAxFalse) z.x = fabs(z.x);
if (fractal->transformCommon.functionEnabledAyFalse) z.y = fabs(z.y);
if (fractal->transformCommon.functionEnabledAzFalse) z.z = fabs(z.z);
}
double th0 = fractal->bulb.betaAngleOffset;
double ph0 = fractal->bulb.alphaAngleOffset;
CVector4 v;
switch (fractal->mandelbulbMulti.orderOfXYZ)
{
case multi_OrderOfXYZ_xyz:
default: v = CVector4(z.x, z.y, z.z, z.w); break;
case multi_OrderOfXYZ_xzy: v = CVector4(z.x, z.z, z.y, z.w); break;
case multi_OrderOfXYZ_yxz: v = CVector4(z.y, z.x, z.z, z.w); break;
case multi_OrderOfXYZ_yzx: v = CVector4(z.y, z.z, z.x, z.w); break;
case multi_OrderOfXYZ_zxy: v = CVector4(z.z, z.x, z.y, z.w); break;
case multi_OrderOfXYZ_zyx: v = CVector4(z.z, z.y, z.x, z.w); break;
}
// if (aux.r < 1e-21)
// aux.r = 1e-21;
// if (v3 < 1e-21 && v3 > -1e-21)
// v3 = (v3 > 0) ? 1e-21 : -1e-21;
if (fractal->mandelbulbMulti.acosOrAsin == multi_acosOrAsin_acos)
th0 += acos(v.x / aux.r);
else
th0 += asin(v.x / aux.r);
if (fractal->mandelbulbMulti.atanOrAtan2 == multi_atanOrAtan2_atan)
ph0 += atan(v.y / v.z);
else
ph0 += atan2(v.y, v.z);
double rp = pow(aux.r, fractal->bulb.power - 1.0);
double th = th0 * fractal->bulb.power * fractal->transformCommon.scaleA1;
double ph = ph0 * fractal->bulb.power * fractal->transformCommon.scaleB1;
aux.DE = rp * aux.DE * fractal->bulb.power + 1.0;
rp *= aux.r;
if (fractal->transformCommon.functionEnabledxFalse)
{ // cosine mode
double sinth = th;
if (fractal->transformCommon.functionEnabledyFalse) sinth = th0;
sinth = sin(sinth);
z = rp * CVector4(sinth * sin(ph), cos(ph) * sinth, cos(th), 0.0);
}
else
{ // sine mode ( default = V2.07))
double costh = th;
if (fractal->transformCommon.functionEnabledzFalse) costh = th0;
costh = cos(costh);
z = rp * CVector4(costh * cos(ph), sin(ph) * costh, sin(th), 0.0);
}
if (fractal->transformCommon.addCpixelEnabledFalse)
{
CVector4 tempC = c;
if (fractal->transformCommon.alternateEnabledFalse) // alternate
{
tempC = aux.c;
switch (fractal->mandelbulbMulti.orderOfXYZC)
{
case multi_OrderOfXYZ_xyz:
default: tempC = CVector4(tempC.x, tempC.y, tempC.z, tempC.w); break;
case multi_OrderOfXYZ_xzy: tempC = CVector4(tempC.x, tempC.z, tempC.y, tempC.w); break;
case multi_OrderOfXYZ_yxz: tempC = CVector4(tempC.y, tempC.x, tempC.z, tempC.w); break;
case multi_OrderOfXYZ_yzx: tempC = CVector4(tempC.y, tempC.z, tempC.x, tempC.w); break;
case multi_OrderOfXYZ_zxy: tempC = CVector4(tempC.z, tempC.x, tempC.y, tempC.w); break;
case multi_OrderOfXYZ_zyx: tempC = CVector4(tempC.z, tempC.y, tempC.x, tempC.w); break;
}
aux.c = tempC;
}
else
{
switch (fractal->mandelbulbMulti.orderOfXYZC)
{
case multi_OrderOfXYZ_xyz:
default: tempC = CVector4(c.x, c.y, c.z, c.w); break;
case multi_OrderOfXYZ_xzy: tempC = CVector4(c.x, c.z, c.y, c.w); break;
case multi_OrderOfXYZ_yxz: tempC = CVector4(c.y, c.x, c.z, c.w); break;
case multi_OrderOfXYZ_yzx: tempC = CVector4(c.y, c.z, c.x, c.w); break;
case multi_OrderOfXYZ_zxy: tempC = CVector4(c.z, c.x, c.y, c.w); break;
case multi_OrderOfXYZ_zyx: tempC = CVector4(c.z, c.y, c.x, c.w); break;
}
}
z += tempC * fractal->transformCommon.constantMultiplierC111;
}
}
/**
* mandelbulbMulti2 3D
*/
void MandelbulbMulti2Iteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
CVector4 c = aux.const_c;
if (fractal->transformCommon.functionEnabledFalse)
{
if (fractal->transformCommon.functionEnabledAxFalse
&& aux.i >= fractal->transformCommon.startIterationsX
&& aux.i < fractal->transformCommon.stopIterationsX)
z.x = fabs(z.x);
if (fractal->transformCommon.functionEnabledAyFalse
&& aux.i >= fractal->transformCommon.startIterationsY
&& aux.i < fractal->transformCommon.stopIterationsY)
z.y = fabs(z.y);
if (fractal->transformCommon.functionEnabledAzFalse
&& aux.i >= fractal->transformCommon.startIterationsZ
&& aux.i < fractal->transformCommon.stopIterationsZ)
z.z = fabs(z.z);
}
double th0 = fractal->bulb.betaAngleOffset;
double ph0 = fractal->bulb.alphaAngleOffset;
CVector3 v;
switch (fractal->sinTan2Trig.orderOfZYX)
{
case multi_OrderOfZYX_zyx:
default: v = CVector3(z.z, z.y, z.x); break;
case multi_OrderOfZYX_zxy: v = CVector3(z.z, z.x, z.y); break;
case multi_OrderOfZYX_yzx: v = CVector3(z.y, z.z, z.x); break;
case multi_OrderOfZYX_yxz: v = CVector3(z.y, z.x, z.z); break;
case multi_OrderOfZYX_xzy: v = CVector3(z.x, z.z, z.y); break;
case multi_OrderOfZYX_xyz: v = CVector3(z.x, z.y, z.z); break;
}
if (fractal->sinTan2Trig.asinOrAcos == multi_asinOrAcos_asin)
th0 += asin(v.x / aux.r);
else
th0 += acos(v.x / aux.r);
if (fractal->sinTan2Trig.atan2OrAtan == multi_atan2OrAtan_atan2)
ph0 += atan2(v.y, v.z);
else
ph0 += atan(v.y / v.z);
double rp = pow(aux.r, fractal->bulb.power - 1.0);
double th = th0 * fractal->bulb.power * fractal->transformCommon.scaleA1;
double ph = ph0 * fractal->bulb.power * fractal->transformCommon.scaleB1;
aux.DE = rp * aux.DE * fractal->bulb.power + 1.0;
rp *= aux.r;
if (fractal->transformCommon.functionEnabledxFalse)
{ // cosine mode
double sinth = th;
if (fractal->transformCommon.functionEnabledyFalse) sinth = th0;
sinth = sin(sinth);
z = rp * CVector4(sinth * sin(ph), cos(ph) * sinth, cos(th), 0.0);
}
else
{ // sine mode ( default = V2.07))
double costh = th;
if (fractal->transformCommon.functionEnabledzFalse) costh = th0;
costh = cos(costh);
z = rp * CVector4(costh * cos(ph), sin(ph) * costh, sin(th), 0.0);
}
if (fractal->transformCommon.functionEnabledKFalse)
{
if (fractal->transformCommon.functionEnabledDFalse
&& aux.i >= fractal->transformCommon.startIterationsD
&& aux.i < fractal->transformCommon.stopIterationsD)
swap(z.x, z.y);
if (fractal->transformCommon.functionEnabledEFalse
&& aux.i >= fractal->transformCommon.startIterationsE
&& aux.i < fractal->transformCommon.stopIterationsE)
swap(z.x, z.z);
// swap
if (fractal->transformCommon.functionEnabledBxFalse) z.x = -z.x;
if (fractal->transformCommon.functionEnabledByFalse) z.y = -z.y;
if (fractal->transformCommon.functionEnabledBzFalse) z.z = -z.z;
}
z += fractal->transformCommon.additionConstant000;
if (fractal->transformCommon.addCpixelEnabledFalse)
{
CVector4 tempC = c;
if (fractal->transformCommon.alternateEnabledFalse) // alternate
{
tempC = aux.c;
switch (fractal->mandelbulbMulti.orderOfXYZC)
{
case multi_OrderOfXYZ_xyz:
default: tempC = CVector4(tempC.x, tempC.y, tempC.z, tempC.w); break;
case multi_OrderOfXYZ_xzy: tempC = CVector4(tempC.x, tempC.z, tempC.y, tempC.w); break;
case multi_OrderOfXYZ_yxz: tempC = CVector4(tempC.y, tempC.x, tempC.z, tempC.w); break;
case multi_OrderOfXYZ_yzx: tempC = CVector4(tempC.y, tempC.z, tempC.x, tempC.w); break;
case multi_OrderOfXYZ_zxy: tempC = CVector4(tempC.z, tempC.x, tempC.y, tempC.w); break;
case multi_OrderOfXYZ_zyx: tempC = CVector4(tempC.z, tempC.y, tempC.x, tempC.w); break;
}
aux.c = tempC;
}
else
{
switch (fractal->mandelbulbMulti.orderOfXYZC)
{
case multi_OrderOfXYZ_xyz:
default: tempC = CVector4(c.x, c.y, c.z, c.w); break;
case multi_OrderOfXYZ_xzy: tempC = CVector4(c.x, c.z, c.y, c.w); break;
case multi_OrderOfXYZ_yxz: tempC = CVector4(c.y, c.x, c.z, c.w); break;
case multi_OrderOfXYZ_yzx: tempC = CVector4(c.y, c.z, c.x, c.w); break;
case multi_OrderOfXYZ_zxy: tempC = CVector4(c.z, c.x, c.y, c.w); break;
case multi_OrderOfXYZ_zyx: tempC = CVector4(c.z, c.y, c.x, c.w); break;
}
}
z += tempC * fractal->transformCommon.constantMultiplierC111;
}
// rotation
if (fractal->transformCommon.functionEnabledRFalse
&& aux.i >= fractal->transformCommon.startIterationsR
&& aux.i < fractal->transformCommon.stopIterationsR)
{
z = fractal->transformCommon.rotationMatrix.RotateVector(z);
}
}
/**
* mandelbulb Quaternion
*
*/
void MandelbulbQuatIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
if (fractal->transformCommon.addCpixelEnabledFalse
&& aux.i >= fractal->transformCommon.startIterationsC
&& aux.i < fractal->transformCommon.stopIterationsC1)
{
CVector4 c = aux.const_c;
CVector4 tempC = c;
if (fractal->transformCommon.alternateEnabledFalse) // alternate
{
tempC = aux.c;
switch (fractal->mandelbulbMulti.orderOfXYZC)
{
case multi_OrderOfXYZ_xyz:
default: tempC = CVector4(tempC.x, tempC.y, tempC.z, tempC.w); break;
case multi_OrderOfXYZ_xzy: tempC = CVector4(tempC.x, tempC.z, tempC.y, tempC.w); break;
case multi_OrderOfXYZ_yxz: tempC = CVector4(tempC.y, tempC.x, tempC.z, tempC.w); break;
case multi_OrderOfXYZ_yzx: tempC = CVector4(tempC.y, tempC.z, tempC.x, tempC.w); break;
case multi_OrderOfXYZ_zxy: tempC = CVector4(tempC.z, tempC.x, tempC.y, tempC.w); break;
case multi_OrderOfXYZ_zyx: tempC = CVector4(tempC.z, tempC.y, tempC.x, tempC.w); break;
}
aux.c = tempC;
}
else
{
switch (fractal->mandelbulbMulti.orderOfXYZC)
{
case multi_OrderOfXYZ_xyz:
default: tempC = CVector4(c.x, c.y, c.z, c.w); break;
case multi_OrderOfXYZ_xzy: tempC = CVector4(c.x, c.z, c.y, c.w); break;
case multi_OrderOfXYZ_yxz: tempC = CVector4(c.y, c.x, c.z, c.w); break;
case multi_OrderOfXYZ_yzx: tempC = CVector4(c.y, c.z, c.x, c.w); break;
case multi_OrderOfXYZ_zxy: tempC = CVector4(c.z, c.x, c.y, c.w); break;
case multi_OrderOfXYZ_zyx: tempC = CVector4(c.z, c.y, c.x, c.w); break;
}
}
z += tempC * fractal->transformCommon.constantMultiplierC111;
}
// Quaternion fold
if (aux.i >= fractal->transformCommon.startIterationsD
&& aux.i < fractal->transformCommon.stopIterationsD1)
{
aux.r = z.Length();
z = CVector4(z.x * z.x - z.y * z.y - z.z * z.z, z.x * z.y, z.x * z.z, 0.0);
aux.DE = aux.DE * 2.0 * aux.r;
double tempL = z.Length();
z *= fractal->transformCommon.constantMultiplier122;
// if (tempL < 1e-21) tempL = 1e-21;
CVector3 tempAvgScale = CVector3(z.x, z.y / 2.0, z.z / 2.0);
double avgScale = tempAvgScale.Length() / tempL;
double tempAux = aux.DE * avgScale;
aux.DE = aux.DE + (tempAux - aux.DE) * fractal->analyticDE.scale1;
z += fractal->transformCommon.offset000;
// if (!fractal->analyticDE.enabledFalse)
// aux.DE = aux.DE * fabs(aux.actualScale) + 1.0;
// else
// aux.DE =
// aux.DE * fabs(aux.actualScale) * fractal->analyticDE.scale1 + fractal->analyticDE.offset1;
}
// sym4
if (fractal->transformCommon.functionEnabledCxFalse
&& aux.i >= fractal->transformCommon.startIterationsB
&& aux.i < fractal->transformCommon.stopIterationsB)
{
aux.r = z.Length();
aux.DE = aux.DE * 2.0 * aux.r;
CVector4 temp = z;
double tempL = temp.Length();
// if (tempL < 1e-21)
// tempL = 1e-21;
z *= fractal->transformCommon.scale3D111;
aux.DE *= z.Length() / tempL;
if (fabs(z.x) < fabs(z.z)) swap(z.x, z.z);
if (fabs(z.x) < fabs(z.y)) swap(z.x, z.y);
if (fabs(z.y) < fabs(z.z)) swap(z.y, z.z);
if (z.x * z.z < 0.0) z.z = -z.z;
if (z.x * z.y < 0.0) z.y = -z.y;
temp.x = z.x * z.x - z.y * z.y - z.z * z.z;
temp.y = 2.0 * z.x * z.y;
temp.z = 2.0 * z.x * z.z;
z = temp + fractal->transformCommon.offsetF000;
// radial offset
double lengthTempZ = -z.Length();
// if (lengthTempZ > -1e-21)
// lengthTempZ = -1e-21; // z is neg.)
z *= 1.0 + fractal->transformCommon.offset / lengthTempZ;
// scale
z *= fractal->transformCommon.scale1;
aux.DE *= fabs(fractal->transformCommon.scale1);
}
// rotation
if (fractal->transformCommon.functionEnabledRFalse
&& aux.i >= fractal->transformCommon.startIterationsR
&& aux.i < fractal->transformCommon.stopIterationsR)
{
z = fractal->transformCommon.rotationMatrix.RotateVector(z);
}
// mandelbulb multi
if (aux.i >= fractal->transformCommon.startIterationsM
&& aux.i < fractal->transformCommon.stopIterationsM)
{
aux.r = z.Length();
if (fractal->transformCommon.functionEnabledFalse)
{
if (fractal->transformCommon.functionEnabledAxFalse
&& aux.i >= fractal->transformCommon.startIterationsX
&& aux.i < fractal->transformCommon.stopIterationsX)
z.x = fabs(z.x);
if (fractal->transformCommon.functionEnabledAyFalse
&& aux.i >= fractal->transformCommon.startIterationsY
&& aux.i < fractal->transformCommon.stopIterationsY)
z.y = fabs(z.y);
if (fractal->transformCommon.functionEnabledAzFalse
&& aux.i >= fractal->transformCommon.startIterationsZ
&& aux.i < fractal->transformCommon.stopIterationsZ)
z.z = fabs(z.z);
}
double th0 = fractal->bulb.betaAngleOffset;
double ph0 = fractal->bulb.alphaAngleOffset;
CVector3 v;
switch (fractal->sinTan2Trig.orderOfZYX)
{
case multi_OrderOfZYX_zyx:
default: v = CVector3(z.z, z.y, z.x); break;
case multi_OrderOfZYX_zxy: v = CVector3(z.z, z.x, z.y); break;
case multi_OrderOfZYX_yzx: v = CVector3(z.y, z.z, z.x); break;
case multi_OrderOfZYX_yxz: v = CVector3(z.y, z.x, z.z); break;
case multi_OrderOfZYX_xzy: v = CVector3(z.x, z.z, z.y); break;
case multi_OrderOfZYX_xyz: v = CVector3(z.x, z.y, z.z); break;
}
if (fractal->sinTan2Trig.asinOrAcos == multi_asinOrAcos_asin)
th0 += asin(v.x / aux.r);
else
th0 += acos(v.x / aux.r);
if (fractal->sinTan2Trig.atan2OrAtan == multi_atan2OrAtan_atan2)
ph0 += atan2(v.y, v.z);
else
ph0 += atan(v.y / v.z);
double rp = pow(aux.r, fractal->bulb.power - 1.0);
double th = th0 * fractal->bulb.power * fractal->transformCommon.scaleA1;
double ph = ph0 * fractal->bulb.power * fractal->transformCommon.scaleB1;
aux.DE = rp * aux.DE * fractal->bulb.power + 1.0;
rp *= aux.r;
if (fractal->transformCommon.functionEnabledxFalse)
{ // cosine mode
double sinth = th;
if (fractal->transformCommon.functionEnabledyFalse) sinth = th0;
sinth = sin(sinth);
z = rp * CVector4(sinth * sin(ph), cos(ph) * sinth, cos(th), 0.0);
}
else
{ // sine mode
double costh = th;
if (fractal->transformCommon.functionEnabledzFalse) costh = th0;
costh = cos(costh);
z = rp * CVector4(costh * cos(ph), sin(ph) * costh, sin(th), 0.0);
}
if (fractal->transformCommon.functionEnabledKFalse)
{
if (fractal->transformCommon.functionEnabledDFalse) swap(z.x, z.y);
if (fractal->transformCommon.functionEnabledEFalse) swap(z.x, z.z);
// swap
if (fractal->transformCommon.functionEnabledBxFalse) z.x = -z.x;
if (fractal->transformCommon.functionEnabledByFalse) z.y = -z.y;
if (fractal->transformCommon.functionEnabledBzFalse) z.z = -z.z;
}
}
z += fractal->transformCommon.additionConstant000;
}
/**
* mandelbulb vary scaleV1
*/
void MandelbulbVaryPowerV1Iteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
double tempVC = fractal->bulb.power; // constant to be varied
if (aux.i >= fractal->transformCommon.startIterations250
&& aux.i < fractal->transformCommon.stopIterations
&& (fractal->transformCommon.stopIterations - fractal->transformCommon.startIterations250
!= 0))
{
int iterationRange =
fractal->transformCommon.stopIterations - fractal->transformCommon.startIterations250;
int currentIteration = (aux.i - fractal->transformCommon.startIterations250);
tempVC += fractal->transformCommon.offset0 * (1.0 * currentIteration) / iterationRange;
}
if (aux.i >= fractal->transformCommon.stopIterations)
{
tempVC = (tempVC + fractal->transformCommon.offset0);
}
// if (aux.r < 1e-21)
// aux.r = 1e-21;
double th0 = asin(z.z / aux.r) + fractal->bulb.betaAngleOffset;
double ph0 = atan2(z.y, z.x) + fractal->bulb.alphaAngleOffset;
double rp = pow(aux.r, tempVC - 1.0);
double th = th0 * tempVC;
double ph = ph0 * tempVC;
double cth = cos(th);
aux.DE = rp * aux.DE * tempVC + 1.0;
rp *= aux.r;
z = CVector4(cth * cos(ph), cth * sin(ph), sin(th), 0.0) * rp;
}
/**
* Menger Cross KIFS
* from code by Knighty
* http://www.fractalforums.com/fragmentarium/
* cross-menger!-can-anyone-do-this/msg93972/#new
*/
void MengerCrossKIFSIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
CVector4 gap = fractal->transformCommon.constantMultiplier000;
double t;
double dot1;
if (fractal->transformCommon.functionEnabledFalse
&& aux.i >= fractal->transformCommon.startIterations
&& aux.i < fractal->transformCommon.stopIterations1)
{
z.y = fabs(z.y);
z.z = fabs(z.z);
if (fractal->transformCommon.functionEnabledFFalse) z.x = fabs(z.x);
dot1 = (z.x * -SQRT_3_4 + z.y * 0.5) * fractal->transformCommon.scale;
t = max(0.0, dot1);
z.x -= (t * -SQRT_3) - 0.5;
z.y = fabs(z.y - t);
if (z.y > z.z) swap(z.y, z.z);
z.y -= 0.75;
z -= gap * CVector4(SQRT_3_4, 1.5, 1.5, 0.0);
if (z.z > z.x) swap(z.z, z.x);
z *= fractal->transformCommon.constantMultiplier111; // post scale
if (fractal->transformCommon.functionEnabledyFalse)
{
z.y = max(0.0, z.y) * fractal->transformCommon.scaleA1;
z.z = max(0.0, z.z) * fractal->transformCommon.scaleB1;
}
z += fractal->transformCommon.additionConstant000; // post offset
z = fractal->transformCommon.rotationMatrix.RotateVector(z);
aux.DE *= fractal->analyticDE.scale1; // tweak
}
if (fractal->transformCommon.functionEnabled && aux.i >= fractal->transformCommon.startIterationsA
&& aux.i < fractal->transformCommon.stopIterationsA)
{ // CrossMengerKIFS
float lengthL;
// z = ( z );//+ preAdd );
z.y = fabs(z.y);
z.z = fabs(z.z);
if (fractal->transformCommon.functionEnabledzFalse) z.x = fabs(z.x);
lengthL = z.x * SQRT_3_4 - z.y * 0.5;
if (lengthL < 0.0)
{
z.x -= SQRT_3_4 * (2.0 * lengthL);
z.y -= -lengthL;
}
lengthL = z.y;
if (lengthL < 0.0)
{
z.y -= 2.0 * lengthL;
}
lengthL = (-z.y + z.z) * SQRT_1_2;
if (lengthL < 0.0)
{
z.y -= -SQRT_1_2 * (2.0 * lengthL);
z.z -= SQRT_1_2 * (2.0 * lengthL);
}
lengthL = z.y;
if (lengthL < 0.5)
{
z.y -= 2.0 * (lengthL - 0.5);
}
CVector4 edge = fractal->transformCommon.offset222;
if (fractal->transformCommon.functionEnabledxFalse)
{
z.x = edge.x - z.x;
z.y = edge.y - z.y;
z.z = edge.z - z.z;
}
z *= fractal->transformCommon.scale3;
z -= CVector4(SQRT_3_4, 1.5, 1.5, 0.0) * (fractal->transformCommon.scale3 - 1.0);
aux.DE *= fractal->transformCommon.scale3;
z += fractal->transformCommon.offset000; // post offset
if (fractal->transformCommon.functionEnabledPFalse)
{
z.x = fabs(z.x + fractal->transformCommon.offset) + fractal->transformCommon.offset0;
}
if (fractal->transformCommon.functionEnabledRFalse
&& aux.i >= fractal->transformCommon.startIterationsR
&& aux.i < fractal->transformCommon.stopIterationsR)
{
z = fractal->transformCommon.rotationMatrix2.RotateVector(z);
}
}
}
/**
* Menger Cross Mod1
* from code by Knighty
* http://www.fractalforums.com/fragmentarium/
* cross-menger!-can-anyone-do-this/msg93972/#new
*/
void MengerCrossMod1Iteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
CVector4 gap = fractal->transformCommon.constantMultiplier000;
if (fractal->transformCommon.functionEnabledx && aux.i >= fractal->transformCommon.startIterations
&& aux.i < fractal->transformCommon.stopIterations1)
{
z.y = fabs(z.y);
z.z = fabs(z.z);
if (fractal->transformCommon.functionEnabledFFalse) z.x = fabs(z.x);
double dot1 = (z.x * -SQRT_3_4 + z.y * 0.5) * fractal->transformCommon.scale;
double t = max(0.0, dot1);
z.x -= t * -SQRT_3 - (0.5 * SQRT_3_4);
z.y = fabs(z.y - t);
if (z.y > z.z) swap(z.y, z.z);
z.y -= 1.5;
z -= gap * CVector4(SQRT_3_4, -1.5, 1.5, 0.0);
if (z.z > z.x) swap(z.z, z.x);
if (fractal->transformCommon.functionEnabledyFalse)
{
if (z.x >= 0.0)
{
z.y = max(0.0, z.y) * fractal->transformCommon.scaleA1;
z.z = max(0.0, z.z) * fractal->transformCommon.scaleB1;
}
}
z = fractal->transformCommon.rotationMatrix.RotateVector(z);
aux.DE *= fractal->analyticDE.scale1; // tweak
}
if (fractal->transformCommon.functionEnabledy
&& aux.i >= fractal->transformCommon.startIterationsA
&& aux.i < fractal->transformCommon.stopIterationsA)
{ // CrossMengerTrick
z.y = fabs(z.y);
z.z = fabs(z.z);
if (fractal->transformCommon.functionEnabledzFalse) z.x = fabs(z.x);
double dot1 = (z.x * -SQRT_3_4 + z.y * 0.5);
double t = 1.0 * max(0.0, dot1);
z.x -= t * -SQRT_3;
if (fractal->transformCommon.functionEnabledXFalse)
z.y = fabs(z.y) - t;
else
{
z.y = fabs(z.y - t);
}
z.x -= SQRT_3_4;
// Choose nearest corner/edge to get translation symmetry (all y & z code)
double dy = 0.0;
double dz = 0.0;
if (z.y > 0.5 && z.z > 0.5) // if both y & z > 0.5 then =1.5
{
dy = 1.5;
dz = 1.5;
}
else if (z.z < z.y)
{
dy = 1.5; // and dz is unchanged
}
else
dz = 1.5; // and dy is unchanged
z.y -= dy;
z.z -= dz;
z *= fractal->transformCommon.scale3;
aux.DE *= fractal->transformCommon.scale3;
z.y += dy;
z.z += dz;
z.x += SQRT_3_4;
if (fractal->transformCommon.functionEnabledPFalse)
{
z.x = fabs(z.x + fractal->transformCommon.offset) + fractal->transformCommon.offset0;
}
if (fractal->transformCommon.functionEnabledRFalse
&& aux.i >= fractal->transformCommon.startIterationsR
&& aux.i < fractal->transformCommon.stopIterationsR)
{
z = fractal->transformCommon.rotationMatrix2.RotateVector(z);
}
}
}
/**
* Menger Sponge formula modified by Mclarekin
* from code by Knighty
*/
void MengerMod1Iteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
z = fabs(z);
if (z.x - z.y < 0.0) swap(z.y, z.x);
if (z.x - z.z < 0.0) swap(z.z, z.x);
if (z.y - z.z < 0.0) swap(z.z, z.y);
z *= fractal->transformCommon.scale3;
z.x -= 2.0 * fractal->transformCommon.constantMultiplier111.x;
z.y -= 2.0 * fractal->transformCommon.constantMultiplier111.y;
if (z.z > 1.0) z.z -= 2.0 * fractal->transformCommon.constantMultiplier111.z;
aux.DE *= fractal->transformCommon.scale3;
if (fractal->transformCommon.rotationEnabled && aux.i >= fractal->transformCommon.startIterations
&& aux.i < fractal->transformCommon.stopIterations)
{
z = fractal->transformCommon.rotationMatrix.RotateVector(z);
}
z += fractal->transformCommon.additionConstant000;
// boxoffset
if (fractal->transformCommon.functionEnabledxFalse
&& aux.i >= fractal->transformCommon.startIterationsA
&& aux.i < fractal->transformCommon.stopIterationsA) // box offset
{
CVector4 temp = z;
z.x = sign(z.x) * fractal->transformCommon.additionConstantA000.x + z.x;
z.y = sign(z.y) * fractal->transformCommon.additionConstantA000.y + z.y;
z.z = sign(z.z) * fractal->transformCommon.additionConstantA000.z + z.z;
if (fractal->transformCommon.functionEnabledFalse)
{
double tempL = temp.Length();
// if (tempL < 1e-21) tempL = 1e-21;
double avgScale = z.Length() / tempL;
aux.DE = aux.DE * avgScale + 1.0;
}
}
if (fractal->transformCommon.functionEnabledFalse)
{
CVector4 zA = (aux.i == fractal->transformCommon.intA) ? z : CVector4();
CVector4 zB = (aux.i == fractal->transformCommon.intB) ? z : CVector4();
z = (z * fractal->transformCommon.scale1) + (zA * fractal->transformCommon.offset)
+ (zB * fractal->transformCommon.offset0);
aux.DE *= fractal->transformCommon.scale1;
}
}
/**
* Menger Middle Mod
*/
void MengerMiddleModIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{ // fabs() and menger fold
z = fabs(z + fractal->transformCommon.additionConstantA000);
if (z.x - z.y < 0.0) swap(z.y, z.x);
if (z.x - z.z < 0.0) swap(z.z, z.x);
if (z.y - z.z < 0.0) swap(z.z, z.y);
if (fractal->mandelbox.mainRotationEnabled && aux.i >= fractal->transformCommon.startIterationsC
&& aux.i < fractal->transformCommon.stopIterationsC) // rotation
{
z = fractal->mandelbox.mainRot.RotateVector(z);
}
if (fractal->transformCommon.functionEnabledBxFalse
&& aux.i >= fractal->transformCommon.startIterationsA
&& aux.i < fractal->transformCommon.stopIterationsA) // box fold
{
if (fabs(z.x) > fractal->mandelbox.foldingLimit)
{
z.x = sign(z.x) * fractal->mandelbox.foldingValue - z.x;
aux.color += fractal->mandelbox.color.factor.x;
}
if (fabs(z.y) > fractal->mandelbox.foldingLimit)
{
z.y = sign(z.y) * fractal->mandelbox.foldingValue - z.y;
aux.color += fractal->mandelbox.color.factor.y;
}
double zLimit = fractal->mandelbox.foldingLimit * fractal->transformCommon.scale1;
double zValue = fractal->mandelbox.foldingValue * fractal->transformCommon.scale1;
if (fabs(z.z) > zLimit)
{
z.z = sign(z.z) * zValue - z.z;
aux.color += fractal->mandelbox.color.factor.z;
}
}
if (fractal->transformCommon.functionEnabledByFalse
&& aux.i >= fractal->transformCommon.startIterations
&& aux.i < fractal->transformCommon.stopIterations)
{ // fabsBoxFold
CVector4 tempA, tempB;
if (fractal->transformCommon.functionEnabledx)
tempA.x = fabs(z.x + fractal->transformCommon.additionConstant111.x);
if (fractal->transformCommon.functionEnabledAx)
tempB.x = fabs(z.x - fractal->transformCommon.additionConstantA111.x);
z.x = tempA.x - tempB.x - (z.x * fractal->transformCommon.scale3D111.x);
if (fractal->transformCommon.functionEnabledy)
tempA.y = fabs(z.y + fractal->transformCommon.additionConstant111.y);
if (fractal->transformCommon.functionEnabledAy)
tempB.y = fabs(z.y - fractal->transformCommon.additionConstantA111.y);
z.y = tempA.y - tempB.y - (z.y * fractal->transformCommon.scale3D111.y);
if (fractal->transformCommon.functionEnabledz)
tempA.z = fabs(z.z + fractal->transformCommon.additionConstant111.z);
if (fractal->transformCommon.functionEnabledAz)
tempB.z = fabs(z.z - fractal->transformCommon.additionConstantA111.z);
z.z = tempA.z - tempB.z - (z.z * fractal->transformCommon.scale3D111.z);
if (aux.i >= fractal->transformCommon.startIterationsB
&& aux.i < fractal->transformCommon.stopIterationsB)
{
z *= fractal->transformCommon.scaleA1;
aux.DE *= fabs(fractal->transformCommon.scaleA1);
}
}
// menger scales and offsets
z *= fractal->transformCommon.scale3;
z.x -= 2.0 * fractal->transformCommon.constantMultiplier111.x;
z.y -= 2.0 * fractal->transformCommon.constantMultiplier111.y;
if (fractal->transformCommon.functionEnabled)
{
if (z.z > 1.0) z.z -= 2.0 * fractal->transformCommon.constantMultiplier111.z;
}
else
{
z.z -= 2.0 * fractal->transformCommon.constantMultiplier111.z;
}
aux.DE *= fractal->transformCommon.scale3;
if (fractal->transformCommon.addCpixelEnabledFalse) // addCpixel options
{
switch (fractal->mandelbulbMulti.orderOfXYZC)
{
case multi_OrderOfXYZ_xyz:
default: aux.c = CVector4(aux.c.x, aux.c.y, aux.c.z, aux.c.w); break;
case multi_OrderOfXYZ_xzy: aux.c = CVector4(aux.c.x, aux.c.z, aux.c.y, aux.c.w); break;
case multi_OrderOfXYZ_yxz: aux.c = CVector4(aux.c.y, aux.c.x, aux.c.z, aux.c.w); break;
case multi_OrderOfXYZ_yzx: aux.c = CVector4(aux.c.y, aux.c.z, aux.c.x, aux.c.w); break;
case multi_OrderOfXYZ_zxy: aux.c = CVector4(aux.c.z, aux.c.x, aux.c.y, aux.c.w); break;
case multi_OrderOfXYZ_zyx: aux.c = CVector4(aux.c.z, aux.c.y, aux.c.x, aux.c.w); break;
}
z += aux.c * fractal->transformCommon.constantMultiplierC111;
}
}
/**
* Menger Sponge and octo
* from code by Knighty
*/
void MengerOctoIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{ // octo
if (aux.i >= fractal->transformCommon.startIterationsE
&& aux.i < fractal->transformCommon.stopIterationsE)
{
if (z.x + z.y < 0.0) z = CVector4(-z.y, -z.x, z.z, z.w);
if (z.x + z.z < 0.0) // z.xz = -z.zx;
z = CVector4(-z.z, z.y, -z.x, z.w);
if (z.x - z.y < 0.0) // z.xy = z.yx;
z = CVector4(z.y, z.x, z.z, z.w);
if (z.x - z.z < 0.0) // z.xz = z.zx;
z = CVector4(z.z, z.y, z.x, z.w);
z.x = fabs(z.x);
z = z * fractal->transformCommon.scale2
- fractal->transformCommon.offset100 * (fractal->transformCommon.scale2 - 1.0);
aux.DE *= fractal->transformCommon.scale2;
}
// box offset
if (fractal->transformCommon.functionEnabledxFalse
&& aux.i >= fractal->transformCommon.startIterationsA
&& aux.i < fractal->transformCommon.stopIterationsA)
{
CVector4 temp = z;
z.x = sign(z.x) * fractal->transformCommon.additionConstantA000.x + z.x;
z.y = sign(z.y) * fractal->transformCommon.additionConstantA000.y + z.y;
z.z = sign(z.z) * fractal->transformCommon.additionConstantA000.z + z.z;
if (fractal->transformCommon.functionEnabledzFalse)
{
double tempL = temp.Length();
// if (tempL < 1e-21) tempL = 1e-21;
double avgScale = z.Length() / tempL;
aux.DE = aux.DE * avgScale + 1.0;
}
}
// spherical fold
if (fractal->transformCommon.functionEnabledSFalse
&& aux.i >= fractal->transformCommon.startIterationsS
&& aux.i < fractal->transformCommon.stopIterationsS)
{
double para = 0.0;
double paraAddP0 = 0.0;
if (fractal->transformCommon.functionEnabledyFalse)
{
// para += paraAddP0 + fractal->transformCommon.minR2p25;
if (fractal->Cpara.enabledLinear)
{
para = fractal->Cpara.para00; // parameter value at iter 0
double temp0 = para;
double tempA = fractal->Cpara.paraA;
double tempB = fractal->Cpara.paraB;
double tempC = fractal->Cpara.paraC;
double lengthAB = fractal->Cpara.iterB - fractal->Cpara.iterA;
double lengthBC = fractal->Cpara.iterC - fractal->Cpara.iterB;
double grade1 = (tempA - temp0) / fractal->Cpara.iterA;
double grade2 = (tempB - tempA) / lengthAB;
double grade3 = (tempC - tempB) / lengthBC;
// slopes
if (aux.i < fractal->Cpara.iterA)
{
para = temp0 + (aux.i * grade1);
}
if (aux.i < fractal->Cpara.iterB && aux.i >= fractal->Cpara.iterA)
{
para = tempA + (aux.i - fractal->Cpara.iterA) * grade2;
}
if (aux.i >= fractal->Cpara.iterB)
{
para = tempB + (aux.i - fractal->Cpara.iterB) * grade3;
}
// Curvi part on "true"
if (fractal->Cpara.enabledCurves)
{
double paraAdd = 0.0;
double paraIt;
if (lengthAB > 2.0 * fractal->Cpara.iterA) // stop error, todo fix.
{
double curve1 = (grade2 - grade1) / (4.0 * fractal->Cpara.iterA);
double tempL = lengthAB - fractal->Cpara.iterA;
double curve2 = (grade3 - grade2) / (4.0 * tempL);
if (aux.i < 2 * fractal->Cpara.iterA)
{
paraIt = tempA - fabs(tempA - aux.i);
paraAdd = paraIt * paraIt * curve1;
}
if (aux.i >= 2 * fractal->Cpara.iterA && aux.i < fractal->Cpara.iterB + tempL)
{
paraIt = tempB - fabs(tempB * aux.i);
paraAdd = paraIt * paraIt * curve2;
}
para += paraAdd;
}
}
}
paraAddP0 = 0.0;
if (fractal->Cpara.enabledParabFalse)
{ // parabolic = paraOffset + iter *slope + (iter *iter *scale)
paraAddP0 = fractal->Cpara.parabOffset0 + (aux.i * fractal->Cpara.parabSlope)
+ (aux.i * aux.i * 0.001 * fractal->Cpara.parabScale);
}
}
para += paraAddP0 + fractal->transformCommon.minR2p25;
// spherical fold
double rr = z.Dot(z);
z += fractal->mandelbox.offset;
// if (r2 < 1e-21) r2 = 1e-21;
if (rr < para)
{
double tglad_factor1 = fractal->transformCommon.maxR2d1 / para;
z *= tglad_factor1;
aux.DE *= tglad_factor1;
aux.color += fractal->mandelbox.color.factorSp1;
}
else if (rr < fractal->transformCommon.maxR2d1)
{
double tglad_factor2 = fractal->transformCommon.maxR2d1 / rr;
z *= tglad_factor2;
aux.DE *= tglad_factor2;
aux.color += fractal->mandelbox.color.factorSp2;
}
z -= fractal->mandelbox.offset;
z *= fractal->transformCommon.scale08;
aux.DE = aux.DE * fabs(fractal->transformCommon.scale08);
}
// rotation
if (fractal->transformCommon.functionEnabledRFalse
&& aux.i >= fractal->transformCommon.startIterationsR
&& aux.i < fractal->transformCommon.stopIterationsR)
{
z = fractal->transformCommon.rotationMatrix.RotateVector(z);
}
// menger
if (fractal->transformCommon.functionEnabledM
&& aux.i >= fractal->transformCommon.startIterationsM
&& aux.i < fractal->transformCommon.stopIterationsM)
{
z = fabs(z);
if (z.x - z.y < 0.0) swap(z.y, z.x);
if (z.x - z.z < 0.0) swap(z.z, z.x);
if (z.y - z.z < 0.0) swap(z.z, z.y);
z *= fractal->transformCommon.scale3;
z.x -= 2.0 * fractal->transformCommon.constantMultiplier111.x;
z.y -= 2.0 * fractal->transformCommon.constantMultiplier111.y;
if (z.z > 1.0) z.z -= 2.0 * fractal->transformCommon.constantMultiplier111.z;
aux.DE *= fractal->transformCommon.scale3;
z += fractal->transformCommon.additionConstant000;
}
// iter weight
if (fractal->transformCommon.functionEnabledFalse)
{
CVector4 zA = (aux.i == fractal->transformCommon.intA) ? z : CVector4();
CVector4 zB = (aux.i == fractal->transformCommon.intB) ? z : CVector4();
z = (z * fractal->transformCommon.scale1) + (zA * fractal->transformCommon.offsetA0)
+ (zB * fractal->transformCommon.offsetB0);
aux.DE *= fractal->transformCommon.scale1;
}
}
/**
* Menger Sponge Polynomial Hybrid modified by Mclarekin
*/
void MengerPwr2PolyIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
CVector4 c = aux.const_c;
if (aux.i >= fractal->transformCommon.startIterations
&& aux.i < fractal->transformCommon.stopIterations1)
{
CVector4 partA = z;
if (fractal->transformCommon.functionEnabledFalse) // fabs
partA = fabs(z);
if (fractal->transformCommon.functionEnabledxFalse) // pwr3 or z * fabs(z^2)
partA *= z;
partA =
partA * fractal->transformCommon.scale2 + fractal->transformCommon.constantMultiplier111;
CVector4 fnZ1 = z;
if (fractal->transformCommon.functionEnabledBxFalse) // cos(z*Pi)
{
double scalePi = M_PI * fractal->transformCommon.scaleC1;
fnZ1.x = cos(z.x * scalePi);
fnZ1.y = cos(z.y * scalePi);
fnZ1.z = cos(z.z * scalePi);
}
if (fractal->transformCommon.functionEnabledyFalse) // pi rotation
fnZ1 = fnZ1.RotateAroundVectorByAngle(fractal->transformCommon.constantMultiplier111.GetXYZ(),
M_PI * fractal->transformCommon.scaleB1);
if (fractal->transformCommon.functionEnabledzFalse) // box offset
{
fnZ1.x = (sign(fnZ1.x) * fractal->transformCommon.additionConstant000.x) + fnZ1.x;
fnZ1.y = (sign(fnZ1.y) * fractal->transformCommon.additionConstant000.y) + fnZ1.y;
fnZ1.z = (sign(fnZ1.z) * fractal->transformCommon.additionConstant000.z) + fnZ1.z;
}
if (fractal->transformCommon.functionEnabledAxFalse) // fabs(fnZ1)
fnZ1 = fabs(fnZ1);
CVector4 partB = z;
if (fractal->transformCommon.functionEnabledAzFalse) partB = fabs(z);
partB *= fractal->transformCommon.scale4;
CVector4 constantMult = CVector4(fractal->transformCommon.constantMultiplierB111.x,
fractal->transformCommon.constantMultiplierB111.y,
fractal->transformCommon.constantMultiplierB111.z, 0.0);
z = constantMult + partB - partA * fnZ1;
z *= fractal->transformCommon.scale025;
aux.DE = aux.DE * 4.0 * fractal->analyticDE.scale1 + fractal->analyticDE.offset1;
}
if (fractal->transformCommon.addCpixelEnabledFalse)
{
CVector4 tempC = c;
if (fractal->transformCommon.alternateEnabledFalse) // alternate
{
tempC = aux.c;
switch (fractal->mandelbulbMulti.orderOfXYZC)
{
case multi_OrderOfXYZ_xyz:
default: tempC = CVector4(tempC.x, tempC.y, tempC.z, tempC.w); break;
case multi_OrderOfXYZ_xzy: tempC = CVector4(tempC.x, tempC.z, tempC.y, tempC.w); break;
case multi_OrderOfXYZ_yxz: tempC = CVector4(tempC.y, tempC.x, tempC.z, tempC.w); break;
case multi_OrderOfXYZ_yzx: tempC = CVector4(tempC.y, tempC.z, tempC.x, tempC.w); break;
case multi_OrderOfXYZ_zxy: tempC = CVector4(tempC.z, tempC.x, tempC.y, tempC.w); break;
case multi_OrderOfXYZ_zyx: tempC = CVector4(tempC.z, tempC.y, tempC.x, tempC.w); break;
}
aux.c = tempC;
}
else
{
switch (fractal->mandelbulbMulti.orderOfXYZC)
{
case multi_OrderOfXYZ_xyz:
default: tempC = CVector4(c.x, c.y, c.z, c.w); break;
case multi_OrderOfXYZ_xzy: tempC = CVector4(c.x, c.z, c.y, c.w); break;
case multi_OrderOfXYZ_yxz: tempC = CVector4(c.y, c.x, c.z, c.w); break;
case multi_OrderOfXYZ_yzx: tempC = CVector4(c.y, c.z, c.x, c.w); break;
case multi_OrderOfXYZ_zxy: tempC = CVector4(c.z, c.x, c.y, c.w); break;
case multi_OrderOfXYZ_zyx: tempC = CVector4(c.z, c.y, c.x, c.w); break;
}
}
z += tempC * fractal->transformCommon.constantMultiplierC111;
}
int count = fractal->transformCommon.int1; // Menger Sponge
int k;
for (k = 0; k < count; k++)
{
z = fabs(z);
if (z.x - z.y < 0.0) swap(z.y, z.x);
if (z.x - z.z < 0.0) swap(z.z, z.x);
if (z.y - z.z < 0.0) swap(z.z, z.y);
z *= fractal->transformCommon.scale3;
z.x -= 2.0 * fractal->transformCommon.constantMultiplierA111.x;
z.y -= 2.0 * fractal->transformCommon.constantMultiplierA111.y;
if (z.z > 1.0) z.z -= 2.0 * fractal->transformCommon.constantMultiplierA111.z;
aux.DE *= fractal->transformCommon.scale3;
if (fractal->transformCommon.rotationEnabled
&& aux.i >= fractal->transformCommon.startIterationsA
&& aux.i < fractal->transformCommon.stopIterationsA) // rotation
{
z = fractal->transformCommon.rotationMatrix.RotateVector(z);
}
z += fractal->transformCommon.additionConstantA000;
}
}
/**
* Menger Prism Shape
* from code by Knighty
* http://www.fractalforums.com/fragmentarium/cross-menger!-can-anyone-do-this/msg93972/#new
*/
void MengerPrismShapeIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
CVector4 gap = fractal->transformCommon.constantMultiplier000;
double t;
double dot1;
if (aux.i >= fractal->transformCommon.startIterationsP
&& aux.i < fractal->transformCommon.stopIterationsP1)
{
z.y = fabs(z.y);
z.z = fabs(z.z);
dot1 = (z.x * -SQRT_3_4 + z.y * 0.5) * fractal->transformCommon.scale;
t = max(0.0, dot1);
z.x -= t * -SQRT_3;
z.y = fabs(z.y - t);
if (z.y > z.z) swap(z.y, z.z);
z -= gap * CVector4(SQRT_3_4, 1.5, 1.5, 0.0);
// z was pos, now some points neg (ie neg shift)
if (z.z > z.x) swap(z.z, z.x);
if (z.x > 0.0)
{
z.y = max(0.0, z.y);
z.z = max(0.0, z.z);
}
}
if (fractal->transformCommon.functionEnabledRFalse
&& aux.i >= fractal->transformCommon.startIterationsR
&& aux.i < fractal->transformCommon.stopIterationsR)
z = fractal->transformCommon.rotationMatrix.RotateVector(z);
if (fractal->transformCommon.benesiT1EnabledFalse
&& aux.i >= fractal->transformCommon.startIterations
&& aux.i < fractal->transformCommon.stopIterationsT1)
{
double tempXZ = z.x * SQRT_2_3 - z.z * SQRT_1_3;
z = CVector4(
(tempXZ - z.y) * SQRT_1_2, (tempXZ + z.y) * SQRT_1_2, z.x * SQRT_1_3 + z.z * SQRT_2_3, z.w);
CVector4 temp = z;
double tempL = temp.Length();
z = fabs(z) * fractal->transformCommon.scale3D222;
// if (tempL < 1e-21) tempL = 1e-21;
double avgScale = z.Length() / tempL;
aux.DE = aux.DE * avgScale + 1.0;
tempXZ = (z.y + z.x) * SQRT_1_2;
z = CVector4(z.z * SQRT_1_3 + tempXZ * SQRT_2_3, (z.y - z.x) * SQRT_1_2,
z.z * SQRT_2_3 - tempXZ * SQRT_1_3, z.w);
z = z - fractal->transformCommon.offset200;
}
if (fractal->transformCommon.functionEnabledxFalse
&& aux.i >= fractal->transformCommon.startIterationsD
&& aux.i < fractal->transformCommon.stopIterationsTM1)
{
double tempXZ = z.x * SQRT_2_3 - z.z * SQRT_1_3;
z = CVector4(
(tempXZ - z.y) * SQRT_1_2, (tempXZ + z.y) * SQRT_1_2, z.x * SQRT_1_3 + z.z * SQRT_2_3, z.w);
CVector4 temp = z;
double tempL = temp.Length();
z = fabs(z) * fractal->transformCommon.scale3D333;
// if (tempL < 1e-21) tempL = 1e-21;
double avgScale = z.Length() / tempL;
aux.DE = aux.DE * avgScale + 1.0;
z = (fabs(z + fractal->transformCommon.additionConstant111)
- fabs(z - fractal->transformCommon.additionConstant111) - z);
tempXZ = (z.y + z.x) * SQRT_1_2;
z = CVector4(z.z * SQRT_1_3 + tempXZ * SQRT_2_3, (z.y - z.x) * SQRT_1_2,
z.z * SQRT_2_3 - tempXZ * SQRT_1_3, z.w);
}
if (fractal->transformCommon.functionEnabledFFalse
&& aux.i >= fractal->transformCommon.startIterationsF
&& aux.i < fractal->transformCommon.stopIterationsF)
{
CVector4 tempA, tempB;
if (fractal->transformCommon.functionEnabledAx)
tempA.x = fabs(z.x + fractal->transformCommon.offsetF000.x);
if (fractal->transformCommon.functionEnabledx)
tempB.x = fabs(z.x - fractal->transformCommon.offset000.x);
z.x = tempA.x - tempB.x - (z.x * fractal->transformCommon.scale3D111.x);
if (fractal->transformCommon.functionEnabledAy)
tempA.y = fabs(z.y + fractal->transformCommon.offsetF000.y);
if (fractal->transformCommon.functionEnabledy)
tempB.y = fabs(z.y - fractal->transformCommon.offset000.y);
z.y = tempA.y - tempB.y - (z.y * fractal->transformCommon.scale3D111.y);
if (fractal->transformCommon.functionEnabledAz)
tempA.z = fabs(z.z + fractal->transformCommon.offsetF000.z);
if (fractal->transformCommon.functionEnabledz)
tempB.z = fabs(z.z - fractal->transformCommon.offset000.z);
z.z = tempA.z - tempB.z - (z.z * fractal->transformCommon.scale3D111.z);
z += fractal->transformCommon.offsetA000;
}
if (fractal->transformCommon.functionEnabled && aux.i >= fractal->transformCommon.startIterationsM
&& aux.i < fractal->transformCommon.stopIterationsM)
{
z = fabs(z);
if (z.x - z.y < 0.0) swap(z.y, z.x);
if (z.x - z.z < 0.0) swap(z.z, z.x);
if (z.y - z.z < 0.0) swap(z.z, z.y);
z *= fractal->transformCommon.scale3;
z.x -= 2.0 * fractal->transformCommon.constantMultiplierA111.x;
z.y -= 2.0 * fractal->transformCommon.constantMultiplierA111.y;
if (z.z > 1.0) z.z -= 2.0 * fractal->transformCommon.constantMultiplierA111.z;
aux.DE *= fractal->transformCommon.scale3;
z += fractal->transformCommon.additionConstantA000;
}
if (fractal->analyticDE.enabledFalse)
aux.DE = aux.DE * fractal->analyticDE.scale1 + fractal->analyticDE.offset0;
}
/**
* Menger Prism Shape2
* from code by Knighty
* http://www.fractalforums.com/fragmentarium/
* cross-menger!-can-anyone-do-this/msg93972/#new
*/
void MengerPrismShape2Iteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
if (fractal->transformCommon.functionEnabledSwFalse)
{
z = CVector4(-z.z, z.x, z.y, z.w);
}
CVector4 gap = fractal->transformCommon.constantMultiplier000;
if (fractal->transformCommon.functionEnabledx
&& aux.i >= fractal->transformCommon.startIterationsP
&& aux.i < fractal->transformCommon.stopIterationsP1)
{
double t;
double dot1;
if (fractal->transformCommon.functionEnabledCxFalse)
{
z.x = fabs(z.x);
}
if (fractal->transformCommon.functionEnabledCy)
{
z.y = fabs(z.y);
}
if (fractal->transformCommon.functionEnabledCz)
{
z.z = fabs(z.z);
}
double tempOff = (fractal->transformCommon.offset0 + SQRT_3_4d2);
switch (fractal->combo.modeA)
{
case combo_mode0:
default:
dot1 = (z.x * -SQRT_3_4 + z.y * 0.5) * fractal->transformCommon.scale;
t = max(0.0, dot1);
z.x -= t * -SQRT_3 - tempOff;
z.y = fabs(z.y - t);
break;
case combo_mode1:
dot1 = (z.x * -SQRT_3_4 + z.y * 0.5) * fractal->transformCommon.scale;
t = max(0.0, dot1);
z.y -= t * -SQRT_3 - tempOff;
z.x = fabs(z.x - t); // x y swap
break;
case combo_mode2:
dot1 = (z.z * -SQRT_3_4 + z.y * 0.5) * fractal->transformCommon.scale;
t = max(0.0, dot1);
z.z -= t * -SQRT_3 - tempOff;
z.y = fabs(z.y - t); // z y swap
break;
case combo_mode3:
dot1 = (z.z * -SQRT_3_4 + z.y * 0.5) * fractal->transformCommon.scale;
t = max(0.0, dot1);
z.y -= t * -SQRT_3 - tempOff;
z.z = fabs(z.z - t); // z y swap
break;
case combo_mode4:
dot1 = (z.x * -SQRT_3_4 + z.y * 0.5) * fractal->transformCommon.scale;
t = max(0.0, dot1);
z.y -= t * -SQRT_3 - tempOff;
z.z -= t * -SQRT_3 - tempOff;
z.x = fabs(z.x - t); // x y swap and other things
z.y = fabs(z.y - t);
break;
case combo_mode5:
dot1 = (z.z * -SQRT_3_4 + z.y * 0.5) * fractal->transformCommon.scale;
t = max(0.0, dot1);
z.x -= t * -SQRT_3 - tempOff;
z.y -= t * -SQRT_3 - tempOff;
z.y = fabs(z.y - t); // x y swap and other things
z.z = fabs(z.z - t);
break;
case combo_mode6:
dot1 = (z.x * -SQRT_3_4 + z.y * 0.5) * fractal->transformCommon.scale;
t = max(0.0, dot1);
z.y -= t * -SQRT_3 - (fractal->transformCommon.offset0);
z.z -= t * -SQRT_3 - (fractal->transformCommon.offset0);
z.x = fabs(z.y - t); // x y swap and other things and swizzle
z.y = fabs(z.x - t);
break;
case combo_mode7:
dot1 = (z.z * -SQRT_3_4 + z.y * 0.5) * fractal->transformCommon.scale;
t = max(0.0, dot1);
z.x -= t * -SQRT_3 - (fractal->transformCommon.offset0);
z.y -= t * -SQRT_3 - (fractal->transformCommon.offset0);
z.y = fabs(z.z - t); // x y swap and other things and swizzle
z.z = fabs(z.y - t);
break;
}
if (z.y > z.z) swap(z.y, z.z);
z.y -= fractal->transformCommon.offsetB0;
z -= gap * CVector4(SQRT_3_4, 1.5, 1.5, 0.0);
if (z.z > z.x) swap(z.z, z.x);
if (fractal->transformCommon.functionEnabledyFalse)
{
z.y = max(0.0, z.y) * fractal->transformCommon.scaleA1;
z.z = max(0.0, z.z) * fractal->transformCommon.scaleB1;
}
if (fractal->transformCommon.functionEnabledzFalse)
{
if (z.x >= 0.0)
{
z.y = max(0.0, z.y) * fractal->transformCommon.scaleA1;
z.z = max(0.0, z.z) * fractal->transformCommon.scaleB1;
}
}
z *= fractal->transformCommon.scale1;
aux.DE *= fractal->transformCommon.scale1;
aux.DE *= fractal->transformCommon.scaleC1;
}
if (fractal->transformCommon.functionEnabledXFalse
&& aux.i >= fractal->transformCommon.startIterationsA
&& aux.i < fractal->transformCommon.stopIterationsA)
{ // CrossMengerTrick
double dd = aux.DE;
z.y = fabs(z.y);
z.z = fabs(z.z);
if (fractal->transformCommon.functionEnabledCyFalse)
{
z.x = fabs(z.x);
}
double dot1 = (z.x * -SQRT_3_4 + z.y * 0.5) * fractal->transformCommon.scaleD1;
double t = max(0.0, dot1);
z.x -= t * -SQRT_3;
if (fractal->transformCommon.functionEnabledBzFalse)
{
z.y = fabs(z.y) - t;
}
else
{
z.y = fabs(z.y - t);
}
z.x -= SQRT_3_4;
double dy = 0.0;
double dz = 0.0;
if (z.y > 0.5 && z.z > 0.5)
{
dy = 1.5;
dz = 1.5;
}
else if (z.z < z.y)
// else if ((z.y - 1.5) * (z.y - 1.5) + z.z * z.z < z.y * z.y + (z.z - 1.5) * (z.z - 1.5))
{
dy = 1.5;
}
else
dz = 1.5;
z.y -= dy;
z.z -= dz;
z *= fractal->transformCommon.scaleA3;
aux.DE *= fractal->transformCommon.scaleA3;
z.y += dy;
z.z += dz;
z.x += SQRT_3_4;
if (fractal->transformCommon.functionEnabledFalse)
{
dd *= FRAC_1_3 * fractal->transformCommon.scaleE1;
z *= dd;
aux.DE *= dd;
}
aux.DE *= fractal->transformCommon.offset1; //.DE tweak cross menger trick part
}
if (fractal->transformCommon.functionEnabledPFalse)
{
z.x = fabs(z.x + fractal->transformCommon.offset) + fractal->transformCommon.offsetC0;
}
// void KIFS(vec3 z)
//{//Pure KIFS... almost correct
if (fractal->transformCommon.functionEnabledKFalse
&& aux.i >= fractal->transformCommon.startIterationsB
&& aux.i < fractal->transformCommon.stopIterationsB)
{
if (fractal->transformCommon.functionEnabledCzFalse)
{
z.x = fabs(fractal->transformCommon.offset - z.x) + fractal->transformCommon.offsetC0;
}
z.y = fabs(z.y);
z.z = fabs(z.z);
double dot2 = (z.x * -SQRT_3_4 + z.y * 0.5) * fractal->transformCommon.scaleF1;
double t = max(0.0, dot2);
z.x -= t * -SQRT_3;
z.y = fabs(z.y - t);
if (z.y > z.z) swap(z.y, z.z);
z.y = fabs(z.y - 0.5) + 0.5;
z -= CVector4(0.5 * SQRT_3, 1.5, 1.5, 0.0);
z *= fractal->transformCommon.scaleB3;
aux.DE *= fractal->transformCommon.scaleB3;
z += CVector4(0.5 * SQRT_3, 1.5, 1.5, 0.0);
}
if (fractal->transformCommon.benesiT1EnabledFalse
&& aux.i >= fractal->transformCommon.startIterations
&& aux.i < fractal->transformCommon.stopIterationsT1)
{
double tempXZ = z.x * SQRT_2_3 - z.z * SQRT_1_3;
z = CVector4(
(tempXZ - z.y) * SQRT_1_2, (tempXZ + z.y) * SQRT_1_2, z.x * SQRT_1_3 + z.z * SQRT_2_3, z.w);
CVector4 tempZ = z;
double tempL = tempZ.Length();
z = fabs(z) * fractal->transformCommon.scale3D222;
// if (tempL < 1e-21) tempL = 1e-21;
double avgScale = z.Length() / tempL;
aux.DE = aux.DE * avgScale + 1.0;
tempXZ = (z.y + z.x) * SQRT_1_2;
z = CVector4(z.z * SQRT_1_3 + tempXZ * SQRT_2_3, (z.y - z.x) * SQRT_1_2,
z.z * SQRT_2_3 - tempXZ * SQRT_1_3, z.w);
z = z - fractal->transformCommon.offset200;
}
if (fractal->transformCommon.benesiT1MEnabledFalse
&& aux.i >= fractal->transformCommon.startIterationsD
&& aux.i < fractal->transformCommon.stopIterationsTM1)
{
double tempXZ = z.x * SQRT_2_3 - z.z * SQRT_1_3;
z = CVector4(
(tempXZ - z.y) * SQRT_1_2, (tempXZ + z.y) * SQRT_1_2, z.x * SQRT_1_3 + z.z * SQRT_2_3, z.w);
CVector4 temp = z;
double tempL = temp.Length();
z = fabs(z) * fractal->transformCommon.scale3D333;
// if (tempL < 1e-21) tempL = 1e-21;
double avgScale = z.Length() / tempL;
aux.DE = aux.DE * avgScale + 1.0;
z = (fabs(z + fractal->transformCommon.additionConstant111)
- fabs(z - fractal->transformCommon.additionConstant111) - z);
tempXZ = (z.y + z.x) * SQRT_1_2;
z = CVector4(z.z * SQRT_1_3 + tempXZ * SQRT_2_3, (z.y - z.x) * SQRT_1_2,
z.z * SQRT_2_3 - tempXZ * SQRT_1_3, z.w);
}
if (fractal->transformCommon.functionEnabledFFalse
&& aux.i >= fractal->transformCommon.startIterationsF
&& aux.i < fractal->transformCommon.stopIterationsF)
{
CVector4 tempA, tempB;
if (fractal->transformCommon.functionEnabledAx)
tempA.x = fabs(z.x + fractal->transformCommon.offsetF000.x);
if (fractal->transformCommon.functionEnabledx)
tempB.x = fabs(z.x - fractal->transformCommon.offset000.x);
z.x = tempA.x - tempB.x - (z.x * fractal->transformCommon.scale3D111.x);
if (fractal->transformCommon.functionEnabledAy)
tempA.y = fabs(z.y + fractal->transformCommon.offsetF000.y);
if (fractal->transformCommon.functionEnabledy)
tempB.y = fabs(z.y - fractal->transformCommon.offset000.y);
z.y = tempA.y - tempB.y - (z.y * fractal->transformCommon.scale3D111.y);
if (fractal->transformCommon.functionEnabledAz)
tempA.z = fabs(z.z + fractal->transformCommon.offsetF000.z);
if (fractal->transformCommon.functionEnabledz)
tempB.z = fabs(z.z - fractal->transformCommon.offset000.z);
z.z = tempA.z - tempB.z - (z.z * fractal->transformCommon.scale3D111.z);
z += fractal->transformCommon.offsetA000;
}
// rotation
if (fractal->transformCommon.functionEnabledRFalse
&& aux.i >= fractal->transformCommon.startIterationsR
&& aux.i < fractal->transformCommon.stopIterationsR)
z = fractal->transformCommon.rotationMatrix.RotateVector(z);
// menger
if (fractal->transformCommon.functionEnabledM
&& aux.i >= fractal->transformCommon.startIterationsM
&& aux.i < fractal->transformCommon.stopIterationsM)
{
z = fabs(z);
if (z.x - z.y < 0.0) swap(z.y, z.x);
if (z.x - z.z < 0.0) swap(z.z, z.x);
if (z.y - z.z < 0.0) swap(z.z, z.y);
z *= fractal->transformCommon.scale3;
z.x -= 2.0 * fractal->transformCommon.constantMultiplierA111.x;
z.y -= 2.0 * fractal->transformCommon.constantMultiplierA111.y;
if (z.z > 1.0) z.z -= 2.0 * fractal->transformCommon.constantMultiplierA111.z;
aux.DE *= fractal->transformCommon.scale3;
z += fractal->transformCommon.additionConstantA000;
}
if (fractal->analyticDE.enabledFalse)
aux.DE = aux.DE * fractal->analyticDE.scale1 + fractal->analyticDE.offset0;
}
/**
* Menger Smooth
* http://www.fractalforums.com/fragmentarium/help-t22583/
*/
void MengerSmoothIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
double sc1 = fractal->transformCommon.scale3 - 1.0; // 3 - 1 = 2, 2/3 = 0.6667;
double sc2 = sc1 / fractal->transformCommon.scale3; // 8 - 1 = 7, 7/8 = 0.89ish;
double OffsetS = fractal->transformCommon.offset0005; //
if (fractal->transformCommon.functionEnabled)
{
// the closer to origin the greater the effect of OffsetSQ
z = CVector4(
sqrt(z.x * z.x + OffsetS), sqrt(z.y * z.y + OffsetS), sqrt(z.z * z.z + OffsetS), z.w);
}
double t;
CVector4 OffsetC = fractal->transformCommon.offset1105;
t = z.x - z.y;
t = 0.5 * (t - sqrt(t * t + OffsetS));
z.x = z.x - t;
z.y = z.y + t;
t = z.x - z.z;
t = 0.5 * (t - sqrt(t * t + OffsetS));
z.x = z.x - t;
z.z = z.z + t;
t = z.y - z.z;
t = 0.5 * (t - sqrt(t * t + OffsetS));
z.y = z.y - t;
z.z = z.z + t;
z.z = z.z - OffsetC.z * sc2; // sc2 reduces C.z
z.z = -sqrt(z.z * z.z + OffsetS);
z.z = z.z + OffsetC.z * sc2;
z.x = fractal->transformCommon.scale3 * z.x - OffsetC.x * sc1; // sc1 scales up C.x
z.y = fractal->transformCommon.scale3 * z.y - OffsetC.y * sc1;
z.z = fractal->transformCommon.scale3 * z.z;
aux.DE *= fractal->transformCommon.scale3;
if (fractal->transformCommon.rotationEnabled && aux.i >= fractal->transformCommon.startIterationsR
&& aux.i < fractal->transformCommon.stopIterationsR)
{
z = fractal->transformCommon.rotationMatrix.RotateVector(z);
}
if (fractal->transformCommon.functionEnabledzFalse)
{
CVector4 zA = (aux.i == fractal->transformCommon.intA) ? z : CVector4();
CVector4 zB = (aux.i == fractal->transformCommon.intB) ? z : CVector4();
z = (z * fractal->transformCommon.scale1) + (zA * fractal->transformCommon.offsetA0)
+ (zB * fractal->transformCommon.offsetB0);
aux.DE *= fractal->transformCommon.scale1;
}
}
/**
* Menger Smooth Mod1, based on :
* http://www.fractalforums.com/fragmentarium/help-t22583/
*/
void MengerSmoothMod1Iteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
if (fractal->transformCommon.functionEnabled)
{
z = CVector4(sqrt(z.x * z.x + fractal->transformCommon.offset0),
sqrt(z.y * z.y + fractal->transformCommon.offset0),
sqrt(z.z * z.z + fractal->transformCommon.offset0), z.w);
}
if (fractal->transformCommon.functionEnabledFFalse)
{
z = fabs(z);
double s = fractal->transformCommon.offset;
z += CVector4(s, s, s, 0.0);
}
double t;
double ScaleP5 = fractal->transformCommon.scale05;
CVector4 OffsetC = fractal->transformCommon.constantMultiplier221;
double OffsetS = fractal->transformCommon.offset0005;
t = z.x - z.y;
t = ScaleP5 * (t - sqrt(t * t + OffsetS * fractal->transformCommon.constantMultiplier111.x));
z.x = z.x - t;
z.y = z.y + t;
t = z.x - z.z;
t = ScaleP5 * (t - sqrt(t * t + OffsetS * fractal->transformCommon.constantMultiplier111.y));
z.x = z.x - t;
z.z = z.z + t;
t = z.y - z.z;
t = ScaleP5 * (t - sqrt(t * t + OffsetS * fractal->transformCommon.constantMultiplier111.z));
z.y = z.y - t;
z.z = z.z + t;
z.z = z.z - OffsetC.z / 3.0;
z.z = -sqrt(z.z * z.z + OffsetS);
z.z = z.z + OffsetC.z / 3.0;
z.x = fractal->transformCommon.scale3 * z.x - OffsetC.x;
z.y = fractal->transformCommon.scale3 * z.y - OffsetC.y;
z.z = fractal->transformCommon.scale3 * z.z;
aux.DE *= fractal->transformCommon.scale3;
if (fractal->transformCommon.rotationEnabled && aux.i >= fractal->transformCommon.startIterationsR
&& aux.i < fractal->transformCommon.stopIterationsR)
{
z = fractal->transformCommon.rotationMatrix.RotateVector(z);
}
if (fractal->transformCommon.functionEnabledxFalse
&& aux.i >= fractal->transformCommon.startIterationsA
&& aux.i < fractal->transformCommon.stopIterationsA) // box offset
{
z.x = sign(z.x) * fractal->transformCommon.additionConstantA000.x + z.x;
z.y = sign(z.y) * fractal->transformCommon.additionConstantA000.y + z.y;
z.z = sign(z.z) * fractal->transformCommon.additionConstantA000.z + z.z;
}
if (fractal->transformCommon.functionEnabledzFalse)
{
CVector4 zA = (aux.i == fractal->transformCommon.intA) ? z : CVector4();
CVector4 zB = (aux.i == fractal->transformCommon.intB) ? z : CVector4();
z = (z * fractal->transformCommon.scale1) + (zA * fractal->transformCommon.offsetA0)
+ (zB * fractal->transformCommon.offsetB0);
aux.DE *= fractal->transformCommon.scale1;
}
}
/**
* Msltoe Donut formula
* @reference
* http://www.fractalforums.com/new-theories-and-research/
* low-hanging-dessert-an-escape-time-donut-fractal/msg90171/#msg90171
*/
void MsltoeDonutIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
double radius2 = fractal->donut.ringThickness;
double nSect = M_PI_2x / fractal->donut.number;
double fact = fractal->donut.factor;
double R = sqrt(z.x * z.x + z.y * z.y);
double R2 = fractal->donut.ringRadius - R;
double t = R2 * R2 + z.z * z.z - radius2 * radius2;
double theta = atan2(z.y, z.x);
double theta2 = nSect * round(theta / nSect);
if (t > 0.03)
{
double c1 = cos(theta2);
double s1 = sin(theta2);
double x1 = c1 * z.x + s1 * z.y;
double y1 = -s1 * z.x + c1 * z.y;
double z1 = z.z;
x1 = x1 - fractal->donut.ringRadius;
z.x = fact * x1;
z.y = fact * z1;
z.z = fact * y1;
}
else
{
z /= t;
}
aux.color += theta2;
}
/**
* MsltoeSym2Mod based on the formula from Mandelbulb3D
* @reference http://www.fractalforums.com/theory/choosing-the-squaring-formula-by-location/15/
*/
void MsltoeSym2ModIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
CVector4 c = aux.const_c;
aux.DE = aux.DE * 2.0 * aux.r;
CVector4 temp = z;
if (fabs(z.y) < fabs(z.z)) // then swap
{
z.y = temp.z; // making z.y furthest away from axis
z.z = temp.y;
}
if (z.y > z.z) // then change sign of z.x and z.z
{
z.x = -z.x;
}
CVector4 z2 = z * z; // squares
double v3 = (z2.x + z2.y + z2.z); // sum of squares
// if (v3 < 1e-21 && v3 > -1e-21)
// v3 = (v3 > 0) ? 1e-21 : -1e-21;
double zr = 1.0 - z2.z / v3;
temp.x = (z2.x - z2.y) * zr;
temp.y = 2.0 * z.x * z.y * zr * fractal->transformCommon.scale; // scaling temp.y
temp.z = 2.0 * z.z * sqrt(z2.x + z2.y);
z = temp + fractal->transformCommon.additionConstant000;
if (fractal->transformCommon.addCpixelEnabledFalse)
{
CVector4 tempFAB = c;
if (fractal->transformCommon.functionEnabledx) tempFAB.x = fabs(tempFAB.x);
if (fractal->transformCommon.functionEnabledy) tempFAB.y = fabs(tempFAB.y);
if (fractal->transformCommon.functionEnabledz) tempFAB.z = fabs(tempFAB.z);
tempFAB *= fractal->transformCommon.constantMultiplier000;
z.x += sign(z.x) * tempFAB.x;
z.y += sign(z.y) * tempFAB.y;
z.z += sign(z.z) * tempFAB.z;
}
double lengthTempZ = -z.Length();
// if (lengthTempZ > -1e-21)
// lengthTempZ = -1e-21; // z is neg.)
z *= 1.0 + fractal->transformCommon.offset / lengthTempZ;
z *= fractal->transformCommon.scale1;
aux.DE *= fabs(fractal->transformCommon.scale1);
}
/**
* MsltoeSym3Mod based on the formula from Mandelbulb3D
* @reference http://www.fractalforums.com/theory/choosing-the-squaring-formula-by-location/15/
*/
void MsltoeSym3ModIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
CVector4 c = aux.const_c;
aux.DE = aux.DE * 2.0 * aux.r;
CVector4 temp = z;
if (fabs(z.y) < fabs(z.z)) // then swap
{
z.y = temp.z; // making z.y furthest away from axis
z.z = temp.y;
}
if (z.y > z.z) // then change sign of z.x and z.z
{
z.x = -z.x;
z.z = -z.z;
}
CVector4 z2 = z * z; // squares
double v3 = (z2.x + z2.y + z2.z)
+ fractal->transformCommon.scale0 * fractal->transformCommon.scale0 * z2.y * z2.z;
; // sum of squares
// if (v3 < 1e-21 && v3 > -1e-21) v3 = (v3 > 0) ? 1e-21 : -1e-21;
double zr = 1.0 - z2.z / v3;
temp.x = (z2.x - z2.y) * zr;
temp.y = 2.0 * z.x * z.y * zr * fractal->transformCommon.scale; // scaling temp.y
temp.z = 2.0 * z.z * sqrt(z2.x + z2.y);
z = temp + fractal->transformCommon.additionConstant000;
if (fractal->transformCommon.addCpixelEnabledFalse)
{
CVector4 tempFAB = c;
if (fractal->transformCommon.functionEnabledx) tempFAB.x = fabs(tempFAB.x);
if (fractal->transformCommon.functionEnabledy) tempFAB.y = fabs(tempFAB.y);
if (fractal->transformCommon.functionEnabledz) tempFAB.z = fabs(tempFAB.z);
tempFAB *= fractal->transformCommon.constantMultiplier000;
z.x += sign(z.x) * tempFAB.x;
z.y += sign(z.y) * tempFAB.y;
z.z += sign(z.z) * tempFAB.z;
}
double lengthTempZ = -z.Length();
// if (lengthTempZ > -1e-21) lengthTempZ = -1e-21; // z is neg.)
z *= 1.0 + fractal->transformCommon.offset / lengthTempZ;
z *= fractal->transformCommon.scale1;
aux.DE = aux.DE * fabs(fractal->transformCommon.scale1) + 1.0;
if (fractal->transformCommon.functionEnabledFalse // quaternion fold
&& aux.i >= fractal->transformCommon.startIterationsA
&& aux.i < fractal->transformCommon.stopIterationsA)
{
aux.r = z.Length();
aux.DE = aux.DE * 2.0 * aux.r;
z = CVector4(z.x * z.x - z.y * z.y - z.z * z.z, z.x * z.y, z.x * z.z, z.w);
if (fractal->analyticDE.enabledFalse)
{
CVector4 temp2 = z;
double tempL = temp2.Length();
z *= CVector4(1.0, 2.0, 2.0, 1.0);
// if (tempL < 1e-21) tempL = 1e-21;
double avgScale = z.Length() / tempL;
// aux.DE *= avgScale * fractal->transformCommon.scaleA1;
double tempAux = aux.DE * avgScale;
aux.DE = aux.DE + (tempAux - aux.DE) * fractal->analyticDE.scale1;
}
else
{
z *= CVector4(1.0, 2.0, 2.0, 1.0);
}
}
}
/**
* MsltoeJuliaBulb Eiffie. Refer post by Eiffie Reply #69 on: January 27, 2015
* @reference http://www.fractalforums.com/theory/choosing-the-squaring-formula-by-location/60/
*/
void EiffieMsltoeIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
CVector4 c = aux.const_c;
double psi = fabs(fmod(atan2(z.z, z.y) + M_PI + M_PI_8, M_PI_4) - M_PI_8);
double lengthYZ = sqrt(z.y * z.y + z.z * z.z);
z.y = cos(psi) * lengthYZ;
z.z = sin(psi) * lengthYZ;
aux.DE = aux.DE * 2.0 * aux.r;
CVector4 z2 = z * z;
double rr = z2.x + z2.y + z2.z;
double m = 1.0 - z2.z / rr;
CVector4 temp;
temp.x = (z2.x - z2.y) * m;
temp.y = 2.0 * z.x * z.y * m * fractal->transformCommon.scale; // scaling y;;
temp.z = 2.0 * z.z * sqrt(z2.x + z2.y);
temp.w = z.w;
z = temp + fractal->transformCommon.additionConstant000;
if (fractal->transformCommon.addCpixelEnabledFalse)
{
CVector4 tempFAB = c;
if (fractal->transformCommon.functionEnabledx) tempFAB.x = fabs(tempFAB.x);
if (fractal->transformCommon.functionEnabledy) tempFAB.y = fabs(tempFAB.y);
if (fractal->transformCommon.functionEnabledz) tempFAB.z = fabs(tempFAB.z);
tempFAB *= fractal->transformCommon.constantMultiplier000;
z.x += sign(z.x) * tempFAB.x;
z.y += sign(z.y) * tempFAB.y;
z.z += sign(z.z) * tempFAB.z;
}
double lengthTempZ = -z.Length();
// if (lengthTempZ > -1e-21) lengthTempZ = -1e-21; // z is neg.)
z *= 1.0 + fractal->transformCommon.offset / lengthTempZ;
z *= fractal->transformCommon.scale1;
/*aux.DE = aux.DE * fabs(fractal->transformCommon.scale1) + 1.0;
// aux.DE *= fabs(fractal->transformCommon.scale1);
if (fractal->analyticDE.enabledFalse)
{ // analytic DE adjustment
aux.DE *= fabs(fractal->transformCommon.scale1) * fractal->analyticDE.scale1;
}
else
{
aux.DE *= fabs(fractal->transformCommon.scale1);
}*/
if (!fractal->analyticDE.enabledFalse)
aux.DE = aux.DE * fabs(fractal->transformCommon.scale1) + 1.0;
else
aux.DE = aux.DE * fabs(fractal->transformCommon.scale1) * fractal->analyticDE.scale1
+ fractal->analyticDE.offset1;
}
/**
* Msltoe_Julia_Bulb_Mod2
* @reference
* http://www.fractalforums.com/theory/choosing-the-squaring-formula-by-location/msg14198/#msg14198
*/
void MsltoeSym3Mod2Iteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
CVector4 c = aux.const_c;
aux.DE = aux.DE * 2.0 * aux.r;
double theta;
double phi;
CVector4 z2 = z * z;
double r = z2.x + z2.y + z2.z;
// if (r < 1e-21)
// r = 1e-21;
double r1 = sqrt(r + fractal->transformCommon.scale0 * z2.y * z2.z);
// if (r1 < 1e-21)
// r1 = 1e-21;
if (z2.z < z2.y)
{
theta = 2.0 * atan2(z.y, z.x);
phi = 2.0 * asin(z.z / r1);
z.x = r * cos(theta) * cos(phi);
z.y = r * sin(theta) * cos(phi);
z.z = -r * sin(phi);
}
else
{
theta = 2.0 * atan2(z.z, z.x);
phi = 2.0 * asin(z.y / r1);
z.x = r * cos(theta) * cos(phi);
z.y = -r * sin(phi);
z.z = r * sin(theta) * cos(phi);
}
z += fractal->transformCommon.additionConstant000;
if (fractal->transformCommon.addCpixelEnabledFalse)
{
CVector4 tempFAB = c;
if (fractal->transformCommon.functionEnabledx) tempFAB.x = fabs(tempFAB.x);
if (fractal->transformCommon.functionEnabledy) tempFAB.y = fabs(tempFAB.y);
if (fractal->transformCommon.functionEnabledz) tempFAB.z = fabs(tempFAB.z);
tempFAB *= fractal->transformCommon.constantMultiplier000;
z.x += sign(z.x) * tempFAB.x;
z.y += sign(z.y) * tempFAB.y;
z.z += sign(z.z) * tempFAB.z;
}
double lengthTempZ = -z.Length();
// if (lengthTempZ > -1e-21)
// lengthTempZ = -1e-21; // z is neg.)
z *= 1.0 + fractal->transformCommon.offset / lengthTempZ;
z *= fractal->transformCommon.scale1;
aux.DE *= fabs(fractal->transformCommon.scale1);
}
/**
* Msltoe_Julia_Bulb_Mod3
* @reference
* http://www.fractalforums.com/theory/choosing-the-squaring-formula-by-location/msg14320/#msg14320
*/
void MsltoeSym3Mod3Iteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
CVector4 c = aux.const_c;
aux.DE = aux.DE * 2.0 * aux.r;
CVector4 z1 = z;
double psi = atan2(z.z, z.y) + M_PI * 2.0;
double psi2 = 0;
while (psi > M_PI_8)
{
psi -= M_PI_4;
psi2 -= M_PI_4; // M_PI_4 = pi/4
}
double cs = cos(psi2);
double sn = sin(psi2);
z1.y = z.y * cs - z.z * sn;
z1.z = z.y * sn + z.z * cs;
z.y = z1.y;
z.z = z1.z;
CVector4 zs = z * z;
double zs2 = zs.x + zs.y;
// if (zs2 < 1e-21)
// zs2 = 1e-21;
double zs3 =
(zs2 + zs.z) + fractal->transformCommon.scale0 * fractal->transformCommon.scale0 * zs.y * zs.z;
double zsd = (1.0 - zs.z / zs3);
z1.x = (zs.x - zs.y) * zsd;
z1.y = (2.0 * z.x * z.y) * zsd * fractal->transformCommon.scale; // scaling y;
z1.z = 2.0 * z.z * sqrt(zs2);
z.x = z1.x;
z.y = z1.y * cs + z1.z * sn;
z.z = -z1.y * sn + z1.z * cs;
z += fractal->transformCommon.additionConstant000;
if (fractal->transformCommon.addCpixelEnabledFalse) // symmetrical addCpixel
{
CVector4 tempFAB = c;
if (fractal->transformCommon.functionEnabledx) tempFAB.x = fabs(tempFAB.x);
if (fractal->transformCommon.functionEnabledy) tempFAB.y = fabs(tempFAB.y);
if (fractal->transformCommon.functionEnabledz) tempFAB.z = fabs(tempFAB.z);
tempFAB *= fractal->transformCommon.constantMultiplier000;
z.x += sign(z.x) * tempFAB.x;
z.y += sign(z.y) * tempFAB.y;
z.z += sign(z.z) * tempFAB.z;
}
double lengthTempZ = -z.Length(); // spherical offset
// if (lengthTempZ > -1e-21)
// lengthTempZ = -1e-21; // z is neg.)
z *= 1.0 + fractal->transformCommon.offset / lengthTempZ;
z *= fractal->transformCommon.scale1;
aux.DE *= fabs(fractal->transformCommon.scale1);
if (fractal->transformCommon.functionEnabledFalse // quaternion fold
&& aux.i >= fractal->transformCommon.startIterationsA
&& aux.i < fractal->transformCommon.stopIterationsA)
{
aux.r = z.Length();
aux.DE = aux.DE * 2.0 * aux.r;
z = CVector4(z.x * z.x - z.y * z.y - z.z * z.z, z.x * z.y, z.x * z.z, z.w);
if (fractal->analyticDE.enabledFalse)
{
CVector4 temp = z;
double tempL = temp.Length();
z *= CVector4(1.0, 2.0, 2.0, 1.0);
// if (tempL < 1e-21)
// tempL = 1e-21;
double avgScale = z.Length() / tempL;
aux.DE *= avgScale;
}
else
{
z *= CVector4(1.0, 2.0, 2.0, 1.0);
}
}
}
/**
* MsltoeSym4Mod Based on the formula from Mandelbulb3D
* @reference http://www.fractalforums.com/theory/choosing-the-squaring-formula-by-location/15/
* This formula contains aux.color
*/
void MsltoeSym4ModIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
CVector4 c = aux.const_c;
CVector4 oldZ = z;
aux.DE = aux.DE * 2.0 * aux.r;
CVector4 temp = z;
double tempL = temp.Length();
// if (tempL < 1e-21)
// tempL = 1e-21;
z *= fractal->transformCommon.scale3D111;
aux.DE *= fabs(z.Length() / tempL);
if (fabs(z.x) < fabs(z.z)) swap(z.x, z.z);
if (fabs(z.x) < fabs(z.y)) swap(z.x, z.y);
if (fabs(z.y) < fabs(z.z)) swap(z.y, z.z);
if (fractal->foldColor.auxColorEnabledFalse)
{
if (z.x != oldZ.x) aux.color += fractal->mandelbox.color.factor.x;
if (z.y != oldZ.y) aux.color += fractal->mandelbox.color.factor.y;
if (z.z != oldZ.z) aux.color += fractal->mandelbox.color.factor.z;
}
if (z.x * z.z < 0.0) z.z = -z.z;
if (z.x * z.y < 0.0) z.y = -z.y;
temp.x = z.x * z.x - z.y * z.y - z.z * z.z;
temp.y = 2.0 * z.x * z.y;
temp.z = 2.0 * z.x * z.z;
z = temp + fractal->transformCommon.additionConstant000;
if (fractal->transformCommon.rotationEnabled)
{
z = fractal->transformCommon.rotationMatrix.RotateVector(z);
}
if (fractal->transformCommon.addCpixelEnabledFalse)
{
CVector4 tempFAB = c;
if (fractal->transformCommon.functionEnabledx) tempFAB.x = fabs(tempFAB.x);
if (fractal->transformCommon.functionEnabledy) tempFAB.y = fabs(tempFAB.y);
if (fractal->transformCommon.functionEnabledz) tempFAB.z = fabs(tempFAB.z);
tempFAB *= fractal->transformCommon.constantMultiplier000;
z.x += sign(z.x) * tempFAB.x;
z.y += sign(z.y) * tempFAB.y;
z.z += sign(z.z) * tempFAB.z;
}
double lengthTempZ = -z.Length();
// if (lengthTempZ > -1e-21)
// lengthTempZ = -1e-21; // z is neg.)
z *= 1.0 + fractal->transformCommon.offset / lengthTempZ;
z *= fractal->transformCommon.scale1;
aux.DE *= fabs(fractal->transformCommon.scale1);
}
/**
* MsltoeToroidal
* @reference http://www.fractalforums.com/theory/toroidal-coordinates/msg9428/
*/
void MsltoeToroidalIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
if (fractal->transformCommon.functionEnabledFalse) // pre-scale
{
z *= fractal->transformCommon.scale3D111;
aux.DE *= z.Length() / aux.r + 1.0;
}
// Toroidal bulb
double r1 = fractal->transformCommon.minR05; // default 0.5
double theta = atan2(z.y, z.x);
double x1 = r1 * cos(theta);
double y1 = r1 * sin(theta);
aux.r = (z.x - x1) * (z.x - x1) + (z.y - y1) * (z.y - y1) + z.z * z.z; //+ 1e-061
double phi = asin(z.z / sqrt(aux.r));
double rp = pow(aux.r, fractal->transformCommon.pwr4); // default 4.0
phi *= fractal->transformCommon.pwr8; // default 8
theta *= fractal->bulb.power; // default 9 gives 8 symmetry
// convert back to cartesian coordinates
z.x = (r1 + rp * cos(phi)) * cos(theta);
z.y = (r1 + rp * cos(phi)) * sin(theta);
z.z = -rp * sin(phi);
if (!fractal->analyticDE.enabledFalse)
{ // analytic DE adjustment,default is, scale1 & offset1 & offset2 = 1.0
aux.DE = pow(aux.r, fractal->transformCommon.pwr4 - 1.0) * aux.DE * aux.DE
* fractal->transformCommon.pwr4
+ 1.0;
}
else
{
aux.DE = pow(aux.r, fractal->transformCommon.pwr4 - fractal->analyticDE.offset1)
* fractal->transformCommon.pwr4 * fractal->analyticDE.scale1 * aux.DE * aux.DE
+ fractal->analyticDE.offset2;
}
if (fractal->transformCommon.functionEnabledAxFalse) // spherical offset
{
double lengthTempZ = -z.Length();
// if (lengthTempZ > -1e-21) lengthTempZ = -1e-21; // z is neg.)
z *= 1.0 + fractal->transformCommon.offset / lengthTempZ;
z *= fractal->transformCommon.scale;
aux.DE = aux.DE * fabs(fractal->transformCommon.scale) + 1.0;
}
// then add Cpixel constant vector
}
/**
* MsltoeToroidalMulti
* @reference http://www.fractalforums.com/theory/toroidal-coordinates/msg9428/
*/
void MsltoeToroidalMultiIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
if (fractal->transformCommon.functionEnabledFalse) // pre-scale
{
z *= fractal->transformCommon.scale3D111;
aux.DE = aux.DE * z.Length() / aux.r + 1.0;
}
// Toroidal bulb multi
double th0 = fractal->bulb.betaAngleOffset;
double ph0 = fractal->bulb.alphaAngleOffset;
double v1, v2, v3;
switch (fractal->sinTan2Trig.orderOfZYX)
{
case multi_OrderOfZYX_zyx:
default:
v1 = z.z;
v2 = z.y;
v3 = z.x;
break;
case multi_OrderOfZYX_zxy:
v1 = z.z;
v2 = z.x;
v3 = z.y;
break;
case multi_OrderOfZYX_yzx:
v1 = z.y;
v2 = z.z;
v3 = z.x;
break;
case multi_OrderOfZYX_yxz:
v1 = z.y;
v2 = z.x;
v3 = z.z;
break;
case multi_OrderOfZYX_xzy:
v1 = z.x;
v2 = z.z;
v3 = z.y;
break;
case multi_OrderOfZYX_xyz:
v1 = z.x;
v2 = z.y;
v3 = z.z;
break;
}
switch (fractal->sinTan2Trig.atan2OrAtan)
{
case multi_atan2OrAtan_atan2: ph0 += atan2(v2, v3); break;
case multi_atan2OrAtan_atan: ph0 += atan(v2 / v3); break;
}
double r1 = fractal->transformCommon.minR05;
double x1 = r1 * cos(ph0);
double y1 = r1 * sin(ph0);
aux.r = (z.x - x1) * (z.x - x1) + (z.y - y1) * (z.y - y1) + z.z * z.z; //+ 1e-061
double sqrT = aux.r;
if (fractal->transformCommon.functionEnabledAy) // sqrt
{
sqrT = sqrt(aux.r);
}
switch (fractal->sinTan2Trig.asinOrAcos)
{
case multi_asinOrAcos_asin: th0 += asin(v1 / sqrT); break;
case multi_asinOrAcos_acos: th0 += acos(v1 / sqrT); break;
}
th0 *= fractal->transformCommon.pwr8; // default 8
ph0 *= fractal->bulb.power; // default 9 gives 8 symmetry
double rp = pow(aux.r, fractal->transformCommon.pwr4);
double costh = cos(th0);
double sinth = sin(th0);
if (fractal->transformCommon.functionEnabledzFalse)
{ // cosine mode
z.x = (r1 + rp * sinth) * sin(ph0);
z.y = (r1 + rp * sinth) * cos(ph0);
z.z = -rp * costh;
}
else
{ // sine mode default
z.x = (r1 + rp * costh) * cos(ph0);
z.y = (r1 + rp * costh) * sin(ph0);
z.z = -rp * sinth;
}
// DEcalc
if (!fractal->analyticDE.enabledFalse)
{ // analytic DE adjustment,default is, scale1 & offset1 & offset2 = 1.0
aux.DE = pow(aux.r, fractal->transformCommon.pwr4 - 1.0) * aux.DE * aux.DE
* fractal->transformCommon.pwr4
+ 1.0;
}
else
{
if (!fractal->transformCommon.functionEnabledAyFalse) aux.DE *= aux.DE;
aux.DE = pow(aux.r, fractal->transformCommon.pwr4 - fractal->analyticDE.offset1)
* fractal->transformCommon.pwr4 * fractal->analyticDE.scale1 * aux.DE
+ fractal->analyticDE.offset2;
}
if (fractal->transformCommon.functionEnabledAxFalse) // spherical offset
{
double lengthTempZ = -z.Length();
// if (lengthTempZ > -1e-21) lengthTempZ = -1e-21; // z is neg.)
z *= 1.0 + fractal->transformCommon.offset / lengthTempZ;
z *= fractal->transformCommon.scale;
aux.DE = aux.DE * fabs(fractal->transformCommon.scale) + 1.0;
}
// then add Cpixel constant vector
}
/**
* Pseudo Kleinian Knighty - Theli-at's Pseudo Kleinian (Scale 1 JuliaBox + Something
* @reference https://github.com/Syntopia/Fragmentarium/blob/master/
* Fragmentarium-Source/Examples/Knighty%20Collection/PseudoKleinian.frag
*/
void PseudoKleinianIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
CVector4 gap = fractal->transformCommon.constantMultiplier000;
double t;
double dot1;
// prism shape
if (fractal->transformCommon.functionEnabledPFalse
&& aux.i >= fractal->transformCommon.startIterationsP
&& aux.i < fractal->transformCommon.stopIterationsP1)
{
z.y = fabs(z.y);
z.z = fabs(z.z);
dot1 = (z.x * -SQRT_3_4 + z.y * 0.5) * fractal->transformCommon.scale;
t = max(0.0, dot1);
z.x -= t * -SQRT_3;
z.y = fabs(z.y - t);
if (z.y > z.z) swap(z.y, z.z);
z -= gap * CVector4(SQRT_3_4, 1.5, 1.5, 0.0);
// z was pos, now some points neg (ie neg shift)
if (z.z > z.x) swap(z.z, z.x);
if (z.x > 0.0)
{
z.y = max(0.0, z.y);
z.z = max(0.0, z.z);
}
}
// box fold
if (fractal->transformCommon.functionEnabledBxFalse
&& aux.i >= fractal->transformCommon.startIterationsA
&& aux.i < fractal->transformCommon.stopIterationsA)
{
if (fabs(z.x) > fractal->mandelbox.foldingLimit)
{
z.x = sign(z.x) * fractal->mandelbox.foldingValue - z.x;
aux.color += fractal->mandelbox.color.factor.x;
}
if (fabs(z.y) > fractal->mandelbox.foldingLimit)
{
z.y = sign(z.y) * fractal->mandelbox.foldingValue - z.y;
aux.color += fractal->mandelbox.color.factor.y;
}
double zLimit = fractal->mandelbox.foldingLimit * fractal->transformCommon.scale1;
double zValue = fractal->mandelbox.foldingValue * fractal->transformCommon.scale1;
if (fabs(z.z) > zLimit)
{
z.z = sign(z.z) * zValue - z.z;
aux.color += fractal->mandelbox.color.factor.z;
}
}
// PseudoKleinian
CVector4 cSize = fractal->transformCommon.additionConstant0777;
CVector4 tempZ = z; // correct c++ version.
if (z.x > cSize.x) tempZ.x = cSize.x;
if (z.x < -cSize.x) tempZ.x = -cSize.x;
if (z.y > cSize.y) tempZ.y = cSize.y;
if (z.y < -cSize.y) tempZ.y = -cSize.y;
if (z.z > cSize.z) tempZ.z = cSize.z;
if (z.z < -cSize.z) tempZ.z = -cSize.z;
z = tempZ * 2.0 - z;
double k = max(fractal->transformCommon.minR05 / z.Dot(z), 1.0);
z *= k;
aux.DE *= k + fractal->analyticDE.tweak005;
// rotation
if (fractal->transformCommon.functionEnabledRFalse
&& aux.i >= fractal->transformCommon.startIterationsR
&& aux.i < fractal->transformCommon.stopIterationsR)
z = fractal->transformCommon.rotationMatrix.RotateVector(z);
// offset
z += fractal->transformCommon.additionConstant000;
aux.pseudoKleinianDE = fractal->analyticDE.scale1;
}
/**
* Pseudo Kleinian Mod1, Knighty - Theli-at's Pseudo Kleinian (Scale 1 JuliaBox + Something
* @reference https://github.com/Syntopia/Fragmentarium/blob/master/
* Fragmentarium-Source/Examples/Knighty%20Collection/PseudoKleinian.frag
*/
void PseudoKleinianMod1Iteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
CVector4 gap = fractal->transformCommon.constantMultiplier000;
if (fractal->transformCommon.functionEnabledPFalse
&& aux.i >= fractal->transformCommon.startIterationsP
&& aux.i < fractal->transformCommon.stopIterationsP1)
{
z.y = fabs(z.y);
z.z = fabs(z.z);
double dot1 = (z.x * -SQRT_3_4 + z.y * 0.5) * fractal->transformCommon.scale;
double t = max(0.0, dot1);
z.x -= t * -SQRT_3;
z.y = fabs(z.y - t);
if (z.y > z.z) swap(z.y, z.z);
z -= gap * CVector4(SQRT_3_4, 1.5, 1.5, 0.0);
// z was pos, now some points neg (ie neg shift)
if (z.z > z.x) swap(z.z, z.x);
if (z.x > 0.0)
{
z.y = max(0.0, z.y);
z.z = max(0.0, z.z);
}
}
if (fractal->transformCommon.functionEnabledRFalse
&& aux.i >= fractal->transformCommon.startIterationsR
&& aux.i < fractal->transformCommon.stopIterationsR)
z = fractal->transformCommon.rotationMatrix.RotateVector(z);
if (fractal->transformCommon.benesiT1EnabledFalse
&& aux.i >= fractal->transformCommon.startIterations
&& aux.i < fractal->transformCommon.stopIterationsT1)
{
double tempXZ = z.x * SQRT_2_3 - z.z * SQRT_1_3;
z = CVector4(
(tempXZ - z.y) * SQRT_1_2, (tempXZ + z.y) * SQRT_1_2, z.x * SQRT_1_3 + z.z * SQRT_2_3, z.w);
CVector4 tempZ = z;
double tempL = tempZ.Length();
z = fabs(z) * fractal->transformCommon.scale3D222;
// if (tempL < 1e-21) tempL = 1e-21;
double avgScale = z.Length() / tempL;
aux.DE = aux.DE * avgScale + 1.0;
tempXZ = (z.y + z.x) * SQRT_1_2;
z = CVector4(z.z * SQRT_1_3 + tempXZ * SQRT_2_3, (z.y - z.x) * SQRT_1_2,
z.z * SQRT_2_3 - tempXZ * SQRT_1_3, z.w);
z = z - fractal->transformCommon.offset200;
}
if (fractal->transformCommon.functionEnabledxFalse
&& aux.i >= fractal->transformCommon.startIterationsD
&& aux.i < fractal->transformCommon.stopIterationsTM1)
{
double tempXZ = z.x * SQRT_2_3 - z.z * SQRT_1_3;
z = CVector4(
(tempXZ - z.y) * SQRT_1_2, (tempXZ + z.y) * SQRT_1_2, z.x * SQRT_1_3 + z.z * SQRT_2_3, z.w);
CVector4 temp = z;
double tempL = temp.Length();
z = fabs(z) * fractal->transformCommon.scale3D333;
// if (tempL < 1e-21) tempL = 1e-21;
double avgScale = z.Length() / tempL;
aux.DE = aux.DE * avgScale + 1.0;
z = (fabs(z + fractal->transformCommon.additionConstant111)
- fabs(z - fractal->transformCommon.additionConstant111) - z);
tempXZ = (z.y + z.x) * SQRT_1_2;
z = CVector4(z.z * SQRT_1_3 + tempXZ * SQRT_2_3, (z.y - z.x) * SQRT_1_2,
z.z * SQRT_2_3 - tempXZ * SQRT_1_3, z.w);
}
if (fractal->transformCommon.functionEnabledFFalse
&& aux.i >= fractal->transformCommon.startIterationsF
&& aux.i < fractal->transformCommon.stopIterationsF)
{
CVector4 tempA, tempB;
if (fractal->transformCommon.functionEnabledAx)
tempA.x = fabs(z.x + fractal->transformCommon.offsetF000.x);
if (fractal->transformCommon.functionEnabledx)
tempB.x = fabs(z.x - fractal->transformCommon.offset000.x);
z.x = tempA.x - tempB.x - (z.x * fractal->transformCommon.scale3D111.x);
if (fractal->transformCommon.functionEnabledAy)
tempA.y = fabs(z.y + fractal->transformCommon.offsetF000.y);
if (fractal->transformCommon.functionEnabledy)
tempB.y = fabs(z.y - fractal->transformCommon.offset000.y);
z.y = tempA.y - tempB.y - (z.y * fractal->transformCommon.scale3D111.y);
if (fractal->transformCommon.functionEnabledAz)
tempA.z = fabs(z.z + fractal->transformCommon.offsetF000.z);
if (fractal->transformCommon.functionEnabledz)
tempB.z = fabs(z.z - fractal->transformCommon.offset000.z);
z.z = tempA.z - tempB.z - (z.z * fractal->transformCommon.scale3D111.z);
z += fractal->transformCommon.offsetA000;
}
double k;
// Pseudo kleinian
CVector4 cSize = fractal->transformCommon.additionConstant0777;
if (fractal->transformCommon.functionEnabledAy
&& aux.i >= fractal->transformCommon.startIterationsC
&& aux.i < fractal->transformCommon.stopIterationsC)
{
CVector4 tempZ = z; // correct c++ version. non conditional mult 2.0
if (z.x > cSize.x) tempZ.x = cSize.x;
if (z.x < -cSize.x) tempZ.x = -cSize.x;
if (z.y > cSize.y) tempZ.y = cSize.y;
if (z.y < -cSize.y) tempZ.y = -cSize.y;
if (z.z > cSize.z) tempZ.z = cSize.z;
if (z.z < -cSize.z) tempZ.z = -cSize.z;
z.z *= fractal->transformCommon.scaleB1;
aux.DE *= fractal->transformCommon.scaleB1;
z = tempZ * 2.0 - z;
k = max(fractal->transformCommon.minR05 / z.Dot(z), 1.0);
z *= k;
aux.DE *= k + fractal->analyticDE.tweak005;
}
if (fractal->transformCommon.functionEnabledAyFalse
&& aux.i >= fractal->transformCommon.startIterationsB
&& aux.i < fractal->transformCommon.stopIterationsB)
{
// variation from openCL conditional mult 2.0
if (z.x > cSize.x) z.x = cSize.x * 2.0 - z.x;
if (z.x < -cSize.x) z.x = -cSize.x * 2.0 - z.x;
if (z.y > cSize.y) z.y = cSize.y * 2.0 - z.y;
if (z.y < -cSize.y) z.y = -cSize.y * 2.0 - z.y;
if (z.z > cSize.z) z.z = cSize.z * 2.0 - z.z;
if (z.z < -cSize.z) z.z = -cSize.z * 2.0 - z.z;
k = max(fractal->transformCommon.minR05 / z.Dot(z), 1.0);
z *= k;
aux.DE *= k + fractal->analyticDE.tweak005;
}
z += fractal->transformCommon.additionConstant000;
if (fractal->transformCommon.functionEnabledMFalse
&& aux.i >= fractal->transformCommon.startIterationsM
&& aux.i < fractal->transformCommon.stopIterationsM)
{
z = fabs(z);
if (z.x - z.y < 0.0) swap(z.y, z.x);
if (z.x - z.z < 0.0) swap(z.z, z.x);
if (z.y - z.z < 0.0) swap(z.z, z.y);
z *= fractal->transformCommon.scale3;
z.x -= 2.0 * fractal->transformCommon.constantMultiplierA111.x;
z.y -= 2.0 * fractal->transformCommon.constantMultiplierA111.y;
if (z.z > 1.0) z.z -= 2.0 * fractal->transformCommon.constantMultiplierA111.z;
aux.DE *= fractal->transformCommon.scale3 * fractal->transformCommon.scaleA1;
z += fractal->transformCommon.additionConstantA000;
}
aux.pseudoKleinianDE = fractal->analyticDE.scale1; // pK DE
}
/**
* Pseudo Kleinian Mod2, Knighty - Theli-at's Pseudo Kleinian (Scale 1 JuliaBox + Something
* @reference https://github.com/Syntopia/Fragmentarium/blob/master/
* Fragmentarium-Source/Examples/Knighty%20Collection/PseudoKleinian.frag
*/
void PseudoKleinianMod2Iteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
CVector4 c = aux.const_c;
CVector4 oldZ = z;
CVector4 zCol = z;
double rrCol = 0.0;
double colorAdd = 0.0;
// spherical fold
if (fractal->transformCommon.functionEnabledSFalse
&& aux.i >= fractal->transformCommon.startIterationsS
&& aux.i < fractal->transformCommon.stopIterationsS)
{
double para = 0.0;
double paraAddP0 = 0.0;
if (fractal->transformCommon.functionEnabledyFalse)
{
if (fractal->Cpara.enabledLinear)
{
para = fractal->Cpara.para00; // parameter value at iter 0
double temp0 = para;
double tempA = fractal->Cpara.paraA;
double tempB = fractal->Cpara.paraB;
double tempC = fractal->Cpara.paraC;
double lengthAB = fractal->Cpara.iterB - fractal->Cpara.iterA;
double lengthBC = fractal->Cpara.iterC - fractal->Cpara.iterB;
double grade1 = (tempA - temp0) / fractal->Cpara.iterA;
double grade2 = (tempB - tempA) / lengthAB;
double grade3 = (tempC - tempB) / lengthBC;
// slopes
if (aux.i < fractal->Cpara.iterA)
{
para = temp0 + (aux.i * grade1);
}
if (aux.i < fractal->Cpara.iterB && aux.i >= fractal->Cpara.iterA)
{
para = tempA + (aux.i - fractal->Cpara.iterA) * grade2;
}
if (aux.i >= fractal->Cpara.iterB)
{
para = tempB + (aux.i - fractal->Cpara.iterB) * grade3;
}
// Curvi part on "true"
if (fractal->Cpara.enabledCurves)
{
double paraAdd = 0.0;
double paraIt;
if (lengthAB > 2.0 * fractal->Cpara.iterA) // stop error, todo fix.
{
double curve1 = (grade2 - grade1) / (4.0 * fractal->Cpara.iterA);
double tempL = lengthAB - fractal->Cpara.iterA;
double curve2 = (grade3 - grade2) / (4.0 * tempL);
if (aux.i < 2 * fractal->Cpara.iterA)
{
paraIt = tempA - fabs(tempA - aux.i);
paraAdd = paraIt * paraIt * curve1;
}
if (aux.i >= 2 * fractal->Cpara.iterA && aux.i < fractal->Cpara.iterB + tempL)
{
paraIt = tempB - fabs(tempB * aux.i);
paraAdd = paraIt * paraIt * curve2;
}
para += paraAdd;
}
}
}
paraAddP0 = 0.0;
if (fractal->Cpara.enabledParabFalse)
{ // parabolic = paraOffset + iter *slope + (iter *iter *scale)
paraAddP0 = fractal->Cpara.parabOffset0 + (aux.i * fractal->Cpara.parabSlope)
+ (aux.i * aux.i * 0.001 * fractal->Cpara.parabScale);
}
}
para += paraAddP0 + fractal->transformCommon.minR2p25;
// spherical fold
double rr = z.Dot(z);
rrCol = rr;
z += fractal->mandelbox.offset;
// if (rr < 1e-21) rr = 1e-21;
if (rr < para)
{
double tglad_factor1 = fractal->transformCommon.maxR2d1 / para;
z *= tglad_factor1;
aux.DE *= tglad_factor1;
}
else if (rr < fractal->transformCommon.maxR2d1) // fractal->mandelbox.fR2
{
double tglad_factor2 = fractal->transformCommon.maxR2d1 / rr;
z *= tglad_factor2;
aux.DE *= tglad_factor2;
}
z -= fractal->mandelbox.offset;
z *= fractal->transformCommon.scale1;
aux.DE = aux.DE * fabs(fractal->transformCommon.scale1) + fractal->analyticDE.offset0;
}
if (fractal->transformCommon.functionEnabledPFalse
&& aux.i >= fractal->transformCommon.startIterationsP
&& aux.i < fractal->transformCommon.stopIterationsP1)
{
CVector4 gap = fractal->transformCommon.constantMultiplier000;
z.y = fabs(z.y);
z.z = fabs(z.z);
double dot1 = (z.x * -SQRT_3_4 + z.y * 0.5) * fractal->transformCommon.scale;
double t = max(0.0, dot1);
z.x -= t * -SQRT_3;
z.y = fabs(z.y - t);
if (z.y > z.z) swap(z.y, z.z);
z -= gap * CVector4(SQRT_3_4, 1.5, 1.5, 0.0);
// z was pos, now some points neg (ie neg shift)
if (z.z > z.x) swap(z.z, z.x);
if (z.x > 0.0)
{
z.y = max(0.0, z.y);
z.z = max(0.0, z.z);
}
}
if (fractal->transformCommon.functionEnabledRFalse
&& aux.i >= fractal->transformCommon.startIterationsR
&& aux.i < fractal->transformCommon.stopIterationsR)
z = fractal->transformCommon.rotationMatrix.RotateVector(z);
if (fractal->transformCommon.benesiT1EnabledFalse
&& aux.i >= fractal->transformCommon.startIterationsT
&& aux.i < fractal->transformCommon.stopIterationsT1)
{
double tempXZ = z.x * SQRT_2_3 - z.z * SQRT_1_3;
z = CVector4(
(tempXZ - z.y) * SQRT_1_2, (tempXZ + z.y) * SQRT_1_2, z.x * SQRT_1_3 + z.z * SQRT_2_3, 0.0);
CVector4 tempZ = z;
double tempL = tempZ.Length();
z = fabs(z) * fractal->transformCommon.scale3D222;
// if (tempL < 1e-21) tempL = 1e-21;
double avgScale = z.Length() / tempL;
aux.DE = aux.DE * avgScale + 1.0;
tempXZ = (z.y + z.x) * SQRT_1_2;
z = CVector4(z.z * SQRT_1_3 + tempXZ * SQRT_2_3, (z.y - z.x) * SQRT_1_2,
z.z * SQRT_2_3 - tempXZ * SQRT_1_3, 0.0);
z = z - fractal->transformCommon.offset200;
}
if (fractal->transformCommon.functionEnabledxFalse
&& aux.i >= fractal->transformCommon.startIterationsD
&& aux.i < fractal->transformCommon.stopIterationsTM1)
{
double tempXZ = z.x * SQRT_2_3 - z.z * SQRT_1_3;
z = CVector4(
(tempXZ - z.y) * SQRT_1_2, (tempXZ + z.y) * SQRT_1_2, z.x * SQRT_1_3 + z.z * SQRT_2_3, 0.0);
CVector4 temp = z;
double tempL = temp.Length();
z = fabs(z) * fractal->transformCommon.scale3D333;
// if (tempL < 1e-21) tempL = 1e-21;
double avgScale = z.Length() / tempL;
aux.DE = aux.DE * avgScale + 1.0;
oldZ = z;
z = (fabs(z + fractal->transformCommon.additionConstant111)
- fabs(z - fractal->transformCommon.additionConstant111) - z);
zCol = z;
/*if (fractal->foldColor.auxColorEnabledFalse)
{
if (z.x != oldZ.x) colorAdd += fractal->mandelbox.color.factor.x;
if (z.y != oldZ.y) colorAdd += fractal->mandelbox.color.factor.y;
if (z.z != oldZ.z) colorAdd += fractal->mandelbox.color.factor.z;
}*/
tempXZ = (z.y + z.x) * SQRT_1_2;
z = CVector4(z.z * SQRT_1_3 + tempXZ * SQRT_2_3, (z.y - z.x) * SQRT_1_2,
z.z * SQRT_2_3 - tempXZ * SQRT_1_3, 0.0);
}
double k;
// Pseudo kleinian
CVector4 cSize = fractal->transformCommon.additionConstant0777;
if (fractal->transformCommon.functionEnabledAy
&& aux.i >= fractal->transformCommon.startIterationsC
&& aux.i < fractal->transformCommon.stopIterationsC)
{
CVector4 tempZ = z; // correct c++ version. non conditional mult 2.0
if (z.x > cSize.x) tempZ.x = cSize.x;
if (z.x < -cSize.x) tempZ.x = -cSize.x;
if (z.y > cSize.y) tempZ.y = cSize.y;
if (z.y < -cSize.y) tempZ.y = -cSize.y;
if (z.z > cSize.z) tempZ.z = cSize.z;
if (z.z < -cSize.z) tempZ.z = -cSize.z;
z = tempZ * 2.0 - z;
k = max(fractal->transformCommon.minR05 / z.Dot(z), 1.0);
z *= k;
aux.DE *= k + fractal->analyticDE.tweak005;
}
if (fractal->transformCommon.functionEnabledAyFalse
&& aux.i >= fractal->transformCommon.startIterationsB
&& aux.i < fractal->transformCommon.stopIterationsB)
{
// variation from openCL conditional mult 2.0
if (z.x > cSize.x) z.x = cSize.x * 2.0 - z.x;
if (z.x < -cSize.x) z.x = -cSize.x * 2.0 - z.x;
if (z.y > cSize.y) z.y = cSize.y * 2.0 - z.y;
if (z.y < -cSize.y) z.y = -cSize.y * 2.0 - z.y;
if (z.z > cSize.z) z.z = cSize.z * 2.0 - z.z;
if (z.z < -cSize.z) z.z = -cSize.z * 2.0 - z.z;
k = max(fractal->transformCommon.minR05 / z.Dot(z), 1.0);
z *= k;
aux.DE *= k + fractal->analyticDE.tweak005;
}
z += fractal->transformCommon.additionConstant000;
if (fractal->transformCommon.functionEnabledFFalse
&& aux.i >= fractal->transformCommon.startIterationsF
&& aux.i < fractal->transformCommon.stopIterationsF)
{
oldZ = z;
z = fabs(z + fractal->transformCommon.offsetA000)
- fabs(z - fractal->transformCommon.offsetA000) - z;
zCol = z;
if (fractal->transformCommon.functionEnabledFalse
&& aux.i >= fractal->transformCommon.startIterationsA
&& aux.i < fractal->transformCommon.stopIterationsA)
{
CVector4 limit = fractal->transformCommon.offsetA000;
CVector4 length = 2.0 * limit;
CVector4 tgladS = 1.0 / length;
CVector4 Add;
Add.w = 0.0;
if (fabs(z.x) < limit.x) Add.x = z.x * z.x * tgladS.x;
if (fabs(z.y) < limit.y) Add.y = z.y * z.y * tgladS.y;
if (fabs(z.z) < limit.z) Add.z = z.z * z.z * tgladS.z;
if (fabs(z.x) > limit.x && fabs(z.x) < length.x)
Add.x = (length.x - fabs(z.x)) * (length.x - fabs(z.x)) * tgladS.x;
if (fabs(z.y) > limit.y && fabs(z.y) < length.y)
Add.y = (length.y - fabs(z.y)) * (length.y - fabs(z.y)) * tgladS.y;
if (fabs(z.z) > limit.z && fabs(z.z) < length.z)
Add.z = (length.z - fabs(z.z)) * (length.z - fabs(z.z)) * tgladS.z;
Add *= fractal->transformCommon.scale3D000;
z.x = (z.x - (sign(z.x) * (Add.x)));
z.y = (z.y - (sign(z.y) * (Add.y)));
z.z = (z.z - (sign(z.z) * (Add.z)));
}
}
if (fractal->transformCommon.addCpixelEnabledFalse) // symmetrical addCpixel
{
CVector4 tempFAB = c;
if (fractal->transformCommon.functionEnabledx) tempFAB.x = fabs(tempFAB.x);
if (fractal->transformCommon.functionEnabledy) tempFAB.y = fabs(tempFAB.y);
if (fractal->transformCommon.functionEnabledz) tempFAB.z = fabs(tempFAB.z);
tempFAB *= fractal->transformCommon.offsetF000;
z.x += sign(z.x) * tempFAB.x;
z.y += sign(z.y) * tempFAB.y;
z.z += sign(z.z) * tempFAB.z;
}
aux.pseudoKleinianDE = fractal->analyticDE.scale1; // pK DE
// aux.pseudoKleinianZZ = fractal->transformCommon.scale0; // pK z.z * z.z * scale0
// color updated v2.13 & mode2 v2.14
if (fractal->foldColor.auxColorEnabledFalse)
{
if (fractal->transformCommon.functionEnabledCxFalse)
{
if (zCol.x != oldZ.x)
colorAdd += fractal->mandelbox.color.factor.x
* (fabs(zCol.x) - fractal->transformCommon.additionConstant111.x);
if (zCol.y != oldZ.y)
colorAdd += fractal->mandelbox.color.factor.y
* (fabs(zCol.y) - fractal->transformCommon.additionConstant111.y);
if (zCol.z != oldZ.z)
colorAdd += fractal->mandelbox.color.factor.z
* (fabs(zCol.z) - fractal->transformCommon.additionConstant111.z);
if (rrCol < fractal->transformCommon.maxR2d1)
{
if (rrCol < fractal->transformCommon.minR2p25)
colorAdd +=
fractal->mandelbox.color.factorSp1 * (fractal->transformCommon.minR2p25 - rrCol)
+ fractal->mandelbox.color.factorSp2
* (fractal->transformCommon.maxR2d1 - fractal->transformCommon.minR2p25);
else
colorAdd +=
fractal->mandelbox.color.factorSp2 * (fractal->transformCommon.maxR2d1 - rrCol);
}
}
else
{
if (zCol.x != oldZ.x) colorAdd += fractal->mandelbox.color.factor.x;
if (zCol.y != oldZ.y) colorAdd += fractal->mandelbox.color.factor.y;
if (zCol.z != oldZ.z) colorAdd += fractal->mandelbox.color.factor.z;
if (rrCol < fractal->transformCommon.minR2p25)
colorAdd += fractal->mandelbox.color.factorSp1;
else if (rrCol < fractal->transformCommon.maxR2d1)
colorAdd += fractal->mandelbox.color.factorSp2;
}
aux.color += colorAdd;
}
}
/**
* Pseudo Kleinian std DE Knighty - Theli-at's Pseudo Kleinian (Scale 1 JuliaBox + Something
* @reference https://github.com/Syntopia/Fragmentarium/blob/master/
* Fragmentarium-Source/Examples/Knighty%20Collection/PseudoKleinian.frag
*/
void PseudoKleinianStdDEIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
CVector4 gap = fractal->transformCommon.constantMultiplier000;
double t;
double dot1;
if (fractal->transformCommon.functionEnabledPFalse
&& aux.i >= fractal->transformCommon.startIterationsP
&& aux.i < fractal->transformCommon.stopIterationsP1)
{
z.y = fabs(z.y);
z.z = fabs(z.z);
dot1 = (z.x * -SQRT_3_4 + z.y * 0.5) * fractal->transformCommon.scale;
t = max(0.0, dot1);
z.x -= t * -SQRT_3;
z.y = fabs(z.y - t);
if (z.y > z.z) swap(z.y, z.z);
z -= gap * CVector4(SQRT_3_4, 1.5, 1.5, 0.0);
// z was pos, now some points neg (ie neg shift)
if (z.z > z.x) swap(z.z, z.x);
if (z.x > 0.0)
{
z.y = max(0.0, z.y);
z.z = max(0.0, z.z);
}
}
if (fractal->transformCommon.functionEnabledRFalse
&& aux.i >= fractal->transformCommon.startIterationsR
&& aux.i < fractal->transformCommon.stopIterationsR)
z = fractal->transformCommon.rotationMatrix.RotateVector(z);
if (fractal->transformCommon.benesiT1EnabledFalse
&& aux.i >= fractal->transformCommon.startIterations
&& aux.i < fractal->transformCommon.stopIterationsT1)
{
double tempXZ = z.x * SQRT_2_3 - z.z * SQRT_1_3;
z = CVector4(
(tempXZ - z.y) * SQRT_1_2, (tempXZ + z.y) * SQRT_1_2, z.x * SQRT_1_3 + z.z * SQRT_2_3, z.w);
CVector4 tempZ = z;
double tempL = tempZ.Length();
z = fabs(z) * fractal->transformCommon.scale3D222;
// if (tempL < 1e-21) tempL = 1e-21;
double avgScale = z.Length() / tempL;
aux.DE = aux.DE * avgScale + 1.0;
tempXZ = (z.y + z.x) * SQRT_1_2;
z = CVector4(z.z * SQRT_1_3 + tempXZ * SQRT_2_3, (z.y - z.x) * SQRT_1_2,
z.z * SQRT_2_3 - tempXZ * SQRT_1_3, z.w);
z = z - fractal->transformCommon.offset200;
}
if (fractal->transformCommon.functionEnabledxFalse
&& aux.i >= fractal->transformCommon.startIterationsD
&& aux.i < fractal->transformCommon.stopIterationsTM1)
{
double tempXZ = z.x * SQRT_2_3 - z.z * SQRT_1_3;
z = CVector4(
(tempXZ - z.y) * SQRT_1_2, (tempXZ + z.y) * SQRT_1_2, z.x * SQRT_1_3 + z.z * SQRT_2_3, z.w);
CVector4 temp = z;
double tempL = temp.Length();
z = fabs(z) * fractal->transformCommon.scale3D333;
// if (tempL < 1e-21) tempL = 1e-21;
double avgScale = z.Length() / tempL;
aux.DE = aux.DE * avgScale + 1.0;
z = (fabs(z + fractal->transformCommon.additionConstant111)
- fabs(z - fractal->transformCommon.additionConstant111) - z);
tempXZ = (z.y + z.x) * SQRT_1_2;
z = CVector4(z.z * SQRT_1_3 + tempXZ * SQRT_2_3, (z.y - z.x) * SQRT_1_2,
z.z * SQRT_2_3 - tempXZ * SQRT_1_3, z.w);
}
if (fractal->transformCommon.functionEnabledFFalse
&& aux.i >= fractal->transformCommon.startIterationsF
&& aux.i < fractal->transformCommon.stopIterationsF)
{
CVector4 tempA, tempB;
if (fractal->transformCommon.functionEnabledAx)
tempA.x = fabs(z.x + fractal->transformCommon.offsetF000.x);
if (fractal->transformCommon.functionEnabledx)
tempB.x = fabs(z.x - fractal->transformCommon.offset000.x);
z.x = tempA.x - tempB.x - (z.x * fractal->transformCommon.scale3D111.x);
if (fractal->transformCommon.functionEnabledAy)
tempA.y = fabs(z.y + fractal->transformCommon.offsetF000.y);
if (fractal->transformCommon.functionEnabledy)
tempB.y = fabs(z.y - fractal->transformCommon.offset000.y);
z.y = tempA.y - tempB.y - (z.y * fractal->transformCommon.scale3D111.y);
if (fractal->transformCommon.functionEnabledAz)
tempA.z = fabs(z.z + fractal->transformCommon.offsetF000.z);
if (fractal->transformCommon.functionEnabledz)
tempB.z = fabs(z.z - fractal->transformCommon.offset000.z);
z.z = tempA.z - tempB.z - (z.z * fractal->transformCommon.scale3D111.z);
z += fractal->transformCommon.offsetA000;
}
if (fractal->transformCommon.functionEnabled && aux.i >= fractal->transformCommon.startIterationsM
&& aux.i < fractal->transformCommon.stopIterationsM)
{
z = fabs(z);
if (z.x - z.y < 0.0) swap(z.y, z.x);
if (z.x - z.z < 0.0) swap(z.z, z.x);
if (z.y - z.z < 0.0) swap(z.z, z.y);
z *= fractal->transformCommon.scale3;
z.x -= 2.0 * fractal->transformCommon.constantMultiplierA111.x;
z.y -= 2.0 * fractal->transformCommon.constantMultiplierA111.y;
if (z.z > 1.0) z.z -= 2.0 * fractal->transformCommon.constantMultiplierA111.z;
aux.DE *= fractal->transformCommon.scale3 * fractal->transformCommon.scaleA1;
z += fractal->transformCommon.additionConstantA000;
}
aux.DE *= fractal->transformCommon.scaleB1;
double k;
// Pseudo kleinian
CVector4 cSize = fractal->transformCommon.additionConstant0777;
if (fractal->transformCommon.functionEnabledAy
&& aux.i >= fractal->transformCommon.startIterationsC
&& aux.i < fractal->transformCommon.stopIterationsC)
{
CVector4 tempZ = z; // correct c++ version.
if (z.x > cSize.x) tempZ.x = cSize.x;
if (z.x < -cSize.x) tempZ.x = -cSize.x;
if (z.y > cSize.y) tempZ.y = cSize.y;
if (z.y < -cSize.y) tempZ.y = -cSize.y;
if (z.z > cSize.z) tempZ.z = cSize.z;
if (z.z < -cSize.z) tempZ.z = -cSize.z;
z *= fractal->transformCommon.scaleB1;
z = tempZ * 2.0 - z;
k = max(fractal->transformCommon.minR05 / z.Dot(z), 1.0);
z *= k;
aux.DE *= k + fractal->analyticDE.tweak005;
}
if (fractal->transformCommon.functionEnabledAyFalse
&& aux.i >= fractal->transformCommon.startIterationsB
&& aux.i < fractal->transformCommon.stopIterationsB)
{
// variation from openCL
if (z.x > cSize.x) z.x = cSize.x * 2.0 - z.x;
if (z.x < -cSize.x) z.x = -cSize.x * 2.0 - z.x;
if (z.y > cSize.y) z.y = cSize.y * 2.0 - z.y;
if (z.y < -cSize.y) z.y = -cSize.y * 2.0 - z.y;
if (z.z > cSize.z) z.z = cSize.z * 2.0 - z.z;
if (z.z < -cSize.z) z.z = -cSize.z * 2.0 - z.z;
k = max(fractal->transformCommon.minR05 / z.Dot(z), 1.0);
z *= k;
aux.DE *= k + fractal->analyticDE.tweak005;
}
z += fractal->transformCommon.additionConstant000;
// aux.pseudoKleinianZZ = fractal->transformCommon.scale0; // pK z.z * z.z * scale0
}
/**
* Quaternion3DE - Quaternion fractal with extended controls
* @reference http://www.fractalforums.com/3d-fractal-generation
* /true-3d-mandlebrot-type-fractal/
*/
void Quaternion3dIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
aux.DE = aux.DE * 2.0 * aux.r;
z = CVector4(z.x * z.x - z.y * z.y - z.z * z.z, z.x * z.y, z.x * z.z, z.w);
double tempL = z.Length();
z *= fractal->transformCommon.constantMultiplier122;
// if (tempL < 1e-21) tempL = 1e-21;
CVector4 tempAvgScale = CVector4(z.x, z.y / 2.0, z.z / 2.0, z.w);
double avgScale = tempAvgScale.Length() / tempL;
double tempAux = aux.DE * avgScale;
aux.DE = aux.DE + (tempAux - aux.DE) * fractal->transformCommon.scaleA1;
if (fractal->transformCommon.rotationEnabled)
z = fractal->transformCommon.rotationMatrix.RotateVector(z);
z += fractal->transformCommon.additionConstant000;
}
/**
* RiemannSphereMsltoe
* @reference http://www.fractalforums.com/the-3d-mandelbulb/
* riemann-fractals/msg33500/#msg33500
*/
void RiemannSphereMsltoeIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
Q_UNUSED(aux);
if (fractal->transformCommon.rotationEnabled)
z = fractal->transformCommon.rotationMatrix.RotateVector(z);
double r = aux.r; //z.Length();
// if (r < 1e-21) r = 1e-21;
z *= fractal->transformCommon.scale / r;
double q = 1.0 / (1.0 - z.z);
double s = z.x * q;
double t = z.y * q;
double p = 1.0 + s * s + t * t;
s = fabs(sin(M_PI * s));
t = fabs(sin(M_PI * t));
r *= r;
// if (r < 1e-21)
// r = 1e-21;
if (p > 36) p = 36; // problem with pow()
r = -0.25 + pow(r, p);
z.x = 2.0 * s;
z.y = 2.0 * t;
z.z = -1.0 + s * s + t * t;
z *= r / (1.0 + s * s + t * t);
z += fractal->transformCommon.additionConstant000;
}
/**
* RiemannSphereMsltoe Variation1
* @reference
* http://www.fractalforums.com/new-theories-and-research/
* revisiting-the-riemann-sphere-%28again%29/
*/
void RiemannSphereMsltoeV1Iteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
Q_UNUSED(aux);
double r = aux.r; // z.Length();
// if (r < 1e-21) r = 1e-21;
z *= fractal->transformCommon.scale / r;
double q = 1.0 / (1.0 - z.z);
CVector4 t3;
t3.x = z.x * q;
t3.y = z.y * q;
t3.z = (r - 1.5) * (1.0 + t3.x * t3.x + t3.y * t3.y);
if (fractal->transformCommon.rotationEnabled)
t3 = fractal->transformCommon.rotationMatrix.RotateVector(t3);
t3.x = t3.x - floor(t3.x + 0.5);
t3.y = t3.y - floor(t3.y + 0.5);
t3.w = z.w;
z = t3 * fractal->transformCommon.constantMultiplier441;
z += fractal->transformCommon.additionConstant000;
}
/**
* RiemannBulbMsltoe Mod2
* @reference
* http://www.fractalforums.com/new-theories-and-research/
* another-way-to-make-my-riemann-sphere-'bulb'-using-a-conformal-transformation/
*/
void RiemannBulbMsltoeMod2Iteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
Q_UNUSED(aux);
double radius2 = fractal->transformCommon.minR05;
double rr = z.x * z.x + z.y * z.y + z.z * z.z; // r2 or point radius squared
if (rr < radius2 * radius2)
{
if (fractal->transformCommon.functionEnabled)
// smooth inside
z *= radius2 * ((rr * 0.1) + 0.4) * 1.18 * fractal->transformCommon.scaleA1 / rr;
else
{
z *= fractal->transformCommon.constantMultiplier111;
}
} // if internal smooth function disabled, then z = z * scale, default vect3(1,1,1)
else
{
// 1st scale variable, default vect3 (1.7, 1.7, 1.7),
z *= fractal->transformCommon.constantMultiplier222;
double shift = fractal->transformCommon.offset1;
// r1 = length^2, // + 1e-061
double r1 = z.x * z.x + (z.y - shift) * (z.y - shift) + z.z * z.z;
// inversions by length^2
z.x = z.x / r1;
z.y = (z.y - shift) / r1;
z.z = z.z / r1;
// 2nd scale variable , default = double (3.0)
z *= fractal->transformCommon.scale3;
// y offset variable, default = double (1.9);
z.y = z.y + fractal->transformCommon.offset105;
if (fractal->transformCommon.functionEnabledx)
{
z.x = z.x - round(z.x); // periodic cubic tiling,
z.z = z.z - round(z.z);
}
if (fractal->transformCommon.functionEnabledxFalse)
{
z.x = fabs(sin(M_PI * z.x * fractal->transformCommon.scale1));
z.z = fabs(sin(M_PI * z.z * fractal->transformCommon.scale1));
}
}
}
/**
* quadratic iteration in imaginary scator algebra
* Use stop at maximum iteration (at maxiter)for the image to rendered correctly
* @reference
* http://www.fractalforums.com/new-theories-and-research/
* ix-possibly-the-holy-grail-fractal-%28in-fff-lore%29
* https://luz.izt.uam.mx/drupal/en/fractals/ix
* @author Manuel Fernandez-Guasti
*/
void ScatorPower2ImaginaryIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
Q_UNUSED(fractal);
Q_UNUSED(aux);
double x2 = z.x * z.x; // + 1e-061;
double y2 = z.y * z.y;
double z2 = z.z * z.z;
double newx = x2 - y2 - z2 + (y2 * z2) / x2;
double newy = 2.0 * z.x * z.y * (1.0 - z2 / x2);
double newz = 2.0 * z.x * z.z * (1.0 - y2 / x2);
z.x = newx;
z.y = newy;
z.z = newz;
}
/**
* quadratic iteration in real scator algebra
* Use stop at maximum iteration (at maxiter)for the image to rendered correctly
* @reference
* https://luz.izt.uam.mx/drupal/en/fractals/hun
* @author Manuel Fernandez-Guasti
*/
void ScatorPower2RealIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
Q_UNUSED(fractal);
Q_UNUSED(aux);
double x2 = z.x * z.x; //+ 1e-061
double y2 = z.y * z.y;
double z2 = z.z * z.z;
double newx = x2 + y2 + z2 + (y2 * z2) / x2;
double newy = 2.0 * z.x * z.y * (1.0 + z2 / x2);
double newz = 2.0 * z.x * z.z * (1.0 + y2 / x2);
z.x = newx;
z.y = newy;
z.z = newz;
}
/**
* quadratic iteration in real or imaginary scator algebra
* @reference
* http://www.fractalforums.com/new-theories-and-research/
* ix-possibly-the-holy-grail-fractal-%28in-fff-lore%29
* https://luz.izt.uam.mx/drupal/en/fractals/ix
* @author Manuel Fernandez-Guasti
* This formula contains aux.DE
*/
void ScatorPower2Iteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
CVector4 oldZ = z;
// Scator real enabled by default
CVector4 zz = z * z;
CVector4 newZ = z;
if (fractal->transformCommon.functionEnabledFalse)
{ // scator imaginary
newZ.x = zz.x - zz.y - zz.z;
newZ.y = z.x * z.y;
newZ.z = z.x * z.z;
newZ *= fractal->transformCommon.constantMultiplier122;
newZ.x += (zz.y * zz.z) / zz.x;
newZ.y *= (1.0 - zz.z / zz.x);
newZ.z *= (1.0 - zz.y / zz.x);
}
else
{ // scator real
newZ.x = zz.x + zz.y + zz.z;
newZ.y = z.x * z.y;
newZ.z = z.x * z.z;
newZ *= fractal->transformCommon.constantMultiplier122;
newZ.x += (zz.y * zz.z) / zz.x;
newZ.y *= (1.0 + zz.z / zz.x);
newZ.z *= (1.0 + zz.y / zz.x);
}
z = newZ;
// addCpixel
if (fractal->transformCommon.addCpixelEnabledFalse
&& aux.i >= fractal->transformCommon.startIterationsE
&& aux.i < fractal->transformCommon.stopIterationsE)
{
CVector4 c = aux.const_c;
CVector4 tempC = c;
if (fractal->transformCommon.alternateEnabledFalse) // alternate
{
tempC = aux.c;
switch (fractal->mandelbulbMulti.orderOfXYZ)
{
case multi_OrderOfXYZ_xyz:
default: tempC = CVector4(tempC.x, tempC.y, tempC.z, tempC.w); break;
case multi_OrderOfXYZ_xzy: tempC = CVector4(tempC.x, tempC.z, tempC.y, tempC.w); break;
case multi_OrderOfXYZ_yxz: tempC = CVector4(tempC.y, tempC.x, tempC.z, tempC.w); break;
case multi_OrderOfXYZ_yzx: tempC = CVector4(tempC.y, tempC.z, tempC.x, tempC.w); break;
case multi_OrderOfXYZ_zxy: tempC = CVector4(tempC.z, tempC.x, tempC.y, tempC.w); break;
case multi_OrderOfXYZ_zyx: tempC = CVector4(tempC.z, tempC.y, tempC.x, tempC.w); break;
}
aux.c = tempC;
}
else
{
switch (fractal->mandelbulbMulti.orderOfXYZ)
{
case multi_OrderOfXYZ_xyz:
default: tempC = CVector4(c.x, c.y, c.z, c.w); break;
case multi_OrderOfXYZ_xzy: tempC = CVector4(c.x, c.z, c.y, c.w); break;
case multi_OrderOfXYZ_yxz: tempC = CVector4(c.y, c.x, c.z, c.w); break;
case multi_OrderOfXYZ_yzx: tempC = CVector4(c.y, c.z, c.x, c.w); break;
case multi_OrderOfXYZ_zxy: tempC = CVector4(c.z, c.x, c.y, c.w); break;
case multi_OrderOfXYZ_zyx: tempC = CVector4(c.z, c.y, c.x, c.w); break;
}
}
z += tempC * fractal->transformCommon.constantMultiplier111;
}
if (fractal->analyticDE.enabled)
{
double r = aux.r; // r = sqrt(zz.x + zz.y + zz.z + (zz.y * zz.z) / zz.x);
double vecDE = 0.0;
if (!fractal->analyticDE.enabledFalse)
{
if (fractal->transformCommon.functionEnabledXFalse)
{
r = oldZ.Length();
}
aux.DE = r * aux.DE * 2.0 * fractal->analyticDE.scale1 + fractal->analyticDE.offset1;
}
else
{
vecDE = fractal->transformCommon.scaleA1 * z.Length() / oldZ.Length();
aux.DE = max(r, vecDE) * aux.DE * 2.0 * fractal->analyticDE.scale1 + fractal->analyticDE.offset1;
}
}
}
/**
* quadratic iteration in real or imaginary scator algebra
* using r = length
* @reference
* http://www.fractalforums.com/new-theories-and-research/
* ix-possibly-the-holy-grail-fractal-%28in-fff-lore%29
* https://luz.izt.uam.mx/drupal/en/fractals/ix
* @author Manuel Fernandez-Guasti
* This formula contains aux.DE
*/
void ScatorPower2StdRIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
CVector4 oldZ = z;
// Scator real enabled
CVector4 zz = z * z;
CVector4 newZ = z;
if (fractal->transformCommon.functionEnabledFalse)
{ // scator imaginary
newZ.x = zz.x - zz.y - zz.z;
newZ.y = z.x * z.y;
newZ.z = z.x * z.z;
newZ *= fractal->transformCommon.constantMultiplier122;
newZ.x += (zz.y * zz.z) / zz.x;
newZ.y *= (1.0 - zz.z / zz.x);
newZ.z *= (1.0 - zz.y / zz.x);
}
else
{ // scator real
newZ.x = zz.x + zz.y + zz.z;
newZ.y = z.x * z.y;
newZ.z = z.x * z.z;
newZ *= fractal->transformCommon.constantMultiplier122;
newZ.x += (zz.y * zz.z) / zz.x;
newZ.y *= (1.0 + zz.z / zz.x);
newZ.z *= (1.0 + zz.y / zz.x);
}
z = newZ;
if (fractal->analyticDE.enabled)
{
double r = aux.r; // r = length;
double vecDE = 0.0;
if (!fractal->analyticDE.enabledFalse)
{
if (fractal->transformCommon.functionEnabledXFalse)
{
r = sqrt(zz.x + zz.y + zz.z + (zz.y * zz.z) / zz.x);
}
aux.DE = r * aux.DE * 2.0 * fractal->analyticDE.scale1 + fractal->analyticDE.offset1;
}
else
{
vecDE = fractal->transformCommon.scaleA1 * z.Length() / oldZ.Length();
aux.DE = max(r, vecDE) * aux.DE * 2.0 * fractal->analyticDE.scale1 + fractal->analyticDE.offset1;
}
}
}
/**
* Sierpinski3D. made from DarkBeam's Sierpinski code from M3D
* @reference
* http://www.fractalforums.com/mandelbulb-3d/custom-formulas-and-transforms-release-t17106/
*/
void Sierpinski3dIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
CVector4 temp = z;
// Normal full tetra-fold;
if (fractal->transformCommon.functionEnabled)
{
if (z.x - z.y < 0.0) swap(z.x, z.y);
if (z.x - z.z < 0.0) swap(z.x, z.z);
if (z.y - z.z < 0.0) swap(z.y, z.z);
if (z.x + z.y < 0.0)
{
temp.x = -z.y;
z.y = -z.x;
z.x = temp.x;
}
if (z.x + z.z < 0.0)
{
temp.x = -z.z;
z.z = -z.x;
z.x = temp.x;
}
if (z.y + z.z < 0.0)
{
temp.y = -z.z;
z.z = -z.y;
z.y = temp.y;
}
}
// Reversed full tetra-fold;
if (fractal->transformCommon.functionEnabledFalse)
{
if (z.x + z.y < 0.0)
{
temp.x = -z.y;
z.y = -z.x;
z.x = temp.x;
}
if (z.x + z.z < 0.0)
{
temp.x = -z.z;
z.z = -z.x;
z.x = temp.x;
}
if (z.y + z.z < 0.0)
{
temp.y = -z.z;
z.z = -z.y;
z.y = temp.y;
}
if (z.x - z.y < 0.0) swap(z.y, z.x);
if (z.x - z.z < 0.0) swap(z.z, z.x);
if (z.y - z.z < 0.0) swap(z.z, z.y);
}
z *= fractal->transformCommon.scaleA2;
if (aux.i >= fractal->transformCommon.startIterationsC
&& aux.i < fractal->transformCommon.stopIterationsC)
{
z -= fractal->transformCommon.offset111; // neg offset
}
// rotation
if (fractal->transformCommon.functionEnabledRFalse
&& aux.i >= fractal->transformCommon.startIterationsR
&& aux.i < fractal->transformCommon.stopIterationsR)
{
z = fractal->transformCommon.rotationMatrix.RotateVector(z);
}
if (!fractal->analyticDE.enabledFalse)
aux.DE *= fabs(fractal->transformCommon.scale2);
else
aux.DE = aux.DE * fabs(fractal->transformCommon.scale2) * fractal->analyticDE.scale1
+ fractal->analyticDE.offset0;
}
/**
* GeneralizedFoldBoxIteration - Quaternion fractal with extended controls
* @reference http://www.fractalforums.com/new-theories-and-research/generalized-box-fold/
* This formula contains aux.color
*/
void GeneralizedFoldBoxIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
CVector3 zXYZ = z.GetXYZ();
int i;
const CVector3 *Nv;
int sides;
switch (fractal->genFoldBox.type)
{
default:
case generalizedFoldBoxType_foldTet:
Nv = fractal->genFoldBox.Nv_tet;
sides = fractal->genFoldBox.sides_tet;
break;
case generalizedFoldBoxType_foldCube:
Nv = fractal->genFoldBox.Nv_cube;
sides = fractal->genFoldBox.sides_cube;
break;
case generalizedFoldBoxType_foldOct:
Nv = fractal->genFoldBox.Nv_oct;
sides = fractal->genFoldBox.sides_oct;
break;
case generalizedFoldBoxType_foldDodeca:
Nv = fractal->genFoldBox.Nv_dodeca;
sides = fractal->genFoldBox.sides_dodeca;
break;
case generalizedFoldBoxType_foldOctCube:
Nv = fractal->genFoldBox.Nv_oct_cube;
sides = fractal->genFoldBox.sides_oct_cube;
break;
case generalizedFoldBoxType_foldIcosa:
Nv = fractal->genFoldBox.Nv_icosa;
sides = fractal->genFoldBox.sides_icosa;
break;
case generalizedFoldBoxType_foldBox6:
Nv = fractal->genFoldBox.Nv_box6;
sides = fractal->genFoldBox.sides_box6;
break;
case generalizedFoldBoxType_foldBox5:
Nv = fractal->genFoldBox.Nv_box5;
sides = fractal->genFoldBox.sides_box5;
break;
}
double melt = fractal->mandelbox.melt;
double solid = fractal->mandelbox.solid;
// Find the closest cutting plane if any that cuts the line between the origin and z.
// Line is parameterized as X = Y + L*a;
// Cutting plane is X.Dot(Nv) = Solid.
// (Y + L*a).Dot(Nv) = solid.
// a = (solid - Y.Dot(Nv))/L.Dot(Nv) = b/c
CVector3 L = zXYZ;
double a = 1.0;
CVector3 Y; // Y is the origin in this case.
int side = -1;
double b, c;
for (i = 0; i < sides; i++)
{
b = solid;
c = L.Dot(Nv[i]);
// A bit subtle here. a_r must be positive and I want to avoid divide by zero.
if ((c > 0.0) && ((a * c) > b))
{
side = i;
a = b / c;
}
}
// If z is above the foldingValue we may have to fold. Else early out.
if (side != -1)
{ // mirror check
int side_m = side;
CVector3 Nv_m = Nv[side_m];
CVector3 X_m = zXYZ - Nv_m * (zXYZ.Dot(Nv_m) - solid);
// Find any plane (Nv_r) closest to X_m that cuts the line between Nv_m and X_m.
// Nv_m cross Nv_r will define a possible rotation axis.
// a = (solid - Y.Dot(Nv)/L.Dot(Nv) = b/c.
L = X_m - Nv_m;
Y = Nv_m;
a = 1.0;
side = -1;
for (i = 0; i < sides; i++)
{
if (i != side_m)
{
b = solid - Y.Dot(Nv[i]);
c = L.Dot(Nv[i]);
// A bit subtle here. a_r must be positive and I want to avoid divide by zero.
if ((c > 0.0) && ((a * c) > b))
{
side = i;
a = b / c;
}
}
}
// Was a cutting plane found?
if (side != -1)
{ // rotation check
CVector3 Xmr_intersect = Y + L * a;
int side_r = side;
CVector3 Nv_r = Nv[side_r];
// The axis of rotation is define by the cross product of Nv_m and Nv_r and
// the intersection of the line between Nv_m and Nv_r and Xmr_intersect.
CVector3 L_r = Nv_m.Cross(Nv_r);
// The closest point between z and the line of rotation can be found by minimizing
// the square of the distance (D) between z and the line
// X = Xmr_intersect + L_r * a_rmin.
// Setting dD/da_rmin equal to zero and solving for a_rmin.
double a_rmin = (zXYZ.Dot(L_r) - Xmr_intersect.Dot(L_r)) / (L_r.Dot(L_r));
// force a_rmin to be positive. I think I made an even number of sign errors here.
if (a_rmin < 0.0)
{
a_rmin = -a_rmin;
L_r = L_r * (-1.0);
}
CVector3 X_r = Xmr_intersect + L_r * a_rmin;
// Find any plane (Nv_i) closest to Xmr_intersect that cuts the line between
// Xmr_intersect and X_r. This will define a possible inversion point.
// a = (solid - Y.Dot(Nv)/L.Dot(Nv) = b/c.
L = X_r - Xmr_intersect;
Y = Xmr_intersect;
a = 1.0;
side = -1;
for (i = 0; i < sides; i++)
{
if ((i != side_m) && (i != side_r))
{
b = solid - Y.Dot(Nv[i]);
c = L.Dot(Nv[i]);
// A bit subtle here. a must be positive and I want to avoid divide by zero.
if ((c > 0.0) && ((a * c) > b))
{
side = i;
a = b / c;
}
}
}
if (side != -1)
{ // inversion check
// Only inversion point possible but still need to check for melt.
CVector3 X_i = Y + L * a;
CVector3 z2X = X_i - zXYZ;
// Is z above the melt layer.
if (z2X.Dot(z2X) > (melt * melt))
{
double z2X_mag = z2X.Length();
zXYZ += z2X * (2.0 * (z2X_mag - melt) / (z2X_mag + .00000001));
aux.color += fractal->mandelbox.color.factor.z;
}
}
else
{
// Only rotation line possible but still need to check for melt.
// Is z above the melt layer.
CVector3 z2X = X_r - zXYZ;
if (z2X.Dot(z2X) > (melt * melt))
{
double z2X_mag = z2X.Length();
zXYZ += z2X * (2.0 * (z2X_mag - melt) / (z2X_mag + .00000001));
aux.color += fractal->mandelbox.color.factor.y;
}
}
}
else
{
// Only mirror plane possible but still need to check for melt.
CVector3 z2X = X_m - zXYZ;
if (z2X.Dot(z2X) > (melt * melt))
{
double z2X_mag = z2X.Length();
zXYZ += z2X * (2.0 * (z2X_mag - melt) / (z2X_mag + .00000001));
aux.color += fractal->mandelbox.color.factor.x;
}
}
} // outside solid
double r2 = zXYZ.Dot(zXYZ);
z = CVector4(zXYZ, z.w);
z += fractal->mandelbox.offset;
if (r2 < fractal->mandelbox.mR2)
{
z *= fractal->mandelbox.mboxFactor1;
aux.DE *= fractal->mandelbox.mboxFactor1;
aux.color += fractal->mandelbox.color.factorSp1;
}
else if (r2 < fractal->mandelbox.fR2)
{
double tglad_factor2 = fractal->mandelbox.fR2 / r2;
z *= tglad_factor2;
aux.DE *= tglad_factor2;
aux.color += fractal->mandelbox.color.factorSp2;
}
z -= fractal->mandelbox.offset;
if (fractal->mandelbox.mainRotationEnabled)
{
z = fractal->mandelbox.mainRot.RotateVector(z);
}
z *= fractal->mandelbox.scale;
aux.DE = aux.DE * fabs(fractal->mandelbox.scale) + 1.0;
}
void BoxFolding(CVector4 &z, const sFractalFoldings *foldings, sExtendedAux &aux)
{
if (z.x > foldings->boxLimit)
{
z.x = foldings->boxValue - z.x;
aux.color *= 0.9;
}
else if (z.x < -foldings->boxLimit)
{
z.x = -foldings->boxValue - z.x;
aux.color *= 0.9;
}
if (z.y > foldings->boxLimit)
{
z.y = foldings->boxValue - z.y;
aux.color *= 0.9;
}
else if (z.y < -foldings->boxLimit)
{
z.y = -foldings->boxValue - z.y;
aux.color *= 0.9;
}
if (z.z > foldings->boxLimit)
{
z.z = foldings->boxValue - z.z;
aux.color *= 0.9;
}
else if (z.z < -foldings->boxLimit)
{
z.z = -foldings->boxValue - z.z;
aux.color *= 0.9;
}
}
void SphericalFolding(CVector4 &z, const sFractalFoldings *foldings, sExtendedAux &aux)
{
double fR2_2 = foldings->sphericalOuter * foldings->sphericalOuter;
double mR2_2 = foldings->sphericalInner * foldings->sphericalInner;
double r2_2 = aux.r * aux.r;
double fold_factor1_2 = fR2_2 / mR2_2;
if (r2_2 < mR2_2)
{
z = z * fold_factor1_2;
aux.DE *= fold_factor1_2;
aux.color *= 0.9;
}
else if (r2_2 < fR2_2)
{
double fold_factor2_2 = fR2_2 / r2_2;
z = z * fold_factor2_2;
aux.DE *= fold_factor2_2;
aux.color *= 0.9;
}
}
// NEW TRANSFORM FORMULAS-----------------------------------------------------------------
/**
* abs add constant, z = abs( z + pre-offset) + Offset
*/
void TransfAbsAddConstantIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
Q_UNUSED(aux);
z += fractal->transformCommon.additionConstant000;
if (fractal->transformCommon.functionEnabledx) z.x = fabs(z.x);
if (fractal->transformCommon.functionEnabledy) z.y = fabs(z.y);
if (fractal->transformCommon.functionEnabledz) z.z = fabs(z.z);
z += fractal->transformCommon.offsetA000;
}
/**
* abs add tglad fold, z = abs( z + constant) - abs( z - constant) - z:
* with a fold tweak option
* This formula contains aux.color
*/
void TransfAbsAddTgladFoldIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
CVector4 limit = fractal->transformCommon.additionConstant000;
double colorAdd = 0.0;
CVector4 oldZ = z;
z = fabs(z + limit) - fabs(z - limit) - z;
if (fractal->transformCommon.functionEnabledFalse
&& aux.i >= fractal->transformCommon.startIterationsA
&& aux.i < fractal->transformCommon.stopIterationsA)
{
// CVector4 limit = fractal->transformCommon.additionConstant000;
CVector4 length = 2.0 * limit;
CVector4 tgladS = 1.0 / length;
CVector4 Add;
Add.w = 0.0;
if (fabs(z.x) < limit.x) Add.x = z.x * z.x * tgladS.x;
if (fabs(z.y) < limit.y) Add.y = z.y * z.y * tgladS.y;
if (fabs(z.z) < limit.z) Add.z = z.z * z.z * tgladS.z;
if (fabs(z.x) > limit.x && fabs(z.x) < length.x)
Add.x = (length.x - fabs(z.x)) * (length.x - fabs(z.x)) * tgladS.x;
if (fabs(z.y) > limit.y && fabs(z.y) < length.y)
Add.y = (length.y - fabs(z.y)) * (length.y - fabs(z.y)) * tgladS.y;
if (fabs(z.z) > limit.z && fabs(z.z) < length.z)
Add.z = (length.z - fabs(z.z)) * (length.z - fabs(z.z)) * tgladS.z;
Add *= fractal->transformCommon.offset000;
z.x = (z.x - (sign(z.x) * (Add.x)));
z.y = (z.y - (sign(z.y) * (Add.y)));
z.z = (z.z - (sign(z.z) * (Add.z)));
}
// aux.color
if (fractal->foldColor.auxColorEnabledFalse)
{
if (z.x != oldZ.x) colorAdd += fractal->mandelbox.color.factor.x;
if (z.y != oldZ.y) colorAdd += fractal->mandelbox.color.factor.y;
if (z.z != oldZ.z) colorAdd += fractal->mandelbox.color.factor.z;
}
// mode 2
if (fractal->transformCommon.functionEnabledCxFalse)
{
if (fabs(z.x) > limit.x)
{
colorAdd += fractal->mandelbox.color.factor.x;
}
else
{
colorAdd += fractal->mandelbox.color.factor.x * (1.0 - (limit.x - fabs(z.x)) / limit.x);
}
if (fabs(z.y) > limit.y)
{
colorAdd += fractal->mandelbox.color.factor.y;
}
else
{
colorAdd += fractal->mandelbox.color.factor.y * (1.0 - (limit.y - fabs(z.y)) / limit.y);
}
if (fabs(z.z) > limit.z)
{
colorAdd += fractal->mandelbox.color.factor.z;
}
else
{
colorAdd += fractal->mandelbox.color.factor.z * (1.0 - (limit.z - fabs(z.z)) / limit.z);
}
aux.color += colorAdd;
}
// mode 3
if (fractal->transformCommon.functionEnabledCyFalse)
{
// double valMinusLim = limit;
if (z.x != oldZ.x)
{
colorAdd += fractal->mandelbox.color.factor.x * (fabs(z.x) - limit.x) / limit.x;
}
if (z.y != oldZ.y)
{
colorAdd += fractal->mandelbox.color.factor.y * (fabs(z.y) - limit.y) / limit.y;
}
if (z.z != oldZ.z)
{
colorAdd += fractal->mandelbox.color.factor.z * (fabs(z.z) - limit.z) / limit.z;
}
aux.color += colorAdd;
}
}
/**
* abs add conditional.
*/
void TransfAbsAddConditionalIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
if (fractal->transformCommon.functionEnabledx)
{
z.x = sign(z.x) * (fractal->transformCommon.offset111.x - fabs(z.x)
+ fabs(z.x) * fractal->transformCommon.offset000.x);
}
/*{
double signZx = sign(z.x);
z.x = (signZx * fractal->transformCommon.offset111.x)
- fabs(z.x) * (signZx - fractal->transformCommon.offset000.x);
}*/
/*{
double Absx = fabs(z.x);
z.x = sign(z.x) * (fractal->transformCommon.offset111.x - Absx
+ Absx * fractal->transformCommon.offset000.x);
}*/
if (fractal->transformCommon.functionEnabledy)
{
z.y = sign(z.y) * (fractal->transformCommon.offset111.y - fabs(z.y)
+ fabs(z.y) * fractal->transformCommon.offset000.y);
}
if (fractal->transformCommon.functionEnabledz)
{
z.z = sign(z.z) * (fractal->transformCommon.offset111.z - fabs(z.z)
+ fabs(z.z) * fractal->transformCommon.offset000.z);
}
// aux.DE = aux.DE * l/L;
aux.DE *= fractal->analyticDE.scale1; // DE tweak
}
/**
* abs Negative abs constant, z = - abs( z + constant)
*/
void TransfNegAbsAddConstantIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
Q_UNUSED(aux);
z += fractal->transformCommon.additionConstant000;
if (fractal->transformCommon.functionEnabledx) z.x = -fabs(z.x);
if (fractal->transformCommon.functionEnabledy) z.y = -fabs(z.y);
if (fractal->transformCommon.functionEnabledz) z.z = -fabs(z.z);
}
/**
* abs Multi - Multiple parameters for abs functions
*/
void TransfAbsAddMultiIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
Q_UNUSED(aux);
CVector4 tempA, tempB;
if (fractal->transformCommon.functionEnabledAx)
tempA.x = fabs(z.x + fractal->transformCommon.additionConstant000.x);
if (fractal->transformCommon.functionEnabledx)
tempB.x = fabs(z.x - fractal->transformCommon.offset000.x);
z.x = tempA.x - tempB.x - (z.x * fractal->transformCommon.scale3D111.x);
if (fractal->transformCommon.functionEnabledAy)
tempA.y = fabs(z.y + fractal->transformCommon.additionConstant000.y);
if (fractal->transformCommon.functionEnabledy)
tempB.y = fabs(z.y - fractal->transformCommon.offset000.y);
z.y = tempA.y - tempB.y - (z.y * fractal->transformCommon.scale3D111.y);
if (fractal->transformCommon.functionEnabledAz)
tempA.z = fabs(z.z + fractal->transformCommon.additionConstant000.z);
if (fractal->transformCommon.functionEnabledz)
tempB.z = fabs(z.z - fractal->transformCommon.offset000.z);
z.z = tempA.z - tempB.z - (z.z * fractal->transformCommon.scale3D111.z);
z += fractal->transformCommon.offsetA000;
}
/**
* Adds c constant to z vector
*/
void TransfAddConstantIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
Q_UNUSED(aux);
z += fractal->transformCommon.additionConstant000;
z += fractal->transformCommon.additionConstantA000;
}
/**
* Adds c constant to z vector
*/
void TransfAddConstantMod1Iteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
Q_UNUSED(aux);
// std offset
z += fractal->transformCommon.additionConstantA000;
// polynomial
if (fractal->transformCommon.functionEnabledBx
&& aux.i >= fractal->transformCommon.startIterationsX
&& aux.i < fractal->transformCommon.stopIterationsX)
{
CVector4 temp = fractal->transformCommon.additionConstant000;
CVector4 temp2 = temp * temp;
CVector4 temp3 = z * z * fractal->transformCommon.scaleA1;
z.x -=
((temp.x * temp2.x) / (temp3.x + temp2.x) - 2.0 * temp.x) * fractal->transformCommon.scale1;
z.y -=
((temp.y * temp2.y) / (temp3.y + temp2.y) - 2.0 * temp.y) * fractal->transformCommon.scale1;
z.z -=
((temp.z * temp2.z) / (temp3.z + temp2.z) - 2.0 * temp.z) * fractal->transformCommon.scale1;
}
else if (fractal->transformCommon.functionEnabledByFalse
&& aux.i >= fractal->transformCommon.startIterationsX
&& aux.i < fractal->transformCommon.stopIterationsX)
{
CVector4 temp = fractal->transformCommon.additionConstant000;
CVector4 temp2 = temp * temp;
CVector4 temp3 = z * z * fractal->transformCommon.scaleA1;
z.x -= ((temp2.x) / (temp3.x + temp2.x) - 2.0 * temp.x)
* fractal->transformCommon.scale1; // * sign(z.x);
z.y -= ((temp2.y) / (temp3.y + temp2.y) - 2.0 * temp.y)
* fractal->transformCommon.scale1; // * sign(z.y);
z.z -= ((temp2.z) / (temp3.z + temp2.z) - 2.0 * temp.z)
* fractal->transformCommon.scale1; // * sign(z.z);
}
}
/**
* Adds c constant to z vector. C addition constant varies based on iteration parameters.
*/
void TransfAddConstantVaryV1Iteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
CVector4 tempVC = fractal->transformCommon.additionConstant000; // constant to be varied
if (aux.i < fractal->transformCommon.startIterations250)
{
;
}
if (aux.i >= fractal->transformCommon.startIterations250
&& aux.i < fractal->transformCommon.stopIterations
&& (fractal->transformCommon.stopIterations - fractal->transformCommon.startIterations250
!= 0))
{
int iterationRange =
fractal->transformCommon.stopIterations - fractal->transformCommon.startIterations250;
int currentIteration = (aux.i - fractal->transformCommon.startIterations250);
tempVC += fractal->transformCommon.offset000 * (1.0 * currentIteration) / iterationRange;
}
if (aux.i >= fractal->transformCommon.stopIterations)
{
tempVC = (tempVC + fractal->transformCommon.offset000);
}
z += tempVC;
}
/**
* Adds Cpixel constant to z vector
*/
void TransfAddCpixelIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
z += aux.const_c * fractal->transformCommon.constantMultiplier111;
}
/**
* Adds Cpixel constant to z vector, swapping the Cpixel vector x and y axes
* disable swap for normal mode
*/
void TransfAddCpixelCxCyAxisSwapIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
CVector4 c = aux.const_c;
CVector4 tempC = c;
if (fractal->transformCommon.functionEnabled)
{
if (fractal->transformCommon.alternateEnabledFalse) // alternate
{
tempC = aux.c;
tempC = CVector4(tempC.y, tempC.x, tempC.z, tempC.w);
aux.c = tempC;
}
else
{
tempC = CVector4(c.y, c.x, c.z, c.w);
}
}
z += tempC * fractal->transformCommon.constantMultiplier111;
}
/**
* Adds Cpixel constant to z vector. Possible to swap Cpixel vector axes.
*/
void TransfAddCpixelAxisSwapIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
CVector4 c = aux.const_c;
CVector4 tempC = c;
if (fractal->transformCommon.alternateEnabledFalse) // alternate
{
tempC = aux.c;
switch (fractal->mandelbulbMulti.orderOfXYZ)
{
case multi_OrderOfXYZ_xyz:
default: tempC = CVector4(tempC.x, tempC.y, tempC.z, tempC.w); break;
case multi_OrderOfXYZ_xzy: tempC = CVector4(tempC.x, tempC.z, tempC.y, tempC.w); break;
case multi_OrderOfXYZ_yxz: tempC = CVector4(tempC.y, tempC.x, tempC.z, tempC.w); break;
case multi_OrderOfXYZ_yzx: tempC = CVector4(tempC.y, tempC.z, tempC.x, tempC.w); break;
case multi_OrderOfXYZ_zxy: tempC = CVector4(tempC.z, tempC.x, tempC.y, tempC.w); break;
case multi_OrderOfXYZ_zyx: tempC = CVector4(tempC.z, tempC.y, tempC.x, tempC.w); break;
}
aux.c = tempC;
}
else
{
switch (fractal->mandelbulbMulti.orderOfXYZ)
{
case multi_OrderOfXYZ_xyz:
default: tempC = CVector4(c.x, c.y, c.z, c.w); break;
case multi_OrderOfXYZ_xzy: tempC = CVector4(c.x, c.z, c.y, c.w); break;
case multi_OrderOfXYZ_yxz: tempC = CVector4(c.y, c.x, c.z, c.w); break;
case multi_OrderOfXYZ_yzx: tempC = CVector4(c.y, c.z, c.x, c.w); break;
case multi_OrderOfXYZ_zxy: tempC = CVector4(c.z, c.x, c.y, c.w); break;
case multi_OrderOfXYZ_zyx: tempC = CVector4(c.z, c.y, c.x, c.w); break;
}
}
z += tempC * fractal->transformCommon.constantMultiplier111;
}
/**
* Adds rotated Cpixel constant to z vector. Possible to swap Cpixel vector axes.
*/
void TransfAddCpixelRotatedIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
CVector4 c = aux.const_c;
CVector4 tempC = c;
if (fractal->transformCommon.alternateEnabledFalse) // alternate
{
tempC = aux.c;
switch (fractal->mandelbulbMulti.orderOfXYZ)
{
case multi_OrderOfXYZ_xyz:
default: tempC = CVector4(tempC.x, tempC.y, tempC.z, tempC.w); break;
case multi_OrderOfXYZ_xzy: tempC = CVector4(tempC.x, tempC.z, tempC.y, tempC.w); break;
case multi_OrderOfXYZ_yxz: tempC = CVector4(tempC.y, tempC.x, tempC.z, tempC.w); break;
case multi_OrderOfXYZ_yzx: tempC = CVector4(tempC.y, tempC.z, tempC.x, tempC.w); break;
case multi_OrderOfXYZ_zxy: tempC = CVector4(tempC.z, tempC.x, tempC.y, tempC.w); break;
case multi_OrderOfXYZ_zyx: tempC = CVector4(tempC.z, tempC.y, tempC.x, tempC.w); break;
}
aux.c = tempC;
}
else
{
switch (fractal->mandelbulbMulti.orderOfXYZ)
{
case multi_OrderOfXYZ_xyz:
default: tempC = CVector4(c.x, c.y, c.z, c.w); break;
case multi_OrderOfXYZ_xzy: tempC = CVector4(c.x, c.z, c.y, c.w); break;
case multi_OrderOfXYZ_yxz: tempC = CVector4(c.y, c.x, c.z, c.w); break;
case multi_OrderOfXYZ_yzx: tempC = CVector4(c.y, c.z, c.x, c.w); break;
case multi_OrderOfXYZ_zxy: tempC = CVector4(c.z, c.x, c.y, c.w); break;
case multi_OrderOfXYZ_zyx: tempC = CVector4(c.z, c.y, c.x, c.w); break;
}
}
if (aux.i >= fractal->transformCommon.startIterationsG
&& aux.i < fractal->transformCommon.stopIterationsG)
{
tempC = fractal->transformCommon.rotationMatrix.RotateVector(tempC);
}
z += tempC * fractal->transformCommon.constantMultiplier111;
}
/**
* Adds Cpixel constant to z vector, scator algebra
* based on Manuel's math
* @reference
* https://luz.izt.uam.mx/drupal/en/fractals/hun
* @author Manuel Fernandez-Guasti
*/
void TransfAddCpixelScatorIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
CVector4 oldZ = z;
CVector4 tempC = aux.const_c;
if (fractal->transformCommon.functionEnabledSwFalse)
swap(tempC.x, tempC.z);
CVector4 cc = tempC * tempC;
CVector4 newC = tempC;
double limitA = fractal->transformCommon.scale0;
if (fractal->transformCommon.functionEnabledRFalse)
{
cc = fabs(tempC);
}
// scator algebra
if ( cc.x < limitA)
{
double temp = 1.0 /cc.x - 1.0;
cc.x =temp;
}
if (!fractal->transformCommon.functionEnabledFalse)
{ // real
newC.x += (cc.y * cc.z) / cc.x; // all pos
newC.y *= (1.0 + cc.z / cc.x);
newC.z *= (1.0 + cc.y / cc.x);
newC *= fractal->transformCommon.constantMultiplier111;
if (fractal->transformCommon.functionEnabledSwFalse)
swap(newC.x, newC.z);
if (!fractal->transformCommon.functionEnabledSFalse)
{
z += newC;
}
else
{
z.x += sign(z.x) * newC.x;
z.y += sign(z.y) * newC.y;
z.z += sign(z.z) * newC.z;
}
}
else
{ // imaginary
newC.x += (cc.y * cc.z) / cc.x; // pos
newC.y *= (1.0 - cc.z / cc.x); //pos neg
newC.z *= (1.0 - cc.y / cc.x); //pos neg
newC *= fractal->transformCommon.constantMultiplier111;
if (fractal->transformCommon.functionEnabledy) newC.y = fabs(newC.y);
if (fractal->transformCommon.functionEnabledz) newC.z = fabs(newC.z);
if (fractal->transformCommon.functionEnabledSwFalse)
swap(newC.x, newC.z);
// add Cpixel
if (!fractal->transformCommon.functionEnabledSFalse)
{
z += newC;
}
else
{
z.x += sign(z.x) * newC.x;
z.y += sign(z.y) * newC.y;
z.z += sign(z.z) * newC.z;
}
}
// DE calculations
if (fractal->analyticDE.enabledFalse)
{
double vecDE = z.Length() / oldZ.Length();
aux.DE =
aux.DE * vecDE * fractal->analyticDE.scale1 + fractal->analyticDE.offset1;
}
}
/**
* Adds Cpixel constant sin or cos
*/
void TransfAddCpixelSinOrCosIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
CVector4 oldZ = z;
CVector4 trigC = aux.const_c * fractal->transformCommon.constantMultiplierC111; // freq
CVector4 trigC0 = trigC;
if (!fractal->transformCommon.functionEnabledBxFalse)
{
// apply simple trig
if (fractal->transformCommon.functionEnabledAx) trigC.x = sin(trigC0.x);
if (fractal->transformCommon.functionEnabledAxFalse) trigC.x = cos(trigC0.x);
if (fractal->transformCommon.functionEnabledAy) trigC.y = sin(trigC0.y);
if (fractal->transformCommon.functionEnabledAyFalse) trigC.y = cos(trigC0.y);
if (fractal->transformCommon.functionEnabledAz) trigC.z = sin(trigC0.z);
if (fractal->transformCommon.functionEnabledAzFalse) trigC.z = cos(trigC0.z);
}
else
{
// mode2
if (fractal->transformCommon.functionEnabledAx) trigC.x = (1.0 + sin(trigC0.x)) * sign(trigC.x) / 2.0;
if (fractal->transformCommon.functionEnabledAxFalse) trigC.x = (1.0 + cos(trigC0.x)) * sign(trigC.x) / 2.0;
if (fractal->transformCommon.functionEnabledAy) trigC.y = (1.0 + sin(trigC0.y)) * sign(trigC.y) / 2.0;
if (fractal->transformCommon.functionEnabledAyFalse) trigC.y = (1.0 + cos(trigC0.y)) * sign(trigC.y) / 2.0;
if (fractal->transformCommon.functionEnabledAz) trigC.z = (1.0 + sin(trigC0.z)) * sign(trigC.z) / 2.0;
if (fractal->transformCommon.functionEnabledAzFalse) trigC.z = (1.0 + cos(trigC0.z)) * sign(trigC.z) / 2.0;
// mode3
if (fractal->transformCommon.functionEnabledByFalse) trigC *= trigC0;
}
trigC *= fractal->transformCommon.constantMultiplier111; // ampl
// add cPixel
if (!fractal->transformCommon.functionEnabledFalse)
{
z += trigC;
}
else
{ // symmetical
trigC = fabs(trigC);
z.x += sign(z.x) * trigC.x;
z.y += sign(z.y) * trigC.y;
z.z += sign(z.z) * trigC.z;
}
// DE tweak (sometimes hepls)
if (fractal->analyticDE.enabledFalse)
{
double tweakDE = z.Length()/oldZ.Length();
aux.DE = aux.DE * tweakDE * fractal->analyticDE.scale1
+ fractal->analyticDE.offset0;
}
}
/**
* Adds Cpixel constant to z vector, with symmetry
*/
void TransfAddCpixelSymmetricalIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
CVector4 tempFAB = aux.const_c;
if (fractal->transformCommon.functionEnabledx) tempFAB.x = fabs(tempFAB.x);
if (fractal->transformCommon.functionEnabledy) tempFAB.y = fabs(tempFAB.y);
if (fractal->transformCommon.functionEnabledz) tempFAB.z = fabs(tempFAB.z);
tempFAB *= fractal->transformCommon.constantMultiplier111;
z.x += sign(z.x) * tempFAB.x;
z.y += sign(z.y) * tempFAB.y;
z.z += sign(z.z) * tempFAB.z;
}
/**
* Adds Cpixel constant to z, Cpixel scaled based on variable iteration parameters.
*/
void TransfAddCpixelVaryV1Iteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
CVector4 tempVC = fractal->transformCommon.constantMultiplier111; // constant to be varied
if (aux.i < fractal->transformCommon.startIterations250)
{
;
}
if (aux.i >= fractal->transformCommon.startIterations250
&& aux.i < fractal->transformCommon.stopIterations
&& (fractal->transformCommon.stopIterations - fractal->transformCommon.startIterations250
!= 0))
{
int iterationRange =
fractal->transformCommon.stopIterations - fractal->transformCommon.startIterations250;
int currentIteration = (aux.i - fractal->transformCommon.startIterations250);
tempVC += fractal->transformCommon.offset000 * (1.0 * currentIteration) / iterationRange;
}
if (aux.i >= fractal->transformCommon.stopIterations)
{
tempVC = (tempVC + fractal->transformCommon.offset000);
}
z += aux.const_c * tempVC;
}
/**
* Add exp2(z)
* z vector version and the xyz axis version can be used together
*/
void TransfAddExp2ZIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
CVector4 tempZ = z;
if (fractal->transformCommon.functionEnabledx)
{
if (fractal->transformCommon.functionEnabledAx)
{
tempZ.x = fabs(z.x);
tempZ.x = exp2(tempZ.x * -fractal->transformCommon.constantMultiplier000.x) - 1.0;
z.x += sign(z.x) * tempZ.x;
}
else if (fractal->transformCommon.functionEnabledAxFalse)
{
tempZ.x = fabs(z.x);
tempZ.x = exp2(tempZ.x * -fractal->transformCommon.constantMultiplier000.x) - 1.0;
z.x -= sign(z.x) * tempZ.x;
}
else // no fabs
z.x += exp2(tempZ.x * fractal->transformCommon.constantMultiplier000.x) - 1.0;
}
if (fractal->transformCommon.functionEnabledy)
{
if (fractal->transformCommon.functionEnabledAy)
{
tempZ.y = fabs(z.y);
tempZ.y = exp2(tempZ.y * -fractal->transformCommon.constantMultiplier000.y) - 1.0;
z.y += sign(z.y) * tempZ.y;
}
else if (fractal->transformCommon.functionEnabledAyFalse)
{
tempZ.y = fabs(z.y);
tempZ.y = exp2(tempZ.y * -fractal->transformCommon.constantMultiplier000.y) - 1.0;
z.y -= sign(z.y) * tempZ.y;
}
else
z.y += exp2(tempZ.y * fractal->transformCommon.constantMultiplier000.y) - 1.0;
}
if (fractal->transformCommon.functionEnabledz)
{
if (fractal->transformCommon.functionEnabledAz)
{
tempZ.z = fabs(z.z);
tempZ.z = exp2(tempZ.z * -fractal->transformCommon.constantMultiplier000.z) - 1.0;
z.z += sign(z.z) * tempZ.z;
}
else if (fractal->transformCommon.functionEnabledAzFalse)
{
tempZ.z = fabs(z.z);
tempZ.z = exp2(tempZ.z * -fractal->transformCommon.constantMultiplier000.z) - 1.0;
z.z -= sign(z.z) * tempZ.z;
}
else
z.z += exp2(tempZ.z * fractal->transformCommon.constantMultiplier000.z) - 1.0;
}
// vector z version
if (fractal->transformCommon.functionEnabledBzFalse)
{
CVector4 tempS;
if (fractal->transformCommon.functionEnabled)
{
tempS = fabs(z);
CVector4 tempT = tempS * -fractal->transformCommon.scale0;
tempS.x = exp2(tempT.x) - 1.0;
tempS.y = exp2(tempT.y) - 1.0;
tempS.z = exp2(tempT.z) - 1.0;
z.x += sign(z.x) * tempS.x;
z.y += sign(z.y) * tempS.y;
z.z += sign(z.z) * tempS.z;
}
else if (fractal->transformCommon.functionEnabledFalse)
{
tempS = fabs(z);
CVector4 tempT = tempS * -fractal->transformCommon.scale0;
tempS.x = exp2(tempT.x) - 1.0;
tempS.y = exp2(tempT.y) - 1.0;
tempS.z = exp2(tempT.z) - 1.0;
z.x -= sign(z.x) * tempS.x;
z.y -= sign(z.y) * tempS.y;
z.z -= sign(z.z) * tempS.z;
}
else
{
CVector4 tempR = z * fractal->transformCommon.scale0;
z.x += exp2(tempR.x) - 1.0;
z.y += exp2(tempR.y) - 1.0;
z.z += exp2(tempR.z) - 1.0;
}
}
if (fractal->transformCommon.functionEnabledByFalse)
aux.DE = aux.DE + exp2(aux.DE * -fractal->transformCommon.scale0) - 1.0;
aux.DE *= fractal->analyticDE.scale1; // DE tweak
}
/**
* benesiT1 3D
* @reference
* http://www.fractalforums.com/new-theories-and-research/
* do-m3d-formula-have-to-be-distance-estimation-formulas/
*/
void TransfBenesiT1Iteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
double tempXZ = z.x * SQRT_2_3 - z.z * SQRT_1_3;
z = CVector4(
(tempXZ - z.y) * SQRT_1_2, (tempXZ + z.y) * SQRT_1_2, z.x * SQRT_1_3 + z.z * SQRT_2_3, z.w);
CVector4 temp = z;
double tempL = temp.Length();
z = fabs(z) * fractal->transformCommon.scale3D222;
// if (tempL < 1e-21) tempL = 1e-21;
double avgScale = z.Length() / tempL;
aux.DE = aux.DE * avgScale + 1.0;
if (fractal->transformCommon.rotationEnabled)
{
z = fractal->transformCommon.rotationMatrix.RotateVector(z);
}
tempXZ = (z.y + z.x) * SQRT_1_2;
z = CVector4(z.z * SQRT_1_3 + tempXZ * SQRT_2_3, (z.y - z.x) * SQRT_1_2,
z.z * SQRT_2_3 - tempXZ * SQRT_1_3, z.w);
z = z - fractal->transformCommon.offset200;
}
/**
* benesiT1Mod 3D based on benesiT1
* @reference
* http://www.fractalforums.com/new-theories-and-research/
* do-m3d-formula-have-to-be-distance-estimation-formulas/
*/
void TransfBenesiT1ModIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
double tempXZ = z.x * SQRT_2_3 - z.z * SQRT_1_3;
z = CVector4(
(tempXZ - z.y) * SQRT_1_2, (tempXZ + z.y) * SQRT_1_2, z.x * SQRT_1_3 + z.z * SQRT_2_3, z.w);
CVector4 temp = z;
double tempL = temp.Length();
z = fabs(z) * fractal->transformCommon.scale3D333;
// if (tempL < 1e-21) tempL = 1e-21;
double avgScale = z.Length() / tempL;
aux.DE = aux.DE * avgScale + 1.0;
z = (fabs(z + fractal->transformCommon.additionConstant111)
- fabs(z - fractal->transformCommon.additionConstant111) - z);
if (fractal->transformCommon.rotationEnabled)
{
z = fractal->transformCommon.rotationMatrix.RotateVector(z);
}
tempXZ = (z.y + z.x) * SQRT_1_2;
z = CVector4(z.z * SQRT_1_3 + tempXZ * SQRT_2_3, (z.y - z.x) * SQRT_1_2,
z.z * SQRT_2_3 - tempXZ * SQRT_1_3, z.w);
}
/**
* benesi T2
* @reference
* http://www.fractalforums.com/new-theories-and-research/
* do-m3d-formula-have-to-be-distance-estimation-formulas/
*/
void TransfBenesiT2Iteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
double tempXZ = z.x * SQRT_2_3 - z.z * SQRT_1_3;
z = CVector4(
(tempXZ - z.y) * SQRT_1_2, (tempXZ + z.y) * SQRT_1_2, z.x * SQRT_1_3 + z.z * SQRT_2_3, z.w);
CVector4 tempV2 = z;
tempV2.x = sqrt(z.y * z.y + z.z * z.z);
tempV2.y = sqrt(z.x * z.x + z.z * z.z); // switching, squared, sqrt
tempV2.z = sqrt(z.x * z.x + z.y * z.y);
z = fabs(tempV2 - fractal->transformCommon.additionConstant111);
CVector4 temp = z;
double tempL = temp.Length();
z = fabs(z) * fractal->transformCommon.scale3D444;
// if (tempL < 1e-21) tempL = 1e-21;
double avgScale = z.Length() / tempL;
aux.DE = aux.DE * avgScale + 1.0;
if (fractal->transformCommon.rotationEnabled)
{
z = fractal->transformCommon.rotationMatrix.RotateVector(z);
}
tempXZ = (z.y + z.x) * SQRT_1_2;
z = CVector4(z.z * SQRT_1_3 + tempXZ * SQRT_2_3, (z.y - z.x) * SQRT_1_2,
z.z * SQRT_2_3 - tempXZ * SQRT_1_3, z.w);
}
/**
* benesi T3
* @reference
* http://www.fractalforums.com/new-theories-and-research/
* do-m3d-formula-have-to-be-distance-estimation-formulas/
*/
void TransfBenesiT3Iteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
Q_UNUSED(aux);
double tempXZ = z.x * SQRT_2_3 - z.z * SQRT_1_3;
z = CVector4(
(tempXZ - z.y) * SQRT_1_2, (tempXZ + z.y) * SQRT_1_2, z.x * SQRT_1_3 + z.z * SQRT_2_3, z.w);
CVector4 tempV2 = z;
tempV2.x = (z.y + z.z);
tempV2.y = (z.x + z.z); // switching
tempV2.z = (z.x + z.y);
z = (fabs(tempV2 - fractal->transformCommon.additionConstant222))
* fractal->transformCommon.scale3D222;
if (fractal->transformCommon.rotationEnabled)
{
z = fractal->transformCommon.rotationMatrix.RotateVector(z);
}
tempXZ = (z.y + z.x) * SQRT_1_2;
z = CVector4(z.z * SQRT_1_3 + tempXZ * SQRT_2_3, (z.y - z.x) * SQRT_1_2,
z.z * SQRT_2_3 - tempXZ * SQRT_1_3, z.w);
}
/**
* benesi T4
* @reference
* http://www.fractalforums.com/new-theories-and-research/
* do-m3d-formula-have-to-be-distance-estimation-formulas/
*/
void TransfBenesiT4Iteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
Q_UNUSED(aux);
double tempXZ = z.x * SQRT_2_3 - z.z * SQRT_1_3;
z = CVector4(
(tempXZ - z.y) * SQRT_1_2, (tempXZ + z.y) * SQRT_1_2, z.x * SQRT_1_3 + z.z * SQRT_2_3, z.w);
CVector4 tempV2 = z;
tempV2.x = (z.y * z.y + z.z * z.z);
tempV2.y = (z.x * z.x + z.z * z.z); // switching, squared,
tempV2.z = (z.x * z.x + z.y * z.y);
z = (fabs(tempV2 - fractal->transformCommon.additionConstant111))
* fractal->transformCommon.scale3D222;
if (fractal->transformCommon.rotationEnabled)
z = fractal->transformCommon.rotationMatrix.RotateVector(z);
tempXZ = (z.y + z.x) * SQRT_1_2;
z = CVector4(z.z * SQRT_1_3 + tempXZ * SQRT_2_3, (z.y - z.x) * SQRT_1_2,
z.z * SQRT_2_3 - tempXZ * SQRT_1_3, z.w);
}
/**
* benesi T5
* @reference
* http://www.fractalforums.com/new-theories-and-research/
* do-m3d-formula-have-to-be-distance-estimation-formulas/
*/
void TransfBenesiT5bIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
Q_UNUSED(aux);
double tempXZ = z.x * SQRT_2_3 - z.z * SQRT_1_3;
z = CVector4(
(tempXZ - z.y) * SQRT_1_2, (tempXZ + z.y) * SQRT_1_2, z.x * SQRT_1_3 + z.z * SQRT_2_3, z.w);
// if (z.x > -1e-21 && z.x < 1e-21)
// z.x = (z.x > 0) ? 1e-21 : -1e-21;
// if (z.y > -1e-21 && z.y < 1e-21)
// z.y = (z.y > 0) ? 1e-21 : -1e-21;
// if (z.z > -1e-21 && z.z < 1e-21)
// z.z = (z.z > 0) ? 1e-21 : -1e-21;
CVector4 tempV2 = z;
tempV2.x =
fabs(pow(pow(z.y, fractal->transformCommon.int8X) + pow(z.z, fractal->transformCommon.int8X),
fractal->transformCommon.power025.x));
tempV2.y =
fabs(pow(pow(z.x, fractal->transformCommon.int8Y) + pow(z.z, fractal->transformCommon.int8Y),
fractal->transformCommon.power025.y));
tempV2.z =
fabs(pow(pow(z.x, fractal->transformCommon.int8Z) + pow(z.y, fractal->transformCommon.int8Z),
fractal->transformCommon.power025.z));
z = (fabs(tempV2 - fractal->transformCommon.offsetC111)) * fractal->transformCommon.scale3Dd222;
if (fractal->transformCommon.rotationEnabled)
z = fractal->transformCommon.rotationMatrix.RotateVector(z);
tempXZ = (z.y + z.x) * SQRT_1_2;
z = CVector4(z.z * SQRT_1_3 + tempXZ * SQRT_2_3, (z.y - z.x) * SQRT_1_2,
z.z * SQRT_2_3 - tempXZ * SQRT_1_3, z.w);
}
/**
* benesi mag forward
* @reference
* http://www.fractalforums.com/new-theories-and-research/do-m3d-formula-have-to-be-distance-estimation-formulas/
*/
void TransfBenesiMagForwardIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
Q_UNUSED(fractal);
Q_UNUSED(aux);
double tempXZ = z.x * SQRT_2_3 - z.z * SQRT_1_3;
z = CVector4(
(tempXZ - z.y) * SQRT_1_2, (tempXZ + z.y) * SQRT_1_2, z.x * SQRT_1_3 + z.z * SQRT_2_3, z.w);
}
/**
* benesi mag backward
* @reference
* http://www.fractalforums.com/new-theories-and-research/do-m3d-formula-have-to-be-distance-estimation-formulas/
*/
void TransfBenesiMagBackwardIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
Q_UNUSED(fractal);
Q_UNUSED(aux);
double tempXZ = (z.y + z.x) * SQRT_1_2;
z = CVector4(z.z * SQRT_1_3 + tempXZ * SQRT_2_3, (z.y - z.x) * SQRT_1_2,
z.z * SQRT_2_3 - tempXZ * SQRT_1_3, z.w);
}
/**
* Benesi Cube to sphere transform
* Warps a cube to a sphere; transform made by M.Benesi, optimized by Luca.
* @reference http://www.fractalforums.com/mathematics/circle2square/
*/
void TransfBenesiCubeSphereIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
Q_UNUSED(fractal);
Q_UNUSED(aux);
z *= z; // so all now positive
// if (z.x == 0.0)
// z.x = 1e-21;
// if (z.z == 0.0)
// z.z = 1e-21;
double rCyz = z.y / z.z;
double rCxyz = (z.y + z.z) / z.x;
if (rCxyz == -1.0) z.z = 1.0; //+ 1e-21
if (rCyz < 1.0)
rCyz = sqrt(rCyz + 1.0);
else
rCyz = sqrt(1.0 / rCyz + 1.0);
if (rCxyz < 1.0)
rCxyz = sqrt(rCxyz + 1.0);
else
rCxyz = sqrt(1.0 / rCxyz + 1.0);
z.y *= rCyz;
z.z *= rCyz;
z *= rCxyz / SQRT_3_2;
}
/**
* Benesi Sphere to Cube transform
* Warps a sphere to a cube; transform made by M.Benesi, optimized by
* Luca. Scavenged and edited from code optimized by Luca.
* @reference http://www.fractalforums.com/mathematics/circle2square/
*/
void TransfBenesiSphereCubeIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
Q_UNUSED(fractal);
Q_UNUSED(aux);
z *= z;
// if (z.z == 0.0) z.z = 1e-21;
double rCyz = z.y / z.z;
if (rCyz < 1.0)
rCyz = 1.0 / sqrt(rCyz + 1.0);
else
rCyz = 1.0 / sqrt(1.0 / rCyz + 1.0);
z.y *= rCyz;
z.z *= rCyz;
// if (z.x == 0.0) z.x = 1e-21;
double rCxyz = (z.y * z.y + z.z * z.z) / z.x;
if (rCxyz < 1.0)
rCxyz = 1.0 / sqrt(rCxyz + 1.0);
else
rCxyz = 1.0 / sqrt(1.0 / rCxyz + 1.0);
z *= rCxyz * SQRT_3_2;
}
/**
* Blockify
* based on a block of Fragmentarium code, from Adam Nixon
* analytic aux.DE
*/
void TransfBlockifyIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
CVector4 oldZ = z;
double master = fractal->transformCommon.scale / 100.0;
CVector4 bSize = fractal->transformCommon.constantMultiplier111 * master;
// bsize maybe shortened to a double??
if (!fractal->transformCommon.functionEnabledFalse)
{
if (!fractal->transformCommon.functionEnabledDFalse)
{
//if (fractal->transformCommon.functionEnabledCx) z.x = floor(z.x / bSize.x) * bSize.x;
//if (fractal->transformCommon.functionEnabledCy) z.y = floor(z.y / bSize.y) * bSize.y;
//if (fractal->transformCommon.functionEnabledCz) z.z = floor(z.z / bSize.z) * bSize.z;
if (fractal->transformCommon.functionEnabledCx) z.x = (floor(z.x / bSize.x) + 0.5) * bSize.x;
if (fractal->transformCommon.functionEnabledCy) z.y = (floor(z.y / bSize.y) + 0.5) * bSize.y;
if (fractal->transformCommon.functionEnabledCz) z.z = (floor(z.z / bSize.z) + 0.5) * bSize.z;
//if (fractal->transformCommon.functionEnabledCx) z.x = (trunc(z.x / bSize.x) + sign(z.x) * 0.5) * bSize.x;
//if (fractal->transformCommon.functionEnabledCy) z.y = (trunc(z.y / bSize.y) + sign(z.y) * 0.5) * bSize.y;
//if (fractal->transformCommon.functionEnabledCz) z.z = (trunc(z.z / bSize.z) + sign(z.z) * 0.5) * bSize.z;
}
else // normalize
{
double rr = z.Dot(z);
z /= rr;
bSize /= 100.0;
if (fractal->transformCommon.functionEnabledCx) z.x = floor(z.x / bSize.x) * bSize.x;
if (fractal->transformCommon.functionEnabledCy) z.y = floor(z.y / bSize.y) * bSize.y;
if (fractal->transformCommon.functionEnabledCz) z.z = floor(z.z / bSize.z) * bSize.z;
z *= rr;
}
}
else // radial
{
double rr = z.Dot(z);
if (fractal->transformCommon.functionEnabledRFalse) rr = sqrt(rr); // z.Length();
if (fractal->transformCommon.functionEnabledBxFalse) rr = z.x * z.x + z.y * z.y;
if (fractal->transformCommon.functionEnabledByFalse) rr = z.y * z.y + z.z * z.z;
if (fractal->transformCommon.functionEnabledBzFalse) rr = z.z * z.z + z.x * z.x;
z /= rr;
rr = floor(rr / master) * master;
z *= rr;
}
// DE thing that has no effect, too small diff?
if (fractal->transformCommon.functionEnabled)
{
double AN = z.Length()/ oldZ.Length();
aux.DE = aux.DE * AN; // * fractal->analyticDE.scale1 + fractal->analyticDE.offset0;
}
// post scale
z *= fractal->transformCommon.scale1;
if (fractal->analyticDE.enabled)
{
if (!fractal->analyticDE.enabledFalse)
aux.DE *= fractal->transformCommon.scale1;
else
aux.DE = aux.DE * fractal->transformCommon.scale1 * fractal->analyticDE.scale1
+ fractal->analyticDE.offset0;
}
}
/**
* Box Fold
* This formula contains aux.color
*/
void TransfBoxFoldIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
CVector4 oldZ = z;
double colorAdd = 0.0;
if (fabs(z.x) > fractal->mandelbox.foldingLimit)
{
z.x = sign(z.x) * fractal->mandelbox.foldingValue - z.x;
}
if (fabs(z.y) > fractal->mandelbox.foldingLimit)
{
z.y = sign(z.y) * fractal->mandelbox.foldingValue - z.y;
}
double zLimit = fractal->mandelbox.foldingLimit * fractal->transformCommon.scale1;
double zValue = fractal->mandelbox.foldingValue * fractal->transformCommon.scale1;
if (fabs(z.z) > zLimit)
{
z.z = sign(z.z) * zValue - z.z;
}
// aux.colo mode 1
if (fractal->foldColor.auxColorEnabledFalse)
{
if (z.x != oldZ.x) colorAdd += fractal->mandelbox.color.factor.x;
if (z.y != oldZ.y) colorAdd += fractal->mandelbox.color.factor.y;
if (z.z != oldZ.z) colorAdd += fractal->mandelbox.color.factor.z;
}
// mode 2
if (fractal->transformCommon.functionEnabledCxFalse)
{
if (fabs(z.x) > fractal->mandelbox.foldingLimit)
{
colorAdd += fractal->mandelbox.color.factor.x;
}
else
{
colorAdd +=
fractal->mandelbox.color.factor.x
* (1.0 - (fractal->mandelbox.foldingLimit - fabs(z.x)) / fractal->mandelbox.foldingLimit);
}
if (fabs(z.y) > fractal->mandelbox.foldingLimit)
{
colorAdd += fractal->mandelbox.color.factor.y;
}
else
{
colorAdd +=
fractal->mandelbox.color.factor.y
* (1.0 - (fractal->mandelbox.foldingLimit - fabs(z.y)) / fractal->mandelbox.foldingLimit);
}
if (fabs(z.z) > fractal->mandelbox.foldingLimit)
{
colorAdd += fractal->mandelbox.color.factor.z;
}
else
{
colorAdd +=
fractal->mandelbox.color.factor.z
* (1.0 - (fractal->mandelbox.foldingLimit - fabs(z.z)) / fractal->mandelbox.foldingLimit);
}
aux.color += colorAdd;
}
// mode 3
if (fractal->transformCommon.functionEnabledCyFalse)
{
double valMinusLim = fractal->mandelbox.foldingValue - fractal->mandelbox.foldingLimit;
if (z.x != oldZ.x)
{
colorAdd += fractal->mandelbox.color.factor.x * (fabs(z.x) - fractal->mandelbox.foldingLimit)
/ valMinusLim;
}
if (z.y != oldZ.y)
{
colorAdd += fractal->mandelbox.color.factor.y * (fabs(z.y) - fractal->mandelbox.foldingLimit)
/ valMinusLim;
}
if (z.z != oldZ.z)
{
colorAdd += fractal->mandelbox.color.factor.z * (fabs(z.z) - fractal->mandelbox.foldingLimit)
/ valMinusLim;
}
aux.color += colorAdd;
}
}
/**
* Box Fold VaryV1. Varies folding limit based on iteration conditions
* This formula contains aux.color
*/
void TransfBoxFoldVaryV1Iteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
CVector4 oldZ = z;
double limit = fractal->mandelbox.foldingLimit;
double tempVC = limit; // constant to be varied
if (aux.i >= fractal->transformCommon.startIterations250
&& aux.i < fractal->transformCommon.stopIterations
&& (fractal->transformCommon.stopIterations - fractal->transformCommon.startIterations250
!= 0))
{
int iterationRange =
fractal->transformCommon.stopIterations - fractal->transformCommon.startIterations250;
int currentIteration = (aux.i - fractal->transformCommon.startIterations250);
tempVC += fractal->transformCommon.offset * (1.0 * currentIteration) / iterationRange;
}
if (aux.i >= fractal->transformCommon.stopIterations)
{
tempVC = (tempVC + fractal->transformCommon.offset);
}
limit = tempVC;
double value = fractal->transformCommon.scale2 * limit;
if (z.x > limit)
{
z.x = value - z.x;
}
else if (z.x < -limit)
{
z.x = -value - z.x;
}
if (z.y > limit)
{
z.y = value - z.y;
;
}
else if (z.y < -limit)
{
z.y = -value - z.y;
}
double zLimit = limit * fractal->transformCommon.scale1;
double zValue = value * fractal->transformCommon.scale1;
if (z.z > zLimit)
{
z.z = zValue - z.z;
}
else if (z.z < -zLimit)
{
z.z = -zValue - z.z;
}
if (fractal->foldColor.auxColorEnabledFalse)
{
if (z.x != oldZ.x) aux.color += fractal->mandelbox.color.factor.x;
if (z.y != oldZ.y) aux.color += fractal->mandelbox.color.factor.y;
if (z.z != oldZ.z) aux.color += fractal->mandelbox.color.factor.z;
}
aux.DE *= fractal->analyticDE.scale1;
}
/**
* Box Fold XYZ, set different folding parameters for each axis
* This formula contains aux.color
*/
void TransfBoxFoldXYZIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
CVector4 oldZ = z;
CVector4 Value4 = fractal->transformCommon.additionConstant222;
if (fractal->transformCommon.functionEnabledFalse)
Value4 = 2.0 * fractal->transformCommon.additionConstant111;
if (z.x > fractal->transformCommon.additionConstant111.x)
{
z.x = Value4.x - z.x;
}
else if (z.x < -fractal->transformCommon.additionConstant111.x)
{
z.x = -Value4.x - z.x;
}
if (z.y > fractal->transformCommon.additionConstant111.y)
{
z.y = Value4.y - z.y;
}
else if (z.y < -fractal->transformCommon.additionConstant111.y)
{
z.y = -Value4.y - z.y;
}
if (z.z > fractal->transformCommon.additionConstant111.z)
{
z.z = Value4.z - z.z;
}
else if (z.z < -fractal->transformCommon.additionConstant111.z)
{
z.z = -Value4.z - z.z;
}
if (fractal->foldColor.auxColorEnabledFalse)
{
if (z.x != oldZ.x) aux.color += fractal->mandelbox.color.factor.x;
if (z.y != oldZ.y) aux.color += fractal->mandelbox.color.factor.y;
if (z.z != oldZ.z) aux.color += fractal->mandelbox.color.factor.z;
}
}
/**
* Box Offset, set different offset for each axis, added symmetrically about the origin
* will cause cuts along axis
*/
void TransfBoxOffsetIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
CVector4 temp = z;
z.x = sign(z.x) * fractal->transformCommon.additionConstant000.x + z.x;
z.y = sign(z.y) * fractal->transformCommon.additionConstant000.y + z.y;
z.z = sign(z.z) * fractal->transformCommon.additionConstant000.z + z.z;
if (fractal->transformCommon.functionEnabledFalse)
{
double tempL = temp.Length();
// if (tempL < 1e-21) tempL = 1e-21;
double avgScale = z.Length() / tempL;
aux.DE = aux.DE * avgScale + 1.0;
}
}
/**
* folding tetra3D from M3D (Luca GN 2011):
* Code taken from the forums, KIFS original thread
* side note - if you disable the 1st half, 2nd half will be
* done even if you disable it... (to avoid a NOP transform)
* @reference
* http://www.fractalforums.com/mandelbulb-3d/custom-formulas-and-transforms-release-t17106/
*/
void TransfFoldingTetra3dIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
Q_UNUSED(aux);
double x1;
double y1;
if (fractal->transformCommon.functionEnabledx)
{
if (z.x + z.y < 0.0)
{
x1 = -z.y;
z.y = -z.x;
z.x = x1;
}
if (z.x + z.z < 0.0)
{
x1 = -z.z;
z.z = -z.x;
z.x = x1;
}
if (z.y + z.z < 0.0)
{
y1 = -z.z;
z.z = -z.y;
z.y = y1;
}
}
if (fractal->transformCommon.functionEnabledy)
{
if (z.x - z.y < 0.0) swap(z.y, z.x);
if (z.x - z.z < 0.0) swap(z.z, z.x);
if (z.y - z.z < 0.0) swap(z.z, z.y);
}
}
/**
* iteration weight. Influence fractal based on the weight of
* Z values after different iterations
*/
void TransfIterationWeightIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
CVector4 zA = (aux.i == fractal->transformCommon.intA) ? z : CVector4();
CVector4 zB = (aux.i == fractal->transformCommon.intB) ? z : CVector4();
z = (z * fractal->transformCommon.scale) + (zA * fractal->transformCommon.offset)
+ (zB * fractal->transformCommon.offset0);
aux.DE *= fractal->transformCommon.scale;
}
/**
* Inverse cylindrical coordinates, very easy transform
* Formula by Luca GN 2011
* @reference
* http://www.fractalforums.com/mandelbulb-3d/custom-formulas-and-transforms-release-t17106/
*/
void TransfInvCylindricalIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
double newZx = z.x;
double newZy = z.y;
if (fractal->transformCommon.functionEnabledFalse) newZx = z.x * cos(z.y);
if (fractal->transformCommon.functionEnabledxFalse) newZy = z.x * sin(z.y);
z = CVector4(z.x * cos(newZy * fractal->transformCommon.scale1),
newZx * sin(z.y * fractal->transformCommon.scale1), z.z * fractal->transformCommon.scaleC1,
z.w)
* fractal->transformCommon.scaleA1;
aux.DE = aux.DE * fabs(fractal->transformCommon.scaleA1) * fractal->transformCommon.scaleB1
+ fractal->transformCommon.offset1;
}
/**
* Linear Combine transform from Mandelbulb3D.
* Can create multiple combination for the addition of Cpixel
* @reference
* http://www.fractalforums.com/mandelbulb-3d/custom-formulas-and-transforms-release-t17106/
*/
void TransfLinCombineCXYZIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
CVector4 c = aux.const_c;
CVector4 temp = c;
CVector4 mulX = fractal->transformCommon.constantMultiplier100;
CVector4 mulY = fractal->transformCommon.constantMultiplier010;
CVector4 mulZ = fractal->transformCommon.constantMultiplier001;
c.x = mulX.x * temp.x + mulX.y * temp.y + mulX.z * temp.z;
c.y = mulY.x * temp.x + mulY.y * temp.y + mulY.z * temp.z;
c.z = mulZ.x * temp.x + mulZ.y * temp.y + mulZ.z * temp.z;
if (fractal->transformCommon.addCpixelEnabledFalse)
{
CVector4 tempC = c;
if (fractal->transformCommon.alternateEnabledFalse) // alternate
{
tempC = aux.c;
switch (fractal->mandelbulbMulti.orderOfXYZC)
{
case multi_OrderOfXYZ_xyz:
default: tempC = CVector4(tempC.x, tempC.y, tempC.z, tempC.w); break;
case multi_OrderOfXYZ_xzy: tempC = CVector4(tempC.x, tempC.z, tempC.y, tempC.w); break;
case multi_OrderOfXYZ_yxz: tempC = CVector4(tempC.y, tempC.x, tempC.z, tempC.w); break;
case multi_OrderOfXYZ_yzx: tempC = CVector4(tempC.y, tempC.z, tempC.x, tempC.w); break;
case multi_OrderOfXYZ_zxy: tempC = CVector4(tempC.z, tempC.x, tempC.y, tempC.w); break;
case multi_OrderOfXYZ_zyx: tempC = CVector4(tempC.z, tempC.y, tempC.x, tempC.w); break;
}
aux.c = tempC;
}
else
{
switch (fractal->mandelbulbMulti.orderOfXYZC)
{
case multi_OrderOfXYZ_xyz:
default: tempC = CVector4(c.x, c.y, c.z, c.w); break;
case multi_OrderOfXYZ_xzy: tempC = CVector4(c.x, c.z, c.y, c.w); break;
case multi_OrderOfXYZ_yxz: tempC = CVector4(c.y, c.x, c.z, c.w); break;
case multi_OrderOfXYZ_yzx: tempC = CVector4(c.y, c.z, c.x, c.w); break;
case multi_OrderOfXYZ_zxy: tempC = CVector4(c.z, c.x, c.y, c.w); break;
case multi_OrderOfXYZ_zyx: tempC = CVector4(c.z, c.y, c.x, c.w); break;
}
}
z += tempC * fractal->transformCommon.constantMultiplier111;
}
}
/**
* Transform Menger Fold
* Menger Sponge formula created by Knighty
* @reference
* http://www.fractalforums.com/ifs-iterated-function-systems/kaleidoscopic-(escape-time-ifs)/
* analytic aux.DE
*/
void TransfMengerFoldIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
if (fractal->transformCommon.functionEnabledx)
{ // fabs() and menger fold
z = fabs(z + fractal->transformCommon.additionConstantA000);
if (z.x - z.y < 0.0) swap(z.y, z.x);
if (z.x - z.z < 0.0) swap(z.z, z.x);
if (z.y - z.z < 0.0) swap(z.z, z.y);
}
if (fractal->transformCommon.functionEnabledy)
{ // menger scales and offsets
z *= fractal->transformCommon.scale3;
z.x -= 2.0 * fractal->transformCommon.constantMultiplier111.x;
z.y -= 2.0 * fractal->transformCommon.constantMultiplier111.y;
if (fractal->transformCommon.functionEnabled)
{
if (z.z > 1.0) // z.z < 1.0 z.z = z.z
z.z -= 2.0 * fractal->transformCommon.constantMultiplier111.z;
}
else
{
z.z -= 2.0 * fractal->transformCommon.constantMultiplier111.z;
}
if (fractal->analyticDE.enabled)
{
if (!fractal->analyticDE.enabledFalse)
aux.DE *= fractal->transformCommon.scale3;
else
aux.DE = aux.DE * fractal->transformCommon.scale3 * fractal->analyticDE.scale1
+ fractal->analyticDE.offset0;
}
}
}
/**
* multiple angle
*/
void TransfMultipleAngleIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
double th0 = asin(z.z / aux.r);
double ph0 = atan2(z.y, z.x);
double th = th0 * fractal->transformCommon.multiplication;
double ph = ph0 * fractal->transformCommon.multiplication;
double cth = cos(th);
z = CVector4(cth * cos(ph), cth * sin(ph), sin(th), 0.0) * aux.r;
}
/**
* Octo
* analytic aux.DE
*/
void TransfOctoFoldIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
if (z.x + z.y < 0.0) z = CVector4(-z.y, -z.x, z.z, z.w);
if (z.x + z.z < 0.0) // z.xz = -z.zx;
z = CVector4(-z.z, z.y, -z.x, z.w);
if (z.x - z.y < 0.0) // z.xy = z.yx;
z = CVector4(z.y, z.x, z.z, z.w);
if (z.x - z.z < 0.0) // z.xz = z.zx;
z = CVector4(z.z, z.y, z.x, z.w);
z.x = fabs(z.x);
z = z * fractal->transformCommon.scale2
- fractal->transformCommon.offset100 * (fractal->transformCommon.scale2 - 1.0);
if (fractal->analyticDE.enabled)
{
if (!fractal->analyticDE.enabledFalse)
aux.DE *= fractal->transformCommon.scale2;
else
aux.DE = aux.DE * fractal->transformCommon.scale2 * fractal->analyticDE.scale1
+ fractal->analyticDE.offset0;
}
}
/**
* Parabolic Fold by mclarekin
*/
void TransfParabFoldIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
CVector4 temp = z;
CVector4 slope2 = fractal->transformCommon.constantMultiplier111;
CVector4 lengthAdd = fractal->transformCommon.additionConstant000;
CVector4 factorP;
factorP.x = -slope2.x / (lengthAdd.x * 2.0);
factorP.y = -slope2.y / (lengthAdd.y * 2.0);
factorP.z = -slope2.z / (lengthAdd.z * 2.0);
if (temp.x > 0)
{
if (temp.x < lengthAdd.x)
{
z.x = z.x * z.x * factorP.x;
}
else
{
z.x = (z.x - lengthAdd.x / 2.0) * slope2.x;
}
}
if (temp.y > 0)
{
if (temp.y < lengthAdd.y)
{
z.y = z.y * z.y * factorP.y;
}
else
{
z.y = (z.y - lengthAdd.y / 2.0) * slope2.y;
}
}
if (temp.z > 0)
{
if (temp.z < lengthAdd.z)
{
z.z = z.z * z.z * factorP.z;
}
else
{
z.z = (z.z - lengthAdd.z / 2.0) * slope2.z;
}
}
if (temp.x < 0)
{
if (temp.x > -lengthAdd.x)
{
z.x = z.x * z.x * -factorP.x;
}
else
{
z.x = (z.x + lengthAdd.x / 2.0) * slope2.x;
}
}
if (temp.y < 0)
{
if (temp.y > -lengthAdd.y)
{
z.y = z.y * z.y * -factorP.y;
}
else
{
z.y = (z.y + lengthAdd.y / 2.0) * slope2.y;
}
}
if (temp.z < 0)
{
if (temp.z > -lengthAdd.z)
{
z.z = z.z * z.z * -factorP.z;
}
else
{
z.z = (z.z + lengthAdd.z / 2.0) * slope2.z;
}
}
if (fractal->transformCommon.functionEnabledxFalse)
{
z = (z - temp) * fractal->transformCommon.scale3D111;
}
if (fractal->transformCommon.functionEnabledyFalse)
{
z = (z - temp) * temp * fractal->transformCommon.scale3D111;
z.x = sign(temp.x) * z.x;
z.y = sign(temp.y) * z.y;
z.z = sign(temp.z) * z.z;
}
if (fractal->transformCommon.functionEnabledzFalse)
{
z = (z - temp) * temp * fractal->transformCommon.scale3D111;
}
if (fractal->analyticDE.enabled)
{
if (!fractal->analyticDE.enabledFalse)
aux.DE = aux.DE * fractal->analyticDE.scale1 + fractal->analyticDE.offset0;
else
{
double avgScale = z.Length() / temp.Length();
aux.DE = aux.DE * avgScale * fractal->analyticDE.scale1 + fractal->analyticDE.offset0;
}
}
}
/**
* platonic solid - from DarkBeam's code
* @reference
* http://www.fractalforums.com/3d-fractal-generation/platonic-dimensions/msg36528/#msg36528
*/
void TransfPlatonicSolidIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
double platonicR = 0.0;
double rho = 0.0;
if (!fractal->transformCommon.functionEnabledFalse)
{
rho = sqrt(aux.r); // the radius
double theta =
cos(fractal->platonicSolid.frequency * z.x) * sin(fractal->platonicSolid.frequency * z.y)
+ cos(fractal->platonicSolid.frequency * z.y) * sin(fractal->platonicSolid.frequency * z.z)
+ cos(fractal->platonicSolid.frequency * z.z) * sin(fractal->platonicSolid.frequency * z.x);
platonicR = theta * fractal->platonicSolid.amplitude + rho * fractal->platonicSolid.rhoMul;
z *= platonicR;
}
else
{
// if (fractal->transformCommon.functionEnabledx) rho = sqrt(z.Length()); // the radius
// if (fractal->transformCommon.functionEnabledyFalse) rho = z.Length();
// if (fractal->transformCommon.functionEnabledzFalse) rho = z.Dot(z);
double rho1 = 0.0;
double rho2 = 0.0;
double rho3 = 0.0;
if (fractal->transformCommon.functionEnabledx) rho1 = sqrt(aux.r);
if (fractal->transformCommon.functionEnabledyFalse) rho2 = aux.r;
if (fractal->transformCommon.functionEnabledzFalse) rho3 = aux.r * aux.r;
if (fractal->transformCommon.functionEnabledAxFalse)
rho = rho1 + (rho2 - rho1) * fractal->transformCommon.scale1;
else if (fractal->transformCommon.functionEnabledAyFalse)
rho = rho2 + (rho3 - rho2) * fractal->transformCommon.scale1;
else
rho = rho1 + rho2 + rho3;
double theta =
cos(fractal->platonicSolid.frequency * z.x) * sin(fractal->platonicSolid.frequency * z.y)
+ cos(fractal->platonicSolid.frequency * z.y) * sin(fractal->platonicSolid.frequency * z.z)
+ cos(fractal->platonicSolid.frequency * z.z) * sin(fractal->platonicSolid.frequency * z.x);
// theta is pos or neg && < 3.0
if (fractal->transformCommon.functionEnabledAzFalse) theta = fabs(theta);
platonicR = theta * fractal->platonicSolid.amplitude + rho * fractal->platonicSolid.rhoMul;
z *= platonicR; // can be neg
}
if (fractal->analyticDE.enabled)
{
aux.DE = aux.DE * fabs(platonicR) * fractal->analyticDE.scale1 + fractal->analyticDE.offset1;
}
}
/**
* poly fold sym DarkBeam's version
* @reference
* DarkBeam (luca) http://www.fractalforums.com/mandelbulber/
* _polyfold_sym-and-polyfoldsymifs-in-mandelbulber-2/msg98162/#msg98162
*/
void TransfPolyFoldSymIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
Q_UNUSED(aux);
int order = fractal->transformCommon.int6;
double div2PI = (double)order / M_PI_2x;
bool cy = false;
int sector = (int)(-div2PI * atan(z.x / z.y));
if (sector & 1) cy = true; // parity if (sector & 1) is a "bit check", true = odd
double angle = (double)(sector / div2PI);
// z.xy = rotate(z.xy,angle); // sin
double tempZx = z.x;
z.x = z.x * cos(angle) - z.y * sin(angle);
z.y = tempZx * sin(angle) + z.y * cos(angle);
if (cy) z.y = -z.y;
// if ((order&1) && (sector == 0)) z.y = fabs(z.y); // more continuous?
}
/**
* poly fold sym multi DarkBeam's version
* @reference
* DarkBeam (luca) http://www.fractalforums.com/mandelbulber/
* _polyfold_sym-and-polyfoldsymifs-in-mandelbulber-2/msg98162/#msg98162
*/
void TransfPolyFoldSymMultiIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
Q_UNUSED(aux);
int order = fractal->transformCommon.int6;
double div2PI = (double)order / M_PI_2x;
double temp = 0.0;
if (fractal->transformCommon.functionEnabledCx)
{
bool cy = false;
int sector = (int)(-div2PI * atan(z.x / z.y));
if (sector & 1) cy = true;
double angle = (double)(sector / div2PI);
temp = z.x;
z.x = z.x * cos(angle) - z.y * sin(angle);
z.y = temp * sin(angle) + z.y * cos(angle);
if (cy == true) z.y = -z.y;
/*if (fractal->transformCommon.functionEnabledFalse)
{
if ((order&1) && (sector == 0)) z.y = fabs(z.y); // more continuous?
else if (cy == true) z.y = -z.y;
}
else if (cy == true) z.y = -z.y;*/
}
if (fractal->transformCommon.functionEnabledCyFalse)
{
bool cz = false;
int sector = (int)(-div2PI * atan(z.y / z.z));
if (sector & 1) cz = true;
double angle = (double)(sector / div2PI);
temp = z.y;
z.y = z.y * cos(angle) - z.z * sin(angle);
z.z = temp * sin(angle) + z.z * cos(angle);
if (cz == true) z.z = -z.z;
}
if (fractal->transformCommon.functionEnabledCzFalse)
{
bool cx = false;
int sector = (int)(-div2PI * atan(z.z / z.x));
if (sector & 1) cx = true;
double angle = (double)(sector / div2PI);
temp = z.z;
z.z = z.z * cos(angle) - z.x * sin(angle);
z.x = temp * sin(angle) + z.x * cos(angle);
if (cx == true) z.x = -z.x;
}
}
/**
* z(n+1) = z(n) * abs(z(n)) ^ p-1
* analytic aux.r-dz
*/
void TransfRPowerIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
double rp = pow(aux.r, fractal->bulb.power - 1.0);
aux.DE = rp * aux.DE * fractal->bulb.power + 1.0;
z *= rp;
}
/**
* z = (Az^2 + Bz + C ) / D; ((VectA +ScaleA * z) * fn(z) + scaleB * z + VectC ) * ScaleD
*/
void TransfPwr2PolynomialIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
CVector4 partA = z;
if (fractal->transformCommon.functionEnabledFalse) // fabs
partA = fabs(z);
if (fractal->transformCommon.functionEnabledxFalse) // pwr3 or z * fabs(z^2)
partA *= z;
partA = partA * fractal->transformCommon.scale2 + fractal->transformCommon.constantMultiplier111;
CVector4 fnZ1 = z;
if (fractal->transformCommon.functionEnabledBxFalse) // cos(z*Pi)
{
double scalePi = M_PI * fractal->transformCommon.scaleC1;
fnZ1.x = cos(z.x * scalePi);
fnZ1.y = cos(z.y * scalePi);
fnZ1.z = cos(z.z * scalePi);
}
if (fractal->transformCommon.functionEnabledyFalse) // pi rotation
fnZ1 = fnZ1.RotateAroundVectorByAngle(fractal->transformCommon.constantMultiplier111.GetXYZ(),
M_PI * fractal->transformCommon.scale0); // * cPI ;
if (fractal->transformCommon.functionEnabledzFalse) // box offset
{
fnZ1.x = fnZ1.x + sign(fnZ1.x) * fractal->transformCommon.additionConstant000.x;
fnZ1.y = fnZ1.y + sign(fnZ1.y) * fractal->transformCommon.additionConstant000.y;
fnZ1.z = fnZ1.z + sign(fnZ1.z) * fractal->transformCommon.additionConstant000.z;
}
if (fractal->transformCommon.functionEnabledAxFalse) // fabs fnZ1
fnZ1 = fabs(fnZ1);
CVector4 partB = z;
if (fractal->transformCommon.functionEnabledAzFalse) partB = fabs(z);
partB *= fractal->transformCommon.scale4;
CVector4 constantMult = CVector4(fractal->transformCommon.constantMultiplierB111.x,
fractal->transformCommon.constantMultiplierB111.y,
fractal->transformCommon.constantMultiplierB111.z, 0.0);
z = constantMult + partB - partA * fnZ1;
z *= fractal->transformCommon.scale025;
aux.DE = aux.DE * 4.0 * fractal->analyticDE.scale1 + fractal->analyticDE.offset1;
}
/**
* Quaternion Fold Transform
* @reference http://www.fractalforums.com/3d-fractal-generation/true-3d-mandlebrot-type-fractal/
*/
void TransfQuaternionFoldIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
CVector4 c = aux.const_c;
z = CVector4(z.x * z.x - z.y * z.y - z.z * z.z, z.x * z.y, z.x * z.z, z.w);
if (fractal->transformCommon.functionEnabledFalse)
{
// aux.DE = aux.DE * 2.0 * aux.r;
// double tempL = z.Length();
z *= fractal->transformCommon.constantMultiplier122;
// if (tempL < 1e-21) tempL = 1e-21;
// CVector4 tempAvgScale = CVector4(z.x, z.y / 2.0, z.z / 2.0, z.w);
// double avgScale = tempAvgScale.Length() / tempL;
// double tempAux = aux.DE * avgScale;
// aux.DE = aux.DE + (tempAux - aux.DE) * fractal->transformCommon.scaleA1;
if (fractal->analyticDE.enabled)
{
if (!fractal->analyticDE.enabledFalse)
aux.DE = aux.DE * 2.0 * aux.r;
else
aux.DE = aux.DE * 2.0 * aux.r * fractal->analyticDE.scale1 + fractal->analyticDE.offset0;
}
// offset
z += fractal->transformCommon.additionConstant000;
}
// addCpixel
if (fractal->transformCommon.addCpixelEnabledFalse)
{
CVector4 tempC = c;
if (fractal->transformCommon.alternateEnabledFalse) // alternate
{
tempC = aux.c;
switch (fractal->mandelbulbMulti.orderOfXYZC)
{
case multi_OrderOfXYZ_xyz:
default: tempC = CVector4(tempC.x, tempC.y, tempC.z, tempC.w); break;
case multi_OrderOfXYZ_xzy: tempC = CVector4(tempC.x, tempC.z, tempC.y, tempC.w); break;
case multi_OrderOfXYZ_yxz: tempC = CVector4(tempC.y, tempC.x, tempC.z, tempC.w); break;
case multi_OrderOfXYZ_yzx: tempC = CVector4(tempC.y, tempC.z, tempC.x, tempC.w); break;
case multi_OrderOfXYZ_zxy: tempC = CVector4(tempC.z, tempC.x, tempC.y, tempC.w); break;
case multi_OrderOfXYZ_zyx: tempC = CVector4(tempC.z, tempC.y, tempC.x, tempC.w); break;
}
aux.c = tempC;
}
else
{
switch (fractal->mandelbulbMulti.orderOfXYZC)
{
case multi_OrderOfXYZ_xyz:
default: tempC = CVector4(c.x, c.y, c.z, c.w); break;
case multi_OrderOfXYZ_xzy: tempC = CVector4(c.x, c.z, c.y, c.w); break;
case multi_OrderOfXYZ_yxz: tempC = CVector4(c.y, c.x, c.z, c.w); break;
case multi_OrderOfXYZ_yzx: tempC = CVector4(c.y, c.z, c.x, c.w); break;
case multi_OrderOfXYZ_zxy: tempC = CVector4(c.z, c.x, c.y, c.w); break;
case multi_OrderOfXYZ_zyx: tempC = CVector4(c.z, c.y, c.x, c.w); break;
}
}
z += tempC * fractal->transformCommon.constantMultiplierC111;
}
}
/**
* Reciprocal3 based on DarkBeam's code from M3D,
* @reference
* http://www.fractalforums.com/mandelbulb-3d/custom-formulas-and-transforms-release-t17106/
*/
void TransfReciprocal3Iteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
CVector4 tempZ = z;
if (fractal->transformCommon.functionEnabledx)
{
if (fractal->transformCommon.functionEnabledAx)
tempZ.x = (1.0 / fractal->transformCommon.offset111.x)
- 1.0 / (fabs(z.x) + fractal->transformCommon.offset111.x);
if (fractal->transformCommon.functionEnabledAxFalse)
tempZ.x = (fractal->transformCommon.offsetA111.x)
- 1.0 / (fabs(z.x) + fractal->transformCommon.offset111.x);
if (fractal->transformCommon.functionEnabledBxFalse)
{
double M1 = fractal->transformCommon.scale1;
double M2 = fractal->transformCommon.scaleA1;
tempZ.x = (1.0 / fractal->transformCommon.offset111.x)
+ (1.0 / fractal->transformCommon.offsetA111.x)
- 1.0 / (fabs(z.x * M1) + fractal->transformCommon.offset111.x)
- 1.0 / ((z.x * z.x * M2) + fractal->transformCommon.offsetA111.x);
}
if (fractal->transformCommon.functionEnabledCxFalse)
{
double M1 = fractal->transformCommon.scale1;
double M2 = fractal->transformCommon.scaleA1;
tempZ.x = fractal->transformCommon.offsetB111.x
- 1.0 / (fabs(z.x * M1) + fractal->transformCommon.offset111.x)
- 1.0 / ((z.x * z.x * M2) + fractal->transformCommon.offsetA111.x);
}
tempZ.x += fabs(z.x) * fractal->transformCommon.offset000.x; // function slope
z.x = sign(z.x) * tempZ.x;
}
if (fractal->transformCommon.functionEnabledy)
{
if (fractal->transformCommon.functionEnabledAx)
tempZ.y = (1.0 / fractal->transformCommon.offset111.y)
- 1.0 / (fabs(z.y) + fractal->transformCommon.offset111.y);
if (fractal->transformCommon.functionEnabledAxFalse)
tempZ.y = (fractal->transformCommon.offsetA111.y)
- 1.0 / (fabs(z.y) + fractal->transformCommon.offset111.y);
if (fractal->transformCommon.functionEnabledBxFalse)
{
double M1 = fractal->transformCommon.scale1;
double M2 = fractal->transformCommon.scaleA1;
tempZ.y = (1.0 / fractal->transformCommon.offset111.y)
+ (1.0 / fractal->transformCommon.offsetA111.y)
- 1.0 / (fabs(z.y * M1) + fractal->transformCommon.offset111.y)
- 1.0 / ((z.y * z.y * M2) + fractal->transformCommon.offsetA111.y);
}
if (fractal->transformCommon.functionEnabledCxFalse)
{
double M1 = fractal->transformCommon.scale1;
double M2 = fractal->transformCommon.scaleA1;
tempZ.y = fractal->transformCommon.offsetB111.y
- 1.0 / (fabs(z.y * M1) + fractal->transformCommon.offset111.y)
- 1.0 / ((z.y * z.y * M2) + fractal->transformCommon.offsetA111.y);
}
tempZ.y += fabs(z.y) * fractal->transformCommon.offset000.y;
z.y = sign(z.y) * tempZ.y;
}
if (fractal->transformCommon.functionEnabledz)
{
if (fractal->transformCommon.functionEnabledAx)
tempZ.z = (1.0 / fractal->transformCommon.offset111.z)
- 1.0 / (fabs(z.z) + fractal->transformCommon.offset111.z);
if (fractal->transformCommon.functionEnabledAxFalse)
tempZ.z = (fractal->transformCommon.offsetA111.z)
- 1.0 / (fabs(z.z) + fractal->transformCommon.offset111.z);
if (fractal->transformCommon.functionEnabledBxFalse)
{
double M1 = fractal->transformCommon.scale1;
double M2 = fractal->transformCommon.scaleA1;
tempZ.z = (1.0 / fractal->transformCommon.offset111.z)
+ (1.0 / fractal->transformCommon.offsetA111.z)
- 1.0 / (fabs(z.z * M1) + fractal->transformCommon.offset111.z)
- 1.0 / ((z.z * z.z * M2) + fractal->transformCommon.offsetA111.z);
}
if (fractal->transformCommon.functionEnabledCxFalse)
{
double M1 = fractal->transformCommon.scale1;
double M2 = fractal->transformCommon.scaleA1;
tempZ.z = fractal->transformCommon.offsetB111.z
- 1.0 / (fabs(z.z * M1) + fractal->transformCommon.offset111.z)
- 1.0 / ((z.z * z.z * M2) + fractal->transformCommon.offsetA111.z);
}
tempZ.z += fabs(z.z) * fractal->transformCommon.offset000.z;
z.z = sign(z.z) * tempZ.z;
}
aux.DE *= fractal->analyticDE.scale1; // DE tweak
}
/**
* rotation
*/
void TransfRotationIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
Q_UNUSED(aux);
z = fractal->transformCommon.rotationMatrix.RotateVector(z);
}
/**
* rotation folding plane
*/
void TransfRotationFoldingPlaneIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
CVector4 zRot;
// cast vector to array pointer for address taking of components in opencl
double *zRotP = (double *)&zRot;
const double *colP = (const double *)&fractal->mandelbox.color.factor;
for (int dim = 0; dim < 3; dim++)
{
// handle each dimension x, y and z sequentially in pointer var dim
double *rotDim = (dim == 0) ? &zRotP[0] : ((dim == 1) ? &zRotP[1] : &zRotP[2]);
const double *colorFactor = (dim == 0) ? &colP[0] : ((dim == 1) ? &colP[1] : &colP[2]);
zRot = fractal->mandelbox.rot[0][dim].RotateVector(z);
if (*rotDim > fractal->mandelbox.foldingLimit)
{
*rotDim = fractal->mandelbox.foldingValue - *rotDim;
z = fractal->mandelbox.rotinv[0][dim].RotateVector(zRot);
aux.color += *colorFactor;
}
else
{
zRot = fractal->mandelbox.rot[1][dim].RotateVector(z);
if (*rotDim < -fractal->mandelbox.foldingLimit)
{
*rotDim = -fractal->mandelbox.foldingValue - *rotDim;
z = fractal->mandelbox.rotinv[1][dim].RotateVector(zRot);
aux.color += *colorFactor;
}
}
}
}
/**
* Rpow3 from M3D.
* Does a power of 3 on the current length of the vector.
* @reference
* http://www.fractalforums.com/mandelbulb-3d/custom-formulas-and-transforms-release-t17106/
*/
void TransfRpow3Iteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
double sqrRout = z.Dot(z) * fractal->transformCommon.scale;
z *= sqrRout;
aux.DE = aux.DE * fabs(sqrRout) + fractal->analyticDE.offset1;
}
/**
* rotation variation v1. Rotation angles vary linearly between iteration parameters.
*/
void TransfRotationVaryV1Iteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
CVector4 tempVC = CVector4(fractal->transformCommon.rotation, 0.0); // constant to be varied
if (aux.i >= fractal->transformCommon.startIterations250
&& aux.i < fractal->transformCommon.stopIterations
&& (fractal->transformCommon.stopIterations - fractal->transformCommon.startIterations250
!= 0))
{
int iterationRange =
fractal->transformCommon.stopIterations - fractal->transformCommon.startIterations250;
int currentIteration = (aux.i - fractal->transformCommon.startIterations250);
tempVC += fractal->transformCommon.offset000 * (1.0 * currentIteration) / iterationRange;
}
if (aux.i >= fractal->transformCommon.stopIterations)
{
tempVC = (tempVC + fractal->transformCommon.offset000);
}
tempVC *= M_PI_180;
z = z.RotateAroundVectorByAngle(CVector3(1.0, 0.0, 0.0), tempVC.x);
z = z.RotateAroundVectorByAngle(CVector3(0.0, 1.0, 0.0), tempVC.y);
z = z.RotateAroundVectorByAngle(CVector3(0.0, 0.0, 1.0), tempVC.z);
}
/**
* rotatedAbs & Rotated Folding transform from M3D
* - Rotate by the given angles
*- fold
*- RotateBack by the given angles
* @reference
* http://www.fractalforums.com/mandelbulb-3d/custom-formulas-and-transforms-release-t17106/
*/
void TransfRotationFoldingIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
Q_UNUSED(aux);
z = fractal->transformCommon.rotationMatrix.RotateVector(z);
if (fractal->transformCommon.functionEnabled)
{
if (fractal->transformCommon.functionEnabledx)
z.x = fabs(z.x + fractal->transformCommon.offset000.x) - fractal->transformCommon.offset000.x;
if (fractal->transformCommon.functionEnabledy)
z.y = fabs(z.y + fractal->transformCommon.offset000.y) - fractal->transformCommon.offset000.y;
if (fractal->transformCommon.functionEnabledz)
z.z = fabs(z.z + fractal->transformCommon.offset000.z) - fractal->transformCommon.offset000.z;
}
if (fractal->transformCommon.functionEnabledAyFalse)
{
if (fractal->transformCommon.functionEnabledAx)
z.x = fabs(z.x + fractal->transformCommon.offset111.x)
- fabs(z.x - fractal->transformCommon.offset111.x) - z.x;
if (fractal->transformCommon.functionEnabledAy)
z.y = fabs(z.y + fractal->transformCommon.offset111.y)
- fabs(z.y - fractal->transformCommon.offset111.y) - z.y;
if (fractal->transformCommon.functionEnabledAz)
z.z = fabs(z.z + fractal->transformCommon.offset111.z)
- fabs(z.z - fractal->transformCommon.offset111.z) - z.z;
}
if (fractal->transformCommon.functionEnabledAzFalse)
{
if (fractal->transformCommon.functionEnabledBx)
{
if (fabs(z.x) > fractal->mandelbox.foldingLimit)
{
z.x = sign(z.x) * fractal->mandelbox.foldingValue - z.x;
// aux.color += fractal->mandelbox.color.factor.x;
}
}
if (fractal->transformCommon.functionEnabledBy)
{
if (fabs(z.y) > fractal->mandelbox.foldingLimit)
{
z.y = sign(z.y) * fractal->mandelbox.foldingValue - z.y;
// aux.color += fractal->mandelbox.color.factor.y;
}
}
if (fractal->transformCommon.functionEnabledBz)
{
double zLimit = fractal->mandelbox.foldingLimit * fractal->transformCommon.scale1;
double zValue = fractal->mandelbox.foldingValue * fractal->transformCommon.scale1;
if (fabs(z.z) > zLimit)
{
z.z = sign(z.z) * zValue - z.z;
// aux.color += fractal->mandelbox.color.factor.z;
}
}
}
z = fractal->transformCommon.rotationMatrix2.RotateVector(z);
}
/**
* scale - simple scale
*/
void TransfScaleIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
z *= fractal->transformCommon.scale;
if (!fractal->analyticDE.enabledFalse)
aux.DE = aux.DE * fabs(fractal->transformCommon.scale) + 1.0;
else
aux.DE = aux.DE * fabs(fractal->transformCommon.scale) * fractal->analyticDE.scale1
+ fractal->analyticDE.offset1;
}
/**
* scale vary V2.12.- based on DarkBeam's maths
* @reference
* http://www.fractalforums.com/mandelbulb-3d/custom-formulas-and-transforms-release-t17106/
*/
void TransfScaleVaryV212Iteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
if (aux.i >= fractal->transformCommon.startIterations
&& aux.i < fractal->transformCommon.stopIterations)
{
if (fractal->transformCommon.functionEnabledBxFalse)
{
aux.actualScaleA = fabs(aux.actualScaleA);
}
aux.actualScaleA =
fractal->transformCommon.scaleMain2 + fractal->transformCommon.scaleVary0 * aux.actualScaleA;
double temp = aux.actualScaleA;
if (fractal->transformCommon.functionEnabledByFalse) // limits
{
if (aux.actualScaleA < fractal->transformCommon.offset0)
temp = fractal->transformCommon.offset0;
if (aux.actualScaleA > fractal->transformCommon.offset4)
temp = fractal->transformCommon.offset4;
}
z *= temp;
aux.DE = aux.DE * fabs(temp) + 1.0;
}
else if (aux.i < fractal->transformCommon.startIterations)
{
z *= fractal->transformCommon.scaleMain2;
aux.DE = aux.DE * fabs(fractal->transformCommon.scaleMain2 + 1.0);
}
else
{
if (fractal->transformCommon.functionEnabledBzFalse)
{
aux.actualScaleA = fractal->transformCommon.scaleMain2;
}
z *= aux.actualScaleA;
aux.DE = aux.DE * fabs(aux.actualScaleA + 1.0);
}
}
/**
* scale vary multi- based on DarkBeam's maths
* @reference
* http://www.fractalforums.com/mandelbulb-3d/custom-formulas-and-transforms-release-t17106/
*/
void TransfScaleVaryMultiIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
if (aux.i >= fractal->transformCommon.startIterations
&& aux.i < fractal->transformCommon.stopIterations)
{
if (fractal->transformCommon.functionEnabledBxFalse)
{
aux.actualScaleA = fabs(aux.actualScaleA);
}
double base = fractal->transformCommon.scaleMain2;
double vary = (aux.actualScaleA - fractal->transformCommon.offset1);
if (fractal->transformCommon.functionEnabled)
{
aux.actualScaleA = base + fractal->transformCommon.scaleVary0 * vary;
}
else if (fractal->transformCommon.functionEnabledCxFalse)
{
base = aux.actualScaleA;
aux.actualScaleA = base + fractal->transformCommon.scale0 * vary;
}
else if (fractal->transformCommon.functionEnabledCyFalse)
{
double base2 = base
+ fractal->transformCommon.scaleVary0
* (aux.actualScaleA - fractal->transformCommon.offset1);
aux.actualScaleA =
base2
+ fractal->transformCommon.scale0 * (aux.actualScaleA - fractal->transformCommon.offset1);
}
else if (fractal->transformCommon.functionEnabledCzFalse)
{
base = aux.actualScaleA;
double base2 =
base
+ fractal->transformCommon.scale0 * (aux.actualScaleA - fractal->transformCommon.offset1);
aux.actualScaleA = base2
+ fractal->transformCommon.scaleVary0
* (aux.actualScaleA - fractal->transformCommon.offset1);
}
double temp = aux.actualScaleA;
if (fractal->transformCommon.functionEnabledByFalse) // limits
{
if (aux.actualScaleA < fractal->transformCommon.offset0)
temp = fractal->transformCommon.offset0;
if (aux.actualScaleA > fractal->transformCommon.offset4)
temp = fractal->transformCommon.offset4;
}
z *= temp;
aux.DE = aux.DE * fabs(temp) + 1.0;
}
else if (aux.i < fractal->transformCommon.startIterations)
{
z *= fractal->transformCommon.scaleMain2;
aux.DE = aux.DE * fabs(fractal->transformCommon.scaleMain2) + 1.0;
}
else
{
if (fractal->transformCommon.functionEnabledBzFalse)
{
aux.actualScaleA = fractal->transformCommon.scaleMain2;
}
z *= aux.actualScaleA;
aux.DE = aux.DE * fabs(aux.actualScaleA) + 1.0;
}
}
/**
* scale variation v1. Scale varies based on iteration parameters.
*/
void TransfScaleVaryV1Iteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
double tempVC = fractal->transformCommon.scale; // constant to be varied
if (aux.i >= fractal->transformCommon.startIterations250
&& aux.i < fractal->transformCommon.stopIterations
&& (fractal->transformCommon.stopIterations - fractal->transformCommon.startIterations250
!= 0))
{
int iterationRange =
fractal->transformCommon.stopIterations - fractal->transformCommon.startIterations250;
int currentIteration = (aux.i - fractal->transformCommon.startIterations250);
tempVC += fractal->transformCommon.offset0 * (1.0 * currentIteration) / iterationRange;
}
if (aux.i >= fractal->transformCommon.stopIterations)
{
tempVC = (tempVC + fractal->transformCommon.offset0);
}
z *= tempVC;
aux.DE = aux.DE * fabs(tempVC) + 1.0; // prepared for future analytic DE for hybrids
}
/**
* Scale varies smoothly based on iteration parameters.
*/
void TransfScaleVaryVCLIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
double para = 0.0;
if (fractal->Cpara.enabledLinear)
{
para = fractal->Cpara.para0; // parameter value at iter 0
double temp0 = para;
double tempA = fractal->Cpara.paraA;
double tempB = fractal->Cpara.paraB;
double tempC = fractal->Cpara.paraC;
double lengthAB = fractal->Cpara.iterB - fractal->Cpara.iterA;
double lengthBC = fractal->Cpara.iterC - fractal->Cpara.iterB;
double grade1 = (tempA - temp0) / fractal->Cpara.iterA;
double grade2 = (tempB - tempA) / lengthAB;
double grade3 = (tempC - tempB) / lengthBC;
// slopes
if (aux.i < fractal->Cpara.iterA)
{
para = temp0 + (aux.i * grade1);
}
if (aux.i < fractal->Cpara.iterB && aux.i >= fractal->Cpara.iterA)
{
para = tempA + (aux.i - fractal->Cpara.iterA) * grade2;
}
if (aux.i >= fractal->Cpara.iterB)
{
para = tempB + (aux.i - fractal->Cpara.iterB) * grade3;
}
// Curvi part on "true"
if (fractal->Cpara.enabledCurves)
{
double paraAdd = 0.0;
double paraIt;
if (lengthAB > 2.0 * fractal->Cpara.iterA) // stop error, todo fix.
{
double curve1 = (grade2 - grade1) / (4.0 * fractal->Cpara.iterA);
double tempL = lengthAB - fractal->Cpara.iterA;
double curve2 = (grade3 - grade2) / (4.0 * tempL);
if (aux.i < 2 * fractal->Cpara.iterA)
{
paraIt = tempA - fabs(tempA - aux.i);
paraAdd = paraIt * paraIt * curve1;
}
if (aux.i >= 2 * fractal->Cpara.iterA && aux.i < fractal->Cpara.iterB + tempL)
{
paraIt = tempB - fabs(tempB * aux.i);
paraAdd = paraIt * paraIt * curve2;
}
para += paraAdd;
}
}
}
// Parabolic
double paraAddP0 = 0.0;
if (fractal->Cpara.enabledParabFalse)
{ // parabolic = paraOffset + iter *slope + (iter *iter *scale)
paraAddP0 = fractal->Cpara.parabOffset + (aux.i * fractal->Cpara.parabSlope)
+ (aux.i * aux.i * 0.001 * fractal->Cpara.parabScale);
}
para += paraAddP0;
z *= para; // using the parameter
aux.DE = aux.DE * fabs(para) + 1.0;
}
/**
* scale 3d. Scale each axis individually
*/
void TransfScale3dIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
z *= fractal->transformCommon.scale3D111;
aux.DE = aux.DE * z.Length() / aux.r + 1.0;
}
/**
* sin or cos z
*/
void TransfSinOrCosIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
CVector4 oldZ = z;
CVector4 trigZ = CVector4(0.0, 0.0, 0.0, 0.0);
CVector4 scaleZ = z * fractal->transformCommon.constantMultiplierC111;
if (fractal->transformCommon.functionEnabledAx)
{
if (!fractal->transformCommon.functionEnabledAxFalse)
trigZ.x = sin(scaleZ.x);
else
trigZ.x = cos(scaleZ.x); // scale =0, cos = 1
}
if (fractal->transformCommon.functionEnabledAy)
{
if (!fractal->transformCommon.functionEnabledAyFalse)
trigZ.y = sin(scaleZ.y);
else
trigZ.y = cos(scaleZ.y);
}
if (fractal->transformCommon.functionEnabledAz)
{
if (!fractal->transformCommon.functionEnabledAzFalse)
trigZ.z = sin(scaleZ.z);
else
trigZ.z = cos(scaleZ.z);
}
z = trigZ * fractal->transformCommon.scale;
if (fractal->transformCommon.functionEnabledFalse)
{
z.x = z.x * fractal->transformCommon.scale / (fabs(oldZ.x) + 1.0);
z.y = z.y * fractal->transformCommon.scale / (fabs(oldZ.y) + 1.0);
z.z = z.z * fractal->transformCommon.scale / (fabs(oldZ.z) + 1.0);
//aux.DE = aux.DE * z.Length() / oldZ.Length();
}
// if z == oldZ z = oldZ * fractal->transformCommon.scale;
if (!fractal->analyticDE.enabledFalse)
aux.DE = aux.DE * fabs(fractal->transformCommon.scale) + 1.0;
else
aux.DE = aux.DE * fabs(fractal->transformCommon.scale) * fractal->analyticDE.scale1
+ fractal->analyticDE.offset1;
}
/**
* sin and cos
*/
void TransfSinAndCosIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
// Q_UNUSED(aux);
CVector4 oldZ = z;
CVector4 sinZ = CVector4(0.0, 0.0, 0.0, 0.0);
CVector4 cosZ = CVector4(0.0, 0.0, 0.0, 0.0);
CVector4 scaleZ = z * fractal->transformCommon.constantMultiplierC111;
if (fractal->transformCommon.functionEnabledAx) sinZ.x = sin(scaleZ.x); // scale =0, sin = 0
if (fractal->transformCommon.functionEnabledAy) sinZ.y = sin(scaleZ.y);
if (fractal->transformCommon.functionEnabledAz) sinZ.z = sin(scaleZ.z);
if (fractal->transformCommon.functionEnabledAxFalse) cosZ.x = cos(scaleZ.x); // scale =0, cos = 1
if (fractal->transformCommon.functionEnabledAyFalse) cosZ.y = cos(scaleZ.y);
if (fractal->transformCommon.functionEnabledAzFalse) cosZ.z = cos(scaleZ.z);
double postScale = fractal->transformCommon.scale;
if (!fractal->transformCommon.functionEnabledFalse)
z = (sinZ + cosZ) * postScale;
else
{
/*enumMulti_orderOfFolds foldN[5] = {fractal->surfFolds.orderOfFolds1,
fractal->surfFolds.orderOfFolds2, fractal->surfFolds.orderOfFolds3,
fractal->surfFolds.orderOfFolds4, fractal->surfFolds.orderOfFolds5};
for (int f = 0; f < 5; f++)
{
switch (foldN[f])
{
case multi_orderOfFolds_type1:
default:
z = sinZ * cosZ * postScale;
break;
case multi_orderOfFolds_type2:
z = oldZ + (sinZ + cosZ) * postScale;
break;
case multi_orderOfFolds_type3:
z = oldZ + (sinZ * cosZ) * postScale;
break;
case multi_orderOfFolds_type4:
z = oldZ * (sinZ + cosZ) * postScale;
break;
case multi_orderOfFolds_type5:
z = oldZ * (sinZ * cosZ) * postScale;
break;
}
}*/
if (fractal->transformCommon.functionEnabled) z = sinZ * cosZ * postScale;
if (fractal->transformCommon.functionEnabledBxFalse) z = oldZ + (sinZ + cosZ) * postScale;
if (fractal->transformCommon.functionEnabledByFalse) z = oldZ + (sinZ * cosZ) * postScale;
if (fractal->transformCommon.functionEnabledCxFalse) z = oldZ * (sinZ + cosZ) * postScale;
if (fractal->transformCommon.functionEnabledCyFalse) z = oldZ * (sinZ * cosZ) * postScale;
}
if (!fractal->analyticDE.enabledFalse)
aux.DE = aux.DE * fabs(fractal->transformCommon.scale) + 1.0;
else
aux.DE = aux.DE * fabs(fractal->transformCommon.scale) * fractal->analyticDE.scale1
+ fractal->analyticDE.offset1;
}
/**
* max sin - cos
*/
void TransfSinAndCosMaxIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
// Q_UNUSED(aux);
CVector4 sinZ = z * fractal->transformCommon.constantMultiplierA111;
CVector4 cosZ = z * fractal->transformCommon.constantMultiplierB111;
sinZ.x = sin(sinZ.x);
sinZ.y = sin(sinZ.y);
sinZ.z = sin(sinZ.z);
cosZ.x = cos(cosZ.x);
cosZ.y = cos(cosZ.y);
cosZ.z = cos(cosZ.z);
CVector4 sinCosZ = sinZ * cosZ;
CVector4 maxZ = z;
maxZ.x = max(max(sinZ.x, cosZ.x), sinCosZ.x);
maxZ.y = max(max(sinZ.y, cosZ.y), sinCosZ.y);
maxZ.z = max(max(sinZ.z, cosZ.z), sinCosZ.z);
if (!fractal->transformCommon.functionEnabledFalse)
{
z = maxZ * fractal->transformCommon.scale;
}
else
{
if (fractal->transformCommon.functionEnabled)
{
z += maxZ * fractal->transformCommon.scale;
}
else
{
//z = maxZ * fractal->transformCommon.scale / (fabs(z) + 1.0);
z.x = maxZ.x * fractal->transformCommon.scale / (fabs(z.x) + 1.0);
z.y = maxZ.y * fractal->transformCommon.scale / (fabs(z.y) + 1.0);
z.z = maxZ.z * fractal->transformCommon.scale / (fabs(z.z) + 1.0);
}
}
if (fractal->analyticDE.enabled) // temp
{
if (!fractal->analyticDE.enabledFalse)
aux.DE = aux.DE * fabs(fractal->transformCommon.scale) + 1.0;
else
aux.DE = aux.DE * fabs(fractal->transformCommon.scale) * fractal->analyticDE.scale1
+ fractal->analyticDE.offset1;
}
}
/**
* spherical invert (modes updated v2.15)
* from M3D. Formula by Luca GN 2011, updated May 2012.
* @reference
* http://www.fractalforums.com/mandelbulb-3d/custom-formulas-and-transforms-release-t17106/
*/
void TransfSphericalInvIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
z += fractal->mandelbox.offset;
z *= fractal->transformCommon.scale;
aux.DE = aux.DE * fabs(fractal->transformCommon.scale) + 1.0;
if (!fractal->transformCommon.functionEnabledzFalse)
{
double r2Inv = 1.0 / z.Dot(z);
z *= r2Inv;
aux.DE *= r2Inv;
}
else // conditional
{
double rr = z.Dot(z);
if (rr < fractal->mandelbox.foldingSphericalFixed)
{
double mode = 0.0;
if (fractal->transformCommon.functionEnabledFalse) // Mode 1 minR0
{
if ( rr < fractal->transformCommon. minR0)
mode = fractal->transformCommon. minR0;
}
if (fractal->transformCommon.functionEnabledxFalse) // Mode 2
{
if ( rr < fractal->transformCommon. minR0)
mode = 2.0 * fractal->transformCommon. minR0 - rr;
}
mode = 1.0 / mode;
z *= mode;
aux.DE *= fabs(mode);
}
}
z -= fractal->mandelbox.offset + fractal->transformCommon.additionConstant000;
if (fractal->analyticDE.enabledFalse)
{
aux.DE = aux.DE * fractal->analyticDE.scale1 + fractal->analyticDE.offset0;
}
}
/**
* inverted sphere z & c- A transform from M3D
* @reference
* http://www.fractalforums.com/mandelbulb-3d/custom-formulas-and-transforms-release-t17106/
* updated v2.12
*/
void TransfSphericalInvCIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
double rSqrL;
CVector4 tempC;
if (fractal->transformCommon.functionEnabledFalse)
{
tempC = aux.c;
// tempC *= fractal->transformCommon.constantMultiplier111;
rSqrL = tempC.Dot(tempC);
// if (rSqrL < 1e-21) rSqrL = 1e-21;
rSqrL = 1.0 / rSqrL;
tempC *= rSqrL;
aux.c = tempC;
tempC *= fractal->transformCommon.constantMultiplier111;
}
else
{
tempC = aux.const_c;
tempC *= fractal->transformCommon.constantMultiplier111;
rSqrL = tempC.Dot(tempC);
// if (rSqrL < 1e-21) rSqrL = 1e-21;
rSqrL = 1.0 / rSqrL;
tempC *= rSqrL;
}
if (fractal->transformCommon.functionEnabledAwFalse)
{
rSqrL = z.Dot(z);
// if (rSqrL < 1e-21) rSqrL = 1e-21;
rSqrL = 1.0 / rSqrL;
z *= rSqrL;
aux.DE *= rSqrL;
z += tempC;
}
z += tempC; //* fractal->transformCommon.constantMultiplier111;
}
/**
* spherical fold MBox
* This formula contains aux.color
*/
void TransfSphericalFoldIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
double r2 = z.Dot(z);
z += fractal->mandelbox.offset;
z *= fractal->transformCommon.scale; // beta
aux.DE = aux.DE * fabs(fractal->transformCommon.scale) + 1.0; // beta
// if (r2 < 1e-21) r2 = 1e-21;
if (r2 < fractal->mandelbox.mR2)
{
z *= fractal->mandelbox.mboxFactor1;
aux.DE *= fractal->mandelbox.mboxFactor1;
if (fractal->foldColor.auxColorEnabledFalse)
{
aux.color += fractal->mandelbox.color.factorSp1;
}
}
else if (r2 < fractal->mandelbox.fR2)
{
double tglad_factor2 = fractal->mandelbox.fR2 / r2;
z *= tglad_factor2;
aux.DE *= tglad_factor2;
if (fractal->foldColor.auxColorEnabledFalse)
{
aux.color += fractal->mandelbox.color.factorSp2;
}
}
z -= fractal->mandelbox.offset;
}
/**
* spherical fold ABox
* from Fractal Forums and M3D
* @reference
* http://www.fractalforums.com/mandelbulb-3d/custom-formulas-and-transforms-release-t17106/
* This formula contains aux.color
*/
void TransfSphericalFoldAboxIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
double r2 = z.Dot(z);
z += fractal->mandelbox.offset;
double sqrtMinR = fractal->transformCommon.sqtR;
if (r2 < sqrtMinR)
{
z *= fractal->transformCommon.mboxFactor1;
aux.DE *= fractal->transformCommon.mboxFactor1;
if (fractal->foldColor.auxColorEnabledFalse)
{
aux.color += fractal->mandelbox.color.factorSp1;
}
}
else if (r2 < 1.0)
{
z *= 1.0 / r2;
aux.DE *= 1.0 / r2;
if (fractal->foldColor.auxColorEnabledFalse)
{
aux.color += fractal->mandelbox.color.factorSp2;
}
}
z -= fractal->mandelbox.offset;
}
/**
* spherical fold varyV1 MBox type
* This formula contains aux.color
*/
void TransfSphericalFoldVaryV1Iteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
double r2 = z.Dot(z);
double tempVCf = fractal->mandelbox.foldingSphericalFixed; // constant to be varied
double tempVCm = fractal->mandelbox.foldingSphericalMin;
if (aux.i >= fractal->transformCommon.startIterationsA
&& aux.i < fractal->transformCommon.stopIterationsA)
{
int iterationRange =
fractal->transformCommon.stopIterationsA - fractal->transformCommon.startIterationsA;
int currentIteration = (aux.i - fractal->transformCommon.startIterationsA);
tempVCf += fractal->transformCommon.offset * (1.0 * currentIteration) / iterationRange;
}
if (aux.i >= fractal->transformCommon.stopIterationsA)
{
tempVCf = (tempVCf + fractal->transformCommon.offset);
}
if (aux.i >= fractal->transformCommon.startIterationsB
&& aux.i < fractal->transformCommon.stopIterationsB)
{
int iterationRange =
fractal->transformCommon.stopIterationsB - fractal->transformCommon.startIterationsB;
int currentIteration = (aux.i - fractal->transformCommon.startIterationsB);
tempVCm += fractal->transformCommon.offset0 * (1.0 * currentIteration) / iterationRange;
}
if (aux.i >= fractal->transformCommon.stopIterationsB)
{
tempVCm = tempVCm + fractal->transformCommon.offset0;
}
z += fractal->mandelbox.offset;
tempVCm *= tempVCm;
tempVCf *= tempVCf;
if (r2 < tempVCm)
{
z *= tempVCf / tempVCm;
aux.DE *= tempVCf / tempVCm;
if (fractal->foldColor.auxColorEnabledFalse)
{
aux.color += fractal->mandelbox.color.factorSp1;
}
}
else if (r2 < tempVCf)
{
double tglad_factor2 = tempVCf / r2;
z *= tglad_factor2;
aux.DE *= tglad_factor2;
if (fractal->foldColor.auxColorEnabledFalse)
{
aux.color += fractal->mandelbox.color.factorSp2;
}
}
z -= fractal->mandelbox.offset;
}
/**
* spherical fold Parab, coded by mclarekin
* @reference
* http://www.fractalforums.com/amazing-box-amazing-surf-and-variations/smooth-spherical-fold/msg101051/#new
* This formula contains aux.color and aux.actualScaleA
*/
void TransfSphericalFoldParabIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
double m = 1.0;
double rr;
// spherical fold
if (fractal->transformCommon.functionEnabledSFalse
&& aux.i >= fractal->transformCommon.startIterationsS
&& aux.i < fractal->transformCommon.stopIterationsS)
{
rr = z.Dot(z);
double tempM = rr;
m = fractal->transformCommon.maxMinR2factor;
// if (r2 < 1e-21) r2 = 1e-21;
if (rr < fractal->transformCommon.minR2p25)
{
if (fractal->transformCommon.functionEnabledAyFalse && m > tempM) m = tempM + (tempM - m);
z *= m;
aux.DE = aux.DE * m;
if (fractal->foldColor.auxColorEnabledFalse)
{
aux.color += fractal->mandelbox.color.factorSp1;
}
}
else if (rr < fractal->transformCommon.maxR2d1)
{
m = fractal->transformCommon.maxR2d1 / rr;
if (fractal->transformCommon.functionEnabledAyFalse && m > tempM) m = tempM + (tempM - m);
z *= m;
aux.DE = aux.DE * m;
if (fractal->foldColor.auxColorEnabledFalse)
{
aux.color += fractal->mandelbox.color.factorSp2;
}
}
}
if (aux.i >= fractal->transformCommon.startIterations
&& aux.i < fractal->transformCommon.stopIterations)
{
rr = z.Dot(z);
z += fractal->mandelbox.offset;
z *= fractal->transformCommon.scale;
aux.DE = aux.DE * fabs(fractal->transformCommon.scale) + 1.0;
double maxScale = fractal->transformCommon.scale4;
double midPoint = (maxScale - 1.0) * 0.5;
rr += fractal->transformCommon.offset0;
double maxR2 = fractal->transformCommon.scale1;
double halfMax = maxR2 * 0.5;
double factor = midPoint / (halfMax * halfMax);
double tempM = rr + fractal->transformCommon.offsetA0;
if (rr < halfMax)
{
m = maxScale - (rr * rr) * factor;
if (fractal->transformCommon.functionEnabledAxFalse && m > tempM) m = tempM + (tempM - m);
z *= m;
aux.DE = aux.DE * m;
if (fractal->foldColor.auxColorEnabledFalse)
{
aux.color += fractal->mandelbox.color.factorSp1;
}
}
else if (rr < maxR2)
{
m = 1.0 + (maxR2 - rr) * (maxR2 - rr) * factor;
if (fractal->transformCommon.functionEnabledAxFalse && m > tempM) m = tempM + (tempM - m);
z *= m;
aux.DE = aux.DE * m;
if (fractal->foldColor.auxColorEnabledFalse)
{
aux.color += fractal->mandelbox.color.factorSp2;
}
z -= fractal->mandelbox.offset;
}
}
double useScale = fractal->transformCommon.scaleA1;
if (fractal->transformCommon.functionEnabledXFalse
&& aux.i >= fractal->transformCommon.startIterationsA
&& aux.i < fractal->transformCommon.stopIterationsA)
{
useScale += aux.actualScaleA;
z *= useScale;
aux.DE = aux.DE * fabs(useScale) * fractal->analyticDE.scale1 + fractal->analyticDE.offset1;
// update actualScale for next iteration
double vary = fractal->transformCommon.scaleVary0
* (fabs(aux.actualScaleA) - fractal->transformCommon.scaleB1);
if (fractal->transformCommon.functionEnabledMFalse)
aux.actualScaleA = -vary;
else
aux.actualScaleA = aux.actualScaleA - vary;
}
else
{
z *= useScale;
aux.DE = aux.DE * fabs(useScale) * fractal->analyticDE.scale1 + fractal->analyticDE.offset1;
}
}
/**
* spherical fold Cuboid
* This has a box shape MinR2 condition
* This formula contains aux.color
*/
void TransfSphericalFoldCuboidIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
CVector4 temp3;
CVector4 R2;
double minR2 = fractal->transformCommon.minR2p25;
CVector4 limitMinR2 = fractal->transformCommon.scaleP222;
double m = fractal->transformCommon.scale;
double rr = z.Dot(z);
z += fractal->transformCommon.offset000;
if (aux.i >= fractal->transformCommon.startIterationsA
&& aux.i < fractal->transformCommon.stopIterationsA)
{
if (fractal->transformCommon.functionEnabledAxFalse)
temp3 = z * z;
else
temp3 = fabs(z);
if (temp3.x < limitMinR2.x && temp3.y < limitMinR2.y && temp3.z < limitMinR2.z)
{ // if inside cuboid
R2.x = limitMinR2.x / temp3.x;
R2.y = limitMinR2.y / temp3.y;
R2.z = limitMinR2.z / temp3.z;
double First = min(R2.x, min(R2.y, R2.z));
minR2 = rr * First;
if (fractal->transformCommon.functionEnabled && minR2 > fractal->transformCommon.maxR2d1)
{ // stop overlapping potential
minR2 = fractal->transformCommon.maxR2d1;
}
m *= fractal->transformCommon.maxR2d1 / minR2;
if (fractal->foldColor.auxColorEnabledFalse)
{
aux.color += fractal->mandelbox.color.factorSp1;
}
}
else if (rr < fractal->transformCommon.maxR2d1)
{
m *= fractal->transformCommon.maxR2d1 / rr;
if (fractal->foldColor.auxColorEnabledFalse)
{
aux.color += fractal->mandelbox.color.factorSp2;
}
}
}
else if (rr < minR2)
{
m *= fractal->transformCommon.maxR2d1 / minR2;
if (fractal->foldColor.auxColorEnabledFalse)
{
aux.color += fractal->mandelbox.color.factorSp1;
}
}
else if (rr < fractal->transformCommon.maxR2d1)
{
m *= fractal->transformCommon.maxR2d1 / rr;
if (fractal->foldColor.auxColorEnabledFalse)
{
aux.color += fractal->mandelbox.color.factorSp2;
}
}
z -= fractal->transformCommon.offset000;
// scale
z *= m;
aux.DE = aux.DE * fabs(m) + 1.0;
}
/**
* spherical fold CHS Cylinder Half Size. DarkBeam s code from M3D
* @reference
* http://www.fractalforums.com/mandelbulb-3d/custom-formulas-and-transforms-release-t17106/
* This formula contains aux.color
*/
void TransfSphericalFoldCHSIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
double tempZ = fabs(z.z) - fractal->transformCommon.offset05;
double rr;
if (aux.i >= fractal->transformCommon.startIterations
&& aux.i < fractal->transformCommon.stopIterations)
{
rr = z.x * z.x + z.y * z.y;
if (tempZ > 0.0) rr = rr + (tempZ * tempZ * fractal->transformCommon.scale1);
}
else
{
rr = z.Dot(z);
}
z += fractal->mandelbox.offset;
z *= fractal->transformCommon.scale;
aux.DE = aux.DE * fabs(fractal->transformCommon.scale) + 1.0;
// Spherical Fold
if (rr < fractal->transformCommon.minR2p25)
{
z *= fractal->transformCommon.maxMinR2factor;
aux.DE *= fractal->transformCommon.maxMinR2factor;
if (fractal->foldColor.auxColorEnabledFalse)
{
aux.color += fractal->mandelbox.color.factorSp1;
}
}
else if (rr < fractal->transformCommon.maxR2d1)
{
double tglad_factor2 = fractal->transformCommon.maxR2d1 / rr;
z *= tglad_factor2;
aux.DE *= tglad_factor2;
if (fractal->foldColor.auxColorEnabledFalse)
{
aux.color += fractal->mandelbox.color.factorSp2;
}
}
z -= fractal->mandelbox.offset;
}
/**
* spherical fold varyVCL MBox type
* This formula contains aux.color
*/
void TransfSphericalFoldVaryVCLIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
double para = 0.0;
if (fractal->Cpara.enabledLinear)
{
para = fractal->Cpara.para00; // parameter value at iter 0
double temp0 = para;
double tempA = fractal->Cpara.paraA;
double tempB = fractal->Cpara.paraB;
double tempC = fractal->Cpara.paraC;
double lengthAB = fractal->Cpara.iterB - fractal->Cpara.iterA;
double lengthBC = fractal->Cpara.iterC - fractal->Cpara.iterB;
double grade1 = (tempA - temp0) / fractal->Cpara.iterA;
double grade2 = (tempB - tempA) / lengthAB;
double grade3 = (tempC - tempB) / lengthBC;
// slopes
if (aux.i < fractal->Cpara.iterA)
{
para = temp0 + (aux.i * grade1);
}
if (aux.i < fractal->Cpara.iterB && aux.i >= fractal->Cpara.iterA)
{
para = tempA + (aux.i - fractal->Cpara.iterA) * grade2;
}
if (aux.i >= fractal->Cpara.iterB)
{
para = tempB + (aux.i - fractal->Cpara.iterB) * grade3;
}
// Curvi part on "true"
if (fractal->Cpara.enabledCurves)
{
double paraAdd = 0.0;
double paraIt;
if (lengthAB > 2.0 * fractal->Cpara.iterA) // stop error, todo fix.
{
double curve1 = (grade2 - grade1) / (4.0 * fractal->Cpara.iterA);
double tempL = lengthAB - fractal->Cpara.iterA;
double curve2 = (grade3 - grade2) / (4.0 * tempL);
if (aux.i < 2 * fractal->Cpara.iterA)
{
paraIt = tempA - fabs(tempA - aux.i);
paraAdd = paraIt * paraIt * curve1;
}
if (aux.i >= 2 * fractal->Cpara.iterA && aux.i < fractal->Cpara.iterB + tempL)
{
paraIt = tempB - fabs(tempB * aux.i);
paraAdd = paraIt * paraIt * curve2;
}
para += paraAdd;
}
}
}
double paraAddP0 = 0.0;
if (fractal->Cpara.enabledParabFalse)
{ // parabolic = paraOffset + iter *slope + (iter *iter *scale)
paraAddP0 = fractal->Cpara.parabOffset0 + (aux.i * fractal->Cpara.parabSlope)
+ (aux.i * aux.i * 0.001 * fractal->Cpara.parabScale);
}
para += paraAddP0 + fractal->transformCommon.minR2p25;
// spherical fold
double r2 = z.Dot(z);
z += fractal->mandelbox.offset;
// if (r2 < 1e-21) r2 = 1e-21;
if (r2 < para)
{
z *= fractal->transformCommon.maxR2d1 / para;
aux.DE *= fractal->transformCommon.maxR2d1 / para;
if (fractal->foldColor.auxColorEnabledFalse)
{
aux.color += fractal->mandelbox.color.factorSp1;
}
}
else if (r2 < fractal->mandelbox.fR2)
{
double tglad_factor2 = fractal->transformCommon.maxR2d1 / r2;
z *= tglad_factor2;
aux.DE *= tglad_factor2;
if (fractal->foldColor.auxColorEnabledFalse)
{
aux.color += fractal->mandelbox.color.factorSp2;
}
}
z -= fractal->mandelbox.offset;
z *= fractal->transformCommon.scale;
aux.DE = aux.DE * fabs(fractal->transformCommon.scale);
}
/**
* spherical fold XYZ Bias
* deforms the MinR2 condition
* This formula contains aux.color
*/
void TransfSphericalFoldXYZBiasIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
CVector4 xyzBias;
double minR2 = fractal->transformCommon.minR2p25;
double MaxR2 = fractal->transformCommon.maxR2d1;
double m = fractal->transformCommon.scale;
if (aux.i >= fractal->transformCommon.startIterationsA
&& aux.i < fractal->transformCommon.stopIterationsA)
{
xyzBias = fabs(aux.c) * fractal->transformCommon.constantMultiplier000;
minR2 = minR2 + (xyzBias.x + xyzBias.y + xyzBias.z);
}
if (fractal->transformCommon.functionEnabledFalse
&& aux.i >= fractal->transformCommon.startIterationsB
&& aux.i < fractal->transformCommon.stopIterationsB)
{
CVector4 cSquared = aux.c * aux.c;
xyzBias = cSquared * fractal->transformCommon.scale3D000;
minR2 = minR2 + (xyzBias.x + xyzBias.y + xyzBias.z);
}
if (fractal->transformCommon.functionEnabled && minR2 > MaxR2)
{
minR2 = MaxR2; // stop overlapping potential
}
double rr = z.Dot(z);
z += fractal->transformCommon.offset000;
if (rr < minR2)
{
m *= fractal->transformCommon.maxR2d1 / minR2;
aux.color += fractal->mandelbox.color.factorSp1;
}
else if (rr < fractal->transformCommon.maxR2d1)
{
m *= fractal->transformCommon.maxR2d1 / rr;
aux.color += fractal->mandelbox.color.factorSp2;
}
z -= fractal->transformCommon.offset000;
z *= m;
aux.DE = aux.DE * fabs(m) + 1.0;
}
/**
* spherical radial offset.
* This formula contains analytic aux.DE and aux.r-dz
*/
void TransfSphericalOffsetIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
// if (-z.Length() > -1e-21) -z.Length() = -1e-21; // z is neg.)
z *= 1.0 + fractal->transformCommon.offset / -z.Length();
z *= fractal->transformCommon.scale;
aux.DE = aux.DE * fractal->transformCommon.scale + fractal->analyticDE.offset1;
}
/**
* spherical radial offset Curvilinear.
* This formula contains analytic aux.DE and aux.r-dz
*/
void TransfSphericalOffsetVCLIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
double para = fractal->Cpara.para00;
double paraAdd = 0.0;
double paraAddP0 = 0.0;
// curvilinear mode
if (fractal->transformCommon.functionEnabled)
{
if (fractal->Cpara.enabledLinear)
{
para = fractal->Cpara.para00; // parameter value at iter 0
double temp0 = para;
double tempA = fractal->Cpara.paraA0;
double tempB = fractal->Cpara.paraB0;
double tempC = fractal->Cpara.paraC0;
double lengthAB = fractal->Cpara.iterB - fractal->Cpara.iterA;
double lengthBC = fractal->Cpara.iterC - fractal->Cpara.iterB;
double grade1 = (tempA - temp0) / fractal->Cpara.iterA;
double grade2 = (tempB - tempA) / lengthAB;
double grade3 = (tempC - tempB) / lengthBC;
// slopes
if (aux.i < fractal->Cpara.iterA)
{
para = temp0 + (aux.i * grade1);
}
if (aux.i < fractal->Cpara.iterB && aux.i >= fractal->Cpara.iterA)
{
para = tempA + (aux.i - fractal->Cpara.iterA) * grade2;
}
if (aux.i >= fractal->Cpara.iterB)
{
para = tempB + (aux.i - fractal->Cpara.iterB) * grade3;
}
// Curvi part on "true"
if (fractal->Cpara.enabledCurves)
{
double paraIt;
if (lengthAB > 2.0 * fractal->Cpara.iterA) // stop error, todo fix.
{
double curve1 = (grade2 - grade1) / (4.0 * fractal->Cpara.iterA);
double tempL = lengthAB - fractal->Cpara.iterA;
double curve2 = (grade3 - grade2) / (4.0 * tempL);
if (aux.i < 2 * fractal->Cpara.iterA)
{
paraIt = tempA - fabs(tempA - aux.i);
paraAdd = paraIt * paraIt * curve1;
}
if (aux.i >= 2 * fractal->Cpara.iterA && aux.i < fractal->Cpara.iterB + tempL)
{
paraIt = tempB - fabs(tempB * aux.i);
paraAdd = paraIt * paraIt * curve2;
}
}
para += paraAdd;
}
}
}
// Parabolic
if (fractal->Cpara.enabledParabFalse)
{ // parabolic = paraOffset + iter *slope + (iter *iter *scale)
paraAddP0 = fractal->Cpara.parabOffset0 + (aux.i * fractal->Cpara.parabSlope)
+ (aux.i * aux.i * 0.001 * fractal->Cpara.parabScale);
para += paraAddP0;
}
// para offset
para += fractal->transformCommon.offset0;
double div = 0.0;
// dot mode
if (fractal->transformCommon.functionEnabledFalse)
{
div = z.Dot(z);
}
else
{
div = z.Length();
}
// using the parameter
z *= 1.0 + para / -div;
// post scale
z *= fractal->transformCommon.scale;
aux.DE = aux.DE * fractal->transformCommon.scale + 1.0;
// DE tweak
aux.DE = aux.DE * fractal->analyticDE.scale1 + fractal->analyticDE.offset0;
}
/**
* spherical pwr fold
* This formula contains aux.color and analytic aux.DE
*/
void TransfSphericalPwrFoldIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
// if (z.x > -1e-21 && z.x < 1e-21) z.x = (z.x > 0) ? 1e-21 : -1e-21;
// if (z.y > -1e-21 && z.y < 1e-21) z.y = (z.y > 0) ? 1e-21 : -1e-21;
// if (z.z > -1e-21 && z.z < 1e-21) z.z = (z.z > 0) ? 1e-21 : -1e-21;
double rr = pow(pow(z.x, fractal->transformCommon.pwr4) + pow(z.y, fractal->transformCommon.pwr4)
+ pow(z.z, fractal->transformCommon.pwr4),
fractal->transformCommon.pwr05);
// if (rr < 1e-21 && rr > -1e-21)
// rr = (rr > 0) ? 1e-21 : -1e-21;
if (rr < fractal->mandelbox.mR2)
{
z *= fractal->mandelbox.mboxFactor1;
aux.DE *= fractal->mandelbox.mboxFactor1;
if (fractal->foldColor.auxColorEnabledFalse)
{
aux.color += fractal->mandelbox.color.factorSp1;
}
}
else if (rr < fractal->mandelbox.fR2)
{
double tglad_factor2 = fractal->mandelbox.fR2 / rr;
z *= tglad_factor2;
aux.DE *= tglad_factor2;
if (fractal->foldColor.auxColorEnabledFalse)
{
aux.color += fractal->mandelbox.color.factorSp2;
}
}
}
/**
* Surf Box Fold
* allows different fold types for each axis.
* amazing surface if one axis has no folds enabled.
* made from various folds found in the posts at fractalforums.com
* This formula contains aux.color, analytic aux.DE and aux.r-dz
*/
void TransfSurfBoxFoldIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
if (fractal->surfBox.enabledX1)
{
z.x =
fabs(z.x + fractal->surfBox.offset1A111.x) - fabs(z.x - fractal->surfBox.offset1A111.x) - z.x;
}
if (fractal->surfBox.enabledX2False)
{ // z = fold - fabs( fabs(z) - fold), Tglad fold
z.x = fractal->surfBox.offset1B111.x - fabs(fabs(z.x) - fractal->surfBox.offset1B111.x);
}
if (fractal->surfBox.enabledX3False)
{
z.x = fabs(z.x + fractal->surfBox.offset2A111.x);
}
if (fractal->surfBox.enabledX4False)
{ // if z > limit) z = Value -z, else if z < limit) z = - Value - z,
if (z.x > fractal->surfBox.offset2B111.x)
{
z.x = fractal->surfBox.offset1A222.x - z.x;
aux.color += fractal->mandelbox.color.factor.x;
}
else if (z.x < -fractal->surfBox.offset2B111.x)
{
z.x = -fractal->surfBox.offset1A222.x - z.x;
aux.color += fractal->mandelbox.color.factor.x;
}
}
if (fractal->surfBox.enabledX5False)
{ // z = fold2 - fabs( fabs(z + fold) - fold2) - fabs(fold)
z.x = fractal->surfBox.offset1B222.x
- fabs(fabs(z.x + fractal->surfBox.offset3A111.x) - fractal->surfBox.offset1B222.x)
- fractal->surfBox.offset3A111.x;
}
if (fractal->surfBox.enabledY1)
{
z.y =
fabs(z.y + fractal->surfBox.offset1A111.y) - fabs(z.y - fractal->surfBox.offset1A111.y) - z.y;
}
if (fractal->surfBox.enabledY2False)
{ // z = fold - fabs( fabs(z) - fold)
z.y = fractal->surfBox.offset1B111.y - fabs(fabs(z.y) - fractal->surfBox.offset1B111.y);
}
if (fractal->surfBox.enabledY3False)
{
z.y = fabs(z.y + fractal->surfBox.offset2A111.y);
}
if (fractal->surfBox.enabledY4False)
{ // if z > limit) z = Value -z, else if z < limit) z = - Value - z,
if (z.y > fractal->surfBox.offset2B111.y)
{
z.y = fractal->surfBox.offset1A222.y - z.y;
aux.color += fractal->mandelbox.color.factor.y;
}
else if (z.y < -fractal->surfBox.offset2B111.y)
{
z.y = -fractal->surfBox.offset1A222.y - z.y;
aux.color += fractal->mandelbox.color.factor.y;
}
}
if (fractal->surfBox.enabledY5False)
{ // z = fold2 - fabs( fabs(z + fold) - fold2) - fabs(fold)
z.y = fractal->surfBox.offset1B222.y
- fabs(fabs(z.y + fractal->surfBox.offset3A111.y) - fractal->surfBox.offset1B222.y)
- fractal->surfBox.offset3A111.y;
}
if (fractal->surfBox.enabledZ1)
{
z.z =
fabs(z.z + fractal->surfBox.offset1A111.z) - fabs(z.z - fractal->surfBox.offset1A111.z) - z.z;
}
if (fractal->surfBox.enabledZ2False)
{ // z = fold - fabs( fabs(z) - fold)
z.z = fractal->surfBox.offset1B111.z - fabs(fabs(z.z) - fractal->surfBox.offset1B111.z);
}
if (fractal->surfBox.enabledZ3False)
{
z.z = fabs(z.z + fractal->surfBox.offset2A111.z);
}
if (fractal->surfBox.enabledZ4False)
{ // if z > limit) z = Value -z, else if z < limit) z = - Value - z,
double limit = fractal->surfBox.offset2B111.z;
double value = fractal->surfBox.offset1A222.z;
double zLimit = limit * fractal->surfBox.scale1Z1;
double zValue = value * fractal->surfBox.scale1Z1;
if (z.z > zLimit)
{
z.z = zValue - z.z;
aux.color += fractal->mandelbox.color.factor.z;
}
else if (z.z < -zLimit)
{
z.z = -zValue - z.z;
aux.color += fractal->mandelbox.color.factor.z;
}
}
if (fractal->surfBox.enabledZ5False)
{ // z = fold2 - fabs( fabs(z + fold) - fold2) - fabs(fold)// DarkBeam's Abox mod1 fold
z.z = fractal->surfBox.offset1B222.z
- fabs(fabs(z.z + fractal->surfBox.offset3A111.z) - fractal->surfBox.offset1B222.z)
- fractal->surfBox.offset3A111.z;
}
aux.DE = aux.DE * fractal->analyticDE.scale1 + fractal->analyticDE.offset0; // tweak
}
/**
* TransfSurfFoldMultiIteration
* Based on amazing_surf_mod1 from Mandelbulb3D
* This formula contains aux.color, analytic aux.DE and aux.r-dz
*/
void TransfSurfFoldMultiIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
if (fractal->transformCommon.functionEnabledAx)
{
z.x = fabs(z.x + fractal->transformCommon.additionConstant111.x)
- fabs(z.x - fractal->transformCommon.additionConstant111.x) - z.x;
z.y = fabs(z.y + fractal->transformCommon.additionConstant111.y)
- fabs(z.y - fractal->transformCommon.additionConstant111.y) - z.y;
}
if (fractal->transformCommon.functionEnabledAyFalse)
{ // z = fold - fabs( fabs(z) - fold)
z.x = fractal->transformCommon.additionConstant111.x
- fabs(fabs(z.x) - fractal->transformCommon.additionConstant111.x);
z.y = fractal->transformCommon.additionConstant111.y
- fabs(fabs(z.y) - fractal->transformCommon.additionConstant111.y);
}
if (fractal->transformCommon.functionEnabledAzFalse)
{
z.x = fabs(z.x + fractal->transformCommon.additionConstant111.x);
z.y = fabs(z.y + fractal->transformCommon.additionConstant111.y);
}
if (fractal->transformCommon.functionEnabledxFalse)
{ // if z > limit) z = Value -z, else if z < limit) z = - Value - z,
if (z.x > fractal->transformCommon.additionConstant111.x)
{
z.x = fractal->mandelbox.foldingValue - z.x;
aux.color += fractal->mandelbox.color.factor.x;
}
else if (z.x < -fractal->transformCommon.additionConstant111.x)
{
z.x = -fractal->mandelbox.foldingValue - z.x;
aux.color += fractal->mandelbox.color.factor.x;
}
if (z.y > fractal->transformCommon.additionConstant111.y)
{
z.y = fractal->mandelbox.foldingValue - z.y;
aux.color += fractal->mandelbox.color.factor.y;
}
else if (z.y < -fractal->transformCommon.additionConstant111.y)
{
z.y = -fractal->mandelbox.foldingValue - z.y;
aux.color += fractal->mandelbox.color.factor.y;
}
}
if (fractal->transformCommon.functionEnabledyFalse)
{ // z = fold2 - fabs( fabs(z + fold) - fold2) - fabs(fold)
z.x = fractal->transformCommon.offset2
- fabs(fabs(z.x + fractal->transformCommon.additionConstant111.x)
- fractal->transformCommon.offset2)
- fractal->transformCommon.additionConstant111.x;
z.y = fractal->transformCommon.offset2
- fabs(fabs(z.y + fractal->transformCommon.additionConstant111.y)
- fractal->transformCommon.offset2)
- fractal->transformCommon.additionConstant111.y;
}
aux.DE = aux.DE * fractal->analyticDE.scale1 + fractal->analyticDE.offset0; // tweak
}
/**
* z vector - axis swap
* @reference
* http://www.fractalforums.com/mandelbulb-3d/custom-formulas-and-transforms-release-t17106/
*/
void TransfZvectorAxisSwapIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
switch (fractal->mandelbulbMulti.orderOfXYZ)
{
case multi_OrderOfXYZ_xyz:
default: z = CVector4(z.x, z.y, z.z, z.w); break;
case multi_OrderOfXYZ_xzy: z = CVector4(z.x, z.z, z.y, z.w); break;
case multi_OrderOfXYZ_yxz: z = CVector4(z.y, z.x, z.z, z.w); break;
case multi_OrderOfXYZ_yzx: z = CVector4(z.y, z.z, z.x, z.w); break;
case multi_OrderOfXYZ_zxy: z = CVector4(z.z, z.x, z.y, z.w); break;
case multi_OrderOfXYZ_zyx: z = CVector4(z.z, z.y, z.x, z.w); break;
}
if (fractal->transformCommon.functionEnabledxFalse) z.x = -z.x;
if (fractal->transformCommon.functionEnabledyFalse) z.y = -z.y;
if (fractal->transformCommon.functionEnabledzFalse) z.z = -z.z;
if (fractal->transformCommon.functionEnabledFalse
&& aux.i >= fractal->transformCommon.startIterations
&& aux.i < fractal->transformCommon.stopIterations)
{
double xTemp = SQRT_1_2 * (z.x - z.y);
z.y = SQRT_1_2 * (z.y + z.x);
z.x = xTemp;
}
}
//-------------------------------- 4D ----------------------------------------------
/**
* Formula based on Mandelbox (ABox). Extended to 4 dimensions
* This formula contains aux.color and aux.actualScale
*/
void Abox4dIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
double colorAdd = 0.0;
double rrCol = 0.0;
CVector4 zCol = z;
aux.actualScale =
fractal->mandelbox.scale + fractal->mandelboxVary4D.scaleVary * (fabs(aux.actualScale) - 1.0);
// parabolic = paraOffset + iter *slope + (iter *iter *scale)
double paraAddP0 = 0.0;
if (fractal->Cpara.enabledParabFalse)
{
double parabScale = 0.0;
if (fractal->Cpara.parabScale != 0.0)
parabScale = aux.i * aux.i * 0.001 * fractal->Cpara.parabScale;
paraAddP0 = fractal->Cpara.parabOffset0 + (aux.i * fractal->Cpara.parabSlope) + (parabScale);
z.w += paraAddP0;
}
CVector4 oldZ = z;
z.x = fabs(z.x + fractal->transformCommon.offset1111.x)
- fabs(z.x - fractal->transformCommon.offset1111.x) - z.x;
z.y = fabs(z.y + fractal->transformCommon.offset1111.y)
- fabs(z.y - fractal->transformCommon.offset1111.y) - z.y;
z.z = fabs(z.z + fractal->transformCommon.offset1111.z)
- fabs(z.z - fractal->transformCommon.offset1111.z) - z.z;
z.w = fabs(z.w + fractal->transformCommon.offset1111.w)
- fabs(z.w - fractal->transformCommon.offset1111.w) - z.w;
zCol = z;
double rr = z.Dot(z);
rrCol = rr;
if (fractal->mandelboxVary4D.rPower != 1.0) rr = pow(rr, fractal->mandelboxVary4D.rPower);
z += fractal->transformCommon.offset0000;
if (rr < fractal->transformCommon.minR2p25)
{
z *= fractal->transformCommon.maxMinR2factor;
aux.DE *= fractal->transformCommon.maxMinR2factor;
}
else if (rr < fractal->transformCommon.maxR2d1)
{
z *= fractal->transformCommon.maxR2d1 / rr;
aux.DE *= fractal->transformCommon.maxR2d1 / rr;
}
z -= fractal->transformCommon.offset0000;
z *= aux.actualScale;
aux.DE = aux.DE * fabs(aux.actualScale) + 1.0;
// 6 plane rotation
if (fractal->transformCommon.functionEnabledRFalse
&& aux.i >= fractal->transformCommon.startIterationsR
&& aux.i < fractal->transformCommon.stopIterationsR)
{
CVector4 tp;
if (fractal->transformCommon.rotation44a.x != 0)
{
tp = z;
double alpha = fractal->transformCommon.rotation44a.x * M_PI_180;
z.x = tp.x * cos(alpha) + tp.y * sin(alpha);
z.y = tp.x * -sin(alpha) + tp.y * cos(alpha);
}
if (fractal->transformCommon.rotation44a.y != 0)
{
tp = z;
double beta = fractal->transformCommon.rotation44a.y * M_PI_180;
z.y = tp.y * cos(beta) + tp.z * sin(beta);
z.z = tp.y * -sin(beta) + tp.z * cos(beta);
}
if (fractal->transformCommon.rotation44a.z != 0)
{
tp = z;
double gamma = fractal->transformCommon.rotation44a.z * M_PI_180;
z.x = tp.x * cos(gamma) + tp.z * sin(gamma);
z.z = tp.x * -sin(gamma) + tp.z * cos(gamma);
}
if (fractal->transformCommon.rotation44b.x != 0)
{
tp = z;
double delta = fractal->transformCommon.rotation44b.x * M_PI_180;
z.x = tp.x * cos(delta) + tp.w * sin(delta);
z.w = tp.x * -sin(delta) + tp.w * cos(delta);
}
if (fractal->transformCommon.rotation44b.y != 0)
{
tp = z;
double epsilon = fractal->transformCommon.rotation44b.y * M_PI_180;
z.y = tp.y * cos(epsilon) + tp.w * sin(epsilon);
z.w = tp.y * -sin(epsilon) + tp.w * cos(epsilon);
}
if (fractal->transformCommon.rotation44b.z != 0)
{
tp = z;
double zeta = fractal->transformCommon.rotation44b.z * M_PI_180;
z.z = tp.z * cos(zeta) + tp.w * sin(zeta);
z.w = tp.z * -sin(zeta) + tp.w * cos(zeta);
}
}
z += fractal->transformCommon.additionConstant0000;
if (fractal->foldColor.auxColorEnabled)
{
if (zCol.x != oldZ.x) colorAdd += fractal->mandelbox.color.factor4D.x;
if (zCol.y != oldZ.y) colorAdd += fractal->mandelbox.color.factor4D.y;
if (zCol.z != oldZ.z) colorAdd += fractal->mandelbox.color.factor4D.z;
if (zCol.w != oldZ.w) colorAdd += fractal->mandelbox.color.factor4D.w;
if (rrCol < fractal->transformCommon.minR2p25)
colorAdd += fractal->mandelbox.color.factorSp1;
else if (rrCol < fractal->transformCommon.maxR2d1)
colorAdd += fractal->mandelbox.color.factorSp2;
aux.color += colorAdd;
}
}
/**
* Bristorbrot formula 4D
* @reference https://code.google.com/archive/p/fractaldimension/
* by Doug Bristor
*/
void Bristorbrot4dIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
aux.DE = aux.DE * 2.0 * aux.r;
double newx = z.x * z.x - z.y * z.y - z.z * z.z - z.w * z.w;
double newy = z.y * (2.0 * z.x - z.z - z.w);
double newz = z.z * (2.0 * z.x + z.y - z.w);
double neww = z.w * (2.0 * z.x + z.y + z.z);
z.x = newx;
z.y = newy;
z.z = newz;
z.w = neww;
z += fractal->transformCommon.additionConstant0000;
}
/**
* boxFold4dBulb.
* This formula contains aux.color and aux.actualScaleA
*/
void BoxFold4dBulbPow2Iteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
double colorAdd = 0.0;
double rrCol = 0.0;
CVector4 zCol = z;
CVector4 oldZ = z;
// parabolic.w = paraOffset + iter *slope + (iter *iter *scale)
double paraAddP0 = 0.0;
if (fractal->Cpara.enabledParabFalse)
{
double parabScale = 0.0;
if (fractal->Cpara.parabScale != 0.0)
parabScale = aux.i * aux.i * 0.001 * fractal->Cpara.parabScale;
paraAddP0 = fractal->Cpara.parabOffset0 + (aux.i * fractal->Cpara.parabSlope) + (parabScale);
z.w += paraAddP0;
}
// sinusoidal w
double sinAdd = 0.0;
if (fractal->transformCommon.functionEnabledDFalse)
{
sinAdd = sin((aux.i + fractal->transformCommon.offset0) / fractal->transformCommon.scaleA1)
* fractal->transformCommon.scaleC1;
z.w += sinAdd;
}
if (aux.i >= fractal->transformCommon.startIterationsB
&& aux.i < fractal->transformCommon.stopIterationsB)
{
oldZ = z;
z.x = fabs(z.x + fractal->transformCommon.offset1111.x)
- fabs(z.x - fractal->transformCommon.offset1111.x) - z.x;
z.y = fabs(z.y + fractal->transformCommon.offset1111.y)
- fabs(z.y - fractal->transformCommon.offset1111.y) - z.y;
z.z = fabs(z.z + fractal->transformCommon.offset1111.z)
- fabs(z.z - fractal->transformCommon.offset1111.z) - z.z;
z.w = fabs(z.w + fractal->transformCommon.offset1111.w)
- fabs(z.w - fractal->transformCommon.offset1111.w) - z.w;
zCol = z;
}
// sph fold
if (aux.i >= fractal->transformCommon.startIterationsS
&& aux.i < fractal->transformCommon.stopIterationsS)
{
double rr = z.Dot(z);
// r power
if (fractal->mandelboxVary4D.rPower != 1.0) rr = pow(rr, fractal->mandelboxVary4D.rPower);
rrCol = rr;
// spherical fold
z += fractal->transformCommon.offset0000;
if (rr < fractal->transformCommon.minR2p25)
{
z *= fractal->transformCommon.maxMinR2factor;
aux.DE *= fractal->transformCommon.maxMinR2factor;
}
else if (rr < fractal->transformCommon.maxR2d1)
{
z *= fractal->transformCommon.maxR2d1 / rr;
aux.DE *= fractal->transformCommon.maxR2d1 / rr;
}
z -= fractal->transformCommon.offset0000;
}
// scale
double useScale = 1.0;
if (aux.i >= fractal->transformCommon.startIterationsC
&& aux.i < fractal->transformCommon.stopIterationsC)
{
useScale = aux.actualScaleA + fractal->transformCommon.scale;
z *= useScale;
aux.DE = aux.DE * fabs(useScale);
if (fractal->transformCommon.functionEnabledSFalse
&& aux.i >= fractal->transformCommon.startIterationsX
&& aux.i < fractal->transformCommon.stopIterationsX)
{
// update actualScale for next iteration
double vary = fractal->transformCommon.scaleVary0
* (fabs(aux.actualScaleA) - fractal->transformCommon.scaleB1);
if (fractal->transformCommon.functionEnabledMFalse)
aux.actualScaleA = -vary;
else
aux.actualScaleA = aux.actualScaleA - vary;
}
}
// 6 plane rotation
if (fractal->transformCommon.functionEnabledRFalse
&& aux.i >= fractal->transformCommon.startIterationsR
&& aux.i < fractal->transformCommon.stopIterationsR)
{
CVector4 tp;
if (fractal->transformCommon.rotation44a.x != 0)
{
tp = z;
double alpha = fractal->transformCommon.rotation44a.x * M_PI_180;
z.x = tp.x * cos(alpha) + tp.y * sin(alpha);
z.y = tp.x * -sin(alpha) + tp.y * cos(alpha);
}
if (fractal->transformCommon.rotation44a.y != 0)
{
tp = z;
double beta = fractal->transformCommon.rotation44a.y * M_PI_180;
z.y = tp.y * cos(beta) + tp.z * sin(beta);
z.z = tp.y * -sin(beta) + tp.z * cos(beta);
}
if (fractal->transformCommon.rotation44a.z != 0)
{
tp = z;
double gamma = fractal->transformCommon.rotation44a.z * M_PI_180;
z.x = tp.x * cos(gamma) + tp.z * sin(gamma);
z.z = tp.x * -sin(gamma) + tp.z * cos(gamma);
}
if (fractal->transformCommon.rotation44b.x != 0)
{
tp = z;
double delta = fractal->transformCommon.rotation44b.x * M_PI_180;
z.x = tp.x * cos(delta) + tp.w * sin(delta);
z.w = tp.x * -sin(delta) + tp.w * cos(delta);
}
if (fractal->transformCommon.rotation44b.y != 0)
{
tp = z;
double epsilon = fractal->transformCommon.rotation44b.y * M_PI_180;
z.y = tp.y * cos(epsilon) + tp.w * sin(epsilon);
z.w = tp.y * -sin(epsilon) + tp.w * cos(epsilon);
}
if (fractal->transformCommon.rotation44b.z != 0)
{
tp = z;
double zeta = fractal->transformCommon.rotation44b.z * M_PI_180;
z.z = tp.z * cos(zeta) + tp.w * sin(zeta);
z.w = tp.z * -sin(zeta) + tp.w * cos(zeta);
}
}
// offset
z += fractal->transformCommon.additionConstant0000;
// bulb pow2
if (aux.i >= fractal->transformCommon.startIterationsA
&& aux.i < fractal->transformCommon.stopIterationsA)
{
aux.r = z.Length();
aux.DE = aux.r * aux.DE * 16.0 * fractal->analyticDE.scale1
* sqrt(fractal->foldingIntPow.zFactor * fractal->foldingIntPow.zFactor + 2.0
+ fractal->analyticDE.offset2)
/ SQRT_3
+ fractal->analyticDE.offset1;
z = z * 2.0;
double x2 = z.x * z.x;
double y2 = z.y * z.y;
double z2 = z.z * z.z;
double temp = 1.0 - z2 / (x2 + y2);
CVector4 zTemp;
zTemp.x = (x2 - y2) * temp;
zTemp.y = 2.0 * z.x * z.y * temp;
zTemp.z = -2.0 * z.z * sqrt(x2 + y2);
zTemp.w = z.w;
z = zTemp;
z.z *= fractal->foldingIntPow.zFactor;
}
// color
if (fractal->foldColor.auxColorEnabledFalse)
{
if (fractal->transformCommon.functionEnabledCxFalse)
{
if (zCol.x != oldZ.x)
colorAdd +=
fractal->mandelbox.color.factor.x * (fabs(zCol.x) - fractal->mandelbox.color.factor4D.x);
if (zCol.y != oldZ.y)
colorAdd +=
fractal->mandelbox.color.factor.y * (fabs(zCol.y) - fractal->mandelbox.color.factor4D.y);
if (zCol.z != oldZ.z)
colorAdd +=
fractal->mandelbox.color.factor.z * (fabs(zCol.z) - fractal->mandelbox.color.factor4D.z);
if (zCol.w != oldZ.w)
colorAdd +=
fractal->mandelbox.color.factor.z * (fabs(zCol.w) - fractal->mandelbox.color.factor4D.w);
if (rrCol < fractal->transformCommon.maxR2d1)
{
if (rrCol < fractal->transformCommon.minR2p25)
colorAdd +=
fractal->mandelbox.color.factorSp1 * (fractal->transformCommon.minR2p25 - rrCol)
+ fractal->mandelbox.color.factorSp2
* (fractal->transformCommon.maxR2d1 - fractal->transformCommon.minR2p25);
else
colorAdd +=
fractal->mandelbox.color.factorSp2 * (fractal->transformCommon.maxR2d1 - rrCol);
}
}
else
{
if (zCol.x != oldZ.x) colorAdd += fractal->mandelbox.color.factor4D.x;
if (zCol.y != oldZ.y) colorAdd += fractal->mandelbox.color.factor4D.y;
if (zCol.z != oldZ.z) colorAdd += fractal->mandelbox.color.factor4D.z;
if (zCol.w != oldZ.w) colorAdd += fractal->mandelbox.color.factor4D.w;
if (rrCol < fractal->transformCommon.minR2p25)
colorAdd += fractal->mandelbox.color.factorSp1;
else if (rrCol < fractal->transformCommon.maxR2d1)
colorAdd += fractal->mandelbox.color.factorSp2;
}
aux.color += colorAdd;
}
}
/**
* Formula based on Mandelbox (ABox). Extended to 4 dimensions and with variable scale parameter.
* This formula contains aux.color and aux.actualScale
*/
void MandelboxVaryScale4dIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
aux.actualScale =
fractal->mandelbox.scale + fractal->mandelboxVary4D.scaleVary * (fabs(aux.actualScale) - 1.0);
double paraAddP0 = 0.0;
if (fractal->Cpara.enabledParabFalse)
{ // parabolic = paraOffset + iter *slope + (iter *iter *scale)
paraAddP0 = fractal->Cpara.parabOffset0 + (aux.i * fractal->Cpara.parabSlope)
+ (aux.i * aux.i * 0.001 * fractal->Cpara.parabScale);
z.w += paraAddP0;
}
CVector4 oldZ = z;
z.x = fabs(z.x + fractal->mandelboxVary4D.fold) - fabs(z.x - fractal->mandelboxVary4D.fold) - z.x;
z.y = fabs(z.y + fractal->mandelboxVary4D.fold) - fabs(z.y - fractal->mandelboxVary4D.fold) - z.y;
z.z = fabs(z.z + fractal->mandelboxVary4D.fold) - fabs(z.z - fractal->mandelboxVary4D.fold) - z.z;
z.w = fabs(z.w + fractal->mandelboxVary4D.fold) - fabs(z.w - fractal->mandelboxVary4D.fold) - z.w;
if (z.x != oldZ.x) aux.color += fractal->mandelbox.color.factor4D.x;
if (z.y != oldZ.y) aux.color += fractal->mandelbox.color.factor4D.y;
if (z.z != oldZ.z) aux.color += fractal->mandelbox.color.factor4D.z;
if (z.w != oldZ.w) aux.color += fractal->mandelbox.color.factor4D.w;
double rr = pow(z.x * z.x + z.y * z.y + z.z * z.z + z.w * z.w, fractal->mandelboxVary4D.rPower);
double m = aux.actualScale;
if (rr < fractal->mandelboxVary4D.minR * fractal->mandelboxVary4D.minR)
{
m = aux.actualScale / (fractal->mandelboxVary4D.minR * fractal->mandelboxVary4D.minR);
aux.color += fractal->mandelbox.color.factorSp1;
}
else if (rr < 1.0)
{
m = aux.actualScale / rr;
aux.color += fractal->mandelbox.color.factorSp2;
}
z *= m;
aux.DE = aux.DE * fabs(m) + 1.0;
// 6 plane rotation
if (fractal->transformCommon.functionEnabledRFalse
&& aux.i >= fractal->transformCommon.startIterationsR
&& aux.i < fractal->transformCommon.stopIterationsR)
{
CVector4 tp;
if (fractal->transformCommon.rotation44a.x != 0)
{
tp = z;
double alpha = fractal->transformCommon.rotation44a.x * M_PI_180;
z.x = tp.x * cos(alpha) + tp.y * sin(alpha);
z.y = tp.x * -sin(alpha) + tp.y * cos(alpha);
}
if (fractal->transformCommon.rotation44a.y != 0)
{
tp = z;
double beta = fractal->transformCommon.rotation44a.y * M_PI_180;
z.y = tp.y * cos(beta) + tp.z * sin(beta);
z.z = tp.y * -sin(beta) + tp.z * cos(beta);
}
if (fractal->transformCommon.rotation44a.z != 0)
{
tp = z;
double gamma = fractal->transformCommon.rotation44a.z * M_PI_180;
z.x = tp.x * cos(gamma) + tp.z * sin(gamma);
z.z = tp.x * -sin(gamma) + tp.z * cos(gamma);
}
if (fractal->transformCommon.rotation44b.x != 0)
{
tp = z;
double delta = fractal->transformCommon.rotation44b.x * M_PI_180;
z.x = tp.x * cos(delta) + tp.w * sin(delta);
z.w = tp.x * -sin(delta) + tp.w * cos(delta);
}
if (fractal->transformCommon.rotation44b.y != 0)
{
tp = z;
double epsilon = fractal->transformCommon.rotation44b.y * M_PI_180;
z.y = tp.y * cos(epsilon) + tp.w * sin(epsilon);
z.w = tp.y * -sin(epsilon) + tp.w * cos(epsilon);
}
if (fractal->transformCommon.rotation44b.z != 0)
{
tp = z;
double zeta = fractal->transformCommon.rotation44b.z * M_PI_180;
z.z = tp.z * cos(zeta) + tp.w * sin(zeta);
z.w = tp.z * -sin(zeta) + tp.w * cos(zeta);
}
}
}
/**
* from Syntopia & DarkBeam's Menger4 code from M3D
* @reference
* http://www.fractalforums.com/mandelbulb-3d/custom-formulas-and-transforms-release-t17106/
*/
void Menger4dIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
if (aux.i >= fractal->transformCommon.startIterationsC
&& aux.i < fractal->transformCommon.stopIterationsC)
{
z += fractal->transformCommon.additionConstant0000; // offset
}
z = fabs(z);
if (z.x - z.y < 0.0) swap(z.y, z.x);
if (z.x - z.z < 0.0) swap(z.z, z.x);
if (z.y - z.z < 0.0) swap(z.z, z.y);
if (z.x - z.w < 0.0) swap(z.w, z.x);
if (z.y - z.w < 0.0) swap(z.w, z.y);
if (z.z - z.w < 0.0) swap(z.w, z.z);
// 6 plane rotation
if (fractal->transformCommon.functionEnabledRFalse
&& aux.i >= fractal->transformCommon.startIterationsR
&& aux.i < fractal->transformCommon.stopIterationsR)
{
CVector4 tp;
if (fractal->transformCommon.rotation44a.x != 0)
{
tp = z;
double alpha = fractal->transformCommon.rotation44a.x * M_PI_180;
z.x = tp.x * cos(alpha) + tp.y * sin(alpha);
z.y = tp.x * -sin(alpha) + tp.y * cos(alpha);
}
if (fractal->transformCommon.rotation44a.y != 0)
{
tp = z;
double beta = fractal->transformCommon.rotation44a.y * M_PI_180;
z.y = tp.y * cos(beta) + tp.z * sin(beta);
z.z = tp.y * -sin(beta) + tp.z * cos(beta);
}
if (fractal->transformCommon.rotation44a.z != 0)
{
tp = z;
double gamma = fractal->transformCommon.rotation44a.z * M_PI_180;
z.x = tp.x * cos(gamma) + tp.z * sin(gamma);
z.z = tp.x * -sin(gamma) + tp.z * cos(gamma);
}
if (fractal->transformCommon.rotation44b.x != 0)
{
tp = z;
double delta = fractal->transformCommon.rotation44b.x * M_PI_180;
z.x = tp.x * cos(delta) + tp.w * sin(delta);
z.w = tp.x * -sin(delta) + tp.w * cos(delta);
}
if (fractal->transformCommon.rotation44b.y != 0)
{
tp = z;
double epsilon = fractal->transformCommon.rotation44b.y * M_PI_180;
z.y = tp.y * cos(epsilon) + tp.w * sin(epsilon);
z.w = tp.y * -sin(epsilon) + tp.w * cos(epsilon);
}
if (fractal->transformCommon.rotation44b.z != 0)
{
tp = z;
double zeta = fractal->transformCommon.rotation44b.z * M_PI_180;
z.z = tp.z * cos(zeta) + tp.w * sin(zeta);
z.w = tp.z * -sin(zeta) + tp.w * cos(zeta);
}
}
double scaleM = fractal->transformCommon.scale3;
CVector4 offsetM = fractal->transformCommon.additionConstant111d5;
z.x = scaleM * z.x - offsetM.x;
z.y = scaleM * z.y - offsetM.y;
z.w = scaleM * z.w - offsetM.w;
z.z -= 0.5 * offsetM.z / scaleM;
z.z = -fabs(-z.z);
z.z += 0.5 * offsetM.z / scaleM;
z.z *= scaleM;
aux.DE *= scaleM;
if (fractal->transformCommon.functionEnabledSFalse
&& aux.i >= fractal->transformCommon.startIterationsS
&& aux.i < fractal->transformCommon.stopIterationsS)
{
double r2 = z.Dot(z);
// if (r2 < 1e-21 && r2 > -1e-21) r2 = (r2 > 0) ? 1e-21 : -1e-21;
if (r2 < fractal->transformCommon.minR2p25)
{
z *= fractal->transformCommon.maxMinR2factor;
aux.DE *= fractal->transformCommon.maxMinR2factor;
aux.color += fractal->mandelbox.color.factorSp1;
}
else if (r2 < fractal->transformCommon.maxR2d1)
{
double tglad_factor2 = fractal->transformCommon.maxR2d1 / r2;
z *= tglad_factor2;
aux.DE *= tglad_factor2;
aux.color += fractal->mandelbox.color.factorSp2;
}
}
if (fractal->transformCommon.functionEnabledFalse)
{
CVector4 zA4 = (aux.i == fractal->transformCommon.intA) ? z : CVector4();
CVector4 zB4 = (aux.i == fractal->transformCommon.intB) ? z : CVector4();
z = (z * fractal->transformCommon.scale) + (zA4 * fractal->transformCommon.offset)
+ (zB4 * fractal->transformCommon.offset0);
aux.DE *= fractal->transformCommon.scale1;
}
aux.DE *= fractal->analyticDE.scale1;
}
/**
* Menger4D MOD1 from Syntopia & DarkBeam's Menger4 code from M3D
* @reference
* http://www.fractalforums.com/mandelbulb-3d/custom-formulas-and-transforms-release-t17106/
*/
void Menger4dMod1Iteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
double paraAddP0 = 0.0;
if (fractal->Cpara.enabledParabFalse)
{ // parabolic = paraOffset + iter *slope + (iter *iter *scale)
paraAddP0 = fractal->Cpara.parabOffset0 + (aux.i * fractal->Cpara.parabSlope)
+ (aux.i * aux.i * 0.001 * fractal->Cpara.parabScale);
z.w += paraAddP0;
}
if (aux.i >= fractal->transformCommon.startIterationsC
&& aux.i < fractal->transformCommon.stopIterationsC)
{
z += fractal->transformCommon.additionConstant0000; // offset
}
z = fabs(z);
if (z.x - z.y < 0.0) swap(z.y, z.x);
if (z.x - z.z < 0.0) swap(z.z, z.x);
if (z.y - z.z < 0.0) swap(z.z, z.y);
if (z.x - z.w < 0.0) swap(z.w, z.x);
if (z.y - z.w < 0.0) swap(z.w, z.y);
if (z.z - z.w < 0.0) swap(z.w, z.z);
// 6 plane rotation
if (fractal->transformCommon.functionEnabledRFalse
&& aux.i >= fractal->transformCommon.startIterationsR
&& aux.i < fractal->transformCommon.stopIterationsR)
{
CVector4 tp;
if (fractal->transformCommon.rotation44a.x != 0)
{
tp = z;
double alpha = fractal->transformCommon.rotation44a.x * M_PI_180;
z.x = tp.x * cos(alpha) + tp.y * sin(alpha);
z.y = tp.x * -sin(alpha) + tp.y * cos(alpha);
}
if (fractal->transformCommon.rotation44a.y != 0)
{
tp = z;
double beta = fractal->transformCommon.rotation44a.y * M_PI_180;
z.y = tp.y * cos(beta) + tp.z * sin(beta);
z.z = tp.y * -sin(beta) + tp.z * cos(beta);
}
if (fractal->transformCommon.rotation44a.z != 0)
{
tp = z;
double gamma = fractal->transformCommon.rotation44a.z * M_PI_180;
z.x = tp.x * cos(gamma) + tp.z * sin(gamma);
z.z = tp.x * -sin(gamma) + tp.z * cos(gamma);
}
if (fractal->transformCommon.rotation44b.x != 0)
{
tp = z;
double delta = fractal->transformCommon.rotation44b.x * M_PI_180;
z.x = tp.x * cos(delta) + tp.w * sin(delta);
z.w = tp.x * -sin(delta) + tp.w * cos(delta);
}
if (fractal->transformCommon.rotation44b.y != 0)
{
tp = z;
double epsilon = fractal->transformCommon.rotation44b.y * M_PI_180;
z.y = tp.y * cos(epsilon) + tp.w * sin(epsilon);
z.w = tp.y * -sin(epsilon) + tp.w * cos(epsilon);
}
if (fractal->transformCommon.rotation44b.z != 0)
{
tp = z;
double zeta = fractal->transformCommon.rotation44b.z * M_PI_180;
z.z = tp.z * cos(zeta) + tp.w * sin(zeta);
z.w = tp.z * -sin(zeta) + tp.w * cos(zeta);
}
}
double scaleM = fractal->transformCommon.scale3;
CVector4 offsetM = fractal->transformCommon.additionConstant111d5;
z.x = scaleM * z.x - offsetM.x;
z.y = scaleM * z.y - offsetM.y;
z.w = scaleM * z.w - offsetM.w;
if (fractal->transformCommon.functionEnabledz
&& aux.i >= fractal->transformCommon.startIterationsM
&& aux.i < fractal->transformCommon.stopIterationsM)
{
z.z -= 0.5 * offsetM.z / scaleM;
z.z = -fabs(-z.z);
z.z += 0.5 * offsetM.z / scaleM;
}
else
{
z.w = scaleM * z.w - offsetM.w;
}
z.z *= scaleM;
aux.DE *= scaleM;
if (fractal->transformCommon.functionEnabledSFalse
&& aux.i >= fractal->transformCommon.startIterationsS
&& aux.i < fractal->transformCommon.stopIterationsS)
{
double r2 = 0.;
if (fractal->transformCommon.functionEnabledBxFalse)
{
r2 = z.x * z.x + z.y * z.y;
}
if (fractal->transformCommon.functionEnabledByFalse)
{
r2 = z.x * z.x + z.y * z.y + z.z * z.z;
}
if (fractal->transformCommon.functionEnabledBz)
//{ r2 = z.Dot(z) ;}
{
r2 = z.x * z.x + z.y * z.y + z.z * z.z + z.w * z.w;
}
// if (r2 < 1e-21 && r2 > -1e-21) r2 = (r2 > 0) ? 1e-21 : -1e-21;
if (r2 < fractal->transformCommon.minR2p25)
{
z *= fractal->transformCommon.maxMinR2factor;
aux.DE *= fractal->transformCommon.maxMinR2factor;
aux.color += fractal->mandelbox.color.factorSp1;
}
else if (r2 < fractal->transformCommon.maxR2d1)
{
double tglad_factor2 = fractal->transformCommon.maxR2d1 / r2;
z *= tglad_factor2;
aux.DE *= tglad_factor2;
aux.color += fractal->mandelbox.color.factorSp2;
}
}
if (fractal->transformCommon.functionEnabledFalse)
{
CVector4 zA4 = (aux.i == fractal->transformCommon.intA) ? z : CVector4();
CVector4 zB4 = (aux.i == fractal->transformCommon.intB) ? z : CVector4();
z = (z * fractal->transformCommon.scale) + (zA4 * fractal->transformCommon.offset)
+ (zB4 * fractal->transformCommon.offset0);
aux.DE *= fractal->transformCommon.scale1;
}
aux.DE *= fractal->analyticDE.scale1;
}
/**
* DarkBeam's MixPinski4 from M3D
* A strange but intriguing fractal, that mixes Sierpinski and Menger folds.
* The amazing thing is that in 3D it does not work so well! LUCA GN 2011
* @reference
* http://www.fractalforums.com/mandelbulb-3d/custom-formulas-and-transforms-release-t17106/
*/
void MixPinski4dIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
if (aux.i >= fractal->transformCommon.startIterationsS
&& aux.i < fractal->transformCommon.stopIterationsS)
{
double temp;
if (z.x + z.y < 0.0)
{
temp = z.x;
z.x = -z.y;
z.y = -temp;
}
if (z.x + z.z < 0.0)
{
temp = z.x;
z.x = -z.z;
z.z = -temp;
}
if (z.y + z.z < 0.0)
{
temp = z.z;
z.z = -z.y;
z.y = -temp;
}
if (z.x + z.w < 0.0)
{
temp = z.x;
z.x = -z.w;
z.w = -temp;
}
if (z.y + z.w < 0.0)
{
temp = z.y;
z.y = -z.w;
z.w = -temp;
}
if (z.z + z.w < 0.0)
{
temp = z.z;
z.z = -z.w;
z.w = -temp;
}
z *= fractal->transformCommon.scale1;
aux.DE *= fabs(fractal->transformCommon.scale1);
}
if (aux.i >= fractal->transformCommon.startIterationsC
&& aux.i < fractal->transformCommon.stopIterationsC)
{
z += fractal->transformCommon.additionConstant0000; // offset
}
// 6 plane rotation
if (fractal->transformCommon.functionEnabledRFalse
&& aux.i >= fractal->transformCommon.startIterationsR
&& aux.i < fractal->transformCommon.stopIterationsR)
{
CVector4 tp;
if (fractal->transformCommon.rotation44a.x != 0)
{
tp = z;
double alpha = fractal->transformCommon.rotation44a.x * M_PI_180;
z.x = tp.x * cos(alpha) + tp.y * sin(alpha);
z.y = tp.x * -sin(alpha) + tp.y * cos(alpha);
}
if (fractal->transformCommon.rotation44a.y != 0)
{
tp = z;
double beta = fractal->transformCommon.rotation44a.y * M_PI_180;
z.y = tp.y * cos(beta) + tp.z * sin(beta);
z.z = tp.y * -sin(beta) + tp.z * cos(beta);
}
if (fractal->transformCommon.rotation44a.z != 0)
{
tp = z;
double gamma = fractal->transformCommon.rotation44a.z * M_PI_180;
z.x = tp.x * cos(gamma) + tp.z * sin(gamma);
z.z = tp.x * -sin(gamma) + tp.z * cos(gamma);
}
if (fractal->transformCommon.rotation44b.x != 0)
{
tp = z;
double delta = fractal->transformCommon.rotation44b.x * M_PI_180;
z.x = tp.x * cos(delta) + tp.w * sin(delta);
z.w = tp.x * -sin(delta) + tp.w * cos(delta);
}
if (fractal->transformCommon.rotation44b.y != 0)
{
tp = z;
double epsilon = fractal->transformCommon.rotation44b.y * M_PI_180;
z.y = tp.y * cos(epsilon) + tp.w * sin(epsilon);
z.w = tp.y * -sin(epsilon) + tp.w * cos(epsilon);
}
if (fractal->transformCommon.rotation44b.z != 0)
{
tp = z;
double zeta = fractal->transformCommon.rotation44b.z * M_PI_180;
z.z = tp.z * cos(zeta) + tp.w * sin(zeta);
z.w = tp.z * -sin(zeta) + tp.w * cos(zeta);
}
}
if (aux.i >= fractal->transformCommon.startIterationsM
&& aux.i < fractal->transformCommon.stopIterationsM)
{
double scaleM = fractal->transformCommon.scale2;
CVector4 offsetM = fractal->transformCommon.additionConstant111d5;
z.x = scaleM * z.x - offsetM.x * (scaleM - 1.0);
z.y = scaleM * z.y - offsetM.y * (scaleM - 1.0);
z.w = scaleM * z.w - offsetM.w * (scaleM - 1.0);
z.z -= 0.5 * offsetM.z * (scaleM - 1.0) / scaleM;
z.z = -fabs(-z.z);
z.z += 0.5 * offsetM.z * (scaleM - 1.0) / scaleM;
z.z = scaleM * z.z;
aux.DE *= fabs(scaleM) * fractal->analyticDE.scale1;
}
}
/**
* Sierpinski4D.from Syntopia & DarkBeam's code
* @reference
* http://www.fractalforums.com/mandelbulb-3d/custom-formulas-and-transforms-release-t17106/
*/
void Sierpinski4dIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
double temp;
if (z.x + z.y < 0.0)
{
temp = z.x;
z.x = -z.y;
z.y = -temp;
}
if (z.x + z.z < 0.0)
{
temp = z.x;
z.x = -z.z;
z.z = -temp;
}
if (z.y + z.z < 0.0)
{
temp = z.z;
z.z = -z.y;
z.y = -temp;
}
if (z.x + z.w < 0.0)
{
temp = z.x;
z.x = -z.w;
z.w = -temp;
}
if (z.y + z.w < 0.0)
{
temp = z.y;
z.y = -z.w;
z.w = -temp;
}
if (z.z + z.w < 0.0)
{
temp = z.z;
z.z = -z.w;
z.w = -temp;
}
z *= fractal->transformCommon.scaleA2;
if (aux.i >= fractal->transformCommon.startIterationsC
&& aux.i < fractal->transformCommon.stopIterationsC)
{
z -= fractal->transformCommon.offset1111; // neg offset
}
// 6 plane rotation
if (fractal->transformCommon.functionEnabledRFalse
&& aux.i >= fractal->transformCommon.startIterationsR
&& aux.i < fractal->transformCommon.stopIterationsR)
{
CVector4 tp;
if (fractal->transformCommon.rotation44a.x != 0)
{
tp = z;
double alpha = fractal->transformCommon.rotation44a.x * M_PI_180;
z.x = tp.x * cos(alpha) + tp.y * sin(alpha);
z.y = tp.x * -sin(alpha) + tp.y * cos(alpha);
}
if (fractal->transformCommon.rotation44a.y != 0)
{
tp = z;
double beta = fractal->transformCommon.rotation44a.y * M_PI_180;
z.y = tp.y * cos(beta) + tp.z * sin(beta);
z.z = tp.y * -sin(beta) + tp.z * cos(beta);
}
if (fractal->transformCommon.rotation44a.z != 0)
{
tp = z;
double gamma = fractal->transformCommon.rotation44a.z * M_PI_180;
z.x = tp.x * cos(gamma) + tp.z * sin(gamma);
z.z = tp.x * -sin(gamma) + tp.z * cos(gamma);
}
if (fractal->transformCommon.rotation44b.x != 0)
{
tp = z;
double delta = fractal->transformCommon.rotation44b.x * M_PI_180;
z.x = tp.x * cos(delta) + tp.w * sin(delta);
z.w = tp.x * -sin(delta) + tp.w * cos(delta);
}
if (fractal->transformCommon.rotation44b.y != 0)
{
tp = z;
double epsilon = fractal->transformCommon.rotation44b.y * M_PI_180;
z.y = tp.y * cos(epsilon) + tp.w * sin(epsilon);
z.w = tp.y * -sin(epsilon) + tp.w * cos(epsilon);
}
if (fractal->transformCommon.rotation44b.z != 0)
{
tp = z;
double zeta = fractal->transformCommon.rotation44b.z * M_PI_180;
z.z = tp.z * cos(zeta) + tp.w * sin(zeta);
z.w = tp.z * -sin(zeta) + tp.w * cos(zeta);
}
}
if (!fractal->analyticDE.enabledFalse) // testing
aux.DE *= fabs(fractal->transformCommon.scaleA2);
else
aux.DE = aux.DE * fabs(fractal->transformCommon.scaleA2) * fractal->analyticDE.scale1
+ fractal->analyticDE.offset0;
}
/**
* Quaternion4D
*/
void Quaternion4dIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
z = CVector4(z.x * z.x - z.y * z.y - z.z * z.z - z.w * z.w, z.x * z.y, z.x * z.z, z.w);
z *= fractal->transformCommon.constantMultiplier1220;
z += fractal->transformCommon.additionConstant0000;
// 6 plane rotation
if (fractal->transformCommon.functionEnabledRFalse
&& aux.i >= fractal->transformCommon.startIterationsR
&& aux.i < fractal->transformCommon.stopIterationsR)
{
CVector4 tp;
if (fractal->transformCommon.rotation44a.x != 0)
{
tp = z;
double alpha = fractal->transformCommon.rotation44a.x * M_PI_180;
z.x = tp.x * cos(alpha) + tp.y * sin(alpha);
z.y = tp.x * -sin(alpha) + tp.y * cos(alpha);
}
if (fractal->transformCommon.rotation44a.y != 0)
{
tp = z;
double beta = fractal->transformCommon.rotation44a.y * M_PI_180;
z.y = tp.y * cos(beta) + tp.z * sin(beta);
z.z = tp.y * -sin(beta) + tp.z * cos(beta);
}
if (fractal->transformCommon.rotation44a.z != 0)
{
tp = z;
double gamma = fractal->transformCommon.rotation44a.z * M_PI_180;
z.x = tp.x * cos(gamma) + tp.z * sin(gamma);
z.z = tp.x * -sin(gamma) + tp.z * cos(gamma);
}
if (fractal->transformCommon.rotation44b.x != 0)
{
tp = z;
double delta = fractal->transformCommon.rotation44b.x * M_PI_180;
z.x = tp.x * cos(delta) + tp.w * sin(delta);
z.w = tp.x * -sin(delta) + tp.w * cos(delta);
}
if (fractal->transformCommon.rotation44b.y != 0)
{
tp = z;
double epsilon = fractal->transformCommon.rotation44b.y * M_PI_180;
z.y = tp.y * cos(epsilon) + tp.w * sin(epsilon);
z.w = tp.y * -sin(epsilon) + tp.w * cos(epsilon);
}
if (fractal->transformCommon.rotation44b.z != 0)
{
tp = z;
double zeta = fractal->transformCommon.rotation44b.z * M_PI_180;
z.z = tp.z * cos(zeta) + tp.w * sin(zeta);
z.w = tp.z * -sin(zeta) + tp.w * cos(zeta);
}
}
}
/**
* QuaternionCubic4d - Quaternion fractal with extended controls
* @reference DarkBeam's cubic quat implementation
* http://www.fractalforums.com/mandelbulb-3d/custom-formulas-and-transforms-release-t17106/
*/
void QuaternionCubic4dIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
if (fractal->transformCommon.functionEnabledxFalse) z.x = fabs(z.x);
if (fractal->transformCommon.functionEnabledyFalse) z.y = fabs(z.y);
if (fractal->transformCommon.functionEnabledzFalse) z.z = fabs(z.z);
if (fractal->transformCommon.functionEnabledwFalse) z.w = fabs(z.w);
CVector4 mul = z * fractal->transformCommon.offset1111;
CVector4 oldZ = z;
CVector4 auxC = aux.c;
z.x = mul.x * z.x - mul.y * z.y - mul.z * z.z - mul.w * z.w
+ (auxC.y * fractal->transformCommon.offsetA0);
z.y = oldZ.y * oldZ.x;
z.z = oldZ.z * oldZ.x;
z.w = oldZ.w * oldZ.x;
z *= fractal->transformCommon.constantMultiplier1220;
z.y += auxC.x * fractal->transformCommon.offsetB0;
z += fractal->transformCommon.additionConstant0000;
// 6 plane rotation
if (fractal->transformCommon.functionEnabledRFalse
&& aux.i >= fractal->transformCommon.startIterationsR
&& aux.i < fractal->transformCommon.stopIterationsR)
{
CVector4 tp;
if (fractal->transformCommon.rotation44a.x != 0)
{
tp = z;
double alpha = fractal->transformCommon.rotation44a.x * M_PI_180;
z.x = tp.x * cos(alpha) + tp.y * sin(alpha);
z.y = tp.x * -sin(alpha) + tp.y * cos(alpha);
}
if (fractal->transformCommon.rotation44a.y != 0)
{
tp = z;
double beta = fractal->transformCommon.rotation44a.y * M_PI_180;
z.y = tp.y * cos(beta) + tp.z * sin(beta);
z.z = tp.y * -sin(beta) + tp.z * cos(beta);
}
if (fractal->transformCommon.rotation44a.z != 0)
{
tp = z;
double gamma = fractal->transformCommon.rotation44a.z * M_PI_180;
z.x = tp.x * cos(gamma) + tp.z * sin(gamma);
z.z = tp.x * -sin(gamma) + tp.z * cos(gamma);
}
if (fractal->transformCommon.rotation44b.x != 0)
{
tp = z;
double delta = fractal->transformCommon.rotation44b.x * M_PI_180;
z.x = tp.x * cos(delta) + tp.w * sin(delta);
z.w = tp.x * -sin(delta) + tp.w * cos(delta);
}
if (fractal->transformCommon.rotation44b.y != 0)
{
tp = z;
double epsilon = fractal->transformCommon.rotation44b.y * M_PI_180;
z.y = tp.y * cos(epsilon) + tp.w * sin(epsilon);
z.w = tp.y * -sin(epsilon) + tp.w * cos(epsilon);
}
if (fractal->transformCommon.rotation44b.z != 0)
{
tp = z;
double zeta = fractal->transformCommon.rotation44b.z * M_PI_180;
z.z = tp.z * cos(zeta) + tp.w * sin(zeta);
z.w = tp.z * -sin(zeta) + tp.w * cos(zeta);
}
}
}
/**
* Adds c constant to z vector 4D
*/
void TransfAddConstant4dIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
Q_UNUSED(aux);
z += fractal->transformCommon.additionConstant0000;
}
/**
* box fold 4D
* This formula contains aux.color
*/
void TransfBoxFold4dIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
CVector4 oldZ = z;
if (z.x > fractal->mandelbox.foldingLimit)
{
z.x = fractal->mandelbox.foldingValue - z.x;
}
else if (z.x < -fractal->mandelbox.foldingLimit)
{
z.x = -fractal->mandelbox.foldingValue - z.x;
}
if (z.y > fractal->mandelbox.foldingLimit)
{
z.y = fractal->mandelbox.foldingValue - z.y;
}
else if (z.y < -fractal->mandelbox.foldingLimit)
{
z.y = -fractal->mandelbox.foldingValue - z.y;
}
if (z.z > fractal->mandelbox.foldingLimit)
{
z.z = fractal->mandelbox.foldingValue - z.z;
}
else if (z.z < -fractal->mandelbox.foldingLimit)
{
z.z = -fractal->mandelbox.foldingValue - z.z;
}
if (z.w > fractal->mandelbox.foldingLimit)
{
z.w = fractal->mandelbox.foldingValue - z.w;
}
else if (z.w < -fractal->mandelbox.foldingLimit)
{
z.w = -fractal->mandelbox.foldingValue - z.w;
}
if (fractal->foldColor.auxColorEnabledFalse)
{
if (z.x != oldZ.x) aux.color += fractal->mandelbox.color.factor4D.x;
if (z.y != oldZ.y) aux.color += fractal->mandelbox.color.factor4D.y;
if (z.z != oldZ.z) aux.color += fractal->mandelbox.color.factor4D.z;
if (z.w != oldZ.w) aux.color += fractal->mandelbox.color.factor4D.w;
}
}
/**
* box fold 4D Tglad
* This formula contains aux.color
*/
void TransfBoxFold4dTgladIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
CVector4 oldZ = z;
z.x = fabs(z.x + fractal->transformCommon.offset1111.x)
- fabs(z.x - fractal->transformCommon.offset1111.x) - z.x;
z.y = fabs(z.y + fractal->transformCommon.offset1111.y)
- fabs(z.y - fractal->transformCommon.offset1111.y) - z.y;
z.z = fabs(z.z + fractal->transformCommon.offset1111.z)
- fabs(z.z - fractal->transformCommon.offset1111.z) - z.z;
z.w = fabs(z.w + fractal->transformCommon.offset1111.w)
- fabs(z.w - fractal->transformCommon.offset1111.w) - z.w;
if (fractal->foldColor.auxColorEnabledFalse)
{
if (z.x != oldZ.x) aux.color += fractal->mandelbox.color.factor4D.x;
if (z.y != oldZ.y) aux.color += fractal->mandelbox.color.factor4D.y;
if (z.z != oldZ.z) aux.color += fractal->mandelbox.color.factor4D.z;
if (z.w != oldZ.w) aux.color += fractal->mandelbox.color.factor4D.w;
}
}
/**
* abs add constant, z = abs( z + constant)
*/
void TransfAbsAddConstant4dIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
Q_UNUSED(aux);
z += fractal->transformCommon.additionConstant0000;
if (fractal->transformCommon.functionEnabledx) z.x = fabs(z.x);
if (fractal->transformCommon.functionEnabledy) z.y = fabs(z.y);
if (fractal->transformCommon.functionEnabledz) z.z = fabs(z.z);
if (fractal->transformCommon.functionEnabled) z.w = fabs(z.w);
}
/**
* abs. Add abs constantV2, z = abs( z + constant) - abs( z - constant) - z:
*/
void TransfAbsAddTgladFold4dIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
Q_UNUSED(aux);
z = fabs(z + fractal->transformCommon.additionConstant0000)
- fabs(z - fractal->transformCommon.additionConstant0000) - z;
}
/**
* abs add conditional4D
*/
void TransfAbsAddConditional4dIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
if (fractal->transformCommon.functionEnabledx)
{
z.x = sign(z.x) * (fractal->transformCommon.offset1111.x - fabs(z.x)
+ fabs(z.x) * fractal->transformCommon.additionConstant0000.x);
}
if (fractal->transformCommon.functionEnabledy)
{
z.y = sign(z.y) * (fractal->transformCommon.offset1111.y - fabs(z.y)
+ fabs(z.y) * fractal->transformCommon.additionConstant0000.y);
}
if (fractal->transformCommon.functionEnabledz)
{
z.z = sign(z.z) * (fractal->transformCommon.offset1111.z - fabs(z.z)
+ fabs(z.z) * fractal->transformCommon.additionConstant0000.z);
}
if (fractal->transformCommon.functionEnabledw)
{
z.w = sign(z.w) * (fractal->transformCommon.offset1111.w - fabs(z.w)
+ fabs(z.w) * fractal->transformCommon.additionConstant0000.w);
}
aux.DE *= fractal->analyticDE.scale1; // DE tweak
}
/**
* iteration weight 4D
*/
void TransfIterationWeight4dIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
CVector4 zA4 = (aux.i == fractal->transformCommon.intA) ? z : CVector4();
CVector4 zB4 = (aux.i == fractal->transformCommon.intB) ? z : CVector4();
z = (z * fractal->transformCommon.scale) + (zA4 * fractal->transformCommon.offset)
+ (zB4 * fractal->transformCommon.offset0);
aux.DE *= fractal->transformCommon.scale;
}
/**
* Reciprocal4D from M3D, DarkBeam's code
* @reference
* http://www.fractalforums.com/mandelbulb-3d/custom-formulas-and-transforms-release-t17106/
*/
void TransfReciprocal4dIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
CVector4 tempZ = z;
if (fractal->transformCommon.functionEnabledx)
{
if (fractal->transformCommon.functionEnabledAx)
tempZ.x = (1.0 / fractal->transformCommon.offset1111.x)
- 1.0 / (fabs(z.x) + fractal->transformCommon.offset1111.x);
if (fractal->transformCommon.functionEnabledAxFalse)
tempZ.x = (fractal->transformCommon.offsetA1111.x)
- 1.0 / (fabs(z.x) + fractal->transformCommon.offset1111.x);
tempZ.x += fabs(z.x) * fractal->transformCommon.additionConstant0000.x; // function slope
z.x = sign(z.x) * tempZ.x;
}
if (fractal->transformCommon.functionEnabledy)
{
if (fractal->transformCommon.functionEnabledAx)
tempZ.y = (1.0 / fractal->transformCommon.offset1111.y)
- 1.0 / (fabs(z.y) + fractal->transformCommon.offset1111.y);
if (fractal->transformCommon.functionEnabledAxFalse)
tempZ.y = (fractal->transformCommon.offsetA1111.y)
- 1.0 / (fabs(z.y) + fractal->transformCommon.offset1111.y);
tempZ.y += fabs(z.y) * fractal->transformCommon.additionConstant0000.y;
z.y = sign(z.y) * tempZ.y;
}
if (fractal->transformCommon.functionEnabledz)
{
if (fractal->transformCommon.functionEnabledAx)
tempZ.z = (1.0 / fractal->transformCommon.offset1111.z)
- 1.0 / (fabs(z.z) + fractal->transformCommon.offset1111.z);
if (fractal->transformCommon.functionEnabledAxFalse)
tempZ.z = (fractal->transformCommon.offsetA1111.z)
- 1.0 / (fabs(z.z) + fractal->transformCommon.offset1111.z);
tempZ.z += fabs(z.z) * fractal->transformCommon.additionConstant0000.z;
z.z = sign(z.z) * tempZ.z;
}
if (fractal->transformCommon.functionEnabledw)
{
if (fractal->transformCommon.functionEnabledAw)
tempZ.w = (1.0 / fractal->transformCommon.offset1111.w)
- 1.0 / (fabs(z.w) + fractal->transformCommon.offset1111.w);
if (fractal->transformCommon.functionEnabledAwFalse)
tempZ.w = (fractal->transformCommon.offsetA1111.w)
- 1.0 / (fabs(z.w) + fractal->transformCommon.offset1111.w);
tempZ.z += fabs(z.w) * fractal->transformCommon.additionConstant0000.w;
z.z = sign(z.w) * tempZ.w;
}
// aux.DE = aux.DE * l/L;
aux.DE *= fractal->analyticDE.scale1; // DE tweak
}
/**
* rotation 4D
*/
void TransfRotation4dIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
// temp 4D rotation
{
Q_UNUSED(aux);
CVector4 tp;
if (fractal->transformCommon.rotation44a.x != 0)
{
tp = z;
double alpha = fractal->transformCommon.rotation44a.x * M_PI_180;
z.x = tp.x * cos(alpha) + tp.y * sin(alpha);
z.y = tp.x * -sin(alpha) + tp.y * cos(alpha);
}
if (fractal->transformCommon.rotation44a.y != 0)
{
tp = z;
double beta = fractal->transformCommon.rotation44a.y * M_PI_180;
z.y = tp.y * cos(beta) + tp.z * sin(beta);
z.z = tp.y * -sin(beta) + tp.z * cos(beta);
}
if (fractal->transformCommon.rotation44a.z != 0)
{
tp = z;
double gamma = fractal->transformCommon.rotation44a.z * M_PI_180;
z.x = tp.x * cos(gamma) + tp.z * sin(gamma);
z.z = tp.x * -sin(gamma) + tp.z * cos(gamma);
}
if (fractal->transformCommon.rotation44b.x != 0)
{
tp = z;
double delta = fractal->transformCommon.rotation44b.x * M_PI_180;
z.x = tp.x * cos(delta) + tp.w * sin(delta);
z.w = tp.x * -sin(delta) + tp.w * cos(delta);
}
if (fractal->transformCommon.rotation44b.y != 0)
{
tp = z;
double epsilon = fractal->transformCommon.rotation44b.y * M_PI_180;
z.y = tp.y * cos(epsilon) + tp.w * sin(epsilon);
z.w = tp.y * -sin(epsilon) + tp.w * cos(epsilon);
}
if (fractal->transformCommon.rotation44b.z != 0)
{
tp = z;
double zeta = fractal->transformCommon.rotation44b.z * M_PI_180;
z.z = tp.z * cos(zeta) + tp.w * sin(zeta);
z.w = tp.z * -sin(zeta) + tp.w * cos(zeta);
}
}
/**
* scale 4D
*/
void TransfScale4dIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
z *= fractal->transformCommon.scale;
aux.DE = aux.DE * fabs(fractal->transformCommon.scale) + 1.0;
}
/**
* spherical fold 4D
* This formula contains aux.color
*/
void TransfSphericalFold4dIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
// double r2 = z.Dot(z);
// double r2 = z.x * z.x + z.y * z.y;
// if (r2 < 1e-21 && r2 > -1e-21) r2 = (r2 > 0) ? 1e-21 : -1e-21;
// r2 += z.z * z.z;
double rr = z.Dot(z);
z += fractal->transformCommon.offset0000;
if (rr < fractal->transformCommon.minR2p25)
{
z *= fractal->transformCommon.maxMinR2factor;
aux.DE *= fractal->transformCommon.maxMinR2factor;
if (fractal->foldColor.auxColorEnabledFalse)
{
aux.color += fractal->mandelbox.color.factorSp1;
}
}
else if (rr < fractal->transformCommon.maxR2d1)
{
z *= fractal->transformCommon.maxR2d1 / rr;
aux.DE *= fractal->transformCommon.maxR2d1 / rr;
if (fractal->foldColor.auxColorEnabledFalse)
{
aux.color += fractal->mandelbox.color.factorSp2;
};
}
z -= fractal->transformCommon.offset0000;
}
/**
* Hybrid Color Trial
*
* for folds the aux.color is updated each iteration
* depending on which slots have formulas that use it
*
* bailout may need to be adjusted with some formulas
*/
void TransfHybridColorIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
// double auxColor = 0.0;
double R2 = 0.0;
double distEst = 0.0;
double planeBias = 0.0;
double linearOffset = 0.0;
// double factorR = fractal->mandelbox.color.factorR;
double componentMaster = 0.0;
double minValue = 0.0;
double lengthIter = 0.0;
double boxTrap = 0.0;
double sphereTrap = 0.0;
// if
{
// radius squared components
if (fractal->transformCommon.functionEnabledRFalse)
{
double temp0 = 0.0;
double temp1 = 0.0;
CVector4 c = aux.c;
temp0 = c.Dot(c) * fractal->foldColor.scaleA0; // initial R2
temp1 = z.Dot(z) * fractal->foldColor.scaleB0;
R2 = temp0 + temp1;
}
// DE component
if (fractal->transformCommon.functionEnabledDFalse)
{
distEst = aux.DE;
double temp5 = 0.0;
temp5 = distEst * fractal->foldColor.scaleD0;
if (fractal->transformCommon.functionEnabledByFalse) temp5 *= 1.0 / (aux.i + 1.0);
if (fractal->transformCommon.functionEnabledBzFalse) temp5 *= 1.0 / (aux.i * aux.i + 1.0);
distEst = temp5;
}
// max linear offset
if (fractal->transformCommon.functionEnabledMFalse)
{
double temp30 = 0.0;
CVector4 temp31 = z;
if (fractal->transformCommon.functionEnabledM) temp31 = fabs(temp31);
temp30 = max(max(temp31.x, temp31.y), temp31.z);
temp30 *= fractal->foldColor.scaleA1;
linearOffset = temp30;
}
// box trap
if (fractal->surfBox.enabledX2False)
{
CVector4 box = fractal->transformCommon.scale3D444;
CVector4 temp35 = z;
double temp39 = 0.0;
if (fractal->transformCommon.functionEnabledCx) temp35 = fabs(temp35);
temp35 = box - temp35;
double temp36 = max(max(temp35.x, temp35.y), temp35.z);
double temp37 = min(min(temp35.x, temp35.y), temp35.z);
temp36 = temp36 + temp37 * fractal->transformCommon.offsetB0;
temp36 *= fractal->transformCommon.scaleC1;
if (fractal->surfBox.enabledY2False)
{
CVector4 temp38 = aux.c;
if (fractal->transformCommon.functionEnabledCz) temp38 = fabs(temp38);
temp38 = box - temp38;
temp39 = max(max(temp38.x, temp38.y), temp38.z);
double temp40 = min(min(temp38.x, temp38.y), temp38.z);
temp39 = temp39 + temp40 * fractal->transformCommon.offsetA0;
temp39 *= fractal->transformCommon.scaleE1;
}
boxTrap = temp36 + temp39;
}
// sphere trap
if (fractal->transformCommon.functionEnabledzFalse)
{
double sphereR2 = fractal->transformCommon.maxR2d1;
double temp45 = z.Dot(z);
double temp46 = sphereR2 - temp45;
double temp47 = temp46;
double temp51 = temp46;
if (fractal->transformCommon.functionEnabledAx) temp51 = fabs(temp51);
temp51 *= fractal->transformCommon.scaleF1;
if (fractal->transformCommon.functionEnabledyFalse && temp45 > sphereR2)
{
temp46 *= temp46 * fractal->transformCommon.scaleG1;
}
if (fractal->transformCommon.functionEnabledPFalse && temp45 < sphereR2)
{
temp47 *= temp47 * fractal->transformCommon.scaleB1;
}
sphereTrap = temp51 + temp47 + temp46;
}
// plane bias
if (fractal->transformCommon.functionEnabledAzFalse)
{
CVector4 tempP = z;
if (fractal->transformCommon.functionEnabledEFalse)
{
tempP.x = tempP.x * tempP.y;
tempP.x *= tempP.x;
}
else
{
tempP.x = fabs(tempP.x * tempP.y);
}
if (fractal->transformCommon.functionEnabledFFalse)
{
tempP.y = tempP.y * tempP.z;
tempP.y *= tempP.y;
}
else
{
tempP.y = fabs(tempP.y * tempP.z);
}
if (fractal->transformCommon.functionEnabledKFalse)
{
tempP.z = tempP.z * tempP.x;
tempP.z *= tempP.z;
}
else
{
tempP.z = fabs(tempP.z * tempP.x);
}
tempP = tempP * fractal->transformCommon.scale3D000;
planeBias = tempP.x + tempP.y + tempP.z;
}
// build componentMaster
componentMaster = (R2 + distEst + planeBias + lengthIter + linearOffset + boxTrap + sphereTrap);
// divide by i option
/*if (fractal->transformCommon.functionEnabledCzFalse
&& aux.i >= fractal->transformCommon.startIterationsT
&& aux.i < fractal->transformCommon.stopIterationsT)
{
componentMaster += componentMaster * (1.0 + fractal->transformCommon.scale / (aux.i + 1.0));
}*/
/* if (fractal->transformCommon.functionEnabledAyFalse)
{ // log
double logCurve = log(componentMaster + 1.0) * fractal->foldColor.scaleE0;
componentMaster += logCurve;
}*/
aux.colorHybrid = componentMaster;
if (fractal->surfBox.enabledZ2False)
{
if (componentMaster < aux.temp100 * fractal->transformCommon.scaleA1)
{
aux.temp100 = componentMaster;
}
minValue = aux.temp100;
aux.colorHybrid += (minValue - aux.colorHybrid) * fractal->surfBox.scale1Z1;
}
aux.colorHybrid *= 256.0;
}
}
/**
* Hybrid Color Trial2
*
* for folds the aux.color is updated each iteration
* depending on which slots have formulas that use it
*
*
* bailout may need to be adjusted with some formulas
*/
void TransfHybridColor2Iteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
// double auxColor = 0.0;
double R2 = 0.0;
double distEst = 0.0;
double planeBias = 0.0;
double linearOffset = 0.0;
// double factorR = fractal->mandelbox.color.factorR;
double componentMaster = 0.0;
double minValue = 0.0;
double lengthIter = 0.0;
double boxTrap = 0.0;
double sphereTrap = 0.0;
float lastDist = 0.0;
float addI = 0.0;
// if
{
// radius squared components
if (fractal->transformCommon.functionEnabledRFalse)
{
double temp0 = 0.0;
double temp1 = 0.0;
CVector4 c = aux.c;
temp0 = c.Dot(c) * fractal->foldColor.scaleA0; // initial R2
temp1 = z.Dot(z) * fractal->foldColor.scaleB0;
R2 = temp0 + temp1;
}
// total distance squared
if (fractal->foldColor.distanceEnabledFalse)
{
if (aux.i >= fractal->transformCommon.startIterationsD
&& aux.i < fractal->transformCommon.stopIterationsD)
{
CVector4 subVs = z - aux.old_z;
lastDist = subVs.Dot(subVs) * fractal->foldColor.scaleB1;
if (fractal->transformCommon.functionEnabledAxFalse)
{
subVs = fabs(subVs);
lastDist = min(min(subVs.x, subVs.y), subVs.z) * fractal->foldColor.scaleB1;
}
else
aux.addDist += lastDist;
}
lastDist = aux.addDist;
// update
aux.old_z = z;
}
/*aux.sum_z +=(z); // fabs
CVector4 sumZ = aux.sum_z;
sumDist = sumZ.Dot(sumZ) * fractal->foldColor.scaleB1;*/
/* CVector4 subV = z - aux.old_z;
subV = fabs(subV);
// sumDist = max(max(subV.x, subV.y), subV.z);
sumDist = min(min(subV.x, subV.y), subV.z) * fractal->foldColor.scaleB1 / 10.0;*/
/*last distance
{
aux.sum_z +=(z); // fabs
CVector4 sumZ = aux.sum_z;
sumDist = sumZ.Dot(sumZ) * fractal->foldColor.scaleB1;
CVector4 subV = z - aux.old_z;
lastDist = subV.Dot(subV) * fractal->foldColor.scaleC1;
// sumDist = max(max(subV.x, subV.y), subV.z);
//sumDist = min(min(subV.x, subV.y), subV.z) * fractal->foldColor.scaleB1 / 10.0;
// update
aux.old_z = z;
}*/
// DE component
if (fractal->transformCommon.functionEnabledDFalse)
{
distEst = aux.DE;
double temp5 = 0.0;
temp5 = distEst * fractal->foldColor.scaleD0;
if (fractal->transformCommon.functionEnabledByFalse) temp5 *= 1.0 / (aux.i + 1.0);
if (fractal->transformCommon.functionEnabledBzFalse) temp5 *= 1.0 / (aux.i * aux.i + 1.0);
distEst = temp5;
}
// max linear offset
if (fractal->transformCommon.functionEnabledMFalse)
{
double temp30 = 0.0;
CVector4 temp31 = z;
if (fractal->transformCommon.functionEnabledM) temp31 = fabs(temp31);
temp30 = max(max(temp31.x, temp31.y), temp31.z);
temp30 *= fractal->foldColor.scaleA1;
linearOffset = temp30;
}
// box trap
if (fractal->surfBox.enabledX2False)
{
CVector4 box = fractal->transformCommon.scale3D444;
CVector4 temp35 = z;
double temp39 = 0.0;
if (fractal->transformCommon.functionEnabledCx) temp35 = fabs(temp35);
temp35 = box - temp35;
double temp36 = max(max(temp35.x, temp35.y), temp35.z);
double temp37 = min(min(temp35.x, temp35.y), temp35.z);
temp36 = temp36 + temp37 * fractal->transformCommon.offsetB0;
temp36 *= fractal->transformCommon.scaleC1;
if (fractal->surfBox.enabledY2False)
{
CVector4 temp38 = aux.c;
if (fractal->transformCommon.functionEnabledCz) temp38 = fabs(temp38);
temp38 = box - temp38;
temp39 = max(max(temp38.x, temp38.y), temp38.z);
double temp40 = min(min(temp38.x, temp38.y), temp38.z);
temp39 = temp39 + temp40 * fractal->transformCommon.offsetA0;
temp39 *= fractal->transformCommon.scaleE1;
}
boxTrap = temp36 + temp39;
}
// sphere trap
if (fractal->transformCommon.functionEnabledzFalse)
{
double sphereR2 = fractal->transformCommon.maxR2d1;
double temp45 = z.Dot(z);
double temp46 = sphereR2 - temp45;
double temp47 = temp46;
double temp51 = temp46;
if (fractal->transformCommon.functionEnabledAx) temp51 = fabs(temp51);
temp51 *= fractal->transformCommon.scaleF1;
if (fractal->transformCommon.functionEnabledyFalse && temp45 > sphereR2)
{
temp46 *= temp46 * fractal->transformCommon.scaleG1;
}
if (fractal->transformCommon.functionEnabledPFalse && temp45 < sphereR2)
{
temp47 *= temp47 * fractal->transformCommon.scaleB1;
}
sphereTrap = temp51 + temp47 + temp46;
}
// plane bias
if (fractal->transformCommon.functionEnabledAzFalse)
{
CVector4 tempP = z;
if (fractal->transformCommon.functionEnabledEFalse)
{
tempP.x = tempP.x * tempP.y;
tempP.x *= tempP.x;
}
else
{
tempP.x = fabs(tempP.x * tempP.y);
}
if (fractal->transformCommon.functionEnabledFFalse)
{
tempP.y = tempP.y * tempP.z;
tempP.y *= tempP.y;
}
else
{
tempP.y = fabs(tempP.y * tempP.z);
}
if (fractal->transformCommon.functionEnabledKFalse)
{
tempP.z = tempP.z * tempP.x;
tempP.z *= tempP.z;
}
else
{
tempP.z = fabs(tempP.z * tempP.x);
}
tempP = tempP * fractal->transformCommon.scale3D000;
planeBias = tempP.x + tempP.y + tempP.z;
}
}
// build componentMaster
componentMaster =
(R2 + distEst + planeBias + lengthIter + linearOffset + boxTrap + addI + sphereTrap + lastDist);
componentMaster *= fractal->transformCommon.scaleA1;
aux.colorHybrid = componentMaster;
if (fractal->surfBox.enabledZ2False)
{
if (componentMaster < aux.temp100) // )
{
aux.temp100 = componentMaster;
}
minValue = aux.temp100;
aux.colorHybrid += (minValue - aux.colorHybrid);
// aux.colorHybrid * (1.0 - fractal->surfBox.scale1Z1) + (minValue *
// fractal->surfBox.scale1Z1);
}
}
/**
* asurf trial beta
* amazing surf from Mandelbulber3D. Formula proposed by Kali, with features added by DarkBeam
*
* Note for the original version apply a c.x c.y SWAP
*
* @reference
* http://www.fractalforums.com/mandelbulb-3d/custom-formulas-and-transforms-release-t17106/
*/
void TestingIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
double colorAdd = 0.0;
CVector4 c = aux.const_c;
// rotate c
/*if (fractal->transformCommon.rotationEnabled && aux.i >=
fractal->transformCommon.startIterationsG
&& aux.i < fractal->transformCommon.stopIterationsG)
{
aux.c = fractal->transformCommon.rotationMatrix.RotateVector(aux.c);
z += aux.c;
}*/
if (fractal->transformCommon.addCpixelEnabledFalse
&& aux.i >= fractal->transformCommon.startIterationsH
&& aux.i < fractal->transformCommon.stopIterationsH)
{
CVector4 tempC = aux.const_c;
if (fractal->transformCommon.alternateEnabledFalse) // alternate
{
tempC = aux.c;
switch (fractal->mandelbulbMulti.orderOfXYZ)
{
case multi_OrderOfXYZ_xyz:
default: tempC = CVector4(tempC.x, tempC.y, tempC.z, tempC.w); break;
case multi_OrderOfXYZ_xzy: tempC = CVector4(tempC.x, tempC.z, tempC.y, tempC.w); break;
case multi_OrderOfXYZ_yxz: tempC = CVector4(tempC.y, tempC.x, tempC.z, tempC.w); break;
case multi_OrderOfXYZ_yzx: tempC = CVector4(tempC.y, tempC.z, tempC.x, tempC.w); break;
case multi_OrderOfXYZ_zxy: tempC = CVector4(tempC.z, tempC.x, tempC.y, tempC.w); break;
case multi_OrderOfXYZ_zyx: tempC = CVector4(tempC.z, tempC.y, tempC.x, tempC.w); break;
}
aux.c = tempC;
}
else
{
switch (fractal->mandelbulbMulti.orderOfXYZ)
{
case multi_OrderOfXYZ_xyz:
default: tempC = CVector4(c.x, c.y, c.z, c.w); break;
case multi_OrderOfXYZ_xzy: tempC = CVector4(c.x, c.z, c.y, c.w); break;
case multi_OrderOfXYZ_yxz: tempC = CVector4(c.y, c.x, c.z, c.w); break;
case multi_OrderOfXYZ_yzx: tempC = CVector4(c.y, c.z, c.x, c.w); break;
case multi_OrderOfXYZ_zxy: tempC = CVector4(c.z, c.x, c.y, c.w); break;
case multi_OrderOfXYZ_zyx: tempC = CVector4(c.z, c.y, c.x, c.w); break;
}
}
if (fractal->transformCommon.rotationEnabled
&& aux.i >= fractal->transformCommon.startIterationsG
&& aux.i < fractal->transformCommon.stopIterationsG)
{
tempC = fractal->transformCommon.rotationMatrix.RotateVector(tempC);
}
z += tempC * fractal->transformCommon.constantMultiplier111;
}
// invert c
if (fractal->transformCommon.functionEnabledCxFalse
&& aux.i >= fractal->transformCommon.startIterationsF
&& aux.i < fractal->transformCommon.stopIterationsF)
{
if (fractal->transformCommon.functionEnabledCyFalse)
{
aux.c *= fractal->transformCommon.scale3D111;
double rSqrL = aux.c.Dot(aux.c);
rSqrL = 1.0 / rSqrL;
aux.c *= rSqrL;
z += aux.c;
}
else
{
c *= fractal->transformCommon.scale3D111;
double rSqrL = c.Dot(c);
rSqrL = 1.0 / rSqrL;
z += c * rSqrL;
}
}
CVector4 oldZ = z;
bool functionEnabledN[5] = {fractal->transformCommon.functionEnabledAx,
fractal->transformCommon.functionEnabledAyFalse,
fractal->transformCommon.functionEnabledAzFalse};
int startIterationN[5] = {fractal->transformCommon.startIterationsA,
fractal->transformCommon.startIterationsB, fractal->transformCommon.startIterationsC,
fractal->transformCommon.startIterationsD, fractal->transformCommon.startIterationsE};
int stopIterationN[5] = {fractal->transformCommon.stopIterationsA,
fractal->transformCommon.stopIterationsB, fractal->transformCommon.stopIterationsC,
fractal->transformCommon.stopIterationsD, fractal->transformCommon.stopIterationsE};
enumMulti_orderOfFolds foldN[5] = {fractal->surfFolds.orderOfFolds1,
fractal->surfFolds.orderOfFolds2, fractal->surfFolds.orderOfFolds3,
fractal->surfFolds.orderOfFolds4, fractal->surfFolds.orderOfFolds5};
for (int f = 0; f < 5; f++)
{
if (functionEnabledN[f] && aux.i >= startIterationN[f] && aux.i < stopIterationN[f])
{
switch (foldN[f])
{
case multi_orderOfFolds_type1: // tglad fold
default:
z.x = fabs(z.x + fractal->transformCommon.additionConstant111.x)
- fabs(z.x - fractal->transformCommon.additionConstant111.x) - z.x;
z.y = fabs(z.y + fractal->transformCommon.additionConstant111.y)
- fabs(z.y - fractal->transformCommon.additionConstant111.y) - z.y;
if (z.x != oldZ.x)
colorAdd += fractal->mandelbox.color.factor.x
* (fabs(z.x) - fractal->transformCommon.offset111.x);
if (z.y != oldZ.y)
colorAdd += fractal->mandelbox.color.factor.y
* (fabs(z.y) - fractal->transformCommon.offset111.y);
if (fractal->transformCommon.functionEnabledCzFalse
&& aux.i >= fractal->transformCommon.startIterationsT
&& aux.i < fractal->transformCommon.stopIterationsT1)
{
CVector4 limit = fractal->transformCommon.additionConstant111;
CVector4 length = 2.0 * limit;
CVector4 tgladS = 1.0 / length;
CVector4 Add;
Add.w = 0.0;
if (fabs(z.x) < limit.x) Add.x = z.x * z.x * tgladS.x;
if (fabs(z.y) < limit.y) Add.y = z.y * z.y * tgladS.y;
// if (fabs(z.z) < limit.z) Add.z = z.z * z.z * tgladS.z;
if (fabs(z.x) > limit.x && fabs(z.x) < length.x)
Add.x = (length.x - fabs(z.x)) * (length.x - fabs(z.x)) * tgladS.x;
if (fabs(z.y) > limit.y && fabs(z.y) < length.y)
Add.y = (length.y - fabs(z.y)) * (length.y - fabs(z.y)) * tgladS.y;
// if (fabs(z.z) > limit.z && fabs(z.z) < length.z)
// Add.z = (length.z - fabs(z.z)) * (length.z - fabs(z.z)) * tgladS.z;
Add *= fractal->transformCommon.scale3D000;
z.x = (z.x - (sign(z.x) * (Add.x)));
z.y = (z.y - (sign(z.y) * (Add.y)));
// z.z = (z.z - (sign(z.z) * (Add.z)));
}
break;
case multi_orderOfFolds_type2: // z = fold - fabs( fabs(z) - fold)
z.x = fractal->transformCommon.additionConstant111.x
- fabs(fabs(z.x) - fractal->transformCommon.offset111.x);
z.y = fractal->transformCommon.additionConstant111.y
- fabs(fabs(z.y) - fractal->transformCommon.offset111.y);
if (z.x != oldZ.x)
colorAdd += fractal->mandelbox.color.factor.x
* (fabs(z.x) - fractal->transformCommon.offset111.x);
if (z.y != oldZ.y)
colorAdd += fractal->mandelbox.color.factor.y
* (fabs(z.y) - fractal->transformCommon.offset111.y);
break;
case multi_orderOfFolds_type3:
// z = fold2 - fabs( fabs(z + fold) - fold2) - fabs(fold)
z.x = fractal->transformCommon.offset2
- fabs(fabs(z.x + fractal->transformCommon.offsetA111.x)
- fractal->transformCommon.offset2)
- fractal->transformCommon.offsetA111.x;
z.y = fractal->transformCommon.offset2
- fabs(fabs(z.y + fractal->transformCommon.offsetA111.y)
- fractal->transformCommon.offset2)
- fractal->transformCommon.offsetA111.y;
if (z.x != oldZ.x)
colorAdd += fractal->mandelbox.color.factor.x
* (fabs(z.x) - fractal->transformCommon.offset111.x);
if (z.y != oldZ.y)
colorAdd += fractal->mandelbox.color.factor.y
* (fabs(z.y) - fractal->transformCommon.offset111.y);
break;
}
}
}
// enable z axis
if (fractal->transformCommon.functionEnabledAxFalse)
{
z.z = fabs(z.z + fractal->transformCommon.additionConstant111.z)
- fabs(z.z - fractal->transformCommon.additionConstant111.z) - z.z;
if (z.z != oldZ.z)
colorAdd +=
fractal->mandelbox.color.factor.z * (fabs(z.z) - fractal->transformCommon.offset111.z);
}
// swap
if (fractal->transformCommon.functionEnabledSwFalse)
{
z = CVector4(z.y, z.x, z.z, z.w);
}
// offset
if (fractal->transformCommon.functionEnabledBzFalse
&& aux.i >= fractal->transformCommon.startIterationsX
&& aux.i < fractal->transformCommon.stopIterationsX)
{
if (fractal->transformCommon.functionEnabledBxFalse)
{
CVector4 temp = fractal->transformCommon.additionConstant000;
CVector4 temp2 = temp * temp;
z.x -= ((temp.x * temp2.x) / ((z.x * z.x) + (temp2.x)) - 2.0 * temp.x)
* fractal->transformCommon.scale1;
z.y -= ((temp.y * temp2.y) / ((z.y * z.y) + (temp2.y)) - 2.0 * temp.y)
* fractal->transformCommon.scale1;
z.z -= ((temp.z * temp2.z) / ((z.z * z.z) + (temp2.z)) - 2.0 * temp.z)
* fractal->transformCommon.scale1;
}
else if (fractal->transformCommon.functionEnabledByFalse)
{
CVector4 temp = fractal->transformCommon.additionConstant000;
CVector4 temp2 = temp * temp;
z.x -= ((temp2.x) / ((z.x * z.x) + (temp2.x)) - 2.0 * temp.x)
* fractal->transformCommon.scale1; // * sign(z.x);
z.y -= ((temp2.y) / ((z.y * z.y) + (temp2.y)) - 2.0 * temp.y)
* fractal->transformCommon.scale1; // * sign(z.y);
z.z -= ((temp2.z) / ((z.z * z.z) + (temp2.z)) - 2.0 * temp.z)
* fractal->transformCommon.scale1; // * sign(z.z);
}
}
else
z += fractal->transformCommon.additionConstant000;
// standard functions
if (fractal->transformCommon.functionEnabledAy)
{
double rr = z.Dot(z);
if (fractal->transformCommon.functionEnabledFalse) // force cylinder fold
rr -= z.z * z.z * fractal->transformCommon.scaleB1; // fold weight
// Mandelbox Spherical fold
if (aux.i >= fractal->transformCommon.startIterationsM
&& aux.i < fractal->transformCommon.stopIterationsM)
{
z += fractal->mandelbox.offset;
// if (r2 < 1e-21) r2 = 1e-21;
if (rr < fractal->transformCommon.minR2p25)
{
double tglad_factor1 = fractal->transformCommon.maxR2d1 / fractal->transformCommon.minR2p25;
z *= tglad_factor1;
aux.DE *= tglad_factor1;
colorAdd += fractal->mandelbox.color.factorSp1 * (fractal->transformCommon.minR2p25 - rr);
}
else if (rr < fractal->transformCommon.maxR2d1)
{
double tglad_factor2 = fractal->transformCommon.maxR2d1 / rr;
z *= tglad_factor2;
aux.DE *= tglad_factor2;
colorAdd += fractal->mandelbox.color.factorSp2 * (fractal->transformCommon.maxR2d1 - rr);
}
z -= fractal->mandelbox.offset;
}
if (aux.i >= fractal->transformCommon.startIterationsS
&& aux.i < fractal->transformCommon.stopIterationsS)
{ // scale
z *= fractal->mandelbox.scale;
aux.DE = aux.DE * fabs(fractal->mandelbox.scale) + 1.0;
}
}
if (fractal->mandelbox.mainRotationEnabled && aux.i >= fractal->transformCommon.startIterationsR
&& aux.i < fractal->transformCommon.stopIterationsR)
z = fractal->mandelbox.mainRot.RotateVector(z);
if (fractal->foldColor.auxColorEnabledFalse)
{
aux.color += colorAdd;
}
}
/**
* 4D boxbulb, Formula based on Mandelbox (ABox). Extended to 4 dimensions and with variable scale
* parameter.
* This formula contains aux.color and aux.actualScale
*/
void Testing4dIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
double colorAdd = 0.0;
double rrCol = 0.0;
CVector4 zCol = z;
CVector4 oldZ = z;
// parabolic.w = paraOffset + iter *slope + (iter *iter *scale)
double paraAddP0 = 0.0;
if (fractal->Cpara.enabledParabFalse)
{
double parabScale = 0.0;
if (fractal->Cpara.parabScale != 0.0)
parabScale = aux.i * aux.i * 0.001 * fractal->Cpara.parabScale;
paraAddP0 = fractal->Cpara.parabOffset0 + (aux.i * fractal->Cpara.parabSlope) + (parabScale);
z.w += paraAddP0;
}
// sinusoidal w
double sinAdd = 0.0;
if (fractal->transformCommon.functionEnabledDFalse)
{
sinAdd = sin((aux.i + fractal->transformCommon.offset0) / fractal->transformCommon.scaleA1)
* fractal->transformCommon.scaleC1;
z.w += sinAdd;
}
/* CVector4 temp = fractal->transformCommon.offset0000;
CVector4 temp2 = temp * temp;
z.x += ((8.0 * temp.x * temp2.x) / ((z.x * z.x) + (4.0 * temp2.x)) - 2.0 * temp.x) * sign(z.x) *
fractal->transformCommon.scale1;
z.y += ((8.0 * temp.y * temp2.y) / ((z.y * z.y) + (4.0 * temp2.y)) - 2.0 * temp.y) * sign(z.y) *
fractal->transformCommon.scale1;
z.z += ((8.0 * temp.z * temp2.z) / ((z.z * z.z) + (4.0 * temp2.z)) - 2.0 * temp.z) * sign(z.z) *
fractal->transformCommon.scale1;
z.w += ((8.0 * temp.w * temp2.w) / ((z.w * z.w) + (4.0 * temp2.w)) - 2.0 * temp.w) * sign(z.w) *
fractal->transformCommon.scale1*/
if (aux.i >= fractal->transformCommon.startIterationsB
&& aux.i < fractal->transformCommon.stopIterationsB)
{
oldZ = z;
z.x = fabs(z.x + fractal->transformCommon.offset1111.x)
- fabs(z.x - fractal->transformCommon.offset1111.x) - z.x;
z.y = fabs(z.y + fractal->transformCommon.offset1111.y)
- fabs(z.y - fractal->transformCommon.offset1111.y) - z.y;
z.z = fabs(z.z + fractal->transformCommon.offset1111.z)
- fabs(z.z - fractal->transformCommon.offset1111.z) - z.z;
z.w = fabs(z.w + fractal->transformCommon.offset1111.w)
- fabs(z.w - fractal->transformCommon.offset1111.w) - z.w;
zCol = z;
}
CVector4 temp = fractal->transformCommon.offset0000;
CVector4 temp2 = temp * temp;
// if (z.w < 1e-016) z.w = 1e-016;
if (z.w < 1e-21 && z.w > -1e-21) z.w = (z.w > 0) ? 1e-21 : -1e-21;
z.x += ((8.0 * temp.x * temp2.x) / ((z.x * z.x) + (4.0 * temp2.x)) - 2.0 * temp.x) * sign(z.x)
* fractal->transformCommon.scale1;
z.y += ((8.0 * temp.y * temp2.y) / ((z.y * z.y) + (4.0 * temp2.y)) - 2.0 * temp.y) * sign(z.y)
* fractal->transformCommon.scale1;
z.z += ((8.0 * temp.z * temp2.z) / ((z.z * z.z) + (4.0 * temp2.z)) - 2.0 * temp.z) * sign(z.z)
* fractal->transformCommon.scale1;
z.w += ((8.0 * temp.w * temp2.w) / ((z.w * z.w) + (4.0 * temp2.w)) - 2.0 * temp.w) * sign(z.w)
* fractal->transformCommon.scale1;
// r power
if (aux.i >= fractal->transformCommon.startIterationsS
&& aux.i < fractal->transformCommon.stopIterationsS)
{
double rr = z.Dot(z);
rrCol = rr;
if (fractal->mandelboxVary4D.rPower != 1.0) rr = pow(rr, fractal->mandelboxVary4D.rPower);
// spherical fold
// z += fractal->transformCommon.offset0000;
if (rr < fractal->transformCommon.minR2p25)
{
z *= fractal->transformCommon.maxMinR2factor;
aux.DE *= fractal->transformCommon.maxMinR2factor;
// colorAdd += fractal->mandelbox.color.factorSp1 * (fractal->transformCommon.minR2p25 - rr);
}
else if (rr < fractal->transformCommon.maxR2d1)
{
z *= fractal->transformCommon.maxR2d1 / rr;
aux.DE *= fractal->transformCommon.maxR2d1 / rr;
// colorAdd += fractal->mandelbox.color.factorSp2 * (rr - fractal->transformCommon.minR2p25);
}
/*else
colorAdd += fractal->mandelbox.color.factorSp2
* (fractal->transformCommon.maxR2d1 - fractal->transformCommon.minR2p25);*/
// z -= fractal->transformCommon.offset0000;
}
// scale
double useScale = 1.0;
if (aux.i >= fractal->transformCommon.startIterationsC
&& aux.i < fractal->transformCommon.stopIterationsC)
{
useScale = aux.actualScaleA + fractal->transformCommon.scale;
z *= useScale;
aux.DE = aux.DE * fabs(useScale);
if (aux.i >= fractal->transformCommon.startIterationsX
&& aux.i < fractal->transformCommon.stopIterationsX)
{
// update actualScale for next iteration
double vary = fractal->transformCommon.scaleVary0
* (fabs(aux.actualScaleA) - fractal->transformCommon.scaleB1);
if (fractal->transformCommon.functionEnabledMFalse)
aux.actualScaleA = -vary;
else
aux.actualScaleA = aux.actualScaleA - vary;
}
}
// 6 plane rotation
if (fractal->transformCommon.functionEnabledRFalse
&& aux.i >= fractal->transformCommon.startIterationsR
&& aux.i < fractal->transformCommon.stopIterationsR)
{
CVector4 tp;
if (fractal->transformCommon.rotation44a.x != 0)
{
tp = z;
double alpha = fractal->transformCommon.rotation44a.x * M_PI_180;
z.x = tp.x * cos(alpha) + tp.y * sin(alpha);
z.y = tp.x * -sin(alpha) + tp.y * cos(alpha);
}
if (fractal->transformCommon.rotation44a.y != 0)
{
tp = z;
double beta = fractal->transformCommon.rotation44a.y * M_PI_180;
z.y = tp.y * cos(beta) + tp.z * sin(beta);
z.z = tp.y * -sin(beta) + tp.z * cos(beta);
}
if (fractal->transformCommon.rotation44a.z != 0)
{
tp = z;
double gamma = fractal->transformCommon.rotation44a.z * M_PI_180;
z.x = tp.x * cos(gamma) + tp.z * sin(gamma);
z.z = tp.x * -sin(gamma) + tp.z * cos(gamma);
}
if (fractal->transformCommon.rotation44b.x != 0)
{
tp = z;
double delta = fractal->transformCommon.rotation44b.x * M_PI_180;
z.x = tp.x * cos(delta) + tp.w * sin(delta);
z.w = tp.x * -sin(delta) + tp.w * cos(delta);
}
if (fractal->transformCommon.rotation44b.y != 0)
{
tp = z;
double epsilon = fractal->transformCommon.rotation44b.y * M_PI_180;
z.y = tp.y * cos(epsilon) + tp.w * sin(epsilon);
z.w = tp.y * -sin(epsilon) + tp.w * cos(epsilon);
}
if (fractal->transformCommon.rotation44b.z != 0)
{
tp = z;
double zeta = fractal->transformCommon.rotation44b.z * M_PI_180;
z.z = tp.z * cos(zeta) + tp.w * sin(zeta);
z.w = tp.z * -sin(zeta) + tp.w * cos(zeta);
}
}
z += fractal->transformCommon.additionConstant0000;
/*CVector4 temp = fractal->transformCommon.offset0000;
CVector4 temp2 = temp * temp;
z.x += ((8.0 * temp.x * temp2.x) / ((z.x * z.x) + (4.0 * temp2.x)) - 2.0 * temp.x) * sign(z.x)
* fractal->transformCommon.scale1;
z.y += ((8.0 * temp.y * temp2.y) / ((z.y * z.y) + (4.0 * temp2.y)) - 2.0 * temp.y) * sign(z.y)
* fractal->transformCommon.scale1;
z.z += ((8.0 * temp.z * temp2.z) / ((z.z * z.z) + (4.0 * temp2.z)) - 2.0 * temp.z) * sign(z.z)
* fractal->transformCommon.scale1;
z.w += ((8.0 * temp.w * temp2.w) / ((z.w * z.w) + (4.0 * temp2.w)) - 2.0 * temp.w) * sign(z.w)
* fractal->transformCommon.scale1;*/
if (aux.i >= fractal->transformCommon.startIterationsA
&& aux.i < fractal->transformCommon.stopIterationsA)
{
aux.r = z.Length();
aux.DE = aux.r * aux.DE * 16.0 * fractal->analyticDE.scale1
* sqrt(fractal->foldingIntPow.zFactor * fractal->foldingIntPow.zFactor + 2.0
+ fractal->analyticDE.offset2)
/ SQRT_3
+ fractal->analyticDE.offset1;
z = z * 2.0;
double x2 = z.x * z.x;
double y2 = z.y * z.y;
double z2 = z.z * z.z;
double temp = 1.0 - z2 / (x2 + y2);
CVector4 zTemp;
zTemp.x = (x2 - y2) * temp;
zTemp.y = 2.0 * z.x * z.y * temp;
zTemp.z = -2.0 * z.z * sqrt(x2 + y2);
zTemp.w = z.w;
z = zTemp;
z.z *= fractal->foldingIntPow.zFactor;
}
// color updated v2.13 & mode2 v2.14
if (fractal->foldColor.auxColorEnabledFalse)
{
if (fractal->transformCommon.functionEnabledCxFalse)
{
if (zCol.x != oldZ.x)
colorAdd +=
fractal->mandelbox.color.factor.x * (fabs(zCol.x) - fractal->mandelbox.color.factor4D.x);
if (zCol.y != oldZ.y)
colorAdd +=
fractal->mandelbox.color.factor.y * (fabs(zCol.y) - fractal->mandelbox.color.factor4D.y);
if (zCol.z != oldZ.z)
colorAdd +=
fractal->mandelbox.color.factor.z * (fabs(zCol.z) - fractal->mandelbox.color.factor4D.z);
if (zCol.w != oldZ.w)
colorAdd +=
fractal->mandelbox.color.factor.z * (fabs(zCol.w) - fractal->mandelbox.color.factor4D.w);
if (rrCol < fractal->transformCommon.maxR2d1)
{
if (rrCol < fractal->transformCommon.minR2p25)
colorAdd +=
fractal->mandelbox.color.factorSp1 * (fractal->transformCommon.minR2p25 - rrCol)
+ fractal->mandelbox.color.factorSp2
* (fractal->transformCommon.maxR2d1 - fractal->transformCommon.minR2p25);
else
colorAdd +=
fractal->mandelbox.color.factorSp2 * (fractal->transformCommon.maxR2d1 - rrCol);
}
}
else
{
if (zCol.x != oldZ.x) colorAdd += fractal->mandelbox.color.factor4D.x;
if (zCol.y != oldZ.y) colorAdd += fractal->mandelbox.color.factor4D.y;
if (zCol.z != oldZ.z) colorAdd += fractal->mandelbox.color.factor4D.z;
if (zCol.w != oldZ.w) colorAdd += fractal->mandelbox.color.factor4D.w;
if (rrCol < fractal->transformCommon.minR2p25)
colorAdd += fractal->mandelbox.color.factorSp1;
else if (rrCol < fractal->transformCommon.maxR2d1)
colorAdd += fractal->mandelbox.color.factorSp2;
}
aux.color += colorAdd;
}
}
/**
*
* quadratic iteration in real or imaginary scator algebra
* @reference
* http://www.fractalforums.com/new-theories-and-research/
* ix-possibly-the-holy-grail-fractal-%28in-fff-lore%29
* https://luz.izt.uam.mx/drupal/en/fractals/ix
* @author Manuel Fernandez-Guasti
*/
void TestingLogIteration(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
{
CVector4 c = aux.const_c;
CVector4 oldZ = z;
// if
{
CVector4 zz = z * z;
// double r = aux.r;
// log DE calc
if (fractal->analyticDE.enabled)
{
double r = sqrt(zz.x + zz.y + zz.z + (zz.y * zz.z) / zz.x);
if (fractal->transformCommon.functionEnabledXFalse) r = z.Length();
if (fractal->transformCommon.functionEnabledyFalse)
r = max(fabs(z.z), max(fabs(z.y), fabs(z.x)));
if (fractal->transformCommon.functionEnabledzFalse)
{
CVector4 zz = z * z;
r = sqrt(max(zz.x + zz.y, max(zz.y + zz.z, zz.x + zz.z)));
}
aux.DE = r * aux.DE * 2.0 * fractal->analyticDE.scale1 + fractal->analyticDE.offset1;
}
// r = max(fabs(z.z), max(fabs(z.y), fabs(z.x)));
// CVector4 zz = z * z;
// r = sqrt(max(zz.x + zz.y, max(zz.y + zz.z, zz.x + zz.z)))
CVector4 newZ = z;
if (fractal->transformCommon.functionEnabledFalse)
/*{
aux.DE = aux.DE * 2.0 * r;
double temp = 1.0 - zz.z / (zz.x + zz.y);
newZ.x = (zz.x - zz.y) * temp;
newZ.y = z.x * z.y * temp;
newZ.z = -z.z * sqrt(zz.x + zz.y);
newZ.x += (zz.y * zz.z) / zz.x;
newZ.y *= (1.0 - zz.z / zz.x);
newZ.z *= (1.0 - zz.y / zz.x);
newZ *= fractal->transformCommon.constantMultiplier122; //vec3 (1,2,2)
z = newZ;
{
Q_UNUSED(fractal);
Q_UNUSED(aux);
double x2 = z.x * z.x; // + 1e-061;
double y2 = z.y * z.y;
double z2 = z.z * z.z;
double newx = x2 - y2 - z2 + (y2 * z2) / x2;
double newy = 2.0 * z.x * z.y * (1.0 - z2 / x2);
double newz = 2.0 * z.x * z.z * (1.0 - y2 / x2);
z.x = newx;
z.y = newy;
z.z = newz;
}
}*/
{
newZ.x = zz.x - zz.y - zz.z;
newZ.y = z.x * z.y;
newZ.z = z.x * z.z;
newZ *= fractal->transformCommon.constantMultiplier122; // vec3 (1,2,2)
if (fractal->transformCommon.functionEnabledDFalse)
{
newZ += c * fractal->transformCommon.additionConstant000;
}
CVector4 scaleScat = fractal->transformCommon.constantMultiplierA111; // vec3 (1,1,1)
newZ.x += scaleScat.x * (zz.y * zz.z / zz.x);
newZ.y *= 1.0 - (scaleScat.y * (zz.z / zz.x));
newZ.z *= 1.0 - (scaleScat.z * (zz.y / zz.x));
if (fractal->transformCommon.functionEnabledSFalse)
{ // rev
zz = newZ * newZ;
newZ.x -= (zz.y * zz.z) / zz.x;
newZ.y /= (1.0 - zz.z / zz.x);
newZ.z /= (1.0 - zz.y / zz.x);
}
z = newZ;
}
else
{
newZ.x = zz.x + zz.y + zz.z; // + (zz.y * zz.z) / zz.x;
newZ.y = z.x * z.y; //* (1.0 + zz.z / zz.x);
newZ.z = z.x * z.z; // * (1.0 + zz.y / zz.x);
newZ *= fractal->transformCommon.constantMultiplier122;
if (fractal->transformCommon.functionEnabledDFalse)
{
newZ += c * fractal->transformCommon.additionConstant000;
}
CVector4 scaleScat = fractal->transformCommon.constantMultiplierA111; // vec3 (1,1,1)
newZ.x += scaleScat.x * (zz.y * zz.z / zz.x);
newZ.y *= 1.0 + (scaleScat.y * (zz.z / zz.x));
newZ.z *= 1.0 + (scaleScat.z * (zz.y / zz.x));
// aux.DE = aux.DE * 2.0 * aux.r;
// double tempL = z.Length();
// if (tempL < 1e-21) tempL = 1e-21;
// CVector4 tempAvgScale = CVector4(z.x, z.y / 2.0, z.z / 2.0, z.w);
// double avgScale = tempAvgScale.Length() / tempL;
// double tempAux = aux.DE * avgScale;
// aux.DE = aux.DE + (tempAux - aux.DE) * fractal->transformCommon.scaleA1;
// newZ += fractal->transformCommon.additionConstant000;
if (fractal->transformCommon.functionEnabledSFalse)
{
zz = newZ * newZ;
newZ.x -= (zz.y * zz.z) / zz.x;
newZ.y /= (1.0 + zz.z / zz.x);
newZ.z /= (1.0 + zz.y / zz.x);
}
z = newZ;
double lengthRatio = oldZ.Length() / z.Length();
aux.DE *= lengthRatio;
}
}
// addCpixel
if (fractal->transformCommon.addCpixelEnabledFalse
&& aux.i >= fractal->transformCommon.startIterationsE
&& aux.i < fractal->transformCommon.stopIterationsE)
{
CVector4 tempC = c;
if (fractal->transformCommon.alternateEnabledFalse) // alternate swap
{
tempC = aux.c;
if (fractal->transformCommon.addCpixelEnabled)
{
CVector4 cc = tempC * tempC;
CVector4 newC = tempC;
if (fractal->transformCommon.functionEnabledFalse)
{
newC.x += (cc.y * cc.z) / cc.x;
newC.y *= (1.0 - cc.z / cc.x);
newC.z *= (1.0 - cc.y / cc.x);
}
else
{
newC.x += (cc.y * cc.z) / cc.x;
newC.y *= (1.0 + cc.z / cc.x);
newC.z *= (1.0 + cc.y / cc.x);
}
tempC = newC;
}
switch (fractal->mandelbulbMulti.orderOfXYZ)
{
case multi_OrderOfXYZ_xyz:
default: tempC = CVector4(tempC.x, tempC.y, tempC.z, tempC.w); break;
case multi_OrderOfXYZ_xzy: tempC = CVector4(tempC.x, tempC.z, tempC.y, tempC.w); break;
case multi_OrderOfXYZ_yxz: tempC = CVector4(tempC.y, tempC.x, tempC.z, tempC.w); break;
case multi_OrderOfXYZ_yzx: tempC = CVector4(tempC.y, tempC.z, tempC.x, tempC.w); break;
case multi_OrderOfXYZ_zxy: tempC = CVector4(tempC.z, tempC.x, tempC.y, tempC.w); break;
case multi_OrderOfXYZ_zyx: tempC = CVector4(tempC.z, tempC.y, tempC.x, tempC.w); break;
}
aux.c = tempC;
}
else
{
if (fractal->transformCommon.addCpixelEnabled) // standard swap
{
CVector4 cc = c * c;
CVector4 newC = c;
if (fractal->transformCommon.functionEnabledFalse)
{
newC.x += 1.0 - (cc.y * cc.z) / cc.x;
// newC.x = c.x; // /(cc.y * cc.z);
// newC.x = (cc.y * cc.z) / cc.x;
newC.y *= (1.0 - cc.z / cc.x);
newC.z *= (1.0 - cc.y / cc.x);
}
else
{
// newC.x = c.x + (cc.y * cc.z) / cc.x;
newC.x = c.x; // /(cc.y * cc.z);
// newC.x = (cc.y * cc.z) / cc.x;
newC.y *= c.y * (1.0 + cc.z / cc.x);
newC.z *= c.z * (1.0 + cc.y / cc.x);
// newC.y = (1.0 + cc.z / cc.x);
// newC.z = (1.0 + cc.y / cc.x);
}
c = newC;
}
switch (fractal->mandelbulbMulti.orderOfXYZ)
{
case multi_OrderOfXYZ_xyz:
default: tempC = CVector4(c.x, c.y, c.z, c.w); break;
case multi_OrderOfXYZ_xzy: tempC = CVector4(c.x, c.z, c.y, c.w); break;
case multi_OrderOfXYZ_yxz: tempC = CVector4(c.y, c.x, c.z, c.w); break;
case multi_OrderOfXYZ_yzx: tempC = CVector4(c.y, c.z, c.x, c.w); break;
case multi_OrderOfXYZ_zxy: tempC = CVector4(c.z, c.x, c.y, c.w); break;
case multi_OrderOfXYZ_zyx: tempC = CVector4(c.z, c.y, c.x, c.w); break;
}
}
z += tempC * fractal->transformCommon.constantMultiplier111;
}
/*double r = aux.r;
if (fractal->transformCommon.functionEnabledXFalse)
{
r = z.Length();
}
else
{
CVector4 zz = z * z;
r = sqrt(zz.x + zz.y + zz.z + (zz.y * zz.z) / (zz.x));
}
aux.DE = r * aux.DE * 2.0 * fractal->analyticDE.scale1 + fractal->analyticDE.offset1;*/
}