mandelbulber2 icon indicating copy to clipboard operation
mandelbulber2 copied to clipboard

custom formulas part2

Open mclarekin opened this issue 4 years ago • 10 comments

a) implement choose different DE function and method for boolean mode slots b) ability to write inline functions

mclarekin avatar Jul 07 '20 12:07 mclarekin

ad a) it need to be implemented ad b) You can write inline functions. Example, where I defined absolute() function just before formula code:

/**
 * Mandelbulber v2, a 3D fractal generator  _%}}i*<.        ____                _______
 * Copyright (C) 2019 Mandelbulber Team   _>]|=||i=i<,     / __ \___  ___ ___  / ___/ /
 *                                        \><||i|=>>%)    / /_/ / _ \/ -_) _ \/ /__/ /__
 * This file is part of Mandelbulber.     )<=i=]=|=i<>    \____/ .__/\__/_//_/\___/____/
 * The project is licensed under GPLv3,   -<>>=|><|||`        /_/
 * see also COPYING file in this folder.    ~+{i%+++
 *
 * Menger Sponge formula created by Knighty
 * @reference
 * http://www.fractalforums.com/ifs-iterated-function-systems/kaleidoscopic-(escape-time-ifs)/

 * This file has been autogenerated by tools/populateUiInformation.php
 * from the file "fractal_menger_sponge.cpp" in the folder formula/definition
 * F E E L   F R E E    T O    E D I T    T H I S    F I L E !
 */

float4 absolute(float4 in)
{
	float4 out;
	out.x = fabs(in.x);
	out.y = fabs(in.y);
	out.z = fabs(in.z);
	out.w = fabs(in.w);
	return out;
}

REAL4 CustomIteration(REAL4 z, __constant sFractalCl *fractal, sExtendedAuxCl *aux)
{
	z = absolute(z);

	if (z.x - z.y < 0.0f)
	{
		REAL temp = z.x;
		z.x = z.y;
		z.y = temp;
	}
	if (z.x - z.z < 0.0f)
	{
		REAL temp = z.x;
		z.x = z.z;
		z.z = temp;
	}
	if (z.y - z.z < 0.0f)
	{
		REAL temp = z.y;
		z.y = z.z;
		z.z = temp;
	}

	z *= fractal->transformCommon.scale3;

	z.x -= 2.0f;
	z.y -= 2.0f;
	if (z.z > 1.0f) z.z -= 2.0f;

	aux->DE *= fractal->transformCommon.scale3;
	return z;
}

buddhi1980 avatar Aug 16 '20 08:08 buddhi1980

b) can i bring a parameter or an aux. into the inline function (i tried but failed)

mclarekin avatar Aug 16 '20 09:08 mclarekin

I tried harder and could bring the parameter in :) so that is OK question is it possible to have inlines in the c++ setup?

mclarekin avatar Aug 16 '20 09:08 mclarekin

You can use any parameters. See this example where I moved SphericalFold to separate function. It has several paremeters: z, r2, fractal and aux.

/**
 * Mandelbulber v2, a 3D fractal generator  _%}}i*<.        ____                _______
 * Copyright (C) 2020 Mandelbulber Team   _>]|=||i=i<,     / __ \___  ___ ___  / ___/ /
 *                                        \><||i|=>>%)    / /_/ / _ \/ -_) _ \/ /__/ /__
 * This file is part of Mandelbulber.     )<=i=]=|=i<>    \____/ .__/\__/_//_/\___/____/
 * The project is licensed under GPLv3,   -<>>=|><|||`        /_/
 * see also COPYING file in this folder.    ~+{i%+++
 *
 * Mandelbox fractal known as AmazingBox or ABox, invented by Tom Lowe in 2010
 * @reference
 * http://www.fractalforums.com/ifs-iterated-function-systems/amazing-fractal/msg12467/#msg12467
 * This formula contains aux.color

 * This file has been autogenerated by tools/populateUiInformation.php
 * from the file "fractal_mandelbox.cpp" in the folder formula/definition
 * F E E L   F R E E    T O    E D I T    T H I S    F I L E !
 */

REAL4 SphericalFold(REAL4 z, REAL r2, __constant sFractalCl *fractal, sExtendedAuxCl *aux)
{
	if (r2 < fractal->mandelbox.mR2)
	{
		z *= fractal->mandelbox.mboxFactor1;
		aux->DE *= fractal->mandelbox.mboxFactor1;
		aux->color += fractal->mandelbox.color.factorSp1;
	}
	else if (r2 < fractal->mandelbox.fR2)
	{
		REAL tglad_factor2 = fractal->mandelbox.fR2 / r2;
		z *= tglad_factor2;
		aux->DE *= tglad_factor2;
		aux->color += fractal->mandelbox.color.factorSp2;
	}
	return z;
}

