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 * from Syntopia & DarkBeam's Menger4 code from M3D
10 * @reference
11 * http://www.fractalforums.com/mandelbulb-3d/custom-formulas-and-transforms-release-t17106/
12
13 * This file has been autogenerated by tools/populateUiInformation.php
14 * from the file "fractal_menger4d.cpp" in the folder formula/definition
15 * D O    N O T    E D I T    T H I S    F I L E !
16 */
17
18REAL4 Menger4dIteration(REAL4 z, __constant sFractalCl *fractal, sExtendedAuxCl *aux)
19{
20	if (aux->i >= fractal->transformCommon.startIterationsC
21			&& aux->i < fractal->transformCommon.stopIterationsC)
22	{
23		z += fractal->transformCommon.additionConstant0000; // offset
24	}
25
26	z = fabs(z);
27	if (z.x - z.y < 0.0f)
28	{
29		REAL temp = z.y;
30		z.y = z.x;
31		z.x = temp;
32	}
33	if (z.x - z.z < 0.0f)
34	{
35		REAL temp = z.z;
36		z.z = z.x;
37		z.x = temp;
38	}
39	if (z.y - z.z < 0.0f)
40	{
41		REAL temp = z.z;
42		z.z = z.y;
43		z.y = temp;
44	}
45	if (z.x - z.w < 0.0f)
46	{
47		REAL temp = z.w;
48		z.w = z.x;
49		z.x = temp;
50	}
51	if (z.y - z.w < 0.0f)
52	{
53		REAL temp = z.w;
54		z.w = z.y;
55		z.y = temp;
56	}
57	if (z.z - z.w < 0.0f)
58	{
59		REAL temp = z.w;
60		z.w = z.z;
61		z.z = temp;
62	}
63
64	// 6 plane rotation
65	if (fractal->transformCommon.functionEnabledRFalse
66			&& aux->i >= fractal->transformCommon.startIterationsR
67			&& aux->i < fractal->transformCommon.stopIterationsR)
68	{
69		REAL4 tp;
70		if (fractal->transformCommon.rotation44a.x != 0)
71		{
72			tp = z;
73			REAL alpha = fractal->transformCommon.rotation44a.x * M_PI_180_F;
74			z.x = tp.x * native_cos(alpha) + tp.y * native_sin(alpha);
75			z.y = tp.x * -native_sin(alpha) + tp.y * native_cos(alpha);
76		}
77		if (fractal->transformCommon.rotation44a.y != 0)
78		{
79			tp = z;
80			REAL beta = fractal->transformCommon.rotation44a.y * M_PI_180_F;
81			z.y = tp.y * native_cos(beta) + tp.z * native_sin(beta);
82			z.z = tp.y * -native_sin(beta) + tp.z * native_cos(beta);
83		}
84		if (fractal->transformCommon.rotation44a.z != 0)
85		{
86			tp = z;
87			REAL gamma = fractal->transformCommon.rotation44a.z * M_PI_180_F;
88			z.x = tp.x * native_cos(gamma) + tp.z * native_sin(gamma);
89			z.z = tp.x * -native_sin(gamma) + tp.z * native_cos(gamma);
90		}
91		if (fractal->transformCommon.rotation44b.x != 0)
92		{
93			tp = z;
94			REAL delta = fractal->transformCommon.rotation44b.x * M_PI_180_F;
95			z.x = tp.x * native_cos(delta) + tp.w * native_sin(delta);
96			z.w = tp.x * -native_sin(delta) + tp.w * native_cos(delta);
97		}
98		if (fractal->transformCommon.rotation44b.y != 0)
99		{
100			tp = z;
101			REAL epsilon = fractal->transformCommon.rotation44b.y * M_PI_180_F;
102			z.y = tp.y * native_cos(epsilon) + tp.w * native_sin(epsilon);
103			z.w = tp.y * -native_sin(epsilon) + tp.w * native_cos(epsilon);
104		}
105		if (fractal->transformCommon.rotation44b.z != 0)
106		{
107			tp = z;
108			REAL zeta = fractal->transformCommon.rotation44b.z * M_PI_180_F;
109			z.z = tp.z * native_cos(zeta) + tp.w * native_sin(zeta);
110			z.w = tp.z * -native_sin(zeta) + tp.w * native_cos(zeta);
111		}
112	}
113
114	REAL scaleM = fractal->transformCommon.scale3;
115	REAL4 offsetM = fractal->transformCommon.additionConstant111d5;
116	z.x = scaleM * z.x - offsetM.x;
117	z.y = scaleM * z.y - offsetM.y;
118	z.w = scaleM * z.w - offsetM.w;
119	z.z -= 0.5f * offsetM.z / scaleM;
120	z.z = -fabs(-z.z);
121	z.z += 0.5f * offsetM.z / scaleM;
122	z.z *= scaleM;
123	aux->DE *= scaleM;
124
125	if (fractal->transformCommon.functionEnabledSFalse
126			&& aux->i >= fractal->transformCommon.startIterationsS
127			&& aux->i < fractal->transformCommon.stopIterationsS)
128	{
129		REAL r2 = dot(z, z);
130		// if (r2 < 1e-21f && r2 > -1e-21f) r2 = (r2 > 0) ? 1e-21f : -1e-21f;
131
132		if (r2 < fractal->transformCommon.minR2p25)
133		{
134			z *= fractal->transformCommon.maxMinR2factor;
135			aux->DE *= fractal->transformCommon.maxMinR2factor;
136			aux->color += fractal->mandelbox.color.factorSp1;
137		}
138		else if (r2 < fractal->transformCommon.maxR2d1)
139		{
140			REAL tglad_factor2 = fractal->transformCommon.maxR2d1 / r2;
141			z *= tglad_factor2;
142			aux->DE *= tglad_factor2;
143			aux->color += fractal->mandelbox.color.factorSp2;
144		}
145	}
146
147	if (fractal->transformCommon.functionEnabledFalse)
148	{
149		REAL4 zA4 = (aux->i == fractal->transformCommon.intA) ? z : (REAL4){0, 0, 0, 0};
150		REAL4 zB4 = (aux->i == fractal->transformCommon.intB) ? z : (REAL4){0, 0, 0, 0};
151
152		z = (z * fractal->transformCommon.scale) + (zA4 * fractal->transformCommon.offset)
153				+ (zB4 * fractal->transformCommon.offset0);
154		aux->DE *= fractal->transformCommon.scale1;
155	}
156
157	aux->DE *= fractal->analyticDE.scale1;
158	return z;
159}