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  * Mandelbox Menger Sponge Hybrid
10  * @reference
11  * http://www.fractalforums.com/ifs-iterated-function-systems/amazing-fractal/msg12467/#msg12467
12  * This formula contains aux.color
13  */
14 
15 #include "all_fractal_definitions.h"
16 
cFractalMandelboxMenger()17 cFractalMandelboxMenger::cFractalMandelboxMenger() : cAbstractFractal()
18 {
19 	nameInComboBox = "Mandelbox - Menger";
20 	internalName = "mandelbox_menger";
21 	internalID = fractal::mandelboxMenger;
22 	DEType = analyticDEType;
23 	DEFunctionType = linearDEFunction;
24 	cpixelAddition = cpixelEnabledByDefault;
25 	defaultBailout = 100.0;
26 	DEAnalyticFunction = analyticFunctionLinear;
27 	coloringFunction = coloringFunctionABox;
28 }
29 
FormulaCode(CVector4 & z,const sFractal * fractal,sExtendedAux & aux)30 void cFractalMandelboxMenger::FormulaCode(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
31 {
32 	CVector4 c = aux.const_c;
33 	double colorAdd = 0.0;
34 	if (fractal->mandelbox.rotationsEnabled)
35 	{
36 		CVector4 zRot;
37 		// cast vector to array pointer for address taking of components in opencl
38 		double *zRotP = (double *)&zRot;
39 		const double *colP = (const double *)&fractal->mandelbox.color.factor;
40 		for (int dim = 0; dim < 3; dim++)
41 		{
42 			// handle each dimension x, y and z sequentially in pointer var dim
43 			double *rotDim = (dim == 0) ? &zRotP[0] : ((dim == 1) ? &zRotP[1] : &zRotP[2]);
44 			const double *colorFactor = (dim == 0) ? &colP[0] : ((dim == 1) ? &colP[1] : &colP[2]);
45 
46 			zRot = fractal->mandelbox.rot[0][dim].RotateVector(z);
47 			if (*rotDim > fractal->mandelbox.foldingLimit)
48 			{
49 				*rotDim = fractal->mandelbox.foldingValue - *rotDim;
50 				z = fractal->mandelbox.rotinv[0][dim].RotateVector(zRot);
51 				colorAdd += *colorFactor;
52 			}
53 			else
54 			{
55 				zRot = fractal->mandelbox.rot[1][dim].RotateVector(z);
56 				if (*rotDim < -fractal->mandelbox.foldingLimit)
57 				{
58 					*rotDim = -fractal->mandelbox.foldingValue - *rotDim;
59 					z = fractal->mandelbox.rotinv[1][dim].RotateVector(zRot);
60 					colorAdd += *colorFactor;
61 				}
62 			}
63 		}
64 	}
65 	else
66 	{
67 		if (aux.i >= fractal->transformCommon.startIterationsA
68 				&& aux.i < fractal->transformCommon.stopIterationsA)
69 		{
70 			if (fabs(z.x) > fractal->mandelbox.foldingLimit)
71 			{
72 				z.x = sign(z.x) * fractal->mandelbox.foldingValue - z.x;
73 				colorAdd += fractal->mandelbox.color.factor.x;
74 			}
75 			if (fabs(z.y) > fractal->mandelbox.foldingLimit)
76 			{
77 				z.y = sign(z.y) * fractal->mandelbox.foldingValue - z.y;
78 				colorAdd += fractal->mandelbox.color.factor.y;
79 			}
80 			double zLimit = fractal->mandelbox.foldingLimit * fractal->transformCommon.scale1;
81 			double zValue = fractal->mandelbox.foldingValue * fractal->transformCommon.scale1;
82 			if (fabs(z.z) > zLimit)
83 			{
84 				z.z = sign(z.z) * zValue - z.z;
85 				colorAdd += fractal->mandelbox.color.factor.z;
86 			}
87 		}
88 	}
89 
90 	if (aux.i >= fractal->transformCommon.startIterationsB
91 			&& aux.i < fractal->transformCommon.stopIterationsB)
92 	{
93 		double r2 = z.Dot(z);
94 		z += fractal->mandelbox.offset;
95 		if (r2 < fractal->mandelbox.mR2)
96 		{
97 			z *= fractal->mandelbox.mboxFactor1;
98 			aux.DE *= fractal->mandelbox.mboxFactor1;
99 			colorAdd += fractal->mandelbox.color.factorSp1;
100 		}
101 		else if (r2 < fractal->mandelbox.fR2)
102 		{
103 			double tglad_factor2 = fractal->mandelbox.fR2 / r2;
104 			z *= tglad_factor2;
105 			aux.DE *= tglad_factor2;
106 			colorAdd += fractal->mandelbox.color.factorSp2;
107 		}
108 		z -= fractal->mandelbox.offset;
109 	}
110 	if (fractal->mandelbox.mainRotationEnabled && aux.i >= fractal->transformCommon.startIterationsR
111 			&& aux.i < fractal->transformCommon.stopIterationsR)
112 		z = fractal->mandelbox.mainRot.RotateVector(z);
113 
114 	if (aux.i >= fractal->transformCommon.startIterationsS
115 			&& aux.i < fractal->transformCommon.stopIterationsS)
116 	{
117 		z = z * fractal->mandelbox.scale;
118 		aux.DE = aux.DE * fabs(fractal->mandelbox.scale) + 1.0;
119 	}
120 
121 	if (fractal->transformCommon.addCpixelEnabledFalse)
122 	{
123 		CVector4 tempC = c;
124 		if (fractal->transformCommon.alternateEnabledFalse) // alternate
125 		{
126 			tempC = aux.c;
127 			switch (fractal->mandelbulbMulti.orderOfXYZ)
128 			{
129 				case multi_OrderOfXYZ_xyz:
130 				default: tempC = CVector4(tempC.x, tempC.y, tempC.z, tempC.w); break;
131 				case multi_OrderOfXYZ_xzy: tempC = CVector4(tempC.x, tempC.z, tempC.y, tempC.w); break;
132 				case multi_OrderOfXYZ_yxz: tempC = CVector4(tempC.y, tempC.x, tempC.z, tempC.w); break;
133 				case multi_OrderOfXYZ_yzx: tempC = CVector4(tempC.y, tempC.z, tempC.x, tempC.w); break;
134 				case multi_OrderOfXYZ_zxy: tempC = CVector4(tempC.z, tempC.x, tempC.y, tempC.w); break;
135 				case multi_OrderOfXYZ_zyx: tempC = CVector4(tempC.z, tempC.y, tempC.x, tempC.w); break;
136 			}
137 			aux.c = tempC;
138 		}
139 		else
140 		{
141 			switch (fractal->mandelbulbMulti.orderOfXYZ)
142 			{
143 				case multi_OrderOfXYZ_xyz:
144 				default: tempC = CVector4(c.x, c.y, c.z, c.w); break;
145 				case multi_OrderOfXYZ_xzy: tempC = CVector4(c.x, c.z, c.y, c.w); break;
146 				case multi_OrderOfXYZ_yxz: tempC = CVector4(c.y, c.x, c.z, c.w); break;
147 				case multi_OrderOfXYZ_yzx: tempC = CVector4(c.y, c.z, c.x, c.w); break;
148 				case multi_OrderOfXYZ_zxy: tempC = CVector4(c.z, c.x, c.y, c.w); break;
149 				case multi_OrderOfXYZ_zyx: tempC = CVector4(c.z, c.y, c.x, c.w); break;
150 			}
151 		}
152 		z += tempC * fractal->transformCommon.constantMultiplier111;
153 	}
154 	if (fractal->transformCommon.functionEnabled && aux.i >= fractal->transformCommon.startIterationsM
155 			&& aux.i < fractal->transformCommon.stopIterationsM)
156 	{
157 		int count = fractal->transformCommon.int1; // Menger Sponge
158 		int k;
159 		for (k = 0; k < count; k++)
160 		{
161 			z = fabs(z);
162 			if (z.x - z.y < 0.0) swap(z.y, z.x);
163 			if (z.x - z.z < 0.0) swap(z.z, z.x);
164 			if (z.y - z.z < 0.0) swap(z.z, z.y);
165 			z *= fractal->transformCommon.scale3;
166 			z.x -= 2.0 * fractal->transformCommon.constantMultiplierA111.x;
167 			z.y -= 2.0 * fractal->transformCommon.constantMultiplierA111.y;
168 			if (z.z > 1.0) z.z -= 2.0 * fractal->transformCommon.constantMultiplierA111.z;
169 			aux.DE *= fabs(fractal->transformCommon.scale3 * fractal->transformCommon.scaleA1);
170 
171 			z += fractal->transformCommon.additionConstantA000;
172 
173 			if (fractal->transformCommon.functionEnabledxFalse) // addCpixel options
174 			{
175 				switch (fractal->mandelbulbMulti.orderOfXYZC)
176 				{
177 					case multi_OrderOfXYZ_xyz:
178 					default: c = CVector4(c.x, c.y, c.z, c.w); break;
179 					case multi_OrderOfXYZ_xzy: c = CVector4(c.x, c.z, c.y, c.w); break;
180 					case multi_OrderOfXYZ_yxz: c = CVector4(c.y, c.x, c.z, c.w); break;
181 					case multi_OrderOfXYZ_yzx: c = CVector4(c.y, c.z, c.x, c.w); break;
182 					case multi_OrderOfXYZ_zxy: c = CVector4(c.z, c.x, c.y, c.w); break;
183 					case multi_OrderOfXYZ_zyx: c = CVector4(c.z, c.y, c.x, c.w); break;
184 				}
185 				z += c * fractal->transformCommon.constantMultiplierB111;
186 			}
187 		}
188 	}
189 	if (fractal->analyticDE.enabledFalse)
190 		aux.DE = aux.DE * fractal->analyticDE.scale1 + fractal->analyticDE.offset0;
191 
192 	aux.color += colorAdd;
193 }
194