1 /** 2 * Mandelbulber v2, a 3D fractal generator _%}}i*<. ______ 3 * Copyright (C) 2020 Mandelbulber Team _>]|=||i=i<, / ____/ __ __ 4 * \><||i|=>>%) / / __/ /___/ /_ 5 * This file is part of Mandelbulber. )<=i=]=|=i<> / /__ /_ __/_ __/ 6 * The project is licensed under GPLv3, -<>>=|><|||` \____/ /_/ /_/ 7 * see also COPYING file in this folder. ~+{i%+++ 8 * 9 * 4D boxbulb, Formula based on Mandelbox (ABox). Extended to 4 dimensions and with variable scale 10 * parameter. 11 * This formula contains aux.color and aux.actualScale 12 */ 13 14 #include "all_fractal_definitions.h" 15 cFractalTesting4d()16cFractalTesting4d::cFractalTesting4d() : cAbstractFractal() 17 { 18 nameInComboBox = "Testing4d"; 19 internalName = "testing4d"; 20 internalID = fractal::testing4d; 21 DEType = analyticDEType; 22 DEFunctionType = logarithmicDEFunction; 23 cpixelAddition = cpixelEnabledByDefault; 24 defaultBailout = 100.0; 25 DEAnalyticFunction = analyticFunctionLogarithmic; 26 coloringFunction = coloringFunctionDefault; 27 } 28 FormulaCode(CVector4 & z,const sFractal * fractal,sExtendedAux & aux)29void cFractalTesting4d::FormulaCode(CVector4 &z, const sFractal *fractal, sExtendedAux &aux) 30 { 31 double colorAdd = 0.0; 32 double rrCol = 0.0; 33 CVector4 zCol = z; 34 CVector4 oldZ = z; 35 36 // parabolic.w = paraOffset + iter *slope + (iter *iter *scale) 37 double paraAddP0 = 0.0; 38 if (fractal->Cpara.enabledParabFalse) 39 { 40 double parabScale = 0.0; 41 if (fractal->Cpara.parabScale != 0.0) 42 parabScale = aux.i * aux.i * 0.001 * fractal->Cpara.parabScale; 43 paraAddP0 = fractal->Cpara.parabOffset0 + (aux.i * fractal->Cpara.parabSlope) + (parabScale); 44 z.w += paraAddP0; 45 } 46 47 // sinusoidal w 48 double sinAdd = 0.0; 49 if (fractal->transformCommon.functionEnabledDFalse) 50 { 51 sinAdd = sin((aux.i + fractal->transformCommon.offset0) / fractal->transformCommon.scaleA1) 52 * fractal->transformCommon.scaleC1; 53 z.w += sinAdd; 54 } 55 56 /* CVector4 temp = fractal->transformCommon.offset0000; 57 CVector4 temp2 = temp * temp; 58 59 z.x += ((8.0 * temp.x * temp2.x) / ((z.x * z.x) + (4.0 * temp2.x)) - 2.0 * temp.x) * sign(z.x) * 60 fractal->transformCommon.scale1; 61 z.y += ((8.0 * temp.y * temp2.y) / ((z.y * z.y) + (4.0 * temp2.y)) - 2.0 * temp.y) * sign(z.y) * 62 fractal->transformCommon.scale1; 63 z.z += ((8.0 * temp.z * temp2.z) / ((z.z * z.z) + (4.0 * temp2.z)) - 2.0 * temp.z) * sign(z.z) * 64 fractal->transformCommon.scale1; 65 z.w += ((8.0 * temp.w * temp2.w) / ((z.w * z.w) + (4.0 * temp2.w)) - 2.0 * temp.w) * sign(z.w) * 66 fractal->transformCommon.scale1*/ 67 68 if (aux.i >= fractal->transformCommon.startIterationsB 69 && aux.i < fractal->transformCommon.stopIterationsB) 70 { 71 oldZ = z; 72 z.x = fabs(z.x + fractal->transformCommon.offset1111.x) 73 - fabs(z.x - fractal->transformCommon.offset1111.x) - z.x; 74 z.y = fabs(z.y + fractal->transformCommon.offset1111.y) 75 - fabs(z.y - fractal->transformCommon.offset1111.y) - z.y; 76 z.z = fabs(z.z + fractal->transformCommon.offset1111.z) 77 - fabs(z.z - fractal->transformCommon.offset1111.z) - z.z; 78 z.w = fabs(z.w + fractal->transformCommon.offset1111.w) 79 - fabs(z.w - fractal->transformCommon.offset1111.w) - z.w; 80 zCol = z; 81 } 82 CVector4 temp = fractal->transformCommon.offset0000; 83 CVector4 temp2 = temp * temp; 84 // if (z.w < 1e-016) z.w = 1e-016; 85 if (z.w < 1e-21 && z.w > -1e-21) z.w = (z.w > 0) ? 1e-21 : -1e-21; 86 z.x += ((8.0 * temp.x * temp2.x) / ((z.x * z.x) + (4.0 * temp2.x)) - 2.0 * temp.x) * sign(z.x) 87 * fractal->transformCommon.scale1; 88 z.y += ((8.0 * temp.y * temp2.y) / ((z.y * z.y) + (4.0 * temp2.y)) - 2.0 * temp.y) * sign(z.y) 89 * fractal->transformCommon.scale1; 90 z.z += ((8.0 * temp.z * temp2.z) / ((z.z * z.z) + (4.0 * temp2.z)) - 2.0 * temp.z) * sign(z.z) 91 * fractal->transformCommon.scale1; 92 z.w += ((8.0 * temp.w * temp2.w) / ((z.w * z.w) + (4.0 * temp2.w)) - 2.0 * temp.w) * sign(z.w) 93 * fractal->transformCommon.scale1; 94 95 // r power 96 if (aux.i >= fractal->transformCommon.startIterationsS 97 && aux.i < fractal->transformCommon.stopIterationsS) 98 { 99 double rr = z.Dot(z); 100 rrCol = rr; 101 if (fractal->mandelboxVary4D.rPower != 1.0) rr = pow(rr, fractal->mandelboxVary4D.rPower); 102 103 // spherical fold 104 // z += fractal->transformCommon.offset0000; 105 if (rr < fractal->transformCommon.minR2p25) 106 { 107 z *= fractal->transformCommon.maxMinR2factor; 108 aux.DE *= fractal->transformCommon.maxMinR2factor; 109 // colorAdd += fractal->mandelbox.color.factorSp1 * (fractal->transformCommon.minR2p25 - rr); 110 } 111 else if (rr < fractal->transformCommon.maxR2d1) 112 { 113 z *= fractal->transformCommon.maxR2d1 / rr; 114 aux.DE *= fractal->transformCommon.maxR2d1 / rr; 115 // colorAdd += fractal->mandelbox.color.factorSp2 * (rr - fractal->transformCommon.minR2p25); 116 } 117 /*else 118 colorAdd += fractal->mandelbox.color.factorSp2 119 * (fractal->transformCommon.maxR2d1 - fractal->transformCommon.minR2p25);*/ 120 121 // z -= fractal->transformCommon.offset0000; 122 } 123 124 // scale 125 double useScale = 1.0; 126 if (aux.i >= fractal->transformCommon.startIterationsC 127 && aux.i < fractal->transformCommon.stopIterationsC) 128 { 129 130 useScale = aux.actualScaleA + fractal->transformCommon.scale; 131 132 z *= useScale; 133 aux.DE = aux.DE * fabs(useScale); 134 135 if (aux.i >= fractal->transformCommon.startIterationsX 136 && aux.i < fractal->transformCommon.stopIterationsX) 137 { 138 // update actualScale for next iteration 139 double vary = fractal->transformCommon.scaleVary0 140 * (fabs(aux.actualScaleA) - fractal->transformCommon.scaleB1); 141 if (fractal->transformCommon.functionEnabledMFalse) 142 aux.actualScaleA = -vary; 143 else 144 aux.actualScaleA = aux.actualScaleA - vary; 145 } 146 } 147 148 // 6 plane rotation 149 if (fractal->transformCommon.functionEnabledRFalse 150 && aux.i >= fractal->transformCommon.startIterationsR 151 && aux.i < fractal->transformCommon.stopIterationsR) 152 { 153 CVector4 tp; 154 if (fractal->transformCommon.rotation44a.x != 0) 155 { 156 tp = z; 157 double alpha = fractal->transformCommon.rotation44a.x * M_PI_180; 158 z.x = tp.x * cos(alpha) + tp.y * sin(alpha); 159 z.y = tp.x * -sin(alpha) + tp.y * cos(alpha); 160 } 161 if (fractal->transformCommon.rotation44a.y != 0) 162 { 163 tp = z; 164 double beta = fractal->transformCommon.rotation44a.y * M_PI_180; 165 z.y = tp.y * cos(beta) + tp.z * sin(beta); 166 z.z = tp.y * -sin(beta) + tp.z * cos(beta); 167 } 168 if (fractal->transformCommon.rotation44a.z != 0) 169 { 170 tp = z; 171 double gamma = fractal->transformCommon.rotation44a.z * M_PI_180; 172 z.x = tp.x * cos(gamma) + tp.z * sin(gamma); 173 z.z = tp.x * -sin(gamma) + tp.z * cos(gamma); 174 } 175 if (fractal->transformCommon.rotation44b.x != 0) 176 { 177 tp = z; 178 double delta = fractal->transformCommon.rotation44b.x * M_PI_180; 179 z.x = tp.x * cos(delta) + tp.w * sin(delta); 180 z.w = tp.x * -sin(delta) + tp.w * cos(delta); 181 } 182 if (fractal->transformCommon.rotation44b.y != 0) 183 { 184 tp = z; 185 double epsilon = fractal->transformCommon.rotation44b.y * M_PI_180; 186 z.y = tp.y * cos(epsilon) + tp.w * sin(epsilon); 187 z.w = tp.y * -sin(epsilon) + tp.w * cos(epsilon); 188 } 189 if (fractal->transformCommon.rotation44b.z != 0) 190 { 191 tp = z; 192 double zeta = fractal->transformCommon.rotation44b.z * M_PI_180; 193 z.z = tp.z * cos(zeta) + tp.w * sin(zeta); 194 z.w = tp.z * -sin(zeta) + tp.w * cos(zeta); 195 } 196 } 197 z += fractal->transformCommon.additionConstant0000; 198 199 /*CVector4 temp = fractal->transformCommon.offset0000; 200 CVector4 temp2 = temp * temp; 201 202 z.x += ((8.0 * temp.x * temp2.x) / ((z.x * z.x) + (4.0 * temp2.x)) - 2.0 * temp.x) * sign(z.x) 203 * fractal->transformCommon.scale1; 204 z.y += ((8.0 * temp.y * temp2.y) / ((z.y * z.y) + (4.0 * temp2.y)) - 2.0 * temp.y) * sign(z.y) 205 * fractal->transformCommon.scale1; 206 z.z += ((8.0 * temp.z * temp2.z) / ((z.z * z.z) + (4.0 * temp2.z)) - 2.0 * temp.z) * sign(z.z) 207 * fractal->transformCommon.scale1; 208 z.w += ((8.0 * temp.w * temp2.w) / ((z.w * z.w) + (4.0 * temp2.w)) - 2.0 * temp.w) * sign(z.w) 209 * fractal->transformCommon.scale1;*/ 210 211 if (aux.i >= fractal->transformCommon.startIterationsA 212 && aux.i < fractal->transformCommon.stopIterationsA) 213 { 214 aux.r = z.Length(); 215 aux.DE = aux.r * aux.DE * 16.0 * fractal->analyticDE.scale1 216 * sqrt(fractal->foldingIntPow.zFactor * fractal->foldingIntPow.zFactor + 2.0 217 + fractal->analyticDE.offset2) 218 / SQRT_3 219 + fractal->analyticDE.offset1; 220 221 z = z * 2.0; 222 double x2 = z.x * z.x; 223 double y2 = z.y * z.y; 224 double z2 = z.z * z.z; 225 double temp = 1.0 - z2 / (x2 + y2); 226 CVector4 zTemp; 227 zTemp.x = (x2 - y2) * temp; 228 zTemp.y = 2.0 * z.x * z.y * temp; 229 zTemp.z = -2.0 * z.z * sqrt(x2 + y2); 230 zTemp.w = z.w; 231 z = zTemp; 232 z.z *= fractal->foldingIntPow.zFactor; 233 } 234 235 // color updated v2.13 & mode2 v2.14 236 if (fractal->foldColor.auxColorEnabledFalse) 237 { 238 if (fractal->transformCommon.functionEnabledCxFalse) 239 { 240 if (zCol.x != oldZ.x) 241 colorAdd += 242 fractal->mandelbox.color.factor.x * (fabs(zCol.x) - fractal->mandelbox.color.factor4D.x); 243 if (zCol.y != oldZ.y) 244 colorAdd += 245 fractal->mandelbox.color.factor.y * (fabs(zCol.y) - fractal->mandelbox.color.factor4D.y); 246 if (zCol.z != oldZ.z) 247 colorAdd += 248 fractal->mandelbox.color.factor.z * (fabs(zCol.z) - fractal->mandelbox.color.factor4D.z); 249 if (zCol.w != oldZ.w) 250 colorAdd += 251 fractal->mandelbox.color.factor.z * (fabs(zCol.w) - fractal->mandelbox.color.factor4D.w); 252 if (rrCol < fractal->transformCommon.maxR2d1) 253 { 254 if (rrCol < fractal->transformCommon.minR2p25) 255 colorAdd += 256 fractal->mandelbox.color.factorSp1 * (fractal->transformCommon.minR2p25 - rrCol) 257 + fractal->mandelbox.color.factorSp2 258 * (fractal->transformCommon.maxR2d1 - fractal->transformCommon.minR2p25); 259 else 260 colorAdd += 261 fractal->mandelbox.color.factorSp2 * (fractal->transformCommon.maxR2d1 - rrCol); 262 } 263 } 264 else 265 { 266 if (zCol.x != oldZ.x) colorAdd += fractal->mandelbox.color.factor4D.x; 267 if (zCol.y != oldZ.y) colorAdd += fractal->mandelbox.color.factor4D.y; 268 if (zCol.z != oldZ.z) colorAdd += fractal->mandelbox.color.factor4D.z; 269 if (zCol.w != oldZ.w) colorAdd += fractal->mandelbox.color.factor4D.w; 270 if (rrCol < fractal->transformCommon.minR2p25) 271 colorAdd += fractal->mandelbox.color.factorSp1; 272 else if (rrCol < fractal->transformCommon.maxR2d1) 273 colorAdd += fractal->mandelbox.color.factorSp2; 274 } 275 aux.color += colorAdd; 276 } 277 } 278