1/**
2 * Mandelbulber v2, a 3D fractal generator  _%}}i*<.        ____                _______
3 * Copyright (C) 2021 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 * Mandelbox fractal known as AmazingBox or ABox, invented by Tom Lowe in 2010
10 * Variable parameters over iteration time
11 * Based on work by Tglad, Buddhi, DarkBeam
12 * @reference
13 * http://www.fractalforums.com/ifs-iterated-function-systems/amazing-fractal/msg12467/#msg12467
14 * This formula contains aux.color and aux.actualScaleA
15
16 * This file has been autogenerated by tools/populateUiInformation.php
17 * from the file "fractal_mandelbox_variable.cpp" in the folder formula/definition
18 * D O    N O T    E D I T    T H I S    F I L E !
19 */
20
21REAL4 MandelboxVariableIteration(REAL4 z, __constant sFractalCl *fractal, sExtendedAuxCl *aux)
22{
23	REAL colorAdd = 0.0f;
24	REAL rrCol = 0.0f;
25	REAL4 zCol = z;
26	REAL4 oldZ = z;
27	REAL4 limit4 = fractal->transformCommon.additionConstant111;
28	REAL4 value4 = 2.0f * fractal->transformCommon.additionConstant111;
29	if (fractal->transformCommon.functionEnabledFalse)
30		value4 = fractal->transformCommon.additionConstant222;
31
32	if (fractal->mandelbox.rotationsEnabled)
33	{ // TODO evaluate implementation of vec3 limit and value
34		/*	REAL4 zRot;
35			// cast vector to array pointer for address taking of components in opencl
36			REAL *zRotP = (REAL *)&zRot;
37			__constant REAL *colP = (__constant REAL *)&fractal->mandelbox.color.factor;
38			for (int dim = 0; dim < 3; dim++)
39			{
40				// handle each dimension x, y and z sequentially in pointer var dim
41				REAL *rotDim = (dim == 0) ? &zRotP[0] : ((dim == 1) ? &zRotP[1] : &zRotP[2]);
42				__constant REAL *colorFactor = (dim == 0) ? &colP[0] : ((dim == 1) ? &colP[1] : &colP[2]);
43
44				zRot = Matrix33MulFloat4(fractal->mandelbox.rot[0][dim], z);
45				if (*rotDim > fractal->mandelbox.foldingLimit)
46				{
47					*rotDim = fractal->mandelbox.foldingValue - *rotDim;
48					z = Matrix33MulFloat4(fractal->mandelbox.rotinv[0][dim], zRot);
49					aux->color += *colorFactor;
50				}
51				else
52				{
53					zRot = Matrix33MulFloat4(fractal->mandelbox.rot[1][dim], z);
54					if (*rotDim < -fractal->mandelbox.foldingLimit)
55					{
56						*rotDim = -fractal->mandelbox.foldingValue - *rotDim;
57						z = Matrix33MulFloat4(fractal->mandelbox.rotinv[1][dim], zRot);
58						aux->color += *colorFactor;
59					}
60				}
61			}*/
62	}
63	else
64	{
65		if (!fractal->transformCommon.functionEnabledCyFalse)
66		{
67			z = fabs(z + limit4) - fabs(z - limit4) - z;
68			zCol = z;
69		}
70		else //  variable limit values
71		{
72			if (fractal->transformCommon.functionEnabledAx)
73			{
74				if (aux->i > fractal->transformCommon.startIterationsC)
75				{
76					limit4.x *= (1.0f
77												- 1.0f
78														/ (1.0f
79															 + (aux->i - fractal->transformCommon.startIterationsC)
80																	 / fractal->transformCommon.offsetA000.x))
81											* fractal->transformCommon.scale3D111.x;
82				}
83				z.x = fabs(z.x + limit4.x) - fabs(z.x - limit4.x) - z.x;
84			}
85			if (fractal->transformCommon.functionEnabledAy)
86			{
87				if (aux->i > fractal->transformCommon.startIterationsY)
88				{
89					limit4.y *= (1.0f
90												- 1.0f
91														/ (1.0f
92															 + (aux->i - fractal->transformCommon.startIterationsY)
93																	 / fractal->transformCommon.offsetA000.y))
94											* fractal->transformCommon.scale3D111.y;
95				}
96				z.y = fabs(z.y + limit4.y) - fabs(z.y - limit4.y) - z.y;
97			}
98			if (fractal->transformCommon.functionEnabledAz)
99			{
100				if (aux->i > fractal->transformCommon.startIterationsZ)
101				{
102					limit4.z *= (1.0f
103												- 1.0f
104														/ (1.0f
105															 + (aux->i - fractal->transformCommon.startIterationsZ)
106																	 / fractal->transformCommon.offsetA000.z))
107											* fractal->transformCommon.scale3D111.z;
108				}
109				z.z = fabs(z.z + limit4.z) - fabs(z.z - limit4.z) - z.z;
110			}
111			zCol = z;
112		}
113	}
114
115	// spherical folding
116	REAL maxR2use = fractal->transformCommon.maxR2d1;
117	REAL minR2use = fractal->transformCommon.minR2p25;
118	// vary maxR2
119	if (fractal->transformCommon.functionEnabledEFalse)
120	{
121		if (aux->i > fractal->transformCommon.startIterationsB)
122		{
123			maxR2use *= (1.0f
124										- 1.0f
125												/ (1.0f
126													 + (aux->i - fractal->transformCommon.startIterationsB)
127															 / fractal->transformCommon.offsetA0))
128									* fractal->transformCommon.scaleA1;
129		}
130	}
131	// vary minR2
132	if (fractal->transformCommon.functionEnabledDFalse)
133	{
134		if (aux->i > fractal->transformCommon.startIterationsA)
135		{
136			minR2use *= (1.0f
137										- 1.0f
138												/ (1.0f
139													 + (aux->i - fractal->transformCommon.startIterationsA)
140															 / fractal->transformCommon.offset0))
141									* fractal->transformCommon.scale1;
142		}
143	}
144
145	REAL rr = dot(z, z);
146	rrCol = rr;
147	// Mandelbox Spherical fold
148
149	z += fractal->mandelbox.offset;
150
151	// if (r2 < 1e-21f) r2 = 1e-21f;
152	if (rr < minR2use)
153	{
154		REAL tglad_factor1 = maxR2use / minR2use;
155		z *= tglad_factor1;
156		aux->DE *= tglad_factor1;
157	}
158	else if (rr < maxR2use)
159	{
160		REAL tglad_factor2 = maxR2use / rr;
161		z *= tglad_factor2;
162		aux->DE *= tglad_factor2;
163	}
164	z -= fractal->mandelbox.offset;
165
166	// 3D Rotation
167	if (fractal->mandelbox
168				.mainRotationEnabled) // z = Matrix33MulFloat4(fractal->mandelbox.mainRot, z);
169	{
170		REAL4 tempVC = (REAL4){fractal->mandelbox.rotationMain.x, fractal->mandelbox.rotationMain.y,
171			fractal->mandelbox.rotationMain.z, 0.0f}; // constant to be varied
172		if (fractal->transformCommon.functionEnabledPFalse)
173		{
174			if (aux->i >= fractal->transformCommon.startIterations
175					&& aux->i < fractal->transformCommon.stopIterations
176					&& (fractal->transformCommon.stopIterations - fractal->transformCommon.startIterations
177							!= 0))
178			{
179				REAL iterationRange =
180					fractal->transformCommon.stopIterations - fractal->transformCommon.startIterations;
181				REAL currentIteration = (aux->i - fractal->transformCommon.startIterations);
182				tempVC += fractal->transformCommon.offset000 * currentIteration / iterationRange;
183			}
184
185			if (aux->i >= fractal->transformCommon.stopIterations)
186			{
187				tempVC += tempVC + fractal->transformCommon.offset000;
188			}
189		}
190
191		tempVC *= M_PI_180_F;
192
193		z = RotateAroundVectorByAngle4(z, (REAL3){1.0f, 0.0f, 0.0f}, tempVC.x);
194		z = RotateAroundVectorByAngle4(z, (REAL3){0.0f, 1.0f, 0.0f}, tempVC.y);
195		z = RotateAroundVectorByAngle4(z, (REAL3){0.0f, 0.0f, 1.0f}, tempVC.z);
196	}
197
198	// scale
199	REAL useScale = 1.0f;
200	{
201		useScale = aux->actualScaleA + fractal->mandelbox.scale;
202
203		z *= useScale;
204		aux->DE = aux->DE * fabs(useScale) + 1.0f;
205		if (fractal->transformCommon.functionEnabledFFalse
206				&& aux->i >= fractal->transformCommon.startIterationsX
207				&& aux->i < fractal->transformCommon.stopIterationsX)
208		{
209			// update actualScaleA for next iteration
210			REAL vary = fractal->transformCommon.scaleVary0
211									* (fabs(aux->actualScaleA) - fractal->transformCommon.scaleB1);
212			if (fractal->transformCommon.functionEnabledNFalse)
213				aux->actualScaleA = -vary;
214			else
215				aux->actualScaleA = aux->actualScaleA - vary;
216		}
217	}
218	// add cpixel
219	REAL4 c = aux->const_c;
220
221	if (fractal->transformCommon.addCpixelEnabledFalse
222			&& aux->i >= fractal->transformCommon.startIterationsH
223			&& aux->i < fractal->transformCommon.stopIterationsH)
224	{
225		REAL4 tempC = aux->const_c;
226		if (fractal->transformCommon.alternateEnabledFalse) // alternate
227		{
228			tempC = aux->c;
229			switch (fractal->mandelbulbMulti.orderOfXYZ)
230			{
231				case multi_OrderOfXYZCl_xyz:
232				default: tempC = (REAL4){tempC.x, tempC.y, tempC.z, tempC.w}; break;
233				case multi_OrderOfXYZCl_xzy: tempC = (REAL4){tempC.x, tempC.z, tempC.y, tempC.w}; break;
234				case multi_OrderOfXYZCl_yxz: tempC = (REAL4){tempC.y, tempC.x, tempC.z, tempC.w}; break;
235				case multi_OrderOfXYZCl_yzx: tempC = (REAL4){tempC.y, tempC.z, tempC.x, tempC.w}; break;
236				case multi_OrderOfXYZCl_zxy: tempC = (REAL4){tempC.z, tempC.x, tempC.y, tempC.w}; break;
237				case multi_OrderOfXYZCl_zyx: tempC = (REAL4){tempC.z, tempC.y, tempC.x, tempC.w}; break;
238			}
239			aux->c = tempC;
240		}
241		else
242		{
243			switch (fractal->mandelbulbMulti.orderOfXYZ)
244			{
245				case multi_OrderOfXYZCl_xyz:
246				default: tempC = (REAL4){c.x, c.y, c.z, c.w}; break;
247				case multi_OrderOfXYZCl_xzy: tempC = (REAL4){c.x, c.z, c.y, c.w}; break;
248				case multi_OrderOfXYZCl_yxz: tempC = (REAL4){c.y, c.x, c.z, c.w}; break;
249				case multi_OrderOfXYZCl_yzx: tempC = (REAL4){c.y, c.z, c.x, c.w}; break;
250				case multi_OrderOfXYZCl_zxy: tempC = (REAL4){c.z, c.x, c.y, c.w}; break;
251				case multi_OrderOfXYZCl_zyx: tempC = (REAL4){c.z, c.y, c.x, c.w}; break;
252			}
253		}
254		// rotate c
255		if (fractal->transformCommon.rotationEnabled
256				&& aux->i >= fractal->transformCommon.startIterationsG
257				&& aux->i < fractal->transformCommon.stopIterationsG)
258		{
259			tempC = Matrix33MulFloat4(fractal->transformCommon.rotationMatrix, tempC);
260		}
261		// vary c
262		if (fractal->transformCommon.functionEnabledMFalse)
263		{
264			if (fractal->transformCommon.functionEnabledx)
265			{
266				if (aux->i > fractal->transformCommon.startIterationsM)
267				{
268					tempC.x *= (1.0f
269											 - 1.0f
270													 / (1.0f
271															+ (aux->i - fractal->transformCommon.startIterationsM)
272																	/ fractal->transformCommon.offsetF000.x))
273										 * fractal->transformCommon.constantMultiplierB111.x;
274				}
275			}
276			if (fractal->transformCommon.functionEnabledy)
277			{
278				if (aux->i > fractal->transformCommon.startIterationsO)
279				{
280					tempC.y *= (1.0f
281											 - 1.0f
282													 / (1.0f
283															+ (aux->i - fractal->transformCommon.startIterationsO)
284																	/ fractal->transformCommon.offsetF000.y))
285										 * fractal->transformCommon.constantMultiplierB111.y;
286				}
287			}
288			if (fractal->transformCommon.functionEnabledz)
289			{
290				if (aux->i > fractal->transformCommon.startIterationsP)
291				{
292					tempC.z *= (1.0f
293											 - 1.0f
294													 / (1.0f
295															+ (aux->i - fractal->transformCommon.startIterationsP)
296																	/ fractal->transformCommon.offsetF000.z))
297										 * fractal->transformCommon.constantMultiplierB111.z;
298				}
299			}
300		}
301		z += tempC * fractal->transformCommon.constantMultiplier111;
302	}
303
304	// DE tweak
305	if (fractal->analyticDE.enabledFalse)
306		aux->DE = aux->DE * fractal->analyticDE.scale1 + fractal->analyticDE.offset0;
307
308	// color updated v2.13 & mode2 v2.14
309	if (fractal->foldColor.auxColorEnabledFalse)
310	{
311		if (fractal->transformCommon.functionEnabledCxFalse)
312		{
313			if (zCol.x != oldZ.x)
314				colorAdd += fractal->mandelbox.color.factor.x
315										* (fabs(zCol.x) - fractal->transformCommon.additionConstant111.x);
316			if (zCol.y != oldZ.y)
317				colorAdd += fractal->mandelbox.color.factor.y
318										* (fabs(zCol.y) - fractal->transformCommon.additionConstant111.y);
319			if (zCol.z != oldZ.z)
320				colorAdd += fractal->mandelbox.color.factor.z
321										* (fabs(zCol.z) - fractal->transformCommon.additionConstant111.z);
322
323			if (rrCol < fractal->transformCommon.maxR2d1)
324			{
325				if (rrCol < fractal->transformCommon.minR2p25)
326					colorAdd +=
327						fractal->mandelbox.color.factorSp1 * (fractal->transformCommon.minR2p25 - rrCol)
328						+ fractal->mandelbox.color.factorSp2
329								* (fractal->transformCommon.maxR2d1 - fractal->transformCommon.minR2p25);
330				else
331					colorAdd +=
332						fractal->mandelbox.color.factorSp2 * (fractal->transformCommon.maxR2d1 - rrCol);
333			}
334		}
335		else
336		{
337			if (zCol.x != oldZ.x) colorAdd += fractal->mandelbox.color.factor.x;
338			if (zCol.y != oldZ.y) colorAdd += fractal->mandelbox.color.factor.y;
339			if (zCol.z != oldZ.z) colorAdd += fractal->mandelbox.color.factor.z;
340
341			if (rrCol < fractal->transformCommon.minR2p25)
342				colorAdd += fractal->mandelbox.color.factorSp1;
343			else if (rrCol < fractal->transformCommon.maxR2d1)
344				colorAdd += fractal->mandelbox.color.factorSp2;
345		}
346		aux->color += colorAdd;
347	}
348	return z;
349}