REAL4 CustomIteration(REAL4 z, __constant sFractalCl *fractal, sExtendedAuxCl *aux)
{
	if (fractal->mandelbox.rotationsEnabled)
	{
		REAL4 zRot;
		// cast vector to array pointer for address taking of components in opencl
		REAL *zRotP = (REAL *)&zRot;
		__constant REAL *colP = (__constant REAL *)&fractal->mandelbox.color.factor;
		for (int dim = 0; dim < 3; dim++)
		{
			// handle each dimension x, y and z sequentially in pointer var dim
			REAL *rotDim = (dim == 0) ? &zRotP[0] : ((dim == 1) ? &zRotP[1] : &zRotP[2]);
			__constant REAL *colorFactor = (dim == 0) ? &colP[0] : ((dim == 1) ? &colP[1] : &colP[2]);

			zRot = Matrix33MulFloat4(fractal->mandelbox.rot[0][dim], z);
			if (*rotDim > fractal->mandelbox.foldingLimit)
			{
				*rotDim = fractal->mandelbox.foldingValue - *rotDim;
				z = Matrix33MulFloat4(fractal->mandelbox.rotinv[0][dim], zRot);
				aux->color += *colorFactor;
			}
			else
			{
				zRot = Matrix33MulFloat4(fractal->mandelbox.rot[1][dim], z);
				if (*rotDim < -fractal->mandelbox.foldingLimit)
				{
					*rotDim = -fractal->mandelbox.foldingValue - *rotDim;
					z = Matrix33MulFloat4(fractal->mandelbox.rotinv[1][dim], zRot);
					aux->color += *colorFactor;
				}
			}
		}
	}
	else
	{
		if (fabs(z.x) > fractal->mandelbox.foldingLimit)
		{
			z.x = sign(z.x) * fractal->mandelbox.foldingValue - z.x;
			aux->color += fractal->mandelbox.color.factor.x;
		}
		if (fabs(z.y) > fractal->mandelbox.foldingLimit)
		{
			z.y = sign(z.y) * fractal->mandelbox.foldingValue - z.y;
			aux->color += fractal->mandelbox.color.factor.y;
		}
		if (fabs(z.z) > fractal->mandelbox.foldingLimit)
		{
			z.z = sign(z.z) * fractal->mandelbox.foldingValue - z.z;
			aux->color += fractal->mandelbox.color.factor.z;
		}
	}

	REAL r2 = dot(z, z);

	z += fractal->mandelbox.offset;

	z = SphericalFold(z, r2, fractal, aux);
	
	z -= fractal->mandelbox.offset;

	if (fractal->mandelbox.mainRotationEnabled) z = Matrix33MulFloat4(fractal->mandelbox.mainRot, z);

	z = z * fractal->mandelbox.scale;
	aux->DE = aux->DE * fabs(fractal->mandelbox.scale) + 1.0f;
	return z;
}

buddhi1980 avatar Aug 16 '20 09:08 buddhi1980

In C++ code you can do the same. You only need to create functions with unique names.

buddhi1980 avatar Aug 16 '20 09:08 buddhi1980

That is great news, as i have implemented some fractals laterly that will benefit by this method, as my current code is repeating the same calculation (i will try it out) and i did not want to add a lot to void sFractal::RecalculateFractalParams() for calculations that are only used by one formula

mclarekin avatar Aug 16 '20 09:08 mclarekin

Ignore last thing i wrote as i was confusing myself

i can shorten the code a lot for some fractal if i use inline e.g mandalays where same function is written six times

but i could use void sFractal::RecalculateFractalParams() for this T>DIFS polyhedra // this block does not use z so could be a precalc REAL cospin = M_PI / (REAL)(Type); cospin = cos(cospin); REAL scospin = sqrt(0.75 - cospin * cospin); REAL4 nc = (REAL4)(-0.5, -cospin, scospin, 0.0); REAL4 pab = (REAL4)(0.0, 0.0, 1.0, 0.0); REAL4 pbc = normalize((REAL4)(scospin, 0.0, 0.5, 0.0)); REAL4 pca = normalize((REAL4)(0.0, scospin, cospin, 0.0));

currently i am repeating this calc for every point, with a constant input "Type" however the complete formula is fast so maybe not clutter up void sFractal::RecalculateFractalParams() by putting it there

mclarekin avatar Aug 16 '20 10:08 mclarekin

c) add aux-> options to drop down menu

mclarekin avatar Feb 15 '21 01:02 mclarekin

d) allow int to have negative value

mclarekin avatar Aug 13 '22 10:08 mclarekin

e) editable parameter names

mclarekin avatar Feb 21 '23 04:02 mclarekin