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