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 * DIFSMultiV1
10 * http://www.iquilezles.org/www/articles/distfunctions/distfunctions.htm
11
12 * This file has been autogenerated by tools/populateUiInformation.php
13 * from the file "fractal_difs_multi_v1.cpp" in the folder formula/definition
14 * D O    N O T    E D I T    T H I S    F I L E !
15 */
16
17REAL4 DIFSMultiV1Iteration(REAL4 z, __constant sFractalCl *fractal, sExtendedAuxCl *aux)
18{
19	REAL colorAdd = 0.0f;
20	REAL4 oldZ = z;
21	REAL4 boxFold = fractal->transformCommon.additionConstantA111;
22
23	// abs
24	if (fractal->transformCommon.functionEnabledAx
25			&& aux->i >= fractal->transformCommon.startIterationsX
26			&& aux->i < fractal->transformCommon.stopIterationsX)
27		z.x = fabs(z.x);
28
29	if (fractal->transformCommon.functionEnabledAy
30			&& aux->i >= fractal->transformCommon.startIterationsY
31			&& aux->i < fractal->transformCommon.stopIterationsY)
32		z.y = fabs(z.y);
33
34	if (fractal->transformCommon.functionEnabledAzFalse
35			&& aux->i >= fractal->transformCommon.startIterationsZ
36			&& aux->i < fractal->transformCommon.stopIterationsZ)
37		z.z = fabs(z.z);
38	if (fractal->transformCommon.functionEnabledFalse)
39	{
40		// xy box fold
41		if (fractal->transformCommon.functionEnabledAFalse
42				&& aux->i >= fractal->transformCommon.startIterationsA
43				&& aux->i < fractal->transformCommon.stopIterationsA)
44		{
45			z.x -= boxFold.x;
46			z.y -= boxFold.y;
47		}
48		// xyz box fold
49		if (fractal->transformCommon.functionEnabledBFalse
50				&& aux->i >= fractal->transformCommon.startIterationsB
51				&& aux->i < fractal->transformCommon.stopIterationsB)
52			z -= boxFold;
53
54		// polyfold
55		if (fractal->transformCommon.functionEnabledPFalse
56				&& aux->i >= fractal->transformCommon.startIterationsP
57				&& aux->i < fractal->transformCommon.stopIterationsP)
58		{
59			z.x = fabs(z.x);
60			REAL psi = M_PI_F / fractal->transformCommon.int6;
61			psi = fabs(fmod(atan2(z.y, z.x) + psi, 2.0f * psi) - psi);
62			REAL len = native_sqrt(z.x * z.x + z.y * z.y);
63			z.x = native_cos(psi) * len;
64			z.y = native_sin(psi) * len;
65		}
66
67		// diag fold1
68		if (fractal->transformCommon.functionEnabledCxFalse
69				&& aux->i >= fractal->transformCommon.startIterationsCx
70				&& aux->i < fractal->transformCommon.stopIterationsCx)
71			if (z.y > z.x)
72			{
73				REAL temp = z.x;
74				z.x = z.y;
75				z.y = temp;
76			}
77
78		// abs offsets
79		if (fractal->transformCommon.functionEnabledCFalse
80				&& aux->i >= fractal->transformCommon.startIterationsC
81				&& aux->i < fractal->transformCommon.stopIterationsC)
82		{
83			REAL xOffset = fractal->transformCommon.offsetC0;
84			if (z.x < xOffset) z.x = fabs(z.x - xOffset) + xOffset;
85		}
86		if (fractal->transformCommon.functionEnabledDFalse
87				&& aux->i >= fractal->transformCommon.startIterationsD
88				&& aux->i < fractal->transformCommon.stopIterationsD)
89		{
90			REAL yOffset = fractal->transformCommon.offsetD0;
91			if (z.y < yOffset) z.y = fabs(z.y - yOffset) + yOffset;
92		}
93
94		// diag fold2
95		if (fractal->transformCommon.functionEnabledCyFalse
96				&& aux->i >= fractal->transformCommon.startIterationsCy
97				&& aux->i < fractal->transformCommon.stopIterationsCy)
98			if (z.y > z.x)
99			{
100				REAL temp = z.x;
101				z.x = z.y;
102				z.y = temp;
103			}
104	}
105
106	// reverse offset part 1
107	if (aux->i >= fractal->transformCommon.startIterationsE
108			&& aux->i < fractal->transformCommon.stopIterationsE)
109		z.x -= fractal->transformCommon.offsetE2;
110
111	if (aux->i >= fractal->transformCommon.startIterationsF
112			&& aux->i < fractal->transformCommon.stopIterationsF)
113		z.y -= fractal->transformCommon.offsetF2;
114
115	// scale
116	REAL useScale = 1.0f;
117	if (aux->i >= fractal->transformCommon.startIterationsS
118			&& aux->i < fractal->transformCommon.stopIterationsS)
119	{
120		useScale = aux->actualScaleA + fractal->transformCommon.scale2;
121		z *= useScale;
122		aux->DE = aux->DE * fabs(useScale) + 1.0f;
123		// else
124
125		if (fractal->transformCommon.functionEnabledKFalse
126				&& aux->i >= fractal->transformCommon.startIterationsK
127				&& aux->i < fractal->transformCommon.stopIterationsK)
128		{
129			// update actualScaleA for next iteration
130			REAL vary = fractal->transformCommon.scaleVary0
131									* (fabs(aux->actualScaleA) - fractal->transformCommon.scaleC1);
132			aux->actualScaleA -= vary;
133		}
134	}
135
136	// reverse offset part 2
137	if (aux->i >= fractal->transformCommon.startIterationsE
138			&& aux->i < fractal->transformCommon.stopIterationsE)
139		z.x += fractal->transformCommon.offsetE2;
140
141	if (aux->i >= fractal->transformCommon.startIterationsF
142			&& aux->i < fractal->transformCommon.stopIterationsF)
143		z.y += fractal->transformCommon.offsetF2;
144
145	// offset
146	z += fractal->transformCommon.offset001;
147
148	// rotation
149	if (fractal->transformCommon.functionEnabledRFalse
150			&& aux->i >= fractal->transformCommon.startIterationsR
151			&& aux->i < fractal->transformCommon.stopIterationsR)
152	{
153		z = Matrix33MulFloat4(fractal->transformCommon.rotationMatrix, z);
154	}
155
156	// DE
157	REAL colorDist = aux->dist;
158	REAL4 zc = oldZ;
159
160	if (fractal->transformCommon.functionEnabledFFalse) zc = z;
161
162	// box
163	if (fractal->transformCommon.functionEnabledM
164			&& aux->i >= fractal->transformCommon.startIterations
165			&& aux->i < fractal->transformCommon.stopIterations)
166	{
167		REAL4 boxSize = fractal->transformCommon.additionConstant111;
168		REAL4 bxV = zc;
169		REAL bxD = 0.0f;
170		bxV = fabs(bxV) - boxSize;
171		bxD = max(bxV.x, max(bxV.y, bxV.z)); // infnorm
172		if (bxD > 0.0f)
173		{
174			bxV.x = max(bxV.x, 0.0f);
175			bxV.y = max(bxV.y, 0.0f);
176			bxV.z = max(bxV.z, 0.0f);
177			aux->DE0 = length(bxV);
178		}
179		aux->dist = min(aux->dist, aux->DE0 / aux->DE);
180	}
181	// sphere
182	if (fractal->transformCommon.functionEnabledMFalse
183			&& aux->i >= fractal->transformCommon.startIterationsM
184			&& aux->i < fractal->transformCommon.stopIterationsM)
185	{
186		aux->DE0 = length(zc) - fractal->transformCommon.offsetR1;
187		aux->dist = min(aux->dist, aux->DE0 / aux->DE);
188	}
189	// cylinder
190	if (fractal->transformCommon.functionEnabledOFalse
191			&& aux->i >= fractal->transformCommon.startIterationsO
192			&& aux->i < fractal->transformCommon.stopIterationsO)
193	{
194		REAL cylD = 0.0f;
195		//- fractal->transformCommon.scale0 * aux->i;
196
197		if (fractal->transformCommon.functionEnabledSwFalse)
198		{
199			REAL temp = zc.x;
200			zc.x = zc.z;
201			zc.z = temp;
202		}
203
204		REAL cylR = native_sqrt(zc.x * zc.x + zc.y * zc.y);
205		REAL cylH = fabs(zc.z) - fractal->transformCommon.offsetA1;
206
207		REAL cylRm = cylR - fractal->transformCommon.radius1;
208
209		if (!fractal->transformCommon.functionEnabledXFalse)
210		{
211			if (!fractal->transformCommon.functionEnabledzFalse) cylR = cylRm;
212			cylR = max(cylR, 0.0f);
213			REAL cylHm = max(cylH, 0.0f);
214			cylD = native_sqrt(cylR * cylR + cylHm * cylHm);
215		}
216		else
217			cylD = native_sqrt(cylRm * cylRm + cylH * cylH);
218
219		aux->DE0 = min(max(cylRm, cylH) - fractal->transformCommon.offsetR0, 0.0f) + cylD;
220		aux->dist = min(aux->dist, aux->DE0 / aux->DE);
221	}
222
223	// torus
224	if (fractal->transformCommon.functionEnabledTFalse
225			&& aux->i >= fractal->transformCommon.startIterationsT
226			&& aux->i < fractal->transformCommon.stopIterationsT)
227	{
228		// swap axis
229		if (fractal->transformCommon.functionEnabledJFalse)
230		{
231			REAL temp = zc.x;
232			zc.x = zc.z;
233			zc.z = temp;
234		}
235
236		REAL T1 = native_sqrt(zc.y * zc.y + zc.x * zc.x) - fractal->transformCommon.offsetT1;
237		aux->DE0 = native_sqrt(T1 * T1 + zc.z * zc.z) - fractal->transformCommon.offset05;
238		aux->dist = min(aux->dist, aux->DE0 / aux->DE);
239	}
240
241	// prism
242	if (fractal->transformCommon.functionEnabledNFalse
243			&& aux->i >= fractal->transformCommon.startIterationsN
244			&& aux->i < fractal->transformCommon.stopIterationsN)
245	{
246		// swap axis
247		if (fractal->transformCommon.functionEnabledEFalse)
248		{
249			REAL temp = zc.x;
250			zc.x = zc.z;
251			zc.z = temp;
252		}
253
254		aux->DE0 = max(fabs(zc.x) - fractal->transformCommon.offset2,
255			max(fabs(zc.y) * SQRT_3_4_F + zc.z * 0.5f, -zc.z) - fractal->transformCommon.offsetA05);
256
257		aux->dist = min(aux->dist, aux->DE0 / aux->DE);
258	}
259
260	// aux->dist tweaks
261	if (fractal->analyticDE.enabledFalse)
262		aux->dist = aux->dist * fractal->analyticDE.scale1 + fractal->analyticDE.offset0;
263
264	// aux->color
265	if (fractal->foldColor.auxColorEnabled)
266	{
267		if (fractal->foldColor.auxColorEnabledFalse)
268		{
269			colorAdd += fractal->foldColor.difs0000.x * fabs(z.x * z.y); // fabs(zc.x * zc.y)
270			colorAdd += fractal->foldColor.difs0000.y * max(z.x, z.y);	 // max(z.x, z.y);
271			colorAdd += fractal->foldColor.difs0000.z * (z.x * z.x + z.y * z.y);
272			colorAdd += fractal->foldColor.difs0000.w * fabs(zc.x * zc.y);
273		}
274		colorAdd += fractal->foldColor.difs1;
275		if (fractal->foldColor.auxColorEnabledA)
276		{
277			if (colorDist != aux->dist) aux->color += colorAdd;
278		}
279		else
280			aux->color += colorAdd;
281	}
282	return z;
283}