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  * BoxBulb power 2 V3  with scaling of z axis
10  * This formula contains aux.color and aux.actualScaleA
11  */
12 
13 #include "all_fractal_definitions.h"
14 
cFractalBoxFoldBulbPow2V3()15 cFractalBoxFoldBulbPow2V3::cFractalBoxFoldBulbPow2V3() : cAbstractFractal()
16 {
17 	nameInComboBox = "Box Fold Bulb Pow 2 V3";
18 	internalName = "box_fold_bulb_pow2_v3";
19 	internalID = fractal::boxFoldBulbPow2V3;
20 	DEType = analyticDEType;
21 	DEFunctionType = logarithmicDEFunction;
22 	cpixelAddition = cpixelEnabledByDefault;
23 	defaultBailout = 100.0;
24 	DEAnalyticFunction = analyticFunctionLogarithmic;
25 	coloringFunction = coloringFunctionDefault;
26 }
27 
FormulaCode(CVector4 & z,const sFractal * fractal,sExtendedAux & aux)28 void cFractalBoxFoldBulbPow2V3::FormulaCode(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
29 {
30 	// sphere inversion
31 	if (fractal->transformCommon.sphereInversionEnabledFalse
32 			&& aux.i >= fractal->transformCommon.startIterations
33 			&& aux.i < fractal->transformCommon.stopIterations1)
34 	{
35 		double rr = 1.0;
36 		z += fractal->transformCommon.offset000;
37 		rr = z.Dot(z);
38 		z *= fractal->transformCommon.scaleG1 / rr;
39 		aux.DE *= (fractal->transformCommon.scaleG1 / rr);
40 		z += fractal->transformCommon.additionConstant000 - fractal->transformCommon.offset000;
41 		z *= fractal->transformCommon.scaleA1;
42 		aux.DE *= fractal->transformCommon.scaleA1;
43 	}
44 
45 	// CVector4 c = aux.const_c;
46 	double colorAdd = 0.0;
47 	double rrCol = 0.0;
48 	CVector4 zCol = z;
49 	CVector4 oldZ = z;
50 
51 	// tglad fold
52 	if (aux.i >= fractal->transformCommon.startIterationsB
53 			&& aux.i < fractal->transformCommon.stopIterationsB)
54 	{
55 		z.x = fabs(z.x + fractal->transformCommon.additionConstant111.x)
56 					- fabs(z.x - fractal->transformCommon.additionConstant111.x) - z.x;
57 		z.y = fabs(z.y + fractal->transformCommon.additionConstant111.y)
58 					- fabs(z.y - fractal->transformCommon.additionConstant111.y) - z.y;
59 		z.z = fabs(z.z + fractal->transformCommon.additionConstant111.z)
60 					- fabs(z.z - fractal->transformCommon.additionConstant111.z) - z.z;
61 		zCol = z;
62 	}
63 
64 	// spherical fold
65 	if (aux.i >= fractal->transformCommon.startIterationsS
66 			&& aux.i < fractal->transformCommon.stopIterationsS)
67 	{
68 		double rr = z.Dot(z);
69 		rrCol = rr;
70 		z += fractal->mandelbox.offset;
71 
72 		// if (r2 < 1e-21) r2 = 1e-21;
73 		if (rr < fractal->transformCommon.minR2p25)
74 		{
75 			double tglad_factor1 = fractal->transformCommon.maxR2d1 / fractal->transformCommon.minR2p25;
76 			z *= tglad_factor1;
77 			aux.DE *= tglad_factor1;
78 		}
79 		else if (rr < fractal->transformCommon.maxR2d1)
80 		{
81 			double tglad_factor2 = fractal->transformCommon.maxR2d1 / rr;
82 			z *= tglad_factor2;
83 			aux.DE *= tglad_factor2;
84 		}
85 		z -= fractal->mandelbox.offset;
86 	}
87 	// scale
88 	if (aux.i >= fractal->transformCommon.startIterationsC
89 			&& aux.i < fractal->transformCommon.stopIterationsC)
90 	{
91 
92 		double useScale = aux.actualScaleA + fractal->transformCommon.scale;
93 
94 		z *= useScale;
95 		aux.DE = aux.DE * fabs(useScale);
96 
97 		if (aux.i >= fractal->transformCommon.startIterationsX
98 				&& aux.i < fractal->transformCommon.stopIterationsX)
99 		{
100 			// update actualScale for next iteration
101 			double vary = fractal->transformCommon.scaleVary0
102 										* (fabs(aux.actualScaleA) - fractal->transformCommon.scaleB1);
103 			if (fractal->transformCommon.functionEnabledMFalse)
104 				aux.actualScaleA = -vary;
105 			else
106 				aux.actualScaleA = aux.actualScaleA - vary;
107 		}
108 	}
109 
110 	if (fractal->transformCommon.functionEnabledXFalse
111 			&& aux.i >= fractal->transformCommon.startIterationsTM
112 			&& aux.i < fractal->transformCommon.stopIterationsTM1)
113 	{
114 		double tempXZ = z.x * SQRT_2_3 - z.z * SQRT_1_3;
115 		z = CVector4(
116 			(tempXZ - z.y) * SQRT_1_2, (tempXZ + z.y) * SQRT_1_2, z.x * SQRT_1_3 + z.z * SQRT_2_3, z.w);
117 		CVector4 temp = z;
118 		double tempL = temp.Length();
119 		z = fabs(z) * fractal->transformCommon.scale3D333;
120 		// if (tempL < 1e-21) tempL = 1e-21;
121 		double avgScale = z.Length() / tempL;
122 		aux.DE = aux.DE * avgScale;
123 		z = (fabs(z + fractal->transformCommon.additionConstantA111)
124 				 - fabs(z - fractal->transformCommon.additionConstantA111) - z);
125 		tempXZ = (z.y + z.x) * SQRT_1_2;
126 		z = CVector4(z.z * SQRT_1_3 + tempXZ * SQRT_2_3, (z.y - z.x) * SQRT_1_2,
127 			z.z * SQRT_2_3 - tempXZ * SQRT_1_3, z.w);
128 	}
129 
130 	// octo
131 	if (fractal->transformCommon.functionEnabledDFalse
132 			&& aux.i >= fractal->transformCommon.startIterationsD
133 			&& aux.i < fractal->transformCommon.stopIterationsD)
134 
135 	{
136 		if (z.x + z.y < 0.0) z = CVector4(-z.y, -z.x, z.z, z.w);
137 
138 		if (z.x + z.z < 0.0) // z.xz = -z.zx;
139 			z = CVector4(-z.z, z.y, -z.x, z.w);
140 
141 		if (z.x - z.y < 0.0) // z.xy = z.yx;
142 			z = CVector4(z.y, z.x, z.z, z.w);
143 
144 		if (z.x - z.z < 0.0) // z.xz = z.zx;
145 			z = CVector4(z.z, z.y, z.x, z.w);
146 
147 		z.x = fabs(z.x);
148 		z = z * fractal->transformCommon.scaleA2
149 				- fractal->transformCommon.offset100 * (fractal->transformCommon.scaleA2 - 1.0);
150 		aux.DE *= fabs(fractal->transformCommon.scaleA2);
151 	}
152 
153 	if (fractal->transformCommon.functionEnabledRFalse
154 			&& aux.i >= fractal->transformCommon.startIterationsR
155 			&& aux.i < fractal->transformCommon.stopIterationsR)
156 		z = fractal->transformCommon.rotationMatrix.RotateVector(z);
157 
158 	if (fractal->transformCommon.functionEnabledFFalse
159 			&& aux.i >= fractal->transformCommon.startIterationsM
160 			&& aux.i < fractal->transformCommon.stopIterationsM)
161 	{ // fabs() and menger fold
162 		z = fabs(z + fractal->transformCommon.additionConstantA000);
163 		if (z.x - z.y < 0.0) swap(z.y, z.x);
164 		if (z.x - z.z < 0.0) swap(z.z, z.x);
165 		if (z.y - z.z < 0.0) swap(z.z, z.y);
166 		// menger scales and offsets
167 		z *= fractal->transformCommon.scale3;
168 		z.x -= 2.0 * fractal->transformCommon.constantMultiplier111.x;
169 		z.y -= 2.0 * fractal->transformCommon.constantMultiplier111.y;
170 		if (fractal->transformCommon.functionEnabled)
171 		{
172 			if (z.z > 1.0) z.z -= 2.0 * fractal->transformCommon.constantMultiplier111.z;
173 		}
174 		else
175 		{
176 			z.z -= 2.0 * fractal->transformCommon.constantMultiplier111.z;
177 		}
178 		aux.DE *= fractal->transformCommon.scale3;
179 	}
180 
181 	if (aux.i >= fractal->transformCommon.startIterationsA
182 			&& aux.i < fractal->transformCommon.stopIterationsA)
183 	{
184 		aux.r = z.Length();
185 
186 		if (fractal->analyticDE.enabledFalse)
187 		{
188 			aux.DE = aux.r * aux.DE * 10.0 * fractal->analyticDE.scale1
189 								 * sqrt(fractal->foldingIntPow.zFactor * fractal->foldingIntPow.zFactor + 2.0
190 												+ fractal->analyticDE.offset2)
191 							 + fractal->analyticDE.offset1;
192 		}
193 		else
194 		{
195 			aux.DE = aux.r * aux.DE * 16.0 * fractal->analyticDE.scale1
196 								 * sqrt(fractal->foldingIntPow.zFactor * fractal->foldingIntPow.zFactor + 2.0
197 												+ fractal->analyticDE.offset2)
198 								 / SQRT_3
199 							 + fractal->analyticDE.offset1;
200 		}
201 
202 		z *= 2.0;
203 		double x2 = z.x * z.x;
204 		double y2 = z.y * z.y;
205 		double z2 = z.z * z.z;
206 		double temp = 1.0 - z2 / (x2 + y2);
207 		CVector4 zTemp;
208 		zTemp.x = (x2 - y2) * temp;
209 		zTemp.y = 2.0 * z.x * z.y * temp;
210 		zTemp.z = -2.0 * z.z * sqrt(x2 + y2);
211 		zTemp.w = z.w;
212 		z = zTemp;
213 		z.z *= fractal->foldingIntPow.zFactor;
214 	}
215 	if (fractal->foldColor.auxColorEnabledFalse)
216 	{
217 		if (zCol.x != oldZ.x)
218 			colorAdd += fractal->mandelbox.color.factor.x
219 									* (fabs(zCol.x) - fractal->transformCommon.additionConstant111.x);
220 		if (zCol.y != oldZ.y)
221 			colorAdd += fractal->mandelbox.color.factor.y
222 									* (fabs(zCol.y) - fractal->transformCommon.additionConstant111.y);
223 		if (zCol.z != oldZ.z)
224 			colorAdd += fractal->mandelbox.color.factor.z
225 									* (fabs(zCol.z) - fractal->transformCommon.additionConstant111.z);
226 
227 		if (rrCol < fractal->transformCommon.maxR2d1)
228 		{
229 			if (rrCol < fractal->transformCommon.minR2p25)
230 				colorAdd += fractal->mandelbox.color.factorSp1 * (fractal->transformCommon.minR2p25 - rrCol)
231 										+ fractal->mandelbox.color.factorSp2
232 												* (fractal->transformCommon.maxR2d1 - fractal->transformCommon.minR2p25);
233 			else
234 				colorAdd += fractal->mandelbox.color.factorSp2 * (fractal->transformCommon.maxR2d1 - rrCol);
235 		}
236 
237 		aux.color += colorAdd;
238 	}
239 }
240