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  * DifsSphereIteration  fragmentarium code, mdifs by knighty (jan 2012)
10  * and http://www.iquilezles.org/www/articles/distfunctions/distfunctions.htm
11  */
12 
13 #include "all_fractal_definitions.h"
14 
cFractalDIFSSphere()15 cFractalDIFSSphere::cFractalDIFSSphere() : cAbstractFractal()
16 {
17 	nameInComboBox = "DIFS Sphere";
18 	internalName = "difs_sphere";
19 	internalID = fractal::dIFSSphere;
20 	DEType = analyticDEType;
21 	DEFunctionType = customDEFunction;
22 	cpixelAddition = cpixelDisabledByDefault;
23 	defaultBailout = 100.0;
24 	DEAnalyticFunction = analyticFunctionCustomDE;
25 	coloringFunction = coloringFunctionDefault;
26 }
27 
FormulaCode(CVector4 & z,const sFractal * fractal,sExtendedAux & aux)28 void cFractalDIFSSphere::FormulaCode(CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
29 {
30 	double colorAdd = 0.0;
31 	CVector4 oldZ = z;
32 	CVector4 boxFold = fractal->transformCommon.additionConstantA111;
33 
34 	// abs z
35 	if (fractal->transformCommon.functionEnabledAx
36 			&& aux.i >= fractal->transformCommon.startIterationsX
37 			&& aux.i < fractal->transformCommon.stopIterationsX)
38 		z.x = fabs(z.x);
39 
40 	if (fractal->transformCommon.functionEnabledAy
41 			&& aux.i >= fractal->transformCommon.startIterationsY
42 			&& aux.i < fractal->transformCommon.stopIterationsY)
43 		z.y = fabs(z.y);
44 
45 	if (fractal->transformCommon.functionEnabledAzFalse
46 			&& aux.i >= fractal->transformCommon.startIterationsZ
47 			&& aux.i < fractal->transformCommon.stopIterationsZ)
48 		z.z = fabs(z.z);
49 
50 	if (fractal->transformCommon.functionEnabledFalse)
51 	{
52 		// xy box fold
53 		if (fractal->transformCommon.functionEnabledAFalse
54 				&& aux.i >= fractal->transformCommon.startIterationsA
55 				&& aux.i < fractal->transformCommon.stopIterationsA)
56 		{
57 			z.x -= boxFold.x;
58 			z.y -= boxFold.y;
59 		}
60 		// xyz box fold
61 		if (fractal->transformCommon.functionEnabledBFalse
62 				&& aux.i >= fractal->transformCommon.startIterationsB
63 				&& aux.i < fractal->transformCommon.stopIterationsB)
64 			z -= boxFold;
65 
66 		// polyfold
67 		if (fractal->transformCommon.functionEnabledPFalse
68 				&& aux.i >= fractal->transformCommon.startIterationsP
69 				&& aux.i < fractal->transformCommon.stopIterationsP)
70 		{
71 			z.x = fabs(z.x);
72 			double psi = M_PI / fractal->transformCommon.int6;
73 			psi = fabs(fmod(atan2(z.y, z.x) + psi, 2.0 * psi) - psi);
74 			double len = sqrt(z.x * z.x + z.y * z.y);
75 			z.x = cos(psi) * len;
76 			z.y = sin(psi) * len;
77 		}
78 		// diag fold1
79 		if (fractal->transformCommon.functionEnabledCxFalse
80 				&& aux.i >= fractal->transformCommon.startIterationsCx
81 				&& aux.i < fractal->transformCommon.stopIterationsCx)
82 			if (z.x > z.y) swap(z.x, z.y);
83 		// abs offsets
84 		if (fractal->transformCommon.functionEnabledCFalse
85 				&& aux.i >= fractal->transformCommon.startIterationsC
86 				&& aux.i < fractal->transformCommon.stopIterationsC)
87 		{
88 			double xOffset = fractal->transformCommon.offsetC0;
89 			if (z.x < xOffset) z.x = fabs(z.x - xOffset) + xOffset;
90 		}
91 		if (fractal->transformCommon.functionEnabledDFalse
92 				&& aux.i >= fractal->transformCommon.startIterationsD
93 				&& aux.i < fractal->transformCommon.stopIterationsD)
94 		{
95 			double yOffset = fractal->transformCommon.offsetD0;
96 			if (z.y < yOffset) z.y = fabs(z.y - yOffset) + yOffset;
97 		}
98 		// diag fold2
99 		if (fractal->transformCommon.functionEnabledCyFalse
100 				&& aux.i >= fractal->transformCommon.startIterationsCy
101 				&& aux.i < fractal->transformCommon.stopIterationsCy)
102 			if (z.x > z.y) swap(z.x, z.y);
103 	}
104 
105 	// reverse offset part 1
106 	if (aux.i >= fractal->transformCommon.startIterationsE
107 			&& aux.i < fractal->transformCommon.stopIterationsE)
108 		z.x -= fractal->transformCommon.offsetE2;
109 
110 	if (aux.i >= fractal->transformCommon.startIterationsF
111 			&& aux.i < fractal->transformCommon.stopIterationsF)
112 		z.y -= fractal->transformCommon.offsetF2;
113 
114 	// scale
115 	double useScale = 1.0;
116 	if (aux.i >= fractal->transformCommon.startIterationsS
117 			&& aux.i < fractal->transformCommon.stopIterationsS)
118 	{
119 		useScale = aux.actualScaleA + fractal->transformCommon.scale2;
120 		z *= useScale;
121 		aux.DE = aux.DE * fabs(useScale) + 1.0;
122 		// scale vary
123 		if (fractal->transformCommon.functionEnabledKFalse
124 				&& aux.i >= fractal->transformCommon.startIterationsK
125 				&& aux.i < fractal->transformCommon.stopIterationsK)
126 		{
127 			// update actualScaleA for next iteration
128 			double vary = fractal->transformCommon.scaleVary0
129 										* (fabs(aux.actualScaleA) - fractal->transformCommon.scaleC1);
130 			aux.actualScaleA -= vary;
131 		}
132 	}
133 
134 	// reverse offset part 2
135 	if (aux.i >= fractal->transformCommon.startIterationsE
136 			&& aux.i < fractal->transformCommon.stopIterationsE)
137 		z.x += fractal->transformCommon.offsetE2;
138 
139 	if (aux.i >= fractal->transformCommon.startIterationsF
140 			&& aux.i < fractal->transformCommon.stopIterationsF)
141 		z.y += fractal->transformCommon.offsetF2;
142 
143 	// offset
144 	z += fractal->transformCommon.offset001;
145 
146 	// rotation
147 	if (fractal->transformCommon.functionEnabledRFalse
148 			&& aux.i >= fractal->transformCommon.startIterationsR
149 			&& aux.i < fractal->transformCommon.stopIterationsR)
150 	{
151 		z = fractal->transformCommon.rotationMatrix.RotateVector(z);
152 	}
153 
154 	// DE
155 	double colorDist = aux.dist;
156 	CVector4 zc = oldZ;
157 
158 	// sphere
159 	if (aux.i >= fractal->transformCommon.startIterations
160 			&& aux.i < fractal->transformCommon.stopIterations)
161 	{
162 		double vecLen;
163 		if (!fractal->transformCommon.functionEnabled4dFalse)
164 		{
165 			CVector3 vec3 = CVector3(zc.x, zc.y, zc.z);
166 			vecLen = vec3.Length();
167 		}
168 		else
169 			vecLen = zc.Length();
170 
171 		double spD = vecLen - fractal->transformCommon.offsetR1;
172 		aux.dist = min(aux.dist, spD / aux.DE);
173 	}
174 	// torus
175 	if (fractal->transformCommon.functionEnabledTFalse
176 			&& aux.i >= fractal->transformCommon.startIterationsT
177 			&& aux.i < fractal->transformCommon.stopIterationsT)
178 	{
179 		double torD;
180 
181 		// swap axis
182 		if (fractal->transformCommon.functionEnabledSwFalse) swap(zc.x, zc.z);
183 
184 		double T1 = sqrt(zc.y * zc.y + zc.x * zc.x) - fractal->transformCommon.offsetT1;
185 		torD = sqrt(T1 * T1 + zc.z * zc.z) - fractal->transformCommon.offset05;
186 
187 		aux.dist = min(aux.dist, torD / aux.DE);
188 	}
189 
190 	// aux.color
191 	if (fractal->foldColor.auxColorEnabled)
192 	{
193 		if (fractal->foldColor.auxColorEnabledFalse)
194 		{
195 			colorAdd += fractal->foldColor.difs0000.x * fabs(z.x * z.y);
196 			colorAdd += fractal->foldColor.difs0000.y * max(z.x, z.y);
197 		}
198 		colorAdd += fractal->foldColor.difs1;
199 		if (fractal->foldColor.auxColorEnabledA)
200 		{
201 			if (colorDist != aux.dist) aux.color += colorAdd;
202 		}
203 		else
204 			aux.color += colorAdd;
205 	}
206 }
207