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  * spherical invert ( v2.17)
10  * from M3D. Formula by Luca GN 2011, updated May 2012.
11  * @reference
12  * http://www.fractalforums.com/mandelbulb-3d/custom-formulas-and-transforms-release-t17106/
13  */
14 
15 #include "all_fractal_definitions.h"
16 
cFractalTransfSphericalInvV2()17 cFractalTransfSphericalInvV2::cFractalTransfSphericalInvV2() : cAbstractFractal()
18 {
19 	nameInComboBox = "T>Spherical Invert V2";
20 	internalName = "transf_spherical_inv_v2";
21 	internalID = fractal::transfSphericalInvV2;
22 	DEType = analyticDEType;
23 	DEFunctionType = withoutDEFunction;
24 	cpixelAddition = cpixelDisabledByDefault;
25 	defaultBailout = 100.0;
26 	DEAnalyticFunction = analyticFunctionNone;
27 	coloringFunction = coloringFunctionDefault;
28 }
29 
FormulaCode(CVector4 & z,const sFractal * fractal,sExtendedAux & aux)30 void cFractalTransfSphericalInvV2::FormulaCode(
31 	CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
32 {
33 	double rr = 0.0;
34 	// unconditional mode
35 	if (fractal->transformCommon.functionEnabledCz)
36 	{
37 		if (aux.i >= fractal->transformCommon.startIterationsD
38 				&& aux.i < fractal->transformCommon.stopIterationsD1)
39 		{
40 			z += fractal->transformCommon.offset000;
41 			rr = z.Dot(z);
42 			z *= fractal->transformCommon.maxR2d1 / rr;
43 			z += fractal->transformCommon.additionConstant000 - fractal->transformCommon.offset000;
44 			// double r = sqrt(rr);
45 			aux.DE = (fractal->transformCommon.maxR2d1) / rr;
46 		}
47 	}
48 
49 	// conditional modes
50 	if (fractal->transformCommon.functionEnabledCxFalse
51 			&& aux.i >= fractal->transformCommon.startIterationsC
52 			&& aux.i < fractal->transformCommon.stopIterationsC)
53 	{
54 		rr = z.Dot(z);
55 		double mode = rr;
56 		z += fractal->mandelbox.offset;
57 
58 		if (rr < fractal->mandelbox.foldingSphericalFixed)
59 		{
60 			mode = 0.0;
61 			if (fractal->transformCommon.functionEnabledFalse) // Mode 1 minR0
62 			{
63 				if (rr < fractal->transformCommon.minR0) mode = fractal->transformCommon.minR0;
64 			}
65 			if (fractal->transformCommon.functionEnabledxFalse) // Mode 2
66 			{
67 				if (rr < fractal->transformCommon.minR0) mode = 2.0 * fractal->transformCommon.minR0 - rr;
68 			}
69 			mode = 1.0 / mode;
70 			z *= mode;
71 			aux.DE *= fabs(mode);
72 		}
73 		z -= fractal->mandelbox.offset;
74 	}
75 
76 	// other modes
77 	if (fractal->transformCommon.functionEnabledCyFalse
78 			&& aux.i >= fractal->transformCommon.startIterationsB
79 			&& aux.i < fractal->transformCommon.stopIterationsB)
80 	{
81 		rr = z.Dot(z);
82 		double mode = rr;
83 		if (rr < fractal->transformCommon.scaleE1) // < maxRR
84 		{
85 			double lengthAB = fractal->transformCommon.scaleE1 - fractal->transformCommon.offsetC0;
86 
87 			if (fractal->transformCommon.functionEnabledyFalse) // Mode 3a, linear addition 0.0 at Max,
88 			{
89 				if (rr < fractal->transformCommon.offsetC0)
90 					mode += rr * (fractal->transformCommon.offset0 / fractal->transformCommon.offsetC0);
91 				else
92 					mode +=
93 						(fractal->transformCommon.scaleE1 - rr) * fractal->transformCommon.offset0 / lengthAB;
94 			}
95 
96 			if (fractal->transformCommon.functionEnabledzFalse) // Mode 3b
97 			{
98 
99 				if (rr > fractal->transformCommon.offsetC0)
100 					mode += fractal->transformCommon.offsetB0 * (fractal->transformCommon.scaleE1 - rr);
101 				else
102 					mode += fractal->transformCommon.offsetA0 * (fractal->transformCommon.offsetC0 - rr)
103 									+ fractal->transformCommon.offsetB0 * lengthAB;
104 			}
105 
106 			if (fractal->transformCommon.functionEnabledwFalse) // Mode 3c, basic parabolic curve
107 			{
108 
109 				double halfLen = fractal->transformCommon.scaleE1 / 2.0;
110 				double slope = 2.0 / fractal->transformCommon.scaleE1;
111 				double factor = slope / fractal->transformCommon.scaleE1;
112 				double parab = 0.0;
113 
114 				if (rr < halfLen)
115 				{
116 					parab = rr * rr * factor * fractal->transformCommon.scaleG1;
117 					mode += rr * slope * fractal->transformCommon.scaleF1 - parab;
118 				}
119 				else
120 				{
121 					double temp = fractal->transformCommon.scaleE1 - rr;
122 					parab = temp * temp * factor * fractal->transformCommon.scaleG1;
123 					mode += temp * slope * fractal->transformCommon.scaleF1 - parab;
124 				}
125 			}
126 
127 			/*if (fractal->transformCommon.functionEnabledwFalse) // Mode 3d
128 			{
129 				mode = rr + fractal->transformCommon.offset0 * (fractal->mandelbox.foldingSphericalFixed -
130 			rr);
131 				if (rr < fractal->transformCommon.minR0)
132 					mode -= rr * (fractal->transformCommon.offset0
133 									* (fractal->mandelbox.foldingSphericalFixed - fractal->transformCommon.minR0))
134 							/ fractal->transformCommon.minR0;
135 			}*/
136 			mode = 1.0 / mode;
137 			z *= mode;
138 			aux.DE *= fabs(mode);
139 		}
140 	}
141 
142 	if (fractal->analyticDE.enabledFalse)
143 	{
144 		aux.DE = aux.DE * fractal->analyticDE.scale1 + fractal->analyticDE.offset0;
145 	}
146 }
147