1 /**
2 * Mandelbulber v2, a 3D fractal generator ,=#MKNmMMKmmßMNWy,
3 * ,B" ]L,,p%%%,,,§;, "K
4 * Copyright (C) 2017-20 Mandelbulber Team §R-==%w["'~5]m%=L.=~5N
5 * ,=mm=§M ]=4 yJKA"/-Nsaj "Bw,==,,
6 * This file is part of Mandelbulber. §R.r= jw",M Km .mM FW ",§=ß., ,TN
7 * ,4R =%["w[N=7]J '"5=],""]]M,w,-; T=]M
8 * Mandelbulber is free software: §R.ß~-Q/M=,=5"v"]=Qf,'§"M= =,M.§ Rz]M"Kw
9 * you can redistribute it and/or §w "xDY.J ' -"m=====WeC=\ ""%""y=%"]"" §
10 * modify it under the terms of the "§M=M =D=4"N #"%==A%p M§ M6 R' #"=~.4M
11 * GNU General Public License as §W =, ][T"]C § § '§ e===~ U !§[Z ]N
12 * published by the 4M",,Jm=,"=e~ § § j]]""N BmM"py=ßM
13 * Free Software Foundation, ]§ T,M=& 'YmMMpM9MMM%=w=,,=MT]M m§;'§,
14 * either version 3 of the License, TWw [.j"5=~N[=§%=%W,T ]R,"=="Y[LFT ]N
15 * or (at your option) TW=,-#"%=;[ =Q:["V"" ],,M.m == ]N
16 * any later version. J§"mr"] ,=,," =="""J]= M"M"]==ß"
17 * §= "=C=4 §"eM "=B:m|4"]#F,§~
18 * Mandelbulber is distributed in "9w=,,]w em%wJ '"~" ,=,,ß"
19 * the hope that it will be useful, . "K= ,=RMMMßM"""
20 * but WITHOUT ANY WARRANTY; .'''
21 * without even the implied warranty
22 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
23 *
24 * See the GNU General Public License for more details.
25 * You should have received a copy of the GNU General Public License
26 * along with Mandelbulber. If not, see <http://www.gnu.org/licenses/>.
27 *
28 * ###########################################################################
29 *
30 * Authors: Krzysztof Marczak (buddhi1980@gmail.com), Graeme McLaren
31 *
32 * CalculateColorIndex(...) - Calculation of the color index of a point
33 * based on miscellaneous criteria
34 */
35 #include "fractal_coloring.hpp"
36
37 #include "fractal.h"
38
39 using std::min;
40
41 using namespace fractal;
42
sFractalColoring()43 sFractalColoring::sFractalColoring()
44 {
45 addEnabledFalse = false;
46 auxColorFalse = false;
47 color4dEnabledFalse = false;
48 colorPreV215False = false;
49 cosEnabledFalse = false;
50 extraColorOptionsEnabledFalse = false;
51 extraColorEnabledFalse = false;
52 globalPaletteFalse = false;
53 icFabsFalse = false;
54 icRadFalse = false;
55 icXYZFalse = false;
56 initCondFalse = false;
57 iterAddScaleTrue = false;
58 iterGroupFalse = false;
59 iterScaleFalse = false;
60 orbitTrapTrue = false;
61 parabEnabledFalse = false;
62 radDiv1e13False = false;
63 radDivDE1e13False = false;
64 radDivDeFalse = false;
65 radDivDeSquaredFalse = false;
66 radFalse = false;
67 radSquaredFalse = false;
68 roundEnabledFalse = false;
69 tempLimitFalse = false; // temporary parameter
70 xyzBiasEnabledFalse = false;
71 xyzDiv1e13False = false;
72 xyzFabsFalse = false;
73 xyzXSqrdFalse = false;
74 xyzYSqrdFalse = false;
75 xyzZSqrdFalse = false;
76
77 coloringAlgorithm = fractalColoring_None;
78 iStartValue = 0;
79
80 CVector3 lineDirection;
81 CVector3 xyz000;
82 CVector3 xyzC111;
83
84 addMax = 0.0;
85 addSpread = 0.0;
86 addStartValue = 0.0;
87 auxColorHybridWeight = 0.0;
88 auxColorWeight = 0.0;
89 cosAdd = 0.0;
90 cosPeriod = 0.0;
91 cosStartValue = 0.0;
92 hybridAuxColorScale1 = 0.0;
93 hybridOrbitTrapScale1 = 0.0;
94 hybridRadDivDeScale1 = 0.0;
95 icRadWeight = 0.0;
96 initialColorValue = 0.0;
97 iterAddScale = 0.0;
98 iterScale = 0.0;
99 maxColorValue = 0.0;
100 minColorValue = 0.0;
101 orbitTrapWeight = 0.0;
102 parabScale = 0.0;
103 parabStartValue = 0.0;
104 radDivDeWeight = 0.0;
105 radDivDeWeight = 0.0;
106 radWeight = 0.0;
107 roundScale = 0.0;
108 sphereRadius = 0.0;
109 xyzIterScale = 0.0;
110 }
111
CalculateColorIndex(bool isHybrid,double r,CVector4 z,double colorMin,const sExtendedAux & extendedAux,const sFractalColoring & fractalColoring,fractal::enumColoringFunction coloringFunction,const sFractal * defaultFractal)112 double CalculateColorIndex(bool isHybrid, double r, CVector4 z, double colorMin,
113 const sExtendedAux &extendedAux, const sFractalColoring &fractalColoring,
114 fractal::enumColoringFunction coloringFunction, const sFractal *defaultFractal)
115 {
116 double colorIndex = 0.0;
117
118 // color by numbers
119 if (fractalColoring.extraColorEnabledFalse)
120 {
121 double colorValue = 0.0;
122
123 // initial color value
124 colorValue = fractalColoring.initialColorValue;
125
126 // colorValue initial condition components
127 if (fractalColoring.initCondFalse)
128 {
129 double initColorValue = 0.0;
130 CVector3 xyzC = CVector3(extendedAux.c.x, extendedAux.c.y, extendedAux.c.z);
131 if (fractalColoring.icRadFalse) initColorValue = xyzC.Length() * fractalColoring.icRadWeight;
132
133 if (fractalColoring.icXYZFalse)
134 {
135 if (fractalColoring.icFabsFalse)
136 {
137 xyzC = xyzC * fractalColoring.xyzC111;
138 }
139 else
140 {
141 xyzC = fabs(xyzC) * fractalColoring.xyzC111;
142 }
143 initColorValue += xyzC.x + xyzC.y + xyzC.z;
144 }
145 colorValue += initColorValue;
146 }
147
148 // orbit trap component
149 if (fractalColoring.orbitTrapTrue)
150 {
151 // if (fractalColoring.tempLimitFalse) minimumR = min(100.0, minimumR); // TEMP for testing
152 colorValue += colorMin * fractalColoring.orbitTrapWeight;
153 }
154
155 // auxiliary color components
156 if (fractalColoring.auxColorFalse)
157 {
158 double auxColor = extendedAux.color;
159 // if (fractalColoring.tempLimitFalse) auxColor = min(auxColor, 1000.0); // TEMP for testing
160 colorValue += auxColor * fractalColoring.auxColorWeight // aux.color
161 + extendedAux.colorHybrid // transf_hybrid_color inputs
162 * fractalColoring.auxColorHybridWeight;
163 }
164
165 // radius components (historic)
166 if (fractalColoring.radFalse)
167 {
168 double rad = r;
169 if (fractalColoring.radDiv1e13False) rad /= 1e13;
170 if (fractalColoring.radSquaredFalse) rad *= rad;
171 colorValue += rad * fractalColoring.radWeight;
172 }
173
174 // radius / DE components (historic)
175 if (fractalColoring.radDivDeFalse)
176 {
177 double distEst = extendedAux.DE;
178
179 double radDE = r;
180 if (fractalColoring.radDivDE1e13False) radDE /= 1e13;
181 if (fractalColoring.radDivDeSquaredFalse) radDE *= radDE;
182 radDE /= distEst;
183 // if (fractalColoring.tempLimitFalse) radDE = min(radDE, 20.0); // TEMP for testing
184
185 colorValue += radDE * fractalColoring.radDivDeWeight;
186 }
187
188 double addValue = 0.0;
189 // XYZ bias (example of a basic input)
190 double xyzValue = 0.0;
191 if (fractalColoring.xyzBiasEnabledFalse)
192 {
193 CVector3 xyzAxis = CVector3(z.x, z.y, z.z);
194 if (fractalColoring.xyzDiv1e13False) xyzAxis /= 1e13;
195
196 if (fractalColoring.xyzFabsFalse)
197 {
198 xyzAxis = xyzAxis * fractalColoring.xyz000;
199 }
200 else
201 {
202 xyzAxis = fabs(xyzAxis) * fractalColoring.xyz000;
203 }
204 if (fractalColoring.xyzXSqrdFalse) xyzAxis.x *= xyzAxis.x;
205 if (fractalColoring.xyzYSqrdFalse) xyzAxis.y *= xyzAxis.y;
206 if (fractalColoring.xyzZSqrdFalse) xyzAxis.z *= xyzAxis.z;
207
208 xyzValue = (xyzAxis.x + xyzAxis.y + xyzAxis.z)
209 * (1.0 + (fractalColoring.xyzIterScale * extendedAux.i));
210 }
211
212 addValue += xyzValue; // addValue accumulates outputs
213
214 colorValue += addValue; // all extra inputs
215
216 // colorValue iteration components
217 if (fractalColoring.iterGroupFalse)
218 {
219 // Iter ADD, this allows the input to be influenced by iteration number
220 if (fractalColoring.iterAddScaleTrue && extendedAux.i > fractalColoring.iStartValue)
221 {
222 int iUse = extendedAux.i - fractalColoring.iStartValue;
223 colorValue += fractalColoring.iterAddScale * iUse;
224 }
225 // Iter SCALE,
226 if (fractalColoring.iterScaleFalse && extendedAux.i >= fractalColoring.iStartValue)
227 {
228 int iUse = extendedAux.i - fractalColoring.iStartValue;
229 colorValue *= (iUse * fractalColoring.iterScale) + 1.0;
230 }
231 }
232
233 // final colorValue controls
234 if (fractalColoring.globalPaletteFalse)
235 {
236 // // add curve function
237 if (fractalColoring.addEnabledFalse)
238 {
239 if (colorValue > fractalColoring.addStartValue)
240 {
241 colorValue +=
242 (1.0
243 - 1.0
244 / (1.0
245 + (colorValue - fractalColoring.addStartValue) / fractalColoring.addSpread))
246 * fractalColoring.addMax;
247 }
248 }
249
250 // parabolic function
251 if (fractalColoring.parabEnabledFalse)
252 {
253 if (colorValue > fractalColoring.parabStartValue)
254 {
255 double parab = colorValue - fractalColoring.cosStartValue;
256 parab = parab * parab * fractalColoring.parabScale;
257 colorValue += parab;
258 }
259 }
260
261 // trig function
262 if (fractalColoring.cosEnabledFalse)
263 {
264 if (colorValue > fractalColoring.cosStartValue)
265 {
266 double trig = (0.5
267 - 0.5
268 * cos((colorValue - fractalColoring.cosStartValue) * M_PI
269 / (fractalColoring.cosPeriod * 2.0)))
270 * fractalColoring.cosAdd;
271 colorValue += trig;
272 }
273 }
274
275 // round function
276 if (fractalColoring.roundEnabledFalse)
277 {
278 double roundScale = fractalColoring.roundScale;
279 colorValue /= roundScale;
280 colorValue = round(colorValue) * roundScale;
281 }
282 }
283
284 // palette max min controls
285 double minCV = fractalColoring.minColorValue;
286 double maxCV = fractalColoring.maxColorValue;
287 if (colorValue < minCV) colorValue = minCV;
288 if (colorValue > maxCV) colorValue = maxCV;
289
290 colorIndex = colorValue * 256.0; // convert to colorValue units
291 }
292
293 // HYBRID MODE coloring
294 else if (isHybrid)
295 {
296 // orbit trap
297 colorMin = min(100.0, colorMin);
298
299 // aux.color (init cond = 1.0)
300 double mboxColor = extendedAux.color;
301 // double mboxColor = min(extendedAux.color, 1000.0);
302
303 // rad/DE
304 double r2 = min(r / fabs(extendedAux.DE), 20.0);
305
306 // summation
307 if (!fractalColoring.extraColorOptionsEnabledFalse)
308 {
309 colorIndex = (colorMin * 1000.0 + mboxColor * 100.0 + r2 * 5000.0);
310 }
311 else
312 {
313 colorIndex = (colorMin * 1000.0 * fractalColoring.hybridOrbitTrapScale1
314 + mboxColor * 100.0 * fractalColoring.hybridAuxColorScale1
315 + r2 * 5000.0 * fractalColoring.hybridRadDivDeScale1);
316 }
317 }
318
319 // NORMAL MODE Coloring (single fractal)
320 else
321 {
322
323 switch (coloringFunction)
324 {
325 case coloringFunctionABox:
326 colorIndex =
327 extendedAux.color * 100.0 // folds part
328 + r * defaultFractal->mandelbox.color.factorR / 1e13 // r or abs z part
329 + ((fractalColoring.coloringAlgorithm != fractalColoring_Standard) ? colorMin * 1000.0
330 : 0.0);
331 // ABOX if fractalColoring_Standard) minimumR = 0.0
332 // ABOX r and minimumR values changed in V215 by bailout update
333 // ABOX extendedAux.color is f(i), change bailout = change value
334 break;
335 case coloringFunctionIFS: colorIndex = colorMin * 1000.0; break;
336 case coloringFunctionAmazingSurf: colorIndex = colorMin * 200.0; break;
337 case coloringFunctionDonut: colorIndex = extendedAux.color * 2000.0 / extendedAux.i; break;
338 case coloringFunctionDefault: colorIndex = colorMin * 5000.0; break;
339 case coloringFunctionUndefined: colorIndex = 0.0; break;
340 }
341 }
342
343 return colorIndex;
344 }
345