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  * Quaternion Fold Transform
10  * @reference http://www.fractalforums.com/3d-fractal-generation/true-3d-mandlebrot-type-fractal/
11  */
12 
13 #include "all_fractal_definitions.h"
14 
cFractalTransfQuaternionFold()15 cFractalTransfQuaternionFold::cFractalTransfQuaternionFold() : cAbstractFractal()
16 {
17 	nameInComboBox = "T>Quaternion Fold";
18 	internalName = "transf_quaternion_fold";
19 	internalID = fractal::transfQuaternionFold;
20 	DEType = analyticDEType;
21 	DEFunctionType = logarithmicDEFunction;
22 	cpixelAddition = cpixelDisabledByDefault;
23 	defaultBailout = 100.0;
24 	DEAnalyticFunction = analyticFunctionNone;
25 	coloringFunction = coloringFunctionDefault;
26 }
27 
FormulaCode(CVector4 & z,const sFractal * fractal,sExtendedAux & aux)28 void cFractalTransfQuaternionFold::FormulaCode(
29 	CVector4 &z, const sFractal *fractal, sExtendedAux &aux)
30 {
31 	CVector4 c = aux.const_c;
32 	// quat fold
33 	z = CVector4(z.x * z.x - z.y * z.y - z.z * z.z, z.x * z.y, z.x * z.z, z.w);
34 
35 	// quat scale and DE fudge
36 
37 	if (fractal->transformCommon.functionEnabledFalse)
38 	{
39 		z *= fractal->transformCommon.constantMultiplier122;
40 		aux.DE *= 2.0;
41 	}
42 
43 	// offset
44 	z += fractal->transformCommon.additionConstant000;
45 
46 	// addCpixel
47 	if (fractal->transformCommon.addCpixelEnabledFalse)
48 	{
49 		CVector4 tempC = c;
50 		if (fractal->transformCommon.alternateEnabledFalse) // alternate
51 		{
52 			tempC = aux.c;
53 			switch (fractal->mandelbulbMulti.orderOfXYZC)
54 			{
55 				case multi_OrderOfXYZ_xyz:
56 				default: tempC = CVector4(tempC.x, tempC.y, tempC.z, tempC.w); break;
57 				case multi_OrderOfXYZ_xzy: tempC = CVector4(tempC.x, tempC.z, tempC.y, tempC.w); break;
58 				case multi_OrderOfXYZ_yxz: tempC = CVector4(tempC.y, tempC.x, tempC.z, tempC.w); break;
59 				case multi_OrderOfXYZ_yzx: tempC = CVector4(tempC.y, tempC.z, tempC.x, tempC.w); break;
60 				case multi_OrderOfXYZ_zxy: tempC = CVector4(tempC.z, tempC.x, tempC.y, tempC.w); break;
61 				case multi_OrderOfXYZ_zyx: tempC = CVector4(tempC.z, tempC.y, tempC.x, tempC.w); break;
62 			}
63 			aux.c = tempC;
64 		}
65 		else
66 		{
67 			switch (fractal->mandelbulbMulti.orderOfXYZC)
68 			{
69 				case multi_OrderOfXYZ_xyz:
70 				default: tempC = CVector4(c.x, c.y, c.z, c.w); break;
71 				case multi_OrderOfXYZ_xzy: tempC = CVector4(c.x, c.z, c.y, c.w); break;
72 				case multi_OrderOfXYZ_yxz: tempC = CVector4(c.y, c.x, c.z, c.w); break;
73 				case multi_OrderOfXYZ_yzx: tempC = CVector4(c.y, c.z, c.x, c.w); break;
74 				case multi_OrderOfXYZ_zxy: tempC = CVector4(c.z, c.x, c.y, c.w); break;
75 				case multi_OrderOfXYZ_zyx: tempC = CVector4(c.z, c.y, c.x, c.w); break;
76 			}
77 		}
78 		z += tempC * fractal->transformCommon.constantMultiplierC111;
79 	}
80 
81 	// tweaking DE
82 	aux.DE = aux.DE * aux.r * fractal->analyticDE.scale1 + fractal->analyticDE.offset0;
83 }
84