fractorium/Source/Ember/Variations06.h
Person 47b6614c8a --Bug fixes
-Fix improper usage of rand() in cpow2, cpow3, hypertile1, hypertile3D1, hypertile3D2, juliac, juliaq.
 -Fix program crashing during density filtering on some Nvidia cards.
 -hypertile3D1 was wrong.
 -Parsing phoenix_julia when coming from Apophysis was wrong.
 -Density filtering was freezing on certain Nvidia cards.

--Code changes
 -Optimize juliac, npolar.
 -Add a new function Crand() which behaves like the legacy C rand() which returns an integer between 0 and 32766, inclusive.
 -Use RandBit() in some places.
 -Remove Zeps() from vignette, it's not needed.
 -Restructure OpenCL code for density filtering such that it does not hang after being compiled on some Nvidia cards, such as the gtx 1660. Remove barriers from conditionals where possible.
2020-12-28 21:46:55 -08:00

5525 lines
188 KiB
C++

#pragma once
#include "Variation.h"
namespace EmberNs
{
/// <summary>
/// hexes.
/// </summary>
template <typename T>
class HexesVariation : public ParametricVariation<T>
{
public:
HexesVariation(T weight = 1.0) : ParametricVariation<T>("hexes", eVariationId::VAR_HEXES, weight)
{
Init();
}
PARVARCOPY(HexesVariation)
virtual void Func(IteratorHelper<T>& helper, Point<T>& outPoint, QTIsaac<ISAAC_SIZE, ISAAC_INT>& rand) override
{
// Xh = (Xo + sqrt(3) * Yo) / (3 * l)
static const T AXhXo = T(1.0 / 3.0);
static const T AXhYo = T(1.7320508075688772935 / 3.0);
// Now: Xh = ( AXhXo * Xo + AXhYo * Yo ) / l;
// Yh = (-Xo + sqrt(3) * Yo) / (3 * l)
static const T AYhXo = T(-1.0 / 3.0);
static const T AYhYo = T(1.7320508075688772935 / 3.0);
// Now: Yh = ( AYhXo * Xo + AYhYo * Yo ) / l;
// Xo = 3/2 * l * (Xh - Yh)
static const T AXoXh = T(1.5);
static const T AXoYh = T(-1.5);
// Now: Xo = ( AXoXh * Xh + AXoYh * Yh ) * l;
// Yo = sqrt(3)/2 * l * (Xh + Yh)
static const T AYoXh = T(1.7320508075688772935 / 2.0);
static const T AYoYh = T(1.7320508075688772935 / 2.0);
static const v2T offset[4] { { 0, 0 }, { 0, 1 }, { 1, 0 }, { 1, 1 } };
int i, j;
T di, dj;
T XCh, YCh, XCo, YCo, DXo, DYo, L, L1, L2, R, s, trgL;
v2T u, v;
v2T P[7];
//For speed/convenience.
s = m_Cellsize;
//Infinite number of small cells? No effect . . .
if (s == 0)
{
helper.Out.x = 0;
helper.Out.y = 0;
helper.Out.z = DefaultZ(helper);
return;
}
//Get co-ordinates, and convert to hex co-ordinates.
u.x = helper.In.x;
u.y = helper.In.y;
XCh = T(Floor((AXhXo * u.x + AXhYo * u.y) / s));
YCh = T(Floor((AYhXo * u.x + AYhYo * u.y) / s));
// Get a set of 4 hex center points, based around the one above
for (i = 0, di = XCh; i < 2; di += 1, i++)//Note that in SP mode, these numbers won't advance if they are on the boundary of what can be represented with an DP number...
{
for (j = 0, dj = YCh; j < 2; dj += 1, j++)//...which is why the check uses i and j.
{
P[(i * 2) + j].x = (AXoXh * di + AXoYh * dj) * s;
P[(i * 2) + j].y = (AYoXh * di + AYoYh * dj) * s;
}
}
int q = m_VarFuncs->Closest(&P[0], 4, u);
//Remake list starting from chosen hex, ensure it is completely surrounded (total 7 points).
//First adjust centers according to which one was found to be closest.
XCh += offset[q].x;
YCh += offset[q].y;
//First point is central/closest.
XCo = (AXoXh * XCh + AXoYh * YCh) * s;
YCo = (AYoXh * XCh + AYoYh * YCh) * s;
P[0].x = XCo;
P[0].y = YCo;
//Next six points are based on hex graph (6 hexes around center). As long as
//center points are not too distorted from simple hex, this defines all possible edges.
//In hex co-ords, offsets are: (0,1) (1,1) (1,0) (0,-1) (-1,-1) (-1, 0).
P[1].x = XCo + (AXoYh) * s;
P[1].y = YCo + (AYoYh) * s;
P[2].x = XCo + (AXoXh + AXoYh) * s;
P[2].y = YCo + (AYoXh + AYoYh) * s;
P[3].x = XCo + (AXoXh) * s;
P[3].y = YCo + (AYoXh) * s;
P[4].x = XCo - AXoYh * s;
P[4].y = YCo - AYoYh * s;
P[5].x = XCo - (AXoXh + AXoYh) * s;
P[5].y = YCo - (AYoXh + AYoYh) * s;
P[6].x = XCo - AXoXh * s;
P[6].y = YCo - AYoXh * s;
L1 = m_VarFuncs->Voronoi(&P[0], 7, 0, u);
//Delta vector from center of hex.
DXo = u.x - P[0].x;
DYo = u.y - P[0].y;
//Apply "interesting bit" to cell's DXo and DYo co-ordinates.
//trgL is the defined value of l, independent of any rotation.
trgL = std::pow(std::abs(L1), m_Power) * m_Scale;//Original added 1e-100, use Zeps to be more precise.
//Rotate.
v.x = DXo * m_RotCos + DYo * m_RotSin;
v.y = -DXo * m_RotSin + DYo * m_RotCos;
//Measure voronoi distance again.
u = v + P[0];
L2 = m_VarFuncs->Voronoi(&P[0], 7, 0, u);
//Scale to meet target size . . . adjust according to how close
//we are to the edge.
//Code here attempts to remove the "rosette" effect caused by
//scaling between.
//L is maximum of L1 or L2 . . .
//When L = 0.8 or higher . . . match trgL/L2 exactly.
//When L = T(0.5) or less . . . match trgL/L1 exactly.
L = std::max(L1, L2);
if (L < T(0.5))
{
R = trgL / L1;
}
else
{
if (L > T(0.8))
R = trgL / L2;
else
R = ((trgL / L1) * (T(0.8) - L) + (trgL / L2) * (L - T(0.5))) / T(0.3);
}
v *= R;
//Add cell center co-ordinates back in.
v += P[0];
//Finally add values in.
helper.Out.x = m_Weight * v.x;
helper.Out.y = m_Weight * v.y;
helper.Out.z = DefaultZ(helper);
}
virtual string OpenCLString() const override
{
ostringstream ss, ss2;
intmax_t i = 0, varIndex = IndexInXform();
ss2 << "_" << XformIndexInEmber() << "]";
string index = ss2.str();
string weight = WeightDefineString();
string cellsize = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string power = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string rotate = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string scale = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string rotsin = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string rotcos = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
ss << "\t{\n"
<< "\t\tint i, j;\n"
<< "\t\treal_t di, dj;\n"
<< "\t\treal_t XCh, YCh, XCo, YCo, DXo, DYo, L, L1, L2, R, s, trgL, Vx, Vy;\n"
<< "\t\treal2 U;\n"
<< "\t\treal2 P[7];\n"
<< "\n"
<< "\t\ts = " << cellsize << ";\n"
<< "\n"
<< "\t\tif (s == 0)\n"
<< "\t\t{\n"
<< "\t\t vOut.x = 0;\n"
<< "\t\t vOut.y = 0;\n"
<< "\t\t vOut.z = " << DefaultZCl()
<< "\t\t return;\n"
<< "\t\t}\n"
<< "\n"
<< "\t\tU.x = vIn.x;\n"
<< "\t\tU.y = vIn.y;\n"
<< "\n"
<< "\t\tXCh = floor(fma(AXhXo, U.x, AXhYo * U.y) / s);\n"
<< "\t\tYCh = floor(fma(AYhXo, U.x, AYhYo * U.y) / s);\n"
<< "\n"
<< "\t\tfor (i = 0, di = XCh; i < 2; di += 1, i++)\n"
<< "\t\t{\n"
<< "\t\t for (j = 0, dj = YCh; j < 2; dj += 1, j++)\n"
<< "\t\t {\n"
<< "\t\t P[(i * 2) + j].x = fma(AXoXh, di, AXoYh * dj) * s;\n"
<< "\t\t P[(i * 2) + j].y = fma(AYoXh, di, AYoYh * dj) * s;\n"
<< "\t\t }\n"
<< "\t\t}\n"
<< "\n"
<< "\t\tint q = Closest(&P[0], 4, &U);\n"
<< "\n"
<< "\t\tXCh += offset[q].x;\n"
<< "\t\tYCh += offset[q].y;\n"
<< "\n"
<< "\t\tXCo = fma(AXoXh, XCh, AXoYh * YCh) * s;\n"
<< "\t\tYCo = fma(AYoXh, XCh, AYoYh * YCh) * s;\n"
<< "\t\tP[0].x = XCo;\n"
<< "\t\tP[0].y = YCo;\n"
<< "\n"
<< "\t\tP[1].x = XCo + (AXoYh)* s;\n"
<< "\t\tP[1].y = YCo + (AYoYh)* s;\n"
<< "\t\tP[2].x = XCo + (AXoXh + AXoYh) * s;\n"
<< "\t\tP[2].y = YCo + (AYoXh + AYoYh) * s;\n"
<< "\t\tP[3].x = XCo + (AXoXh)* s;\n"
<< "\t\tP[3].y = YCo + (AYoXh)* s;\n"
<< "\t\tP[4].x = XCo - AXoYh * s;\n"
<< "\t\tP[4].y = YCo - AYoYh * s;\n"
<< "\t\tP[5].x = XCo - (AXoXh + AXoYh) * s;\n"
<< "\t\tP[5].y = YCo - (AYoXh + AYoYh) * s;\n"
<< "\t\tP[6].x = XCo - AXoXh * s;\n"
<< "\t\tP[6].y = YCo - AYoXh * s;\n"
<< "\n"
<< "\t\tL1 = Voronoi(&P[0], 7, 0, &U);\n"
<< "\n"
<< "\t\tDXo = U.x - P[0].x;\n"
<< "\t\tDYo = U.y - P[0].y;\n"
<< "\n"
<< "\t\ttrgL = pow(fabs(L1), " << power << ") * " << scale << ";\n"
<< "\n"
<< "\t\tVx = fma( DXo, " << rotcos << ", DYo * " << rotsin << ");\n"
<< "\t\tVy = fma(-DXo, " << rotsin << ", DYo * " << rotcos << ");\n"
<< "\n"
<< "\t\tU.x = Vx + P[0].x;\n"
<< "\t\tU.y = Vy + P[0].y;\n"
<< "\t\tL2 = Voronoi(&P[0], 7, 0, &U);\n"
<< "\t\tL = max(L1, L2);\n"
<< "\n"
<< "\t\tif (L < 0.5)\n"
<< "\t\t{\n"
<< "\t\t R = trgL / L1;\n"
<< "\t\t}\n"
<< "\t\telse\n"
<< "\t\t{\n"
<< "\t\t if (L > 0.8)\n"
<< "\t\t R = trgL / L2;\n"
<< "\t\t else\n"
<< "\t\t R = fma(trgL / L1, (real_t)(0.8) - L, (trgL / L2) * (L - (real_t)(0.5))) / 0.3;\n"
<< "\t\t}\n"
<< "\n"
<< "\t\tVx *= R;\n"
<< "\t\tVy *= R;\n"
<< "\n"
<< "\t\tVx += P[0].x;\n"
<< "\t\tVy += P[0].y;\n"
<< "\n"
<< "\t\tvOut.x = " << weight << " * Vx;\n"
<< "\t\tvOut.y = " << weight << " * Vy;\n"
<< "\t\tvOut.z = " << DefaultZCl()
<< "\t}\n";
return ss.str();
}
virtual vector<string> OpenCLGlobalFuncNames() const override
{
return vector<string> { "Zeps", "Sqr", "Vratio", "Voronoi", "Closest" };
}
virtual string OpenCLFuncsString() const override
{
return
"constant real_t AXhXo = (real_t)(1.0 / 3.0);\n"
"constant real_t AXhYo = (real_t)(1.7320508075688772935 / 3.0);\n"
"constant real_t AYhXo = (real_t)(-1.0 / 3.0);\n"
"constant real_t AYhYo = (real_t)(1.7320508075688772935 / 3.0);\n"
"constant real_t AXoXh = (real_t)(1.5);\n"
"constant real_t AXoYh = (real_t)(-1.5);\n"
"constant real_t AYoXh = (real_t)(1.7320508075688772935 / 2.0);\n"
"constant real_t AYoYh = (real_t)(1.7320508075688772935 / 2.0);\n"
"constant real2 offset[4] = { { 0, 0 }, { 0, 1 }, { 1, 0 }, { 1, 1 } };\n"
"\n";
}
virtual void Precalc() override
{
m_RotSin = std::sin(m_Rotate * M_2PI);
m_RotCos = std::cos(m_Rotate * M_2PI);
}
protected:
void Init()
{
string prefix = Prefix();
m_Params.clear();
m_Params.push_back(ParamWithName<T>(&m_Cellsize, prefix + "hexes_cellsize", 1));
m_Params.push_back(ParamWithName<T>(&m_Power, prefix + "hexes_power", 1));
m_Params.push_back(ParamWithName<T>(&m_Rotate, prefix + "hexes_rotate", T(0.166)));
m_Params.push_back(ParamWithName<T>(&m_Scale, prefix + "hexes_scale", 1));
m_Params.push_back(ParamWithName<T>(true, &m_RotSin, prefix + "hexes_rotsin"));//Precalc.
m_Params.push_back(ParamWithName<T>(true, &m_RotCos, prefix + "hexes_rotcos"));
}
private:
T m_Cellsize;
T m_Power;
T m_Rotate;
T m_Scale;
T m_RotSin;//Precalc.
T m_RotCos;
shared_ptr<VarFuncs<T>> m_VarFuncs = VarFuncs<T>::Instance();
};
/// <summary>
/// nBlur.
/// </summary>
template <typename T>
class NblurVariation : public ParametricVariation<T>
{
struct RandXyParams
{
T NumEdges;
T RatioHole;
T CircumCircle;
T EqualBlur;
T ExactCalc;
T MidAngle;
T AngStart;
T AngStripes;
T HasStripes;
T NegStripes;
T MaxStripes;
T Tan90M2;
T ArcTan1;
T ArcTan2;
T RatioStripes;
T RatioComplement;
T SpeedCalc1;
T SpeedCalc2;
T LenInnerEdges;
T LenOuterEdges;
T X;
T Y;
T LenXY;
};
public:
NblurVariation(T weight = 1.0) : ParametricVariation<T>("nBlur", eVariationId::VAR_NBLUR, weight)
{
Init();
}
PARVARCOPY(NblurVariation)
virtual void Func(IteratorHelper<T>& helper, Point<T>& outPoint, QTIsaac<ISAAC_SIZE, ISAAC_INT>& rand) override
{
T xTmp, yTmp;
RandXyParams params;
params.NumEdges = m_NumEdges;
params.RatioHole = m_RatioHole;
params.CircumCircle = m_CircumCircle;
params.EqualBlur = m_EqualBlur;
params.ExactCalc = m_ExactCalc;
params.MidAngle = m_MidAngle;
params.AngStart = m_AngStart;
params.AngStripes = m_AngStripes;
params.HasStripes = m_HasStripes;
params.NegStripes = m_NegStripes;
params.MaxStripes = m_MaxStripes;
params.Tan90M2 = m_Tan90M2;
params.ArcTan1 = m_ArcTan1;
params.ArcTan2 = m_ArcTan2;
params.RatioStripes = m_RatioStripes;
params.RatioComplement = m_RatioComplement;
params.SpeedCalc1 = m_SpeedCalc1;
params.SpeedCalc2 = m_SpeedCalc2;
RandXY(params, rand);
if ((m_ExactCalc == 1) && (m_CircumCircle == 0))
while ((params.LenXY < params.LenInnerEdges) || (params.LenXY > params.LenOuterEdges))
RandXY(params, rand);
if ((m_ExactCalc == 1) && (m_CircumCircle == 1))
while (params.LenXY < params.LenInnerEdges)
RandXY(params, rand);
xTmp = params.X;
yTmp = params.Y;
params.X = m_Cosa * xTmp - m_Sina * yTmp;
params.Y = m_Sina * xTmp + m_Cosa * yTmp;
helper.Out.x = m_AdjustedWeight * params.X;
helper.Out.y = m_AdjustedWeight * params.Y;
helper.Out.z = DefaultZ(helper);
}
virtual string OpenCLString() const override
{
ostringstream ss, ss2;
intmax_t i = 0;
ss2 << "_" << XformIndexInEmber() << "]";
string index = ss2.str();
string weight = WeightDefineString();
string numEdges = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string numStripes = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string ratioStripes = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string ratioHole = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string circumCircle = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string adjustToLinear = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string equalBlur = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string exactCalc = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string highlightEdges = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string ratioComplement = "parVars[" + ToUpper(m_Params[i++].Name()) + index;//Precalc.
string midAngle = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string angStart = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string angStripes = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string hasStripes = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string negStripes = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string maxStripes = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string absStripes = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string sina = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string cosa = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string tan90M2 = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string arcTan1 = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string arcTan2 = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string speedCalc1 = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string speedCalc2 = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string adjustedWeight = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
ss << "\t{\n"
<< "\t\treal_t xTmp, yTmp;\n"
<< "\t\tRandXyParams params;\n"
<< "\n"
<< "\t\tparams.NumEdges = " << numEdges << ";\n"
<< "\t\tparams.RatioHole = " << ratioHole << ";\n"
<< "\t\tparams.CircumCircle = " << circumCircle << ";\n"
<< "\t\tparams.EqualBlur = " << equalBlur << ";\n"
<< "\t\tparams.ExactCalc = " << exactCalc << ";\n"
<< "\t\tparams.MidAngle = " << midAngle << ";\n"
<< "\t\tparams.AngStart = " << angStart << ";\n"
<< "\t\tparams.AngStripes = " << angStripes << ";\n"
<< "\t\tparams.HasStripes = " << hasStripes << ";\n"
<< "\t\tparams.NegStripes = " << negStripes << ";\n"
<< "\t\tparams.MaxStripes = " << maxStripes << ";\n"
<< "\t\tparams.Tan90M2 = " << tan90M2 << ";\n"
<< "\t\tparams.ArcTan1 = " << arcTan1 << ";\n"
<< "\t\tparams.ArcTan2 = " << arcTan2 << ";\n"
<< "\t\tparams.RatioStripes = " << ratioStripes << ";\n"
<< "\t\tparams.RatioComplement = " << ratioComplement << ";\n"
<< "\t\tparams.SpeedCalc1 = " << speedCalc1 << ";\n"
<< "\t\tparams.SpeedCalc2 = " << speedCalc2 << ";\n"
<< "\n"
<< "\t\tRandXY(&params, mwc);\n"
<< "\n"
<< "\t\tif ((" << exactCalc << " == 1) && (" << circumCircle << " == 0))\n"
<< "\t\t while ((params.LenXY < params.LenInnerEdges) || (params.LenXY > params.LenOuterEdges))\n"
<< "\t\t RandXY(&params, mwc);\n"
<< "\n"
<< "\t\tif ((" << exactCalc << " == 1) && (" << circumCircle << " == 1))\n"
<< "\t\t while (params.LenXY < params.LenInnerEdges)\n"
<< "\t\t RandXY(&params, mwc);\n"
<< "\n"
<< "\t\txTmp = params.X;\n"
<< "\t\tyTmp = params.Y;\n"
<< "\n"
<< "\t\tparams.X = fma(" << cosa << ", xTmp, -(" << sina << " * yTmp));\n"
<< "\t\tparams.Y = fma(" << sina << ", xTmp, " << cosa << " * yTmp);\n"
<< "\n"
<< "\t\tvOut.x = " << adjustedWeight << " * params.X;\n"
<< "\t\tvOut.y = " << adjustedWeight << " * params.Y;\n"
<< "\t\tvOut.z = " << DefaultZCl()
<< "\t}\n";
return ss.str();
}
virtual vector<string> OpenCLGlobalFuncNames() const override
{
return vector<string> { "Swap" };
}
virtual string OpenCLFuncsString() const override
{
return
"typedef struct __attribute__ " ALIGN_CL " _RandXyParams\n"
"{\n"
" real_t NumEdges;\n"
" real_t RatioHole;\n"
" real_t CircumCircle;\n"
" real_t EqualBlur;\n"
" real_t ExactCalc;\n"
" real_t MidAngle;\n"
" real_t AngStart;\n"
" real_t AngStripes;\n"
" real_t HasStripes;\n"
" real_t NegStripes;\n"
" real_t MaxStripes;\n"
" real_t Tan90M2;\n"
" real_t ArcTan1;\n"
" real_t ArcTan2;\n"
" real_t RatioStripes;\n"
" real_t RatioComplement;\n"
" real_t SpeedCalc1;\n"
" real_t SpeedCalc2;\n"
" real_t LenInnerEdges;\n"
" real_t LenOuterEdges;\n"
" real_t X;\n"
" real_t Y;\n"
" real_t LenXY;\n"
"} RandXyParams;\n"
"\n"
"static void RandXY(RandXyParams* params, uint2* mwc)\n"
"{\n"
" real_t angXY, angMem, angTmp;\n"
" real_t ratioTmp, ratioTmpNum, ratioTmpDen;\n"
" real_t xTmp, yTmp;\n"
" real_t ranTmp;\n"
" int count;\n"
"\n"
" if (params->ExactCalc == 1)\n"
" angXY = MwcNext01(mwc) * M_2PI;\n"
" else\n"
" angXY = (atan(params->ArcTan1 * (MwcNext01(mwc) - 0.5)) / params->ArcTan2 + 0.5 + (real_t)(MwcNextRange(mwc, (uint)params->NumEdges))) * params->MidAngle;\n"
"\n"
" params->X = sincos(angXY, &params->Y);\n"
" angMem = angXY;\n"
"\n"
" while (angXY > params->MidAngle)\n"
" angXY -= params->MidAngle;\n"
"\n"
" if (params->HasStripes == 1)\n"
" {\n"
" count = 0;\n"
" angTmp = params->AngStart;\n"
"\n"
" while (angXY > angTmp)\n"
" {\n"
" angTmp += params->AngStripes;\n"
"\n"
" if (angTmp > params->MidAngle)\n"
" angTmp = params->MidAngle;\n"
"\n"
" count++;\n"
" }\n"
"\n"
" if (angTmp != params->MidAngle)\n"
" angTmp -= params->AngStart;\n"
"\n"
" if (params->NegStripes == 0)\n"
" {\n"
" if ((count & 1) == 1)\n"
" {\n"
" if (angXY > angTmp)\n"
" {\n"
" angXY = angXY + params->AngStart;\n"
" angMem = angMem + params->AngStart;\n"
" params->X = sincos(angMem, &params->Y);\n"
" angTmp += params->AngStripes;\n"
" count++;\n"
" }\n"
" else\n"
" {\n"
" angXY = angXY - params->AngStart;\n"
" angMem = angMem - params->AngStart;\n"
" params->X = sincos(angMem, &params->Y);\n"
" angTmp -= params->AngStripes;\n"
" count--;\n"
" }\n"
" }\n"
"\n"
" if (((count & 1) == 0) && (params->RatioStripes > 1))\n"
" {\n"
" if ((angXY > angTmp) && (count != params->MaxStripes))\n"
" {\n"
" angMem = angMem - angXY + angTmp + (angXY - angTmp) / params->AngStart * params->RatioStripes * params->AngStart;\n"
" angXY = angTmp + (angXY - angTmp) / params->AngStart * params->RatioStripes * params->AngStart;\n"
" params->X = sincos(angMem, &params->Y);\n"
" }\n"
" else\n"
" {\n"
" angMem = angMem - angXY + angTmp - (angTmp - angXY) / params->AngStart * params->RatioStripes * params->AngStart;\n"
" angXY = angTmp + (angXY - angTmp) / params->AngStart * params->RatioStripes * params->AngStart;\n"
" params->X = sincos(angMem, &params->Y);\n"
" }\n"
" }\n"
"\n"
" if (((count & 1) == 0) && (params->RatioStripes < 1))\n"
" {\n"
" if ((fabs(angXY - angTmp) > params->SpeedCalc2) && (count != params->MaxStripes))\n"
" {\n"
" if ((angXY - angTmp) > params->SpeedCalc2)\n"
" {\n"
" ratioTmpNum = (angXY - (angTmp + params->SpeedCalc2)) * params->SpeedCalc2;\n"
" ratioTmpDen = params->AngStart - params->SpeedCalc2;\n"
" ratioTmp = ratioTmpNum / ratioTmpDen;\n"
" params->X = sincos((angMem - angXY + angTmp + ratioTmp), &params->Y);\n"
" angXY = angTmp + ratioTmp;\n"
" }\n"
"\n"
" if ((angTmp - angXY) > params->SpeedCalc2)\n"
" {\n"
" ratioTmpNum = (angTmp - params->SpeedCalc2 - angXY) * params->SpeedCalc2;\n"
" ratioTmpDen = params->AngStart - params->SpeedCalc2;\n"
" ratioTmp = ratioTmpNum / ratioTmpDen;\n"
" params->X = sincos((angMem - angXY + angTmp - ratioTmp), &params->Y);\n"
" angXY = angTmp - ratioTmp;\n"
" }\n"
" }\n"
"\n"
" if (count == params->MaxStripes)\n"
" {\n"
" if ((angTmp - angXY) > params->SpeedCalc2)\n"
" {\n"
" ratioTmpNum = (angTmp - params->SpeedCalc2 - angXY) * params->SpeedCalc2;\n"
" ratioTmpDen = params->AngStart - params->SpeedCalc2;\n"
" ratioTmp = ratioTmpNum / ratioTmpDen;\n"
" params->X = sincos((angMem - angXY + angTmp - ratioTmp), &params->Y);\n"
" angXY = angTmp - ratioTmp;\n"
" }\n"
" }\n"
" }\n"
" }\n"
" else\n"
" {\n"
" Swap(&params->RatioStripes, &params->RatioComplement);\n"
" Swap(&params->SpeedCalc1, &params->SpeedCalc2);\n"
"\n"
" if ((count & 1) == 0)\n"
" {\n"
" if ((angXY > angTmp) && (count != params->MaxStripes))\n"
" {\n"
" angXY = angXY + params->AngStart;\n"
" angMem = angMem + params->AngStart;\n"
" params->X = sincos(angMem, &params->Y);\n"
" angTmp += params->AngStripes;\n"
" count++;\n"
" }\n"
" else\n"
" {\n"
" angXY = angXY - params->AngStart;\n"
" angMem = angMem - params->AngStart;\n"
" params->X = sincos(angMem, &params->Y);\n"
" angTmp -= params->AngStripes;\n"
" count--;\n"
" }\n"
" }\n"
"\n"
" if (((count & 1) == 1) && (params->RatioStripes > 1))\n"
" {\n"
" if ((angXY > angTmp) && (count != params->MaxStripes))\n"
" {\n"
" angMem = angMem - angXY + angTmp + (angXY - angTmp) / params->AngStart * params->RatioStripes * params->AngStart;\n"
" angXY = angTmp + (angXY - angTmp) / params->AngStart * params->RatioStripes * params->AngStart;\n"
" params->X = sincos(angMem, &params->Y);\n"
" }\n"
" else\n"
" {\n"
" angMem = angMem - angXY + angTmp - (angTmp - angXY) / params->AngStart * params->RatioStripes * params->AngStart;\n"
" angXY = angTmp + (angXY - angTmp) / params->AngStart * params->RatioStripes * params->AngStart;\n"
" params->X = sincos(angMem, &params->Y);\n"
" }\n"
" }\n"
"\n"
" if (((count & 1) == 1) && (params->RatioStripes < 1))\n"
" {\n"
" if ((fabs(angXY - angTmp) > params->SpeedCalc2) && (count != params->MaxStripes))\n"
" {\n"
" if ((angXY - angTmp) > params->SpeedCalc2)\n"
" {\n"
" ratioTmpNum = (angXY - (angTmp + params->SpeedCalc2)) * params->SpeedCalc2;\n"
" ratioTmpDen = params->AngStart - params->SpeedCalc2;\n"
" ratioTmp = ratioTmpNum / ratioTmpDen;\n"
" params->X = sincos((angMem - angXY + angTmp + ratioTmp), &params->Y);\n"
" angXY = angTmp + ratioTmp;\n"
" }\n"
"\n"
" if ((angTmp - angXY) > params->SpeedCalc2)\n"
" {\n"
" ratioTmpNum = (angTmp - params->SpeedCalc2 - angXY) * params->SpeedCalc2;\n"
" ratioTmpDen = params->AngStart - params->SpeedCalc2;\n"
" ratioTmp = ratioTmpNum / ratioTmpDen;\n"
" params->X = sincos((angMem - angXY + angTmp - ratioTmp), &params->Y);\n"
" angXY = angTmp - ratioTmp;\n"
" }\n"
" }\n"
"\n"
" if (count == params->MaxStripes)\n"
" {\n"
" angTmp = params->MidAngle;\n"
"\n"
" if ((angTmp - angXY) > params->SpeedCalc2)\n"
" {\n"
" ratioTmpNum = (angTmp - params->SpeedCalc2 - angXY) * params->SpeedCalc2;\n"
" ratioTmpDen = params->AngStart - params->SpeedCalc2;\n"
" ratioTmp = ratioTmpNum / ratioTmpDen;\n"
" params->X = sincos((angMem - angXY + angTmp - ratioTmp), &params->Y);\n"
" angXY = angTmp - ratioTmp;\n"
" }\n"
" }\n"
" }\n"
"\n"
" Swap(&params->RatioStripes, &params->RatioComplement);\n"
" Swap(&params->SpeedCalc1, &params->SpeedCalc2);\n"
" }\n"
" }\n"
"\n"
" xTmp = params->Tan90M2 / (params->Tan90M2 - tan(angXY));\n"
" yTmp = xTmp * tan(angXY);\n"
" params->LenOuterEdges = sqrt(fma(xTmp, xTmp, SQR(yTmp)));\n"
"\n"
" if (params->ExactCalc == 1)\n"
" {\n"
" if (params->EqualBlur == 1)\n"
" ranTmp = sqrt(MwcNext01(mwc));\n"
" else\n"
" ranTmp = MwcNext01(mwc);\n"
" }\n"
" else\n"
" {\n"
" if (params->CircumCircle == 1)\n"
" {\n"
" if (params->EqualBlur == 1)\n"
" ranTmp = sqrt(MwcNext01(mwc));\n"
" else\n"
" ranTmp = MwcNext01(mwc);\n"
" }\n"
" else\n"
" {\n"
" if (params->EqualBlur == 1)\n"
" ranTmp = sqrt(MwcNext01(mwc)) * params->LenOuterEdges;\n"
" else\n"
" ranTmp = MwcNext01(mwc) * params->LenOuterEdges;\n"
" }\n"
" }\n"
"\n"
" params->LenInnerEdges = params->RatioHole * params->LenOuterEdges;\n"
"\n"
" if (params->ExactCalc == 0)\n"
" {\n"
" if (ranTmp < params->LenInnerEdges)\n"
" {\n"
" if (params->CircumCircle == 1)\n"
" {\n"
" if (params->EqualBlur == 1)\n"
" ranTmp = fma(sqrt(MwcNext01(mwc)), (1 - params->LenInnerEdges + EPS), params->LenInnerEdges);\n"
" else\n"
" ranTmp = fma(MwcNext01(mwc), (1 - params->LenInnerEdges + EPS), params->LenInnerEdges);\n"
" }\n"
" else\n"
" {\n"
" if (params->EqualBlur == 1)\n"
" ranTmp = fma(sqrt(MwcNext01(mwc)), (params->LenOuterEdges - params->LenInnerEdges), params->LenInnerEdges);\n"
" else\n"
" ranTmp = fma(MwcNext01(mwc), (params->LenOuterEdges - params->LenInnerEdges), params->LenInnerEdges);\n"
" }\n"
" }\n"
" }\n"
"\n"
" params->X *= ranTmp;\n"
" params->Y *= ranTmp;\n"
" params->LenXY = sqrt(fma(params->X, params->X, SQR(params->Y)));\n"
"}\n\n"
;
}
virtual void Precalc() override
{
if (m_NumEdges < 3)
m_NumEdges = 3;
if (m_NumStripes != 0)
{
m_HasStripes = 1;
if (m_NumStripes < 0)
m_NegStripes = 1;
else
m_NegStripes = 0;
}
else
{
m_HasStripes = 0;
m_NegStripes = 0;
}
m_AbsStripes = std::abs(m_NumStripes);
m_MidAngle = M_2PI / m_NumEdges;
if (m_HasStripes == 1)
{
m_AngStripes = m_MidAngle / (2 * m_AbsStripes);
m_AngStart = m_AngStripes / 2;
m_RatioComplement = 2 - m_RatioStripes;
}
if ((m_RatioHole > T(0.95)) && (m_ExactCalc == 1) && (m_CircumCircle == 0))
m_RatioHole = T(0.95);
m_Tan90M2 = std::tan(T(M_PI_2) + m_MidAngle / 2);
sincos((m_MidAngle / 2), &m_Sina, &m_Cosa);
if (m_HighlightEdges <= 0.1)
m_HighlightEdges = T(0.1);
if (m_AdjustToLinear == 1)
{
if (int(m_NumEdges) % 4 == 0)
m_AdjustedWeight = m_Weight / Zeps(std::sqrt(2 - 2 * std::cos(m_MidAngle * (m_NumEdges / 2 - 1))) / 2);
else
m_AdjustedWeight = m_Weight / Zeps(std::sqrt(2 - 2 * std::cos(m_MidAngle * std::floor((m_NumEdges / 2)))) / 2);
}
else
m_AdjustedWeight = m_Weight;
if (m_CircumCircle == 1)
{
m_ExactCalc = 0;
m_HighlightEdges = T(0.1);
}
m_SpeedCalc1 = m_RatioComplement * m_AngStart;
m_SpeedCalc2 = m_RatioStripes * m_AngStart;
m_MaxStripes = 2 * m_AbsStripes;
if (m_NegStripes == 0)
{
m_ArcTan1 = (13 / std::pow(m_NumEdges, T(1.3))) * m_HighlightEdges;
m_ArcTan2 = (2 * std::atan(m_ArcTan1 / -2));
}
else
{
m_ArcTan1 = (T(7.5) / std::pow(m_NumEdges, T(1.3))) * m_HighlightEdges;
m_ArcTan2 = 2 * std::atan(m_ArcTan1 / -2);
}
}
protected:
void Init()
{
string prefix = Prefix();
m_Params.clear();
m_Params.reserve(25);
m_Params.push_back(ParamWithName<T>(&m_NumEdges, prefix + "nBlur_numEdges", 3, eParamType::INTEGER));
m_Params.push_back(ParamWithName<T>(&m_NumStripes, prefix + "nBlur_numStripes", 0, eParamType::INTEGER));
m_Params.push_back(ParamWithName<T>(&m_RatioStripes, prefix + "nBlur_ratioStripes", 1, eParamType::REAL, 0, 2));
m_Params.push_back(ParamWithName<T>(&m_RatioHole, prefix + "nBlur_ratioHole", 0, eParamType::REAL, 0, 1));
m_Params.push_back(ParamWithName<T>(&m_CircumCircle, prefix + "nBlur_circumCircle", 0, eParamType::INTEGER, 0, 1));
m_Params.push_back(ParamWithName<T>(&m_AdjustToLinear, prefix + "nBlur_adjustToLinear", 1, eParamType::INTEGER, 0, 1));
m_Params.push_back(ParamWithName<T>(&m_EqualBlur, prefix + "nBlur_equalBlur", 1, eParamType::INTEGER, 0, 1));
m_Params.push_back(ParamWithName<T>(&m_ExactCalc, prefix + "nBlur_exactCalc", 0, eParamType::INTEGER, 0, 1));
m_Params.push_back(ParamWithName<T>(&m_HighlightEdges, prefix + "nBlur_highlightEdges", 1));
m_Params.push_back(ParamWithName<T>(true, &m_RatioComplement, prefix + "nBlur_ratioComplement"));//Precalc.
m_Params.push_back(ParamWithName<T>(true, &m_MidAngle, prefix + "nBlur_midAngle"));
m_Params.push_back(ParamWithName<T>(true, &m_AngStart, prefix + "nBlur_angStart"));
m_Params.push_back(ParamWithName<T>(true, &m_AngStripes, prefix + "nBlur_angStripes"));
m_Params.push_back(ParamWithName<T>(true, &m_HasStripes, prefix + "nBlur_hasStripes"));
m_Params.push_back(ParamWithName<T>(true, &m_NegStripes, prefix + "nBlur_negStripes"));
m_Params.push_back(ParamWithName<T>(true, &m_MaxStripes, prefix + "nBlur_maxStripes"));
m_Params.push_back(ParamWithName<T>(true, &m_AbsStripes, prefix + "nBlur_absStripes"));
m_Params.push_back(ParamWithName<T>(true, &m_Sina, prefix + "nBlur_sina"));
m_Params.push_back(ParamWithName<T>(true, &m_Cosa, prefix + "nBlur_cosa"));
m_Params.push_back(ParamWithName<T>(true, &m_Tan90M2, prefix + "nBlur_tan90m2"));
m_Params.push_back(ParamWithName<T>(true, &m_ArcTan1, prefix + "nBlur_arcTan1"));
m_Params.push_back(ParamWithName<T>(true, &m_ArcTan2, prefix + "nBlur_arcTan2"));
m_Params.push_back(ParamWithName<T>(true, &m_SpeedCalc1, prefix + "nBlur_speedCalc1"));
m_Params.push_back(ParamWithName<T>(true, &m_SpeedCalc2, prefix + "nBlur_speedCalc2"));
m_Params.push_back(ParamWithName<T>(true, &m_AdjustedWeight, prefix + "nBlur_adjustedWeight"));
}
private:
static void RandXY(RandXyParams& params, QTIsaac<ISAAC_SIZE, ISAAC_INT>& rand)
{
T angXY, angMem, angTmp;
T ratioTmp, ratioTmpNum, ratioTmpDen;
T xTmp, yTmp;
T ranTmp, x;
int count;
if (params.ExactCalc == 1)
angXY = rand.Frand01<T>() * M_2PI;
else
angXY = (std::atan(params.ArcTan1 * (rand.Frand01<T>() - T(0.5))) / params.ArcTan2 + T(0.5) + T(rand.Rand(size_t(params.NumEdges)))) * params.MidAngle;
sincos(angXY, &params.X, &params.Y);
angMem = angXY;
while (angXY > params.MidAngle)
angXY -= params.MidAngle;
if (params.HasStripes == 1)
{
count = 0;
angTmp = params.AngStart;
while (angXY > angTmp)
{
angTmp += params.AngStripes;
if (angTmp > params.MidAngle)
angTmp = params.MidAngle;
count++;
}
if (angTmp != params.MidAngle)
angTmp -= params.AngStart;
if (params.NegStripes == 0)
{
if ((count & 1) == 1)
{
if (angXY > angTmp)
{
angXY = angXY + params.AngStart;
angMem = angMem + params.AngStart;
sincos(angMem, &params.X, &params.Y);
angTmp += params.AngStripes;
count++;
}
else
{
angXY = angXY - params.AngStart;
angMem = angMem - params.AngStart;
sincos(angMem, &params.X, &params.Y);
angTmp -= params.AngStripes;
count--;
}
}
if (((count & 1) == 0) && (params.RatioStripes > 1))
{
if ((angXY > angTmp) && (count != params.MaxStripes))
{
angMem = angMem - angXY + angTmp + (angXY - angTmp) / params.AngStart * params.RatioStripes * params.AngStart;
angXY = angTmp + (angXY - angTmp) / params.AngStart * params.RatioStripes * params.AngStart;
sincos(angMem, &params.X, &params.Y);
}
else
{
angMem = angMem - angXY + angTmp - (angTmp - angXY) / params.AngStart * params.RatioStripes * params.AngStart;
angXY = angTmp + (angXY - angTmp) / params.AngStart * params.RatioStripes * params.AngStart;
sincos(angMem, &params.X, &params.Y);
}
}
if (((count & 1) == 0) && (params.RatioStripes < 1))
{
if ((std::abs(angXY - angTmp) > params.SpeedCalc2) && (count != params.MaxStripes))
{
if ((angXY - angTmp) > params.SpeedCalc2)
{
ratioTmpNum = (angXY - (angTmp + params.SpeedCalc2)) * params.SpeedCalc2;
ratioTmpDen = params.AngStart - params.SpeedCalc2;
ratioTmp = ratioTmpNum / ratioTmpDen;
x = angMem - angXY + angTmp + ratioTmp;
sincos(x, &params.X, &params.Y);
angXY = angTmp + ratioTmp;
}
if ((angTmp - angXY) > params.SpeedCalc2)
{
ratioTmpNum = (angTmp - params.SpeedCalc2 - angXY) * params.SpeedCalc2;
ratioTmpDen = params.AngStart - params.SpeedCalc2;
ratioTmp = ratioTmpNum / ratioTmpDen;
x = angMem - angXY + angTmp - ratioTmp;
sincos(x, &params.X, &params.Y);
angXY = angTmp - ratioTmp;
}
}
if (count == params.MaxStripes)
{
if ((angTmp - angXY) > params.SpeedCalc2)
{
ratioTmpNum = (angTmp - params.SpeedCalc2 - angXY) * params.SpeedCalc2;
ratioTmpDen = params.AngStart - params.SpeedCalc2;
ratioTmp = ratioTmpNum / ratioTmpDen;
x = angMem - angXY + angTmp - ratioTmp;
sincos(x, &params.X, &params.Y);
angXY = angTmp - ratioTmp;
}
}
}
}
else
{
std::swap(params.RatioStripes, params.RatioComplement);
std::swap(params.SpeedCalc1, params.SpeedCalc2);
if ((count & 1) == 0)
{
if ((angXY > angTmp) && (count != params.MaxStripes))
{
angXY = angXY + params.AngStart;
angMem = angMem + params.AngStart;
sincos(angMem, &params.X, &params.Y);
angTmp += params.AngStripes;
count++;
}
else
{
angXY = angXY - params.AngStart;
angMem = angMem - params.AngStart;
sincos(angMem, &params.X, &params.Y);
angTmp -= params.AngStripes;
count--;
}
}
if (((count & 1) == 1) && (params.RatioStripes > 1))
{
if ((angXY > angTmp) && (count != params.MaxStripes))
{
angMem = angMem - angXY + angTmp + (angXY - angTmp) / params.AngStart * params.RatioStripes * params.AngStart;
angXY = angTmp + (angXY - angTmp) / params.AngStart * params.RatioStripes * params.AngStart;
sincos(angMem, &params.X, &params.Y);
}
else
{
angMem = angMem - angXY + angTmp - (angTmp - angXY) / params.AngStart * params.RatioStripes * params.AngStart;
angXY = angTmp + (angXY - angTmp) / params.AngStart * params.RatioStripes * params.AngStart;
sincos(angMem, &params.X, &params.Y);
}
}
if (((count & 1) == 1) && (params.RatioStripes < 1))
{
if ((std::abs(angXY - angTmp) > params.SpeedCalc2) && (count != params.MaxStripes))
{
if ((angXY - angTmp) > params.SpeedCalc2)
{
ratioTmpNum = (angXY - (angTmp + params.SpeedCalc2)) * params.SpeedCalc2;
ratioTmpDen = params.AngStart - params.SpeedCalc2;
ratioTmp = ratioTmpNum / ratioTmpDen;
x = angMem - angXY + angTmp + ratioTmp;
sincos(x, &params.X, &params.Y);
angXY = angTmp + ratioTmp;
}
if ((angTmp - angXY) > params.SpeedCalc2)
{
ratioTmpNum = (angTmp - params.SpeedCalc2 - angXY) * params.SpeedCalc2;
ratioTmpDen = params.AngStart - params.SpeedCalc2;
ratioTmp = ratioTmpNum / ratioTmpDen;
x = angMem - angXY + angTmp - ratioTmp;
sincos(x, &params.X, &params.Y);
angXY = angTmp - ratioTmp;
}
}
if (count == params.MaxStripes)
{
angTmp = params.MidAngle;
if ((angTmp - angXY) > params.SpeedCalc2)
{
ratioTmpNum = (angTmp - params.SpeedCalc2 - angXY) * params.SpeedCalc2;
ratioTmpDen = params.AngStart - params.SpeedCalc2;
ratioTmp = ratioTmpNum / ratioTmpDen;
x = angMem - angXY + angTmp - ratioTmp;
sincos(x, &params.X, &params.Y);
angXY = angTmp - ratioTmp;
}
}
}
std::swap(params.RatioStripes, params.RatioComplement);
std::swap(params.SpeedCalc1, params.SpeedCalc2);
}
}
xTmp = params.Tan90M2 / (params.Tan90M2 - std::tan(angXY));
yTmp = xTmp * std::tan(angXY);
params.LenOuterEdges = std::sqrt(SQR(xTmp) + SQR(yTmp));
if (params.ExactCalc == 1)
{
if (params.EqualBlur == 1)
ranTmp = std::sqrt(rand.Frand01<T>());
else
ranTmp = rand.Frand01<T>();
}
else
{
if (params.CircumCircle == 1)
{
if (params.EqualBlur == 1)
ranTmp = std::sqrt(rand.Frand01<T>());
else
ranTmp = rand.Frand01<T>();
}
else
{
if (params.EqualBlur == 1)
ranTmp = std::sqrt(rand.Frand01<T>()) * params.LenOuterEdges;
else
ranTmp = rand.Frand01<T>() * params.LenOuterEdges;
}
}
params.LenInnerEdges = params.RatioHole * params.LenOuterEdges;
if (params.ExactCalc == 0)
{
if (ranTmp < params.LenInnerEdges)
{
if (params.CircumCircle == 1)
{
if (params.EqualBlur == 1)
ranTmp = params.LenInnerEdges + std::sqrt(rand.Frand01<T>()) * (1 - params.LenInnerEdges + EPS);
else
ranTmp = params.LenInnerEdges + rand.Frand01<T>() * (1 - params.LenInnerEdges + EPS);
}
else
{
if (params.EqualBlur == 1)
ranTmp = params.LenInnerEdges + std::sqrt(rand.Frand01<T>()) * (params.LenOuterEdges - params.LenInnerEdges);
else
ranTmp = params.LenInnerEdges + rand.Frand01<T>() * (params.LenOuterEdges - params.LenInnerEdges);
}
}
}
params.X *= ranTmp;
params.Y *= ranTmp;
params.LenXY = std::sqrt(SQR(params.X) + SQR(params.Y));
}
T m_NumEdges;
T m_NumStripes;
T m_RatioStripes;
T m_RatioHole;
T m_CircumCircle;
T m_AdjustToLinear;
T m_EqualBlur;
T m_ExactCalc;
T m_HighlightEdges;
T m_RatioComplement;//Precalc.
T m_MidAngle;
T m_AngStart;
T m_AngStripes;
T m_HasStripes;
T m_NegStripes;
T m_MaxStripes;
T m_AbsStripes;
T m_Sina;
T m_Cosa;
T m_Tan90M2;
T m_ArcTan1;
T m_ArcTan2;
T m_SpeedCalc1;
T m_SpeedCalc2;
T m_AdjustedWeight;
};
/// <summary>
/// octapol.
/// </summary>
template <typename T>
class OctapolVariation : public ParametricVariation<T>
{
public:
OctapolVariation(T weight = 1.0) : ParametricVariation<T>("octapol", eVariationId::VAR_OCTAPOL, weight)
{
Init();
}
PARVARCOPY(OctapolVariation)
virtual void Func(IteratorHelper<T>& helper, Point<T>& outPoint, QTIsaac<ISAAC_SIZE, ISAAC_INT>& rand) override
{
bool clear = false;
T x = helper.In.x * T(0.15), y = helper.In.y * T(0.15), z = helper.In.z, r = 0, u = 0, v = 0;
v2T xy = { x, y };
v2T tempOut = { 0, 0 };
if ((m_TempRad > 0) && HitsCircleAroundOrigin(m_TempRad, xy, r))
{
T rd = std::log(Sqr(r / m_TempRad));
T phi = std::atan2(y, x);
tempOut.x = m_Weight * Lerp(x, phi, rd * m_Polarweight);
tempOut.y = m_Weight * Lerp(y, r, rd * m_Polarweight);
}
else if (HitsSquareAroundOrigin(m_St, xy))
{
if (HitsRect(m_H, m_K, xy) || HitsRect(m_J, m_D, xy) ||
HitsRect(m_A, m_J, xy) || HitsRect(m_K, m_E, xy) ||
HitsTriangle(m_I, m_A, m_H, xy, u, v) ||
HitsTriangle(m_J, m_B, m_C, xy, u, v) ||
HitsTriangle(m_L, m_D, m_E, xy, u, v) ||
HitsTriangle(m_K, m_F, m_G, xy, u, v))
{
tempOut.x = m_Weight * x;
tempOut.y = m_Weight * y;
}
else
clear = true;
}
else
clear = true;
if (clear)
{
if (m_VarType == eVariationType::VARTYPE_PRE)
{
helper.m_TransX = 0;
helper.m_TransY = 0;
}
else
{
outPoint.m_X = 0;
outPoint.m_Y = 0;
}
}
helper.Out.x = tempOut.x + (m_Weight * x);
helper.Out.y = tempOut.y + (m_Weight * y);
helper.Out.z = m_Weight * z;
}
virtual string OpenCLString() const override
{
ostringstream ss, ss2;
intmax_t i = 0, varIndex = IndexInXform();
ss2 << "_" << XformIndexInEmber();
string weight = WeightDefineString();
string index = ss2.str() + "]";
string stateIndex = ss2.str();
string polarweight = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string radius = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string s = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string t = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string tempRad = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string abss = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string abst = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string st = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string axStartIndex = ToUpper(m_Params[i].Name()) + stateIndex; i += 2;
string bxStartIndex = ToUpper(m_Params[i].Name()) + stateIndex; i += 2;
string cxStartIndex = ToUpper(m_Params[i].Name()) + stateIndex; i += 2;
string dxStartIndex = ToUpper(m_Params[i].Name()) + stateIndex; i += 2;
string exStartIndex = ToUpper(m_Params[i].Name()) + stateIndex; i += 2;
string fxStartIndex = ToUpper(m_Params[i].Name()) + stateIndex; i += 2;
string gxStartIndex = ToUpper(m_Params[i].Name()) + stateIndex; i += 2;
string hxStartIndex = ToUpper(m_Params[i].Name()) + stateIndex; i += 2;
string ixStartIndex = ToUpper(m_Params[i].Name()) + stateIndex; i += 2;
string jxStartIndex = ToUpper(m_Params[i].Name()) + stateIndex; i += 2;
string kxStartIndex = ToUpper(m_Params[i].Name()) + stateIndex; i += 2;
string lxStartIndex = ToUpper(m_Params[i].Name()) + stateIndex;
ss << "\t{\n"
<< "\t\tbool clear = false;\n"
<< "\t\treal_t x = vIn.x * 0.15, y = vIn.y * 0.15, z = vIn.z, r = 0, u = 0, v = 0, x2 = 0, y2 = 0;\n"
<< "\t\treal2 xy = { x, y };\n"
<< "\t\treal2 tempOut = { 0, 0 };\n"
<< "\t\treal2 A = { parVars[" << axStartIndex << "], parVars[" << axStartIndex << " + 1] };\n"
<< "\t\treal2 B = { parVars[" << bxStartIndex << "], parVars[" << bxStartIndex << " + 1] };\n"
<< "\t\treal2 C = { parVars[" << cxStartIndex << "], parVars[" << cxStartIndex << " + 1] };\n"
<< "\t\treal2 D = { parVars[" << dxStartIndex << "], parVars[" << dxStartIndex << " + 1] };\n"
<< "\t\treal2 E = { parVars[" << exStartIndex << "], parVars[" << exStartIndex << " + 1] };\n"
<< "\t\treal2 F = { parVars[" << fxStartIndex << "], parVars[" << fxStartIndex << " + 1] };\n"
<< "\t\treal2 G = { parVars[" << gxStartIndex << "], parVars[" << gxStartIndex << " + 1] };\n"
<< "\t\treal2 H = { parVars[" << hxStartIndex << "], parVars[" << hxStartIndex << " + 1] };\n"
<< "\t\treal2 I = { parVars[" << ixStartIndex << "], parVars[" << ixStartIndex << " + 1] };\n"
<< "\t\treal2 J = { parVars[" << jxStartIndex << "], parVars[" << jxStartIndex << " + 1] };\n"
<< "\t\treal2 K = { parVars[" << kxStartIndex << "], parVars[" << kxStartIndex << " + 1] };\n"
<< "\t\treal2 L = { parVars[" << lxStartIndex << "], parVars[" << lxStartIndex << " + 1] };\n"
<< "\n"
<< "\t\tif ((" << tempRad << " > 0) && HitsCircleAroundOrigin(" << tempRad << ", &xy, &r))\n"
<< "\t\t{\n"
<< "\t\t real_t rd = log(Sqr(r / " << tempRad << "));\n"
<< "\t\t real_t phi = atan2(y, x);\n"
<< "\n"
<< "\t\t tempOut.x = " << weight << " * Lerp(x, phi, rd * " << polarweight << ");\n"
<< "\t\t tempOut.y = " << weight << " * Lerp(y, r, rd * " << polarweight << ");\n"
<< "\t\t}\n"
<< "\t\telse if (HitsSquareAroundOrigin(" << st << ", &xy))\n"
<< "\t\t{\n"
<< "\t\t if (HitsRect(&H, &K, &xy) || HitsRect(&J, &D, &xy) ||\n"
<< "\t\t HitsRect(&A, &J, &xy) || HitsRect(&K, &E, &xy) ||\n"
<< "\t\t HitsTriangle(&I, &A, &H, &xy, &u, &v) ||\n"
<< "\t\t HitsTriangle(&J, &B, &C, &xy, &u, &v) ||\n"
<< "\t\t HitsTriangle(&L, &D, &E, &xy, &u, &v) ||\n"
<< "\t\t HitsTriangle(&K, &F, &G, &xy, &u, &v))\n"
<< "\t\t {\n"
<< "\t\t tempOut.x = " << weight << " * x;\n"
<< "\t\t tempOut.y = " << weight << " * y;\n"
<< "\t\t }\n"
<< "\t\t else\n"
<< "\t\t clear = true;\n"
<< "\t\t}\n"
<< "\t\telse\n"
<< "\t\t clear = true;\n"
<< "\n"
<< "\t\tif (clear)\n"
<< "\t\t{\n";
if (m_VarType == eVariationType::VARTYPE_PRE)
{
ss
<< "\t\t transX = 0;\n"
<< "\t\t transY = 0;\n";
}
else
{
ss
<< "\t\t outPoint->m_X = 0;\n"
<< "\t\t outPoint->m_Y = 0;\n";
}
ss
<< "\t\t}\n"
<< "\n"
<< "\t\tvOut.x = fma(" << weight << ", x, tempOut.x);\n"
<< "\t\tvOut.y = fma(" << weight << ", y, tempOut.y);\n"
<< "\t\tvOut.z = " << weight << " * z;\n"
<< "\t}\n";
return ss.str();
}
virtual vector<string> OpenCLGlobalFuncNames() const override
{
return vector<string> { "Lerp", "Sqr" };
}
virtual string OpenCLFuncsString() const override
{
return
"static int HitsRect(real2* tl, real2* br, real2* p)\n"
"{\n"
" return ((*p).x >= (*tl).x && (*p).y >= (*tl).y && (*p).x <= (*br).x && (*p).y <= (*br).y);\n"
"}\n"
"\n"
"static int HitsSquareAroundOrigin(real_t a, real2* p)\n"
"{\n"
" return (fabs((*p).x) <= a && fabs((*p).y) <= a);\n"
"}\n"
"\n"
"static int HitsCircleAroundOrigin(real_t radius, real2* p, real_t* r)\n"
"{\n"
" if (radius == 0)\n"
" return 1;\n"
"\n"
" *r = sqrt(fma((*p).x, (*p).x, SQR((*p).y)));\n"
" return (*r <= radius);\n"
"}\n"
"\n"
"static int HitsTriangle(real2* a, real2* b, real2* c, real2* p, real_t* u, real_t* v)\n"
"{\n"
" real2 v0 = { (*c).x - (*a).x, (*c).y - (*a).y };\n"
" real2 v1 = { (*b).x - (*a).x, (*b).y - (*a).y };\n"
" real2 v2 = { (*p).x - (*a).x, (*p).y - (*a).y };\n"
" real_t d00 = dot(v0, v0);\n"
" real_t d01 = dot(v0, v1);\n"
" real_t d02 = dot(v0, v2);\n"
" real_t d11 = dot(v1, v1);\n"
" real_t d12 = dot(v1, v2);\n"
" real_t denom = fma(d00, d11, -(d01 * d01));\n"
"\n"
" if (denom != 0)\n"
" {\n"
" *u = fma(d11, d02, -(d01 * d12)) / denom;\n"
" *v = fma(d00, d12, -(d01 * d02)) / denom;\n"
" }\n"
" else\n"
" *u = *v = 0;\n"
"\n"
" return ((*u + *v) < 1) && (*u > 0) && (*v > 0);\n"
"}\n\n";
}
virtual void Precalc() override
{
static const T DENOM_SQRT2 = T(0.707106781);
m_AbsS = std::abs(m_S);
m_AbsT = std::abs(m_T);
m_St = m_AbsS * T(0.5) + m_AbsT;
m_TempRad = DENOM_SQRT2 * m_AbsS * std::abs(m_Radius);
m_A = { -T(0.5)* m_AbsS, T(0.5)* m_AbsS + m_AbsT };
m_B = { T(0.5)* m_AbsS, T(0.5)* m_AbsS + m_AbsT };
m_C = { m_AbsT, T(0.5)* m_AbsS };
m_D = { m_AbsT, -T(0.5)* m_AbsS };
m_E = { T(0.5)* m_AbsS, -T(0.5)* m_AbsS - m_AbsT };
m_F = { -T(0.5)* m_AbsS, -T(0.5)* m_AbsS - m_AbsT };
m_G = { -m_AbsT, -T(0.5)* m_AbsS };
m_H = { -m_AbsT, T(0.5)* m_AbsS };
m_I = { -T(0.5)* m_AbsS, T(0.5)* m_AbsS };
m_J = { T(0.5)* m_AbsS, T(0.5)* m_AbsS };
m_K = { -T(0.5)* m_AbsS, -T(0.5)* m_AbsS };
m_L = { T(0.5)* m_AbsS, -T(0.5)* m_AbsS };
}
protected:
void Init()
{
string prefix = Prefix();
m_Params.clear();
m_Params.push_back(ParamWithName<T>(&m_Polarweight, prefix + "octapol_polarweight"));
m_Params.push_back(ParamWithName<T>(&m_Radius, prefix + "octapol_radius", 1));
m_Params.push_back(ParamWithName<T>(&m_S, prefix + "octapol_s", T(0.5)));
m_Params.push_back(ParamWithName<T>(&m_T, prefix + "octapol_t", T(0.5)));
m_Params.push_back(ParamWithName<T>(true, &m_TempRad, prefix + "octapol_rad"));//Precalc.
m_Params.push_back(ParamWithName<T>(true, &m_AbsS, prefix + "octapol_abss"));
m_Params.push_back(ParamWithName<T>(true, &m_AbsT, prefix + "octapol_abst"));
m_Params.push_back(ParamWithName<T>(true, &m_St, prefix + "octapol_absst"));
m_Params.push_back(ParamWithName<T>(true, &m_A.x, prefix + "octapol_ax"));
m_Params.push_back(ParamWithName<T>(true, &m_A.y, prefix + "octapol_ay"));
m_Params.push_back(ParamWithName<T>(true, &m_B.x, prefix + "octapol_bx"));
m_Params.push_back(ParamWithName<T>(true, &m_B.y, prefix + "octapol_by"));
m_Params.push_back(ParamWithName<T>(true, &m_C.x, prefix + "octapol_cx"));
m_Params.push_back(ParamWithName<T>(true, &m_C.y, prefix + "octapol_cy"));
m_Params.push_back(ParamWithName<T>(true, &m_D.x, prefix + "octapol_dx"));
m_Params.push_back(ParamWithName<T>(true, &m_D.y, prefix + "octapol_dy"));
m_Params.push_back(ParamWithName<T>(true, &m_E.x, prefix + "octapol_ex"));
m_Params.push_back(ParamWithName<T>(true, &m_E.y, prefix + "octapol_ey"));
m_Params.push_back(ParamWithName<T>(true, &m_F.x, prefix + "octapol_fx"));
m_Params.push_back(ParamWithName<T>(true, &m_F.y, prefix + "octapol_fy"));
m_Params.push_back(ParamWithName<T>(true, &m_G.x, prefix + "octapol_gx"));
m_Params.push_back(ParamWithName<T>(true, &m_G.y, prefix + "octapol_gy"));
m_Params.push_back(ParamWithName<T>(true, &m_H.x, prefix + "octapol_hx"));
m_Params.push_back(ParamWithName<T>(true, &m_H.y, prefix + "octapol_hy"));
m_Params.push_back(ParamWithName<T>(true, &m_I.x, prefix + "octapol_ix"));
m_Params.push_back(ParamWithName<T>(true, &m_I.y, prefix + "octapol_iy"));
m_Params.push_back(ParamWithName<T>(true, &m_J.x, prefix + "octapol_jx"));
m_Params.push_back(ParamWithName<T>(true, &m_J.y, prefix + "octapol_jy"));
m_Params.push_back(ParamWithName<T>(true, &m_K.x, prefix + "octapol_kx"));
m_Params.push_back(ParamWithName<T>(true, &m_K.y, prefix + "octapol_ky"));
m_Params.push_back(ParamWithName<T>(true, &m_L.x, prefix + "octapol_lx"));
m_Params.push_back(ParamWithName<T>(true, &m_L.y, prefix + "octapol_ly"));
}
private:
int HitsRect(v2T& tl, v2T& br, v2T& p)
{
return (p.x >= tl.x && p.y >= tl.y && p.x <= br.x && p.y <= br.y);
}
int HitsSquareAroundOrigin(T a, v2T& p)
{
return (std::abs(p.x) <= a && std::abs(p.y) <= a);
}
int HitsCircleAroundOrigin(T radius, v2T& p, T& r)
{
if (radius == 0)
return 1;
r = std::sqrt(SQR(p.x) + SQR(p.y));
return (r <= radius);
}
int HitsTriangle(v2T& a, v2T& b, v2T& c, v2T& p, T& u, T& v)
{
v2T v0 = { c.x - a.x, c.y - a.y };
v2T v1 = { b.x - a.x, b.y - a.y };
v2T v2 = { p.x - a.x, p.y - a.y };
T d00 = glm::dot(v0, v0);
T d01 = glm::dot(v0, v1);
T d02 = glm::dot(v0, v2);
T d11 = glm::dot(v1, v1);
T d12 = glm::dot(v1, v2);
T denom = (d00 * d11 - d01 * d01);
if (denom != 0)
{
u = (d11 * d02 - d01 * d12) / denom;
v = (d00 * d12 - d01 * d02) / denom;
}
else
u = v = 0;
return ((u + v) < 1) && (u > 0) && (v > 0);
}
T m_Polarweight;
T m_Radius;
T m_S;
T m_T;
T m_TempRad;//Precalc.
T m_AbsS;
T m_AbsT;
T m_St;
v2T m_A;
v2T m_B;
v2T m_C;
v2T m_D;
v2T m_E;
v2T m_F;
v2T m_G;
v2T m_H;
v2T m_I;
v2T m_J;
v2T m_K;
v2T m_L;
};
/// <summary>
/// crob.
/// This uses the input point in an extremely rare way since it changes it.
/// </summary>
template <typename T>
class CrobVariation : public ParametricVariation<T>
{
public:
CrobVariation(T weight = 1.0) : ParametricVariation<T>("crob", eVariationId::VAR_CROB, weight)
{
Init();
}
PARVARCOPY(CrobVariation)
virtual void Func(IteratorHelper<T>& helper, Point<T>& outPoint, QTIsaac<ISAAC_SIZE, ISAAC_INT>& rand) override
{
T gradTmp, secTmp, xTmp = 0, yTmp = 0;
if ((helper.In.x < m_LeftBorder) || (helper.In.x > m_RightBorder) || (helper.In.y < m_TopBorder) || (helper.In.y > m_BottomBorder))
{
if (m_Blur == 0)
{
if (m_VarType == eVariationType::VARTYPE_REG)
{
helper.In.x = helper.m_TransX = 0;//This will not only overwrite the current output point running sum, but also set
helper.In.y = helper.m_TransY = 0;//the affine transformed point so that any future variation that uses it directly will get the updated value.
}
}
else
{
secTmp = rand.Frand01<T>();
if (secTmp < m_SetProb)
{
do
{
yTmp = m_Top + rand.Frand01<T>() * m_YInt2;
xTmp = m_Right - pow(rand.Frand01<T>(), m_DirectBlur) * m_RatioBlur * m_MinInt2;
}
while ((yTmp - m_Y0c) / Zeps(xTmp - m_X0c) < -1);
if (secTmp < m_SetProbH)
xTmp = m_Left + m_Right - xTmp;
if ((secTmp > m_SetProbQ) && (secTmp < m_SetProbTQ))
yTmp = m_Bottom + m_Top - yTmp;
}
else
{
do
{
xTmp = m_Right - rand.Frand01<T>() * m_XInt2;
yTmp = m_Top + std::pow(rand.Frand01<T>(), m_DirectBlur) * m_RatioBlur * m_MinInt2;
gradTmp = (yTmp - m_Y0c) / Zeps(xTmp - m_X0c);
}
while ((gradTmp <= 0) && (gradTmp > -1));
if (secTmp > m_SetProbH)
yTmp = m_Bottom + m_Top - yTmp;
if ((secTmp > m_SetProbQ) && (secTmp < m_SetProbTQ))
xTmp = m_Left + m_Right - xTmp;
}
if (m_VarType == eVariationType::VARTYPE_REG)
{
helper.In.x = helper.m_TransX = xTmp;//This will not only overwrite the current output point running sum, but also set
helper.In.y = helper.m_TransY = yTmp;//the affine transformed point so that any future variation that uses it directly will get the updated value.
}
}
}
helper.Out.x = xTmp;
helper.Out.y = yTmp;
helper.Out.z = DefaultZ(helper);
}
virtual string OpenCLString() const override
{
ostringstream ss, ss2;
intmax_t i = 0;
ss2 << "_" << XformIndexInEmber() << "]";
string index = ss2.str();
string weight = WeightDefineString();
string top = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string bottom = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string left = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string right = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string blur = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string ratioBlur = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string directBlur = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string xInterval = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string yInterval = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string xInt2 = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string yInt2 = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string minInt2 = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string x0 = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string y0 = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string x0c = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string y0c = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string setProb = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string setProbH = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string setProbQ = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string setProbTQ = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string setCompProb = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string setCompProbH = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string setCompProbQ = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string setCompProbTQ = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string topBorder = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string bottomBorder = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string leftBorder = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string rightBorder = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
ss << "\t{\n"
<< "\t\treal_t gradTmp, secTmp, xTmp = 0, yTmp = 0;\n"
<< "\n"
<< "\t\tif ((vIn.x < " << leftBorder << ") || (vIn.x > " << rightBorder << ") || (vIn.y < " << topBorder << ") || (vIn.y > " << bottomBorder << "))\n"
<< "\t\t{\n"
<< "\t\t if (" << blur << " == 0)\n"
<< "\t\t {\n";
if (m_VarType == eVariationType::VARTYPE_REG)
{
ss
<< "\t\t vIn.x = transX = 0;\n"
<< "\t\t vIn.y = transY = 0;\n";
}
ss
<< "\t\t }\n"
<< "\t\t else\n"
<< "\t\t {\n"
<< "\t\t secTmp = MwcNext01(mwc);\n"
<< "\n"
<< "\t\t if (secTmp < " << setProb << ")\n"
<< "\t\t {\n"
<< "\t\t do\n"
<< "\t\t {\n"
<< "\t\t yTmp = fma(MwcNext01(mwc), " << yInt2 << ", " << top << ");\n"
<< "\t\t xTmp = " << right << " - pow(MwcNext01(mwc), " << directBlur << ") * " << ratioBlur << " * " << minInt2 << ";\n"
<< "\t\t } while ((yTmp - " << y0c << ") / Zeps(xTmp - " << x0c << ") < -1);\n"
<< "\n"
<< "\t\t if (secTmp < " << setProbH << ")\n"
<< "\t\t xTmp = " << left << " + " << right << " - xTmp;\n"
<< "\n"
<< "\t\t if ((secTmp > " << setProbQ << ") && (secTmp < " << setProbTQ << "))\n"
<< "\t\t yTmp = " << bottom << " + " << top << " - yTmp;\n"
<< "\t\t }\n"
<< "\t\t else\n"
<< "\t\t {\n"
<< "\t\t do\n"
<< "\t\t {\n"
<< "\t\t xTmp = " << right << " - MwcNext01(mwc) * " << xInt2 << ";\n"
<< "\t\t yTmp = " << top << " + pow(MwcNext01(mwc), " << directBlur << ") * " << ratioBlur << " * " << minInt2 << ";\n"
<< "\t\t gradTmp = (yTmp - " << y0c << ") / Zeps(xTmp - " << x0c << ");\n"
<< "\t\t } while ((gradTmp <= 0) && (gradTmp > -1));\n"
<< "\n"
<< "\t\t if (secTmp > " << setProbH << ")\n"
<< "\t\t yTmp = " << bottom << " + " << top << " - yTmp;\n"
<< "\n"
<< "\t\t if ((secTmp > " << setProbQ << ") && (secTmp < " << setProbTQ << "))\n"
<< "\t\t xTmp = " << left << " + " << right << " - xTmp;\n"
<< "\t\t }\n"
<< "\n";
if (m_VarType == eVariationType::VARTYPE_REG)
{
ss
<< "\t\t vIn.x = transX = xTmp;\n"
<< "\t\t vIn.y = transY = yTmp;\n";
}
ss
<< "\t\t\t}\n"
<< "\t\t}\n"
<< "\n"
<< "\t\tvOut.x = xTmp;\n"
<< "\t\tvOut.y = yTmp;\n"
<< "\t\tvOut.z = " << DefaultZCl()
<< "\t}\n";
return ss.str();
}
virtual void Precalc() override
{
if (m_Top > m_Bottom)
std::swap(m_Top, m_Bottom);
if (m_Top == m_Bottom)
{
m_Top = -1;
m_Bottom = 1;
}
if (m_Left > m_Right)
std::swap(m_Left, m_Right);
if (m_Left == m_Right)
{
m_Left = -1;
m_Right = 1;
}
if (m_DirectBlur < 0)
m_DirectBlur = 0;
if (m_Blur != 0)
m_Blur = 1;
m_XInterval = std::abs(m_Right) - m_Left;
m_YInterval = std::abs(m_Bottom) - m_Top;
m_XInt2 = m_XInterval / 2;
m_YInt2 = m_YInterval / 2;
if (m_XInt2 > m_YInt2)
m_MinInt2 = m_YInt2;
else
m_MinInt2 = m_XInt2;
m_X0 = m_Right - m_XInt2;
m_Y0 = m_Top + m_YInt2;
if (m_XInt2 > m_YInt2)
{
m_X0c = m_Right - m_MinInt2;
m_Y0c = m_Y0;
}
else if (m_XInt2 < m_YInt2)
{
m_X0c = m_X0;
m_Y0c = m_Top + m_MinInt2;
}
else
{
m_X0c = m_X0;
m_Y0c = m_Y0;
}
m_SetProb = m_YInterval / (m_XInterval + m_YInterval);
m_SetProbQ = T(0.25) * m_SetProb;
m_SetProbH = T(0.50) * m_SetProb;
m_SetProbTQ = T(0.75) * m_SetProb;
m_SetCompProb = T(1.0) - m_SetProb;
m_SetCompProbQ = m_SetProb + T(0.25) * m_SetCompProb;
m_SetCompProbH = m_SetProb + T(0.50) * m_SetCompProb;
m_SetCompProbTQ = m_SetProb + T(0.75) * m_SetCompProb;
if (m_Blur == 0)
{
m_TopBorder = m_Top;
m_BottomBorder = m_Bottom;
m_LeftBorder = m_Left;
m_RightBorder = m_Right;
}
else
{
m_TopBorder = m_Top + m_MinInt2 * m_RatioBlur;
m_BottomBorder = m_Bottom - m_MinInt2 * m_RatioBlur;
m_LeftBorder = m_Left + m_MinInt2 * m_RatioBlur;
m_RightBorder = m_Right - m_MinInt2 * m_RatioBlur;
}
}
virtual vector<string> OpenCLGlobalFuncNames() const override
{
return vector<string> { "Zeps" };
}
protected:
void Init()
{
string prefix = Prefix();
m_Params.clear();
m_Params.push_back(ParamWithName<T>(&m_Top, prefix + "crob_top", -1));
m_Params.push_back(ParamWithName<T>(&m_Bottom, prefix + "crob_bottom", 1));
m_Params.push_back(ParamWithName<T>(&m_Left, prefix + "crob_left", -1));
m_Params.push_back(ParamWithName<T>(&m_Right, prefix + "crob_right", 1));
m_Params.push_back(ParamWithName<T>(&m_Blur, prefix + "crob_blur", 1, eParamType::INTEGER));
m_Params.push_back(ParamWithName<T>(&m_RatioBlur, prefix + "crob_ratioBlur", T(0.5), eParamType::REAL, 0, 1));
m_Params.push_back(ParamWithName<T>(&m_DirectBlur, prefix + "crob_directBlur", 2));
m_Params.push_back(ParamWithName<T>(true, &m_XInterval, prefix + "crob_xinterval"));
m_Params.push_back(ParamWithName<T>(true, &m_YInterval, prefix + "crob_yinterval"));
m_Params.push_back(ParamWithName<T>(true, &m_XInt2, prefix + "crob_xint2"));
m_Params.push_back(ParamWithName<T>(true, &m_YInt2, prefix + "crob_yint2"));
m_Params.push_back(ParamWithName<T>(true, &m_MinInt2, prefix + "crob_minint2"));
m_Params.push_back(ParamWithName<T>(true, &m_X0, prefix + "crob_x0"));
m_Params.push_back(ParamWithName<T>(true, &m_Y0, prefix + "crob_y0"));
m_Params.push_back(ParamWithName<T>(true, &m_X0c, prefix + "crob_x0c"));
m_Params.push_back(ParamWithName<T>(true, &m_Y0c, prefix + "crob_y0c"));
m_Params.push_back(ParamWithName<T>(true, &m_SetProb, prefix + "crob_set_prob"));
m_Params.push_back(ParamWithName<T>(true, &m_SetProbH, prefix + "crob_set_prob_h"));
m_Params.push_back(ParamWithName<T>(true, &m_SetProbQ, prefix + "crob_set_prob_q"));
m_Params.push_back(ParamWithName<T>(true, &m_SetProbTQ, prefix + "crob_set_prob_tq"));
m_Params.push_back(ParamWithName<T>(true, &m_SetCompProb, prefix + "crob_set_comp_prob"));
m_Params.push_back(ParamWithName<T>(true, &m_SetCompProbH, prefix + "crob_set_comp_prob_h"));
m_Params.push_back(ParamWithName<T>(true, &m_SetCompProbQ, prefix + "crob_set_comp_prob_q"));
m_Params.push_back(ParamWithName<T>(true, &m_SetCompProbTQ, prefix + "crob_set_comp_prob_tq"));
m_Params.push_back(ParamWithName<T>(true, &m_TopBorder, prefix + "crob_top_border"));
m_Params.push_back(ParamWithName<T>(true, &m_BottomBorder, prefix + "crob_bottom_border"));
m_Params.push_back(ParamWithName<T>(true, &m_LeftBorder, prefix + "crob_left_border"));
m_Params.push_back(ParamWithName<T>(true, &m_RightBorder, prefix + "crob_right_border"));
}
private:
T m_Top;
T m_Bottom;
T m_Left;
T m_Right;
T m_Blur;
T m_RatioBlur;
T m_DirectBlur;
T m_XInterval;//Precalc.
T m_YInterval;
T m_XInt2;
T m_YInt2;
T m_MinInt2;
T m_X0;
T m_Y0;
T m_X0c;
T m_Y0c;
T m_SetProb;
T m_SetProbH;
T m_SetProbQ;
T m_SetProbTQ;
T m_SetCompProb;
T m_SetCompProbH;
T m_SetCompProbQ;
T m_SetCompProbTQ;
T m_TopBorder;
T m_BottomBorder;
T m_LeftBorder;
T m_RightBorder;
};
/// <summary>
/// bubbleT3D.
/// </summary>
template <typename T>
class BubbleT3DVariation : public ParametricVariation<T>
{
public:
BubbleT3DVariation(T weight = 1.0) : ParametricVariation<T>("bubbleT3D", eVariationId::VAR_BUBBLET3D, weight, true)
{
Init();
}
PARVARCOPY(BubbleT3DVariation)
virtual void Func(IteratorHelper<T>& helper, Point<T>& outPoint, QTIsaac<ISAAC_SIZE, ISAAC_INT>& rand) override
{
T x = helper.In.x, y = helper.In.y, z = helper.In.z;
T xTmp, yTmp, angTmp, angRot, fac;
T rad = Zeps<T>(helper.m_PrecalcSumSquares / 4 + 1);
T angXY, angZ;
T c, s;
angXY = std::atan2(x, y);
if (angXY < 0)
angXY += M_2PI;
if (m_AbsNumberStripes != 0)
{
while (angXY > m_AngStrip2)
{
angXY -= m_AngStrip2;
}
if (m_InvStripes == 0)
{
if (angXY > m_AngStrip1)
{
if (m_ModusBlur == 0)
{
x = 0;
y = 0;
}
else
{
if (m_RatioStripes == 1)
{
xTmp = m_C * x - m_S * y;
yTmp = m_S * x + m_C * y;
x = xTmp;
y = yTmp;
}
else
{
angRot = (angXY - m_AngStrip1) / Zeps<T>(m_AngStrip2 - m_AngStrip1);
angRot = angXY - angRot * m_AngStrip1;
sincos(angRot, &s, &c);
xTmp = c * x - s * y;
yTmp = s * x + c * y;
x = xTmp;
y = yTmp;
}
}
}
}
else
{
if (angXY < m_AngStrip1)
{
if (m_ModusBlur == 0)
{
x = 0;
y = 0;
}
else
{
if (m_AbsNumberStripes == 1)
{
xTmp = m_C * x - m_S * y;
yTmp = m_S * x + m_C * y;
x = xTmp;
y = yTmp;
}
else
{
angRot = (angXY - m_AngStrip1) / m_AngStrip1;
angRot = angXY - angRot * (m_AngStrip2 - m_AngStrip1);
sincos(angRot, &s, &c);
xTmp = c * x - s * y;
yTmp = s * x + c * y;
x = xTmp;
y = yTmp;
}
}
}
}
}
x = x / rad;
y = y / rad;
if ((x != 0) || (y != 0))
{
z = 2 / std::pow(rad, m_ExponentZ) - 1;
if (m_ExponentZ <= 2)
angZ = T(M_PI) - std::acos((z / (SQR(x) + SQR(y) + SQR(z))));
else
angZ = T(M_PI) - std::atan2(Sqr(SQR(x) + SQR(y)), z);
}
else
{
z = 0;
angZ = 0;
}
if (m_SymmetryZ == 0)
{
if (m_InvHole == 0)
{
if (angZ > m_AngleHoleTemp)
{
if ((m_ModusBlur == 0) || (m_ExponentZ != 1))
{
x = 0;
y = 0;
z = 0;
}
else
{
angTmp = (T(M_PI) - angZ) / Zeps<T>(m_AngHoleComp * m_AngleHoleTemp - T(M_PI_2));
angZ -= T(M_PI_2);
fac = std::cos(angTmp) / std::cos(angZ);
x *= fac;
y *= fac;
z *= (std::sin(angTmp) / std::sin(angZ));
}
}
}
else
{
if (angZ < m_AngleHoleTemp)
{
if ((m_ModusBlur == 0) || (m_ExponentZ != 1))
{
x = 0;
y = 0;
z = 0;
}
else
{
angTmp = T(M_PI) - angZ / Zeps<T>(m_AngHoleComp * m_AngleHoleTemp - T(M_PI_2));
angZ -= T(M_PI_2);
fac = std::cos(angTmp) / std::cos(angZ);
x *= fac;
y *= fac;
z *= (std::sin(angTmp) / std::sin(angZ));
}
}
}
}
else
{
if ((angZ > m_AngleHoleTemp) || (angZ < (T(M_PI) - m_AngleHoleTemp)))
{
if ((m_ModusBlur == 0) || (m_ExponentZ != 1))
{
x = 0;
y = 0;
z = 0;
}
else
{
if (angZ > m_AngleHoleTemp)
angTmp = (T(M_PI) - angZ) / m_AngHoleComp * (T(M_PI) - 2 * m_AngHoleComp) + m_AngHoleComp - T(M_PI_2);
else
angTmp = T(M_PI_2) - (angZ / m_AngHoleComp * (T(M_PI) - 2 * m_AngHoleComp) + m_AngHoleComp);
angZ -= T(M_PI_2);
fac = std::cos(angTmp) / std::cos(angZ);
x *= fac;
y *= fac;
z *= (std::sin(angTmp) / std::sin(angZ));
}
}
}
helper.Out.x = m_Weight * x;
helper.Out.y = m_Weight * y;
helper.Out.z = m_Weight * z;
}
virtual string OpenCLString() const override
{
ostringstream ss, ss2;
intmax_t i = 0, varIndex = IndexInXform();
ss2 << "_" << XformIndexInEmber();
string weight = WeightDefineString();
string index = ss2.str() + "]";
string numberStripes = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string ratioStripes = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string angleHole = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string exponentZ = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string symmetryZ = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string modusBlur = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string absNumberStripes = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string angHoleTemp = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string angStrip = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string angStrip1 = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string angStrip2 = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string invStripes = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string angHoleComp = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string invHole = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string c = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string s = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
ss << "\t{\n"
"\t\treal_t x = vIn.x, y = vIn.y, z = vIn.z;\n"
"\t\treal_t xTmp, yTmp, angTmp, angRot, fac;\n"
"\t\treal_t rad = Zeps(precalcSumSquares / 4 + 1);\n"
"\t\treal_t angXY, angZ;\n"
"\t\treal_t c, s;\n"
"\t\t\n"
"\t\tangXY = atan2(x, y);\n"
"\t\t\n"
"\t\tif (angXY < 0)\n"
"\t\t angXY += M_2PI;\n"
"\t\t\n"
"\t\tif (" << absNumberStripes << " != 0)\n"
"\t\t{\n"
"\t\t while (angXY > " << angStrip2 << ")\n"
"\t\t {\n"
"\t\t angXY -= " << angStrip2 << ";\n"
"\t\t }\n"
"\t\t\n"
"\t\t if (" << invStripes << " == 0)\n"
"\t\t {\n"
"\t\t if (angXY > " << angStrip1 << ")\n"
"\t\t {\n"
"\t\t if (" << modusBlur << " == 0)\n"
"\t\t {\n"
"\t\t x = 0;\n"
"\t\t y = 0;\n"
"\t\t }\n"
"\t\t else\n"
"\t\t {\n"
"\t\t if (" << ratioStripes << " == 1)\n"
"\t\t {\n"
"\t\t xTmp = fma(" << c << ", x, -(" << s << " * y));\n"
"\t\t yTmp = fma(" << s << ", x, " << c << " * y);\n"
"\t\t x = xTmp;\n"
"\t\t y = yTmp;\n"
"\t\t }\n"
"\t\t else\n"
"\t\t {\n"
"\t\t angRot = (angXY - " << angStrip1 << ") / Zeps(" << angStrip2 << " - " << angStrip1 << ");\n"
"\t\t angRot = angXY - angRot * " << angStrip1 << ";\n"
"\t\t s = sincos(angRot, &c);\n"
"\t\t xTmp = fma(c, x, -(s * y));\n"
"\t\t yTmp = fma(s, x, c * y);\n"
"\t\t x = xTmp;\n"
"\t\t y = yTmp;\n"
"\t\t }\n"
"\t\t }\n"
"\t\t }\n"
"\t\t }\n"
"\t\t else\n"
"\t\t {\n"
"\t\t if (angXY < " << angStrip1 << ")\n"
"\t\t {\n"
"\t\t if (" << modusBlur << " == 0)\n"
"\t\t {\n"
"\t\t x = 0;\n"
"\t\t y = 0;\n"
"\t\t }\n"
"\t\t else\n"
"\t\t {\n"
"\t\t if (" << absNumberStripes << " == 1)\n"
"\t\t {\n"
"\t\t xTmp = fma(" << c << ", x, -(" << s << " * y));\n"
"\t\t yTmp = fma(" << s << ", x, " << c << " * y);\n"
"\t\t x = xTmp;\n"
"\t\t y = yTmp;\n"
"\t\t }\n"
"\t\t else\n"
"\t\t {\n"
"\t\t angRot = (angXY - " << angStrip1 << ") / " << angStrip1 << ";\n"
"\t\t angRot = angXY - angRot * (" << angStrip2 << " - " << angStrip1 << ");\n"
"\t\t s = sincos(angRot, &c);\n"
"\t\t xTmp = fma(c, x, -(s * y));\n"
"\t\t yTmp = fma(s, x, c * y);\n"
"\t\t x = xTmp;\n"
"\t\t y = yTmp;\n"
"\t\t }\n"
"\t\t }\n"
"\t\t }\n"
"\t\t }\n"
"\t\t}\n"
"\t\t\n"
"\t\tx = x / rad;\n"
"\t\ty = y / rad;\n"
"\t\t\n"
"\t\tif ((x != 0) || (y != 0))\n"
"\t\t{\n"
"\t\t z = 2 / pow(rad, " << exponentZ << ") - 1;\n"
"\t\t\n"
"\t\t if (" << exponentZ << " <= 2)\n"
"\t\t angZ = MPI - acos((z / fma(x, x, fma(y, y, SQR(z)))));\n"
"\t\t else\n"
"\t\t angZ = MPI - atan2(Sqr(fma(x, x, SQR(y))), z);\n"
"\t\t}\n"
"\t\telse\n"
"\t\t{\n"
"\t\t z = 0;\n"
"\t\t angZ = 0;\n"
"\t\t}\n"
"\t\t\n"
"\t\tif (" << symmetryZ << " == 0)\n"
"\t\t{\n"
"\t\t if (" << invHole << " == 0)\n"
"\t\t {\n"
"\t\t if (angZ > " << angHoleTemp << ")\n"
"\t\t {\n"
"\t\t if ((" << modusBlur << " == 0) || (" << exponentZ << " != 1))\n"
"\t\t {\n"
"\t\t x = 0;\n"
"\t\t y = 0;\n"
"\t\t z = 0;\n"
"\t\t }\n"
"\t\t else\n"
"\t\t {\n"
"\t\t angTmp = (MPI - angZ) / Zeps(fma(" << angHoleComp << ", " << angHoleTemp << ", -MPI2));\n"
"\t\t angZ -= MPI2;\n"
"\t\t fac = cos(angTmp) / cos(angZ);\n"
"\t\t x *= fac;\n"
"\t\t y *= fac;\n"
"\t\t z *= (sin(angTmp) / sin(angZ));\n"
"\t\t }\n"
"\t\t }\n"
"\t\t }\n"
"\t\t else\n"
"\t\t {\n"
"\t\t if (angZ < " << angHoleTemp << ")\n"
"\t\t {\n"
"\t\t if ((" << modusBlur << " == 0) || (" << exponentZ << " != 1))\n"
"\t\t {\n"
"\t\t x = 0;\n"
"\t\t y = 0;\n"
"\t\t z = 0;\n"
"\t\t }\n"
"\t\t else\n"
"\t\t {\n"
"\t\t angTmp = MPI - angZ / Zeps(fma(" << angHoleComp << ", " << angHoleTemp << ", -MPI2));\n"
"\t\t angZ -= MPI2;\n"
"\t\t fac = cos(angTmp) / cos(angZ);\n"
"\t\t x *= fac;\n"
"\t\t y *= fac;\n"
"\t\t z *= (sin(angTmp) / sin(angZ));\n"
"\t\t }\n"
"\t\t }\n"
"\t\t }\n"
"\t\t}\n"
"\t\telse\n"
"\t\t{\n"
"\t\t if ((angZ > " << angHoleTemp << ") || (angZ < (MPI - " << angHoleTemp << ")))\n"
"\t\t {\n"
"\t\t if ((" << modusBlur << " == 0) || (" << exponentZ << " != 1))\n"
"\t\t {\n"
"\t\t x = 0;\n"
"\t\t y = 0;\n"
"\t\t z = 0;\n"
"\t\t }\n"
"\t\t else\n"
"\t\t {\n"
"\t\t if (angZ > " << angHoleTemp << ")\n"
"\t\t angTmp = (MPI - angZ) / " << angHoleComp << " * (MPI - 2 * " << angHoleComp << ") + " << angHoleComp << " - MPI2;\n"
"\t\t else\n"
"\t\t angTmp = MPI2 - (angZ / " << angHoleComp << " * (MPI - 2 * " << angHoleComp << ") + " << angHoleComp << ");\n"
"\n"
"\t\t angZ -= MPI2;\n"
"\t\t fac = cos(angTmp) / cos(angZ);\n"
"\t\t x *= fac;\n"
"\t\t y *= fac;\n"
"\t\t z *= (sin(angTmp) / sin(angZ));\n"
"\t\t }\n"
"\t\t }\n"
"\t\t}\n"
"\t\t\n"
"\t\tvOut.x = " << weight << " * x;\n"
"\t\tvOut.y = " << weight << " * y;\n"
"\t\tvOut.z = " << weight << " * z;\n"
"\t}\n";
return ss.str();
}
virtual vector<string> OpenCLGlobalFuncNames() const override
{
return vector<string> { "Sqr", "Zeps" };
}
virtual void Precalc() override
{
if (m_NumberStripes < 0)
{
m_AbsNumberStripes = std::abs(m_NumberStripes);
m_InvStripes = 1;
}
else
{
m_AbsNumberStripes = m_NumberStripes;
m_InvStripes = 0;
}
if (m_AbsNumberStripes != 0)
{
m_AngStrip = T(M_PI) / m_AbsNumberStripes;
m_AngStrip2 = 2 * m_AngStrip;
sincos(m_AngStrip, &m_S, &m_C);
ClampRef<T>(m_RatioStripes, T(0.01), T(1.99));
m_AngStrip1 = Zeps<T>(m_RatioStripes * m_AngStrip);
}
if (m_SymmetryZ == 1)
{
if (m_AngleHole < 0)
m_AngleHoleTemp = std::abs(m_AngleHole);
else if (m_AngleHole > T(179.9))
m_AngleHoleTemp = T(179.9);
else
m_AngleHoleTemp = m_AngleHole;
}
else
m_AngleHoleTemp = m_AngleHole;
if (m_AngleHoleTemp < 0)
{
m_AngleHoleTemp = std::abs(m_AngleHole);
m_InvHole = 1;
m_AngleHoleTemp = (m_AngleHoleTemp / 360 * M_2PI) / 2;
}
else
{
m_InvHole = 0;
m_AngleHoleTemp = T(M_PI) - (m_AngleHoleTemp / 360 * M_2PI) / 2;
}
m_AngHoleComp = T(M_PI) - m_AngleHoleTemp;
}
protected:
void Init()
{
string prefix = Prefix();
m_Params.clear();
m_Params.reserve(14);
m_Params.push_back(ParamWithName<T>(&m_NumberStripes, prefix + "bubbleT3D_number_of_stripes", 0, eParamType::INTEGER));
m_Params.push_back(ParamWithName<T>(&m_RatioStripes, prefix + "bubbleT3D_ratio_of_stripes", 1, eParamType::REAL, 0, 2));
m_Params.push_back(ParamWithName<T>(&m_AngleHole, prefix + "bubbleT3D_angle_of_hole", 0, eParamType::REAL, -360, 360));
m_Params.push_back(ParamWithName<T>(&m_ExponentZ, prefix + "bubbleT3D_exponentZ", 1));
m_Params.push_back(ParamWithName<T>(&m_SymmetryZ, prefix + "bubbleT3D_symmetryZ", 0, eParamType::INTEGER, 0, 1));
m_Params.push_back(ParamWithName<T>(&m_ModusBlur, prefix + "bubbleT3D_modusBlur", 0, eParamType::INTEGER, 0, 1));
m_Params.push_back(ParamWithName<T>(true, &m_AbsNumberStripes, prefix + "bubbleT3D_abs_number_of_stripes"));//Precalc.
m_Params.push_back(ParamWithName<T>(true, &m_AngleHoleTemp, prefix + "bubbleT3D_ang_hole_temp"));
m_Params.push_back(ParamWithName<T>(true, &m_AngStrip, prefix + "bubbleT3D_ang_strip"));
m_Params.push_back(ParamWithName<T>(true, &m_AngStrip1, prefix + "bubbleT3D_ang_strip1"));
m_Params.push_back(ParamWithName<T>(true, &m_AngStrip2, prefix + "bubbleT3D_ang_strip2"));
m_Params.push_back(ParamWithName<T>(true, &m_InvStripes, prefix + "bubbleT3D_inv_stripes"));
m_Params.push_back(ParamWithName<T>(true, &m_AngHoleComp, prefix + "bubbleT3D_ang_hole_comp"));
m_Params.push_back(ParamWithName<T>(true, &m_InvHole, prefix + "bubbleT3D_inv_hole"));
m_Params.push_back(ParamWithName<T>(true, &m_C, prefix + "bubbleT3D_c"));
m_Params.push_back(ParamWithName<T>(true, &m_S, prefix + "bubbleT3D_s"));
}
private:
T m_NumberStripes;
T m_RatioStripes;
T m_AngleHole;
T m_ExponentZ;
T m_SymmetryZ;
T m_ModusBlur;
T m_AbsNumberStripes;//Precalc.
T m_AngleHoleTemp;
T m_AngStrip;
T m_AngStrip1;
T m_AngStrip2;
T m_InvStripes;
T m_AngHoleComp;
T m_InvHole;
T m_C;
T m_S;
};
// -------------------------------------------------------------
// Modes
// "Lagacy" modes from v1
#define MODE_SPHERICAL 0
#define MODE_BUBBLE 1
#define MODE_BLUR_LEGACY 2
// New modes in v2
#define MODE_BLUR_NEW 3
#define MODE_BLUR_ZIGZAG 4
#define MODE_RAWCIRCLE 5
#define MODE_RAWX 6
#define MODE_RAWY 7
#define MODE_RAWXY 8
#define MODE_SHIFTX 9
#define MODE_SHIFTY 10
#define MODE_SHIFTXY 11
#define MODE_SINUSOIDAL 12
#define MODE_SWIRL 13
#define MODE_HYPERBOLIC 14
#define MODE_JULIA 15
#define MODE_DISC 16
#define MODE_RINGS 17
#define MODE_CYLINDER 18
#define MODE_BLUR_RING 19
#define MODE_BLUR_RING2 20
#define MODE_SHIFTTHETA 21
#define MODE_SHIFTNSTRETCH 22
#define MODE_SHIFTTANGENT 23
#define MODE_XMIRROR 24
#define MODE_XYMIRROR 25
#define MODE_SPHERICAL2 26
// -------------------------------------------------------------
// Wave types
#define WAVE_SIN 0
#define WAVE_COS 1
#define WAVE_SQUARE 2
#define WAVE_SAW 3
#define WAVE_TRIANGLE 4
#define WAVE_CONCAVE 5
#define WAVE_CONVEX 6
#define WAVE_NGON 7
// New wave types in v2
#define WAVE_INGON 8
// -------------------------------------------------------------
// Layer types
#define LAYER_ADD 0
#define LAYER_MULT 1
#define LAYER_MAX 2
#define LAYER_MIN 3
// -------------------------------------------------------------
// Interpolation types
#define LERP_LINEAR 0
#define LERP_BEZIER 1
// -------------------------------------------------------------
// Sine/Cosine interpretation types
#define SINCOS_MULTIPLY 0
#define SINCOS_MIXIN 1
/// <summary>
/// synth.
/// </summary>
template <typename T>
class SynthVariation : public ParametricVariation<T>
{
public:
SynthVariation(T weight = 1.0) : ParametricVariation<T>("synth", eVariationId::VAR_SYNTH, weight, true, true, false, true)
{
Init();
}
PARVARCOPY(SynthVariation)
virtual void Func(IteratorHelper<T>& helper, Point<T>& outPoint, QTIsaac<ISAAC_SIZE, ISAAC_INT>& rand) override
{
T Vx, Vy, radius, theta; // Position vector in cartesian and polar co-ords
T thetaFactor; // Evaluation of synth() function for current point
T s, c, mu; // Handy temp variables, s & c => sine & cosine, mu = generic temp param
int synthMode = int(m_SynthMode);
int synthSmooth = int(m_SynthSmooth);
SynthStruct synth;
synth.SynthA = m_SynthA;
synth.SynthB = m_SynthB;
synth.SynthBPhs = m_SynthBPhs;
synth.SynthBFrq = m_SynthBFrq;
synth.SynthBSkew = m_SynthBSkew;
synth.SynthBType = int(m_SynthBType);
synth.SynthBLayer = int(m_SynthBLayer);
synth.SynthC = m_SynthC;
synth.SynthCPhs = m_SynthCPhs;
synth.SynthCFrq = m_SynthCFrq;
synth.SynthCSkew = m_SynthCSkew;
synth.SynthCType = int(m_SynthCType);
synth.SynthCLayer = int(m_SynthCLayer);
synth.SynthD = m_SynthD;
synth.SynthDPhs = m_SynthDPhs;
synth.SynthDFrq = m_SynthDFrq;
synth.SynthDSkew = m_SynthDSkew;
synth.SynthDType = int(m_SynthDType);
synth.SynthDLayer = int(m_SynthDLayer);
synth.SynthE = m_SynthE;
synth.SynthEPhs = m_SynthEPhs;
synth.SynthEFrq = m_SynthEFrq;
synth.SynthESkew = m_SynthESkew;
synth.SynthEType = int(m_SynthEType);
synth.SynthELayer = int(m_SynthELayer);
synth.SynthF = m_SynthF;
synth.SynthFPhs = m_SynthFPhs;
synth.SynthFFrq = m_SynthFFrq;
synth.SynthFSkew = m_SynthFSkew;
synth.SynthFType = int(m_SynthFType);
synth.SynthFLayer = int(m_SynthFLayer);
synth.SynthMix = m_SynthMix;
switch (synthMode)
{
case MODE_SPHERICAL: // Power YES, Smooth YES
// Re-write of spherical with synth tweak
Vx = helper.In.x;
Vy = helper.In.y;
radius = std::pow(Zeps<T>(helper.m_PrecalcSumSquares), (m_SynthPower + 1) / 2);
// Get angle and angular factor
theta = helper.m_PrecalcAtanxy;
thetaFactor = SynthValue(synth, theta);
radius = Interpolate(radius, thetaFactor, synthSmooth);
sincos(theta, &s, &c);
// Write to running totals for transform
helper.Out.x = m_Weight * radius * s;
helper.Out.y = m_Weight * radius * c;
break;
case MODE_BUBBLE: // Power NO, Smooth YES
// Re-write of bubble with synth tweak
Vx = helper.In.x;
Vy = helper.In.y;
radius = helper.m_PrecalcSqrtSumSquares / (helper.m_PrecalcSumSquares / 4 + 1);
// Get angle and angular factor
theta = helper.m_PrecalcAtanxy;
thetaFactor = SynthValue(synth, theta);
radius = Interpolate(radius, thetaFactor, synthSmooth);
sincos(theta, &s, &c);
// Write to running totals for transform
helper.Out.x = m_Weight * radius * s;
helper.Out.y = m_Weight * radius * c;
break;
case MODE_BLUR_LEGACY: // Power YES, Smooth YES
// "old" blur style, has some problems with moire-style artefacts
radius = (rand.Frand01<T>() + rand.Frand01<T>() + T(0.002) * rand.Frand01<T>()) / T(2.002);
theta = M_2PI * rand.Frand01<T>() - T(M_PI);
Vx = radius * std::sin(theta);
Vy = radius * std::cos(theta);
radius = std::pow(Zeps<T>(radius * radius), m_SynthPower / 2);
// Get angle and angular factor
thetaFactor = SynthValue(synth, theta);
radius = m_Weight * Interpolate(radius, thetaFactor, synthSmooth);
// Write back to running totals for new vector
helper.Out.x = Vx * radius;
helper.Out.y = Vy * radius;
break;
case MODE_BLUR_NEW: // Power YES, Smooth YES
// Blur style, with normal smoothing function
// Choose radius randomly, then adjust distribution using pow
radius = T(0.5) * (rand.Frand01<T>() + rand.Frand01<T>());
theta = M_2PI * rand.Frand01<T>() - T(M_PI);
radius = std::pow(Zeps<T>(SQR(radius)), -m_SynthPower / 2);
// Get angular factor defining the shape
thetaFactor = SynthValue(synth, theta);
// Get final radius after synth applied
radius = Interpolate(radius, thetaFactor, synthSmooth);
sincos(theta, &s, &c);
// Write to running totals for transform
helper.Out.x = m_Weight * radius * s;
helper.Out.y = m_Weight * radius * c;
break;
case MODE_BLUR_ZIGZAG: // Power YES, Smooth YES
// Blur effect based on line segment
// theta is used as x value
// Vy is y value
Vy = 1 + T(0.1) * (rand.Frand01<T>() + rand.Frand01<T>() - 1) * m_SynthPower;
theta = 2 * std::asin((rand.Frand01<T>() - T(0.5)) * 2);
// Get angular factor defining the shape
thetaFactor = SynthValue(synth, theta);
// Get new location
Vy = Interpolate(Vy, thetaFactor, synthSmooth);
// Write to running totals for transform
helper.Out.x = m_Weight * (theta / T(M_PI));
helper.Out.y = m_Weight * (Vy - 1);
break;
case MODE_RAWCIRCLE: // Power NO, Smooth YES
// Get current radius and angle
radius = helper.m_PrecalcSqrtSumSquares;
theta = helper.m_PrecalcAtanxy;
// Calculate new radius
thetaFactor = SynthValue(synth, theta);
radius = Interpolate(radius, thetaFactor, synthSmooth);
sincos(theta, &s, &c);
// Write to running totals for transform
helper.Out.x = m_Weight * radius * s;
helper.Out.y = m_Weight * radius * c;
break;
case MODE_RAWX: // Power NO, Smooth YES
// Use x and y values directly
Vx = helper.In.x;
Vy = helper.In.y;
// x value will be mapped according to synth(y) value
thetaFactor = SynthValue(synth, Vy);
// Write to running totals for transform
helper.Out.x = m_Weight * Interpolate(Vx, thetaFactor, synthSmooth);
helper.Out.y = m_Weight * Vy;
break;
case MODE_RAWY: // Power NO, Smooth YES
// Use x and y values directly
Vx = helper.In.x;
Vy = helper.In.y;
// y value will be mapped according to synth(x) value
thetaFactor = SynthValue(synth, Vx);
// Write to running totals for transform
helper.Out.x = m_Weight * Vx;
helper.Out.y = m_Weight * Interpolate(Vy, thetaFactor, synthSmooth);
break;
case MODE_RAWXY: // Power NO, Smooth YES
// Use x and y values directly
Vx = helper.In.x;
Vy = helper.In.y;
// x value will be mapped according to synth(y) value
thetaFactor = SynthValue(synth, Vy);
helper.Out.x = m_Weight * Interpolate(Vx, thetaFactor, synthSmooth);
// y value will be mapped according to synth(x) value
thetaFactor = SynthValue(synth, Vx);
helper.Out.y = m_Weight * Interpolate(Vy, thetaFactor, synthSmooth);
break;
case MODE_SHIFTX: // Power NO, Smooth YES
// Use x and y values directly
Vx = helper.In.x;
Vy = helper.In.y;
// Write to running totals for transform
helper.Out.x = m_Weight * (Vx + SynthValue(synth, Vy) - 1);
helper.Out.y = m_Weight * Vy;
break;
case MODE_SHIFTY: // Power NO, Smooth NO
// Use x and y values directly
Vx = helper.In.x;
Vy = helper.In.y;
// Write to running totals for transform
helper.Out.x = m_Weight * Vx;
helper.Out.y = m_Weight * (Vy + SynthValue(synth, Vx) - 1);
break;
case MODE_SHIFTXY: // Power NO, Smooth NO
// Use x and y values directly
Vx = helper.In.x;
Vy = helper.In.y;
// Write to running totals for transform
helper.Out.x = m_Weight * (Vx + SynthValue(synth, Vy) - 1);
helper.Out.y = m_Weight * (Vy + SynthValue(synth, Vx) - 1);
break;
case MODE_SINUSOIDAL: // Power NO, Smooth NO
Vx = helper.In.x;
Vy = helper.In.y;
// The default mix=0 is same as normal sin
helper.Out.x = m_Weight * (SynthValue(synth, Vx) - 1 + (1 - m_SynthMix) * std::sin(Vx));
helper.Out.y = m_Weight * (SynthValue(synth, Vy) - 1 + (1 - m_SynthMix) * std::sin(Vy));
break;
case MODE_SWIRL: // Power YES, Smooth WAVE
Vx = helper.In.x;
Vy = helper.In.y;
radius = std::pow(Zeps<T>(helper.m_PrecalcSumSquares), m_SynthPower / 2);
// Synth-modified sine & cosine
SynthSinCos(synth, radius, s, c, synthSmooth);
helper.Out.x = m_Weight * (s * Vx - c * Vy);
helper.Out.y = m_Weight * (c * Vx + s * Vy);
break;
case MODE_HYPERBOLIC: // Power YES, Smooth WAVE
Vx = helper.In.x;
Vy = helper.In.y;
radius = std::pow(Zeps<T>(helper.m_PrecalcSumSquares), m_SynthPower / 2);
theta = helper.m_PrecalcAtanxy;
// Synth-modified sine & cosine
SynthSinCos(synth, theta, s, c, synthSmooth);
helper.Out.x = m_Weight * s / radius;
helper.Out.y = m_Weight * c * radius;
break;
case MODE_JULIA: // Power YES, Smooth WAVE
Vx = helper.In.x;
Vy = helper.In.y;
radius = std::pow(Zeps<T>(helper.m_PrecalcSumSquares), m_SynthPower / 4);
theta = helper.m_PrecalcAtanxy / 2;
if (rand.Frand01<T>() < T(0.5))
theta += T(M_PI);
// Synth-modified sine & cosine
SynthSinCos(synth, theta, s, c, synthSmooth);
helper.Out.x = m_Weight * radius * c;
helper.Out.y = m_Weight * radius * s;
break;
case MODE_DISC: // Power YES, Smooth WAVE
Vx = helper.In.x;
Vy = helper.In.y;
theta = helper.m_PrecalcAtanxy / T(M_PI);
radius = T(M_PI) * std::pow(Zeps<T>(helper.m_PrecalcSumSquares), m_SynthPower / 2);
// Synth-modified sine & cosine
SynthSinCos(synth, radius, s, c, synthSmooth);
helper.Out.x = m_Weight * s * theta;
helper.Out.y = m_Weight * c * theta;
break;
case MODE_RINGS: // Power PARAM, Smooth WAVE
Vx = helper.In.x;
Vy = helper.In.y;
radius = helper.m_PrecalcSqrtSumSquares;
theta = helper.m_PrecalcAtanxy;
mu = Zeps<T>(SQR(m_SynthPower));
radius += -2 * mu * int((radius + mu) / (2 * mu)) + radius * (1 - mu);
SynthSinCos(synth, radius, s, c, synthSmooth);
helper.Out.x = m_Weight * s * theta;
helper.Out.y = m_Weight * c * theta;
break;
case MODE_CYLINDER: // Power YES, Smooth WAVE
Vx = helper.In.x;
Vy = helper.In.y;
radius = std::pow(Zeps<T>(helper.m_PrecalcSumSquares), m_SynthPower / 2);
// Modified sine only used here
SynthSinCos(synth, Vx, s, c, synthSmooth);
helper.Out.x = m_Weight * radius * s;
helper.Out.y = m_Weight * radius * Vy;
break;
case MODE_BLUR_RING: // Power YES, Smooth YES
// Blur style, with normal smoothing function
radius = 1 + T(0.1) * (rand.Frand01<T>() + rand.Frand01<T>() - 1) * m_SynthPower;
theta = M_2PI * rand.Frand01<T>() - T(M_PI);
// Get angular factor defining the shape
thetaFactor = SynthValue(synth, theta);
// Get final radius after synth applied
radius = Interpolate(radius, thetaFactor, synthSmooth);
sincos(theta, &s, &c);
// Write to running totals for transform
helper.Out.x = m_Weight * radius * s;
helper.Out.y = m_Weight * radius * c;
break;
case MODE_BLUR_RING2: // Power YES, Smooth NO
// Simple, same-thickness ring
// Choose radius randomly, then adjust distribution using pow
theta = M_2PI * rand.Frand01<T>() - T(M_PI);
radius = std::pow(Zeps<T>(rand.Frand01<T>()), m_SynthPower);
// Get final radius after synth applied
radius = SynthValue(synth, theta) + T(0.1) * radius;
sincos(theta, &s, &c);
// Write to running totals for transform
helper.Out.x = m_Weight * radius * s;
helper.Out.y = m_Weight * radius * c;
break;
case MODE_SHIFTTHETA: // Power YES, Smooth NO
// Use (adjusted) radius to move point around circle
Vx = helper.In.x;
Vy = helper.In.y;
radius = std::pow(Zeps<T>(helper.m_PrecalcSumSquares), m_SynthPower / 2);
theta = helper.m_PrecalcAtanxy - 1 + SynthValue(synth, radius);
sincos(theta, &s, &c);
// Write to running totals for transform
helper.Out.x = m_Weight * radius * s;
helper.Out.y = m_Weight * radius * c;
break;
case MODE_SHIFTNSTRETCH:
// Use (adjusted) radius to move point around circle
Vx = helper.In.x;
Vy = helper.In.y;
radius = std::pow(Zeps<T>(helper.m_PrecalcSumSquares), m_SynthPower / 2);
theta = helper.m_PrecalcAtanxy - 1 + SynthValue(synth, radius);
sincos(theta, &s, &c);
// Write to running totals for transform
helper.Out.x = m_Weight * radius * s;
helper.Out.y = m_Weight * radius * c;
break;
case MODE_SHIFTTANGENT:
// Use (adjusted) radius to move point tangentially to circle
Vx = helper.In.x;
Vy = helper.In.y;
radius = std::pow(Zeps<T>(helper.m_PrecalcSumSquares), m_SynthPower / 2);
sincos(helper.m_PrecalcAtanxy, &s, &c);
// Adjust Vx and Vy directly
mu = SynthValue(synth, radius) - 1;
Vx += mu * c;
Vy -= mu * s;
// Write to running totals for transform
helper.Out.x = m_Weight * Vx;
helper.Out.y = m_Weight * Vy;
break;
case MODE_XMIRROR:
Vx = helper.In.x;
Vy = helper.In.y;
// Modified sine only used here
mu = SynthValue(synth, Vx) - 1;
Vy = 2 * mu - Vy;
helper.Out.x = m_Weight * Vx;
helper.Out.y = m_Weight * Vy;
break;
case MODE_XYMIRROR:
Vx = helper.In.x;
Vy = helper.In.y;
// radius sneakily being used to represent something completely different, sorry!
mu = SynthValue(synth, Vx) - 1;
radius = SynthValue(synth, Vy) - 1;
Vy = 2 * mu - Vy;
Vx = 2 * radius - Vx;
helper.Out.x = m_Weight * Vx;
helper.Out.y = m_Weight * Vy;
break;
case MODE_SPHERICAL2:
default:
Vx = helper.In.x;
Vy = helper.In.y;
radius = helper.m_PrecalcSqrtSumSquares;
// Get angle and angular factor
theta = helper.m_PrecalcAtanxy;
thetaFactor = SynthValue(synth, theta);
radius = Interpolate(radius, thetaFactor, synthSmooth);
radius = std::pow(radius, m_SynthPower);
sincos(theta, &s, &c);
// Write to running totals for transform
helper.Out.x = m_Weight * radius * s;
helper.Out.y = m_Weight * radius * c;
break;
}
helper.Out.z = DefaultZ(helper);
}
virtual string OpenCLString() const override
{
ostringstream ss, ss2;
intmax_t i = 0, varIndex = IndexInXform();
ss2 << "_" << XformIndexInEmber();
string weight = WeightDefineString();
string index = ss2.str() + "]";
string synthA = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string synthMode = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string synthPower = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string synthMix = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string synthSmooth = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string synthB = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string synthBType = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string synthBSkew = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string synthBFrq = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string synthBPhs = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string synthBLayer = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string synthC = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string synthCType = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string synthCSkew = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string synthCFrq = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string synthCPhs = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string synthCLayer = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string synthD = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string synthDType = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string synthDSkew = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string synthDFrq = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string synthDPhs = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string synthDLayer = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string synthE = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string synthEType = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string synthESkew = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string synthEFrq = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string synthEPhs = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string synthELayer = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string synthF = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string synthFType = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string synthFSkew = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string synthFFrq = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string synthFPhs = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string synthFLayer = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
ss << "\t{\n"
<< "\t\treal_t Vx, Vy, radius, theta;\n"
<< "\t\treal_t thetaFactor;\n"
<< "\t\treal_t s, c, mu;\n"
<< "\t\tint synthMode = (int)" << synthMode << ";\n"
<< "\t\tint synthSmooth = (int)" << synthSmooth << ";\n"
<< "\t\tSynthStruct synth;\n"
<< "\n"
<< "\t\tsynth.SynthA = " << synthA << ";\n"
<< "\t\tsynth.SynthB = " << synthB << ";\n"
<< "\t\tsynth.SynthBPhs = " << synthBPhs << ";\n"
<< "\t\tsynth.SynthBFrq = " << synthBFrq << ";\n"
<< "\t\tsynth.SynthBSkew = " << synthBSkew << ";\n"
<< "\t\tsynth.SynthBType = (int)" << synthBType << ";\n"
<< "\t\tsynth.SynthBLayer = (int)" << synthBLayer << ";\n"
<< "\t\tsynth.SynthC = " << synthC << ";\n"
<< "\t\tsynth.SynthCPhs = " << synthCPhs << ";\n"
<< "\t\tsynth.SynthCFrq = " << synthCFrq << ";\n"
<< "\t\tsynth.SynthCSkew = " << synthCSkew << ";\n"
<< "\t\tsynth.SynthCType = (int)" << synthCType << ";\n"
<< "\t\tsynth.SynthCLayer = (int)" << synthCLayer << ";\n"
<< "\t\tsynth.SynthD = " << synthD << ";\n"
<< "\t\tsynth.SynthDPhs = " << synthDPhs << ";\n"
<< "\t\tsynth.SynthDFrq = " << synthDFrq << ";\n"
<< "\t\tsynth.SynthDSkew = " << synthDSkew << ";\n"
<< "\t\tsynth.SynthDType = (int)" << synthDType << ";\n"
<< "\t\tsynth.SynthDLayer = (int)" << synthDLayer << ";\n"
<< "\t\tsynth.SynthE = " << synthE << ";\n"
<< "\t\tsynth.SynthEPhs = " << synthEPhs << ";\n"
<< "\t\tsynth.SynthEFrq = " << synthEFrq << ";\n"
<< "\t\tsynth.SynthESkew = " << synthESkew << ";\n"
<< "\t\tsynth.SynthEType = (int)" << synthEType << ";\n"
<< "\t\tsynth.SynthELayer = (int)" << synthELayer << ";\n"
<< "\t\tsynth.SynthF = " << synthF << ";\n"
<< "\t\tsynth.SynthFPhs = " << synthFPhs << ";\n"
<< "\t\tsynth.SynthFFrq = " << synthFFrq << ";\n"
<< "\t\tsynth.SynthFSkew = " << synthFSkew << ";\n"
<< "\t\tsynth.SynthFType = (int)" << synthFType << ";\n"
<< "\t\tsynth.SynthFLayer = (int)" << synthFLayer << ";\n"
<< "\t\tsynth.SynthMix = " << synthMix << ";\n"
<< "\n"
<< "\t\tswitch (synthMode)\n"
<< "\t\t{\n"
<< "\t\tcase MODE_SPHERICAL:\n"
<< "\t\t Vx = vIn.x;\n"
<< "\t\t Vy = vIn.y;\n"
<< "\t\t radius = pow(Zeps(precalcSumSquares), (" << synthPower << " + 1) / 2);\n"
<< "\t\t theta = precalcAtanxy;\n"
<< "\t\t thetaFactor = SynthValue(&synth, theta);\n"
<< "\t\t radius = Interpolate(radius, thetaFactor, synthSmooth);\n"
<< "\t\t s = sincos(theta, &c);\n"
<< "\t\t vOut.x = " << weight << " * radius * s;\n"
<< "\t\t vOut.y = " << weight << " * radius * c;\n"
<< "\t\t break;\n"
<< "\n"
<< "\t\tcase MODE_BUBBLE:\n"
<< "\t\t Vx = vIn.x;\n"
<< "\t\t Vy = vIn.y;\n"
<< "\t\t radius = precalcSqrtSumSquares / (precalcSumSquares / 4 + 1);\n"
<< "\t\t theta = precalcAtanxy;\n"
<< "\t\t thetaFactor = SynthValue(&synth, theta);\n"
<< "\t\t radius = Interpolate(radius, thetaFactor, synthSmooth);\n"
<< "\t\t s = sincos(theta, &c);\n"
<< "\t\t vOut.x = " << weight << " * radius * s;\n"
<< "\t\t vOut.y = " << weight << " * radius * c;\n"
<< "\t\t break;\n"
<< "\n"
<< "\t\tcase MODE_BLUR_LEGACY:\n"
<< "\t\t radius = fma((real_t)(0.002), MwcNext01(mwc), MwcNext01(mwc) + MwcNext01(mwc)) / 2.002;\n"
<< "\t\t theta = fma(M_2PI, MwcNext01(mwc), -MPI);\n"
<< "\t\t Vx = radius * sin(theta);\n"
<< "\t\t Vy = radius * cos(theta);\n"
<< "\t\t radius = pow(Zeps(radius * radius), " << synthPower << " / 2);\n"
<< "\t\t thetaFactor = SynthValue(&synth, theta);\n"
<< "\t\t radius = " << weight << " * Interpolate(radius, thetaFactor, synthSmooth);\n"
<< "\t\t vOut.x = Vx * radius;\n"
<< "\t\t vOut.y = Vy * radius;\n"
<< "\t\t break;\n"
<< "\n"
<< "\t\tcase MODE_BLUR_NEW:\n"
<< "\t\t radius = 0.5 * (MwcNext01(mwc) + MwcNext01(mwc));\n"
<< "\t\t theta = fma(M_2PI, MwcNext01(mwc), -MPI);\n"
<< "\t\t radius = pow(Zeps(SQR(radius)), -" << synthPower << " / 2);\n"
<< "\t\t thetaFactor = SynthValue(&synth, theta);\n"
<< "\t\t radius = Interpolate(radius, thetaFactor, synthSmooth);\n"
<< "\t\t s = sincos(theta, &c);\n"
<< "\t\t vOut.x = " << weight << " * radius * s;\n"
<< "\t\t vOut.y = " << weight << " * radius * c;\n"
<< "\t\t break;\n"
<< "\n"
<< "\t\tcase MODE_BLUR_ZIGZAG:\n"
<< "\t\t Vy = fma((real_t)(0.1), (MwcNext01(mwc) + MwcNext01(mwc) - 1) * " << synthPower << ", (real_t)(1.0));\n"
<< "\t\t theta = 2 * asin((MwcNext01(mwc) - 0.5) * 2);\n"
<< "\t\t thetaFactor = SynthValue(&synth, theta);\n"
<< "\t\t Vy = Interpolate(Vy, thetaFactor, synthSmooth);\n"
<< "\t\t vOut.x = " << weight << " * (theta / MPI);\n"
<< "\t\t vOut.y = " << weight << " * (Vy - 1);\n"
<< "\t\t break;\n"
<< "\n"
<< "\t\tcase MODE_RAWCIRCLE:\n"
<< "\t\t radius = precalcSqrtSumSquares;\n"
<< "\t\t theta = precalcAtanxy;\n"
<< "\t\t thetaFactor = SynthValue(&synth, theta);\n"
<< "\t\t radius = Interpolate(radius, thetaFactor, synthSmooth);\n"
<< "\t\t s = sincos(theta, &c);\n"
<< "\t\t vOut.x = " << weight << " * radius * s;\n"
<< "\t\t vOut.y = " << weight << " * radius * c;\n"
<< "\t\t break;\n"
<< "\n"
<< "\t\tcase MODE_RAWX:\n"
<< "\t\t Vx = vIn.x;\n"
<< "\t\t Vy = vIn.y;\n"
<< "\t\t thetaFactor = SynthValue(&synth, Vy);\n"
<< "\t\t vOut.x = " << weight << " * Interpolate(Vx, thetaFactor, synthSmooth);\n"
<< "\t\t vOut.y = " << weight << " * Vy;\n"
<< "\t\t break;\n"
<< "\n"
<< "\t\tcase MODE_RAWY:\n"
<< "\t\t Vx = vIn.x;\n"
<< "\t\t Vy = vIn.y;\n"
<< "\t\t thetaFactor = SynthValue(&synth, Vx);\n"
<< "\t\t vOut.x = " << weight << " * Vx;\n"
<< "\t\t vOut.y = " << weight << " * Interpolate(Vy, thetaFactor, synthSmooth);\n"
<< "\t\t break;\n"
<< "\n"
<< "\t\tcase MODE_RAWXY:\n"
<< "\t\t Vx = vIn.x;\n"
<< "\t\t Vy = vIn.y;\n"
<< "\t\t thetaFactor = SynthValue(&synth, Vy);\n"
<< "\t\t vOut.x = " << weight << " * Interpolate(Vx, thetaFactor, synthSmooth);\n"
<< "\t\t thetaFactor = SynthValue(&synth, Vx);\n"
<< "\t\t vOut.y = " << weight << " * Interpolate(Vy, thetaFactor, synthSmooth);\n"
<< "\t\t break;\n"
<< "\n"
<< "\t\tcase MODE_SHIFTX:\n"
<< "\t\t Vx = vIn.x;\n"
<< "\t\t Vy = vIn.y;\n"
<< "\t\t vOut.x = " << weight << " * (Vx + SynthValue(&synth, Vy) - 1);\n"
<< "\t\t vOut.y = " << weight << " * Vy;\n"
<< "\t\t break;\n"
<< "\n"
<< "\t\tcase MODE_SHIFTY:\n"
<< "\t\t Vx = vIn.x;\n"
<< "\t\t Vy = vIn.y;\n"
<< "\t\t vOut.x = " << weight << " * Vx;\n"
<< "\t\t vOut.y = " << weight << " * (Vy + SynthValue(&synth, Vx) - 1);\n"
<< "\t\t break;\n"
<< "\n"
<< "\t\tcase MODE_SHIFTXY:\n"
<< "\t\t Vx = vIn.x;\n"
<< "\t\t Vy = vIn.y;\n"
<< "\t\t vOut.x = " << weight << " * (Vx + SynthValue(&synth, Vy) - 1);\n"
<< "\t\t vOut.y = " << weight << " * (Vy + SynthValue(&synth, Vx) - 1);\n"
<< "\t\t break;\n"
<< "\n"
<< "\t\tcase MODE_SINUSOIDAL:\n"
<< "\t\t Vx = vIn.x;\n"
<< "\t\t Vy = vIn.y;\n"
<< "\t\t vOut.x = " << weight << " * fma((real_t)(1.0) - " << synthMix << ", sin(Vx), SynthValue(&synth, Vx) - (real_t)(1.0));\n"
<< "\t\t vOut.y = " << weight << " * fma((real_t)(1.0) - " << synthMix << ", sin(Vy), SynthValue(&synth, Vy) - (real_t)(1.0));\n"
<< "\t\t break;\n"
<< "\n"
<< "\t\tcase MODE_SWIRL:\n"
<< "\t\t Vx = vIn.x;\n"
<< "\t\t Vy = vIn.y;\n"
<< "\t\t radius = pow(Zeps(precalcSumSquares), " << synthPower << " / 2);\n"
<< "\t\t SynthSinCos(&synth, radius, &s, &c, synthSmooth);\n"
<< "\t\t vOut.x = " << weight << " * fma(s, Vx, -(c * Vy));\n"
<< "\t\t vOut.y = " << weight << " * fma(c, Vx, s * Vy);\n"
<< "\t\t break;\n"
<< "\n"
<< "\t\tcase MODE_HYPERBOLIC:\n"
<< "\t\t Vx = vIn.x;\n"
<< "\t\t Vy = vIn.y;\n"
<< "\t\t radius = pow(Zeps(precalcSumSquares), " << synthPower << " / 2);\n"
<< "\t\t theta = precalcAtanxy;\n"
<< "\t\t SynthSinCos(&synth, theta, &s, &c, synthSmooth);\n"
<< "\t\t vOut.x = " << weight << " * s / radius;\n"
<< "\t\t vOut.y = " << weight << " * c * radius;\n"
<< "\t\t break;\n"
<< "\n"
<< "\t\tcase MODE_JULIA:\n"
<< "\t\t Vx = vIn.x;\n"
<< "\t\t Vy = vIn.y;\n"
<< "\t\t radius = pow(Zeps(precalcSumSquares), " << synthPower << " / 4);\n"
<< "\t\t theta = precalcAtanxy / 2;\n"
<< "\n"
<< "\t\t if (MwcNext01(mwc) < 0.5)\n"
<< "\t\t theta += MPI;\n"
<< "\n"
<< "\t\t SynthSinCos(&synth, theta, &s, &c, synthSmooth);\n"
<< "\t\t vOut.x = " << weight << " * radius * c;\n"
<< "\t\t vOut.y = " << weight << " * radius * s;\n"
<< "\t\t break;\n"
<< "\n"
<< "\t\tcase MODE_DISC:\n"
<< "\t\t Vx = vIn.x;\n"
<< "\t\t Vy = vIn.y;\n"
<< "\t\t theta = precalcAtanxy / MPI;\n"
<< "\t\t radius = MPI * pow(Zeps(precalcSumSquares), " << synthPower << " / 2);\n"
<< "\t\t SynthSinCos(&synth, radius, &s, &c, synthSmooth);\n"
<< "\t\t vOut.x = " << weight << " * s * theta;\n"
<< "\t\t vOut.y = " << weight << " * c * theta;\n"
<< "\t\t break;\n"
<< "\n"
<< "\t\tcase MODE_RINGS:\n"
<< "\t\t Vx = vIn.x;\n"
<< "\t\t Vy = vIn.y;\n"
<< "\t\t radius = precalcSqrtSumSquares;\n"
<< "\t\t theta = precalcAtanxy;\n"
<< "\t\t mu = Zeps(SQR(" << synthPower << "));\n"
<< "\t\t radius += fma((real_t)(-2.0) * mu, (real_t)(int)((radius + mu) / (2 * mu)), radius * ((real_t)(1.0) - mu));\n"
<< "\t\t SynthSinCos(&synth, radius, &s, &c, synthSmooth);\n"
<< "\t\t vOut.x = " << weight << " * s * theta;\n"
<< "\t\t vOut.y = " << weight << " * c * theta;\n"
<< "\t\t break;\n"
<< "\n"
<< "\t\tcase MODE_CYLINDER:\n"
<< "\t\t Vx = vIn.x;\n"
<< "\t\t Vy = vIn.y;\n"
<< "\t\t radius = pow(Zeps(precalcSumSquares), " << synthPower << " / 2);\n"
<< "\t\t SynthSinCos(&synth, Vx, &s, &c, synthSmooth);\n"
<< "\t\t vOut.x = " << weight << " * radius * s;\n"
<< "\t\t vOut.y = " << weight << " * radius * Vy;\n"
<< "\t\t break;\n"
<< "\n"
<< "\t\tcase MODE_BLUR_RING:\n"
<< "\t\t radius = fma((real_t)(0.1) * " << synthPower << ", MwcNext01(mwc) + MwcNext01(mwc) - (real_t)(1.0), (real_t)(1.0));\n"
<< "\t\t theta = M_2PI * MwcNext01(mwc) - MPI;\n"
<< "\t\t thetaFactor = SynthValue(&synth, theta);\n"
<< "\t\t radius = Interpolate(radius, thetaFactor, synthSmooth);\n"
<< "\t\t s = sincos(theta, &c);\n"
<< "\t\t vOut.x = " << weight << " * radius * s;\n"
<< "\t\t vOut.y = " << weight << " * radius * c;\n"
<< "\t\t break;\n"
<< "\n"
<< "\t\tcase MODE_BLUR_RING2:\n"
<< "\t\t theta = fma(M_2PI, MwcNext01(mwc), -MPI);\n"
<< "\t\t radius = pow(Zeps(MwcNext01(mwc)), " << synthPower << ");\n"
<< "\t\t radius = fma((real_t)(0.1), radius, SynthValue(&synth, theta));\n"
<< "\t\t s = sincos(theta, &c);\n"
<< "\t\t vOut.x = " << weight << " * radius * s;\n"
<< "\t\t vOut.y = " << weight << " * radius * c;\n"
<< "\t\t break;\n"
<< "\n"
<< "\t\tcase MODE_SHIFTTHETA:\n"
<< "\t\t Vx = vIn.x;\n"
<< "\t\t Vy = vIn.y;\n"
<< "\t\t radius = pow(Zeps(precalcSumSquares), " << synthPower << " / 2);\n"
<< "\t\t theta = precalcAtanxy - 1 + SynthValue(&synth, radius);\n"
<< "\t\t s = sincos(theta, &c);\n"
<< "\t\t vOut.x = " << weight << " * radius * s;\n"
<< "\t\t vOut.y = " << weight << " * radius * c;\n"
<< "\t\t break;\n"
<< "\t\tcase MODE_SHIFTNSTRETCH:\n"
<< "\t\t Vx = vIn.x;\n"
<< "\t\t Vy = vIn.y;\n"
<< "\t\t radius = pow(Zeps(precalcSumSquares), " << synthPower << " / 2);\n"
<< "\t\t theta = precalcAtanxy - 1 + SynthValue(&synth, radius);\n"
<< "\t\t s = sincos(theta, &c);\n"
<< "\t\t vOut.x = " << weight << " * radius * s;\n"
<< "\t\t vOut.y = " << weight << " * radius * c;\n"
<< "\t\t break;\n"
<< "\n"
<< "\t\tcase MODE_SHIFTTANGENT:\n"
<< "\t\t Vx = vIn.x;\n"
<< "\t\t Vy = vIn.y;\n"
<< "\t\t radius = pow(Zeps(precalcSumSquares), " << synthPower << " / 2);\n"
<< "\t\t s = sincos(precalcAtanxy, &c);\n"
<< "\t\t mu = SynthValue(&synth, radius) - 1;\n"
<< "\t\t Vx += mu * c;\n"
<< "\t\t Vy -= mu * s;\n"
<< "\t\t vOut.x = " << weight << " * Vx;\n"
<< "\t\t vOut.y = " << weight << " * Vy;\n"
<< "\t\t break;\n"
<< "\n"
<< "\t\tcase MODE_XMIRROR:\n"
<< "\t\t Vx = vIn.x;\n"
<< "\t\t Vy = vIn.y;\n"
<< "\t\t mu = SynthValue(&synth, Vx) - 1;\n"
<< "\t\t Vy = fma((real_t)(2.0), mu, -Vy);\n"
<< "\t\t vOut.x = " << weight << " * Vx;\n"
<< "\t\t vOut.y = " << weight << " * Vy;\n"
<< "\t\t break;\n"
<< "\n"
<< "\t\tcase MODE_XYMIRROR:\n"
<< "\t\t Vx = vIn.x;\n"
<< "\t\t Vy = vIn.y;\n"
<< "\t\t mu = SynthValue(&synth, Vx) - 1;\n"
<< "\t\t radius = SynthValue(&synth, Vy) - 1;\n"
<< "\t\t Vy = fma((real_t)(2.0), mu, -Vy);\n"
<< "\t\t Vx = fma((real_t)(2.0), radius, -Vx);\n"
<< "\t\t vOut.x = " << weight << " * Vx;\n"
<< "\t\t vOut.y = " << weight << " * Vy;\n"
<< "\t\t break;\n"
<< "\n"
<< "\t\tcase MODE_SPHERICAL2:\n"
<< "\t\tdefault:\n"
<< "\t\t Vx = vIn.x;\n"
<< "\t\t Vy = vIn.y;\n"
<< "\t\t radius = precalcSqrtSumSquares;\n"
<< "\t\t theta = precalcAtanxy;\n"
<< "\t\t thetaFactor = SynthValue(&synth, theta);\n"
<< "\t\t radius = Interpolate(radius, thetaFactor, synthSmooth);\n"
<< "\t\t radius = pow(radius, " << synthPower << ");\n"
<< "\t\t s = sincos(theta, &c);\n"
<< "\t\t vOut.x = " << weight << " * radius * s;\n"
<< "\t\t vOut.y = " << weight << " * radius * c;\n"
<< "\t\t break;\n"
<< "\t\t}\n"
<< "\n"
<< "\t\tvOut.z = " << DefaultZCl()
<< "\t}\n";
return ss.str();
}
virtual vector<string> OpenCLGlobalFuncNames() const override
{
return vector<string> { "Zeps", "Sqr" };
}
virtual string OpenCLFuncsString() const override
{
return
"#define MODE_SPHERICAL 0\n"
"#define MODE_BUBBLE 1\n"
"#define MODE_BLUR_LEGACY 2\n"
"#define MODE_BLUR_NEW 3\n"
"#define MODE_BLUR_ZIGZAG 4\n"
"#define MODE_RAWCIRCLE 5\n"
"#define MODE_RAWX 6\n"
"#define MODE_RAWY 7\n"
"#define MODE_RAWXY 8\n"
"#define MODE_SHIFTX 9\n"
"#define MODE_SHIFTY 10\n"
"#define MODE_SHIFTXY 11\n"
"#define MODE_SINUSOIDAL 12\n"
"#define MODE_SWIRL 13\n"
"#define MODE_HYPERBOLIC 14\n"
"#define MODE_JULIA 15\n"
"#define MODE_DISC 16\n"
"#define MODE_RINGS 17\n"
"#define MODE_CYLINDER 18\n"
"#define MODE_BLUR_RING 19\n"
"#define MODE_BLUR_RING2 20\n"
"#define MODE_SHIFTTHETA 21\n"
"#define MODE_SHIFTNSTRETCH 22\n"
"#define MODE_SHIFTTANGENT 23\n"
"#define MODE_XMIRROR 24\n"
"#define MODE_XYMIRROR 25\n"
"#define MODE_SPHERICAL2 26\n"
"#define WAVE_SIN 0\n"
"#define WAVE_COS 1\n"
"#define WAVE_SQUARE 2\n"
"#define WAVE_SAW 3\n"
"#define WAVE_TRIANGLE 4\n"
"#define WAVE_CONCAVE 5\n"
"#define WAVE_CONVEX 6\n"
"#define WAVE_NGON 7\n"
"#define WAVE_INGON 8\n"
"#define LAYER_ADD 0\n"
"#define LAYER_MULT 1\n"
"#define LAYER_MAX 2\n"
"#define LAYER_MIN 3\n"
"#define LERP_LINEAR 0\n"
"#define LERP_BEZIER 1\n"
"#define SINCOS_MULTIPLY 0\n"
"#define SINCOS_MIXIN 1\n"
"\n"
"typedef struct __attribute__ " ALIGN_CL " _SynthStruct\n"
"{\n"
" real_t SynthA;\n"
" real_t SynthB;\n"
" real_t SynthBPhs;\n"
" real_t SynthBFrq;\n"
" real_t SynthBSkew;\n"
" int SynthBType;\n"
" int SynthBLayer;\n"
" real_t SynthC;\n"
" real_t SynthCPhs;\n"
" real_t SynthCFrq;\n"
" real_t SynthCSkew;\n"
" int SynthCType;\n"
" int SynthCLayer;\n"
" real_t SynthD;\n"
" real_t SynthDPhs;\n"
" real_t SynthDFrq;\n"
" real_t SynthDSkew;\n"
" int SynthDType;\n"
" int SynthDLayer;\n"
" real_t SynthE;\n"
" real_t SynthEPhs;\n"
" real_t SynthEFrq;\n"
" real_t SynthESkew;\n"
" int SynthEType;\n"
" int SynthELayer;\n"
" real_t SynthF;\n"
" real_t SynthFPhs;\n"
" real_t SynthFFrq;\n"
" real_t SynthFSkew;\n"
" int SynthFType;\n"
" int SynthFLayer;\n"
" real_t SynthMix;\n"
"} SynthStruct;\n"
"\n"
"static void SynthValueProc(real_t* synthA, real_t* thetaFactor, real_t theta, real_t* synth, real_t* phs, real_t* frq, real_t* skew, real_t* x, real_t* y, real_t* z, int* type, int* layer)\n"
"{\n"
" if (*synth != 0)\n"
" {\n"
" *z = fma(theta, *frq, *phs);\n"
" *y = *z / M_2PI;\n"
" *y -= floor(*y);\n"
"\n"
" if (*skew != 0)\n"
" {\n"
" *z = fma((real_t)(0.5), *skew, (real_t)(0.5));\n"
"\n"
" if (*y > *z)\n"
" *y = fma((real_t)(0.5), (*y - *z) / Zeps(1 - *z), (real_t)(0.5));\n"
" else\n"
" *y = 0.5 - 0.5 * (*z - *y) / Zeps(*z);\n"
" }\n"
"\n"
" switch (*type)\n"
" {\n"
" case WAVE_SIN:\n"
" *x = sin(*y * M_2PI);\n"
" break;\n"
" case WAVE_COS:\n"
" *x = cos(*y * M_2PI);\n"
" break;\n"
" case WAVE_SQUARE:\n"
" *x = *y > 0.5 ? 1.0 : -1.0;\n"
" break;\n"
" case WAVE_SAW:\n"
" *x = 1 - 2 * *y;\n"
" break;\n"
" case WAVE_TRIANGLE:\n"
" *x = *y > 0.5 ? 3 - 4 * *y : fma((real_t)(2.0), *y, (real_t)(-1.0));\n"
" break;\n"
" case WAVE_CONCAVE:\n"
" *x = fma((real_t)(8.0), Sqr(*y - 0.5), (real_t)(-1.0));\n"
" break;\n"
" case WAVE_CONVEX:\n"
" *x = fma((real_t)(2.0), sqrt(*y), (real_t)(-1.0));\n"
" break;\n"
" case WAVE_NGON:\n"
" *y -= 0.5;\n"
" *y *= M_2PI / *frq;\n"
" *x = 1 / Zeps(cos(*y)) - 1;\n"
" break;\n"
" case WAVE_INGON:\n"
" *y -= 0.5;\n"
" *y *= M_2PI / *frq;\n"
" *z = cos(*y);\n"
" *x = *z / Zeps(1 - *z);\n"
" break;\n"
" }\n"
"\n"
" switch (*layer)\n"
" {\n"
" case LAYER_ADD:\n"
" *thetaFactor += *synth * *x;\n"
" break;\n"
" case LAYER_MULT:\n"
" *thetaFactor *= fma(*synth, *x, (real_t)(1.0));\n"
" break;\n"
" case LAYER_MAX:\n"
" *z = fma(*synth, *x, *synthA);\n"
" *thetaFactor = (*thetaFactor > *z ? *thetaFactor : *z);\n"
" break;\n"
" case LAYER_MIN:\n"
" *z = fma(*synth, *x, *synthA);\n"
" *thetaFactor = (*thetaFactor < *z ? *thetaFactor : *z);\n"
" break;\n"
" }\n"
" }\n"
"}\n"
"\n"
"static real_t SynthValue(SynthStruct* s, real_t theta)\n"
"{\n"
" real_t x, y, z;\n"
" real_t thetaFactor = s->SynthA;\n"
"\n"
" SynthValueProc(&(s->SynthA), &thetaFactor, theta, &(s->SynthB), &(s->SynthBPhs), &(s->SynthBFrq), &(s->SynthBSkew), &x, &y, &z, &(s->SynthBType), &(s->SynthBLayer));\n"
" SynthValueProc(&(s->SynthA), &thetaFactor, theta, &(s->SynthC), &(s->SynthCPhs), &(s->SynthCFrq), &(s->SynthCSkew), &x, &y, &z, &(s->SynthCType), &(s->SynthCLayer));\n"
" SynthValueProc(&(s->SynthA), &thetaFactor, theta, &(s->SynthD), &(s->SynthDPhs), &(s->SynthDFrq), &(s->SynthDSkew), &x, &y, &z, &(s->SynthDType), &(s->SynthDLayer));\n"
" SynthValueProc(&(s->SynthA), &thetaFactor, theta, &(s->SynthE), &(s->SynthEPhs), &(s->SynthEFrq), &(s->SynthESkew), &x, &y, &z, &(s->SynthEType), &(s->SynthELayer));\n"
" SynthValueProc(&(s->SynthA), &thetaFactor, theta, &(s->SynthF), &(s->SynthFPhs), &(s->SynthFFrq), &(s->SynthFSkew), &x, &y, &z, &(s->SynthFType), &(s->SynthFLayer));\n"
"\n"
" return fma(thetaFactor, s->SynthMix, (1 - s->SynthMix));\n"
"}\n"
"\n"
"static real_t BezierQuadMap(real_t x, real_t m)\n"
"{\n"
" real_t a = 1;\n"
" real_t t = 0;\n"
"\n"
" if (m < 0) { m = -m; a = -1; }\n"
" if (x < 0) { x = -x; a = -a; }\n"
"\n"
" real_t iM = 1e10;\n"
"\n"
" if (m > 1.0e-10)\n"
" iM = 1 / m;\n"
"\n"
" real_t L = iM < m * 2 ? m * 2 : iM;\n"
"\n"
" if ((x > L) || (m == 1))\n"
" return a * x;\n"
"\n"
" if ((m < 1) && (x <= 1))\n"
" {\n"
" t = x;\n"
"\n"
" if (fabs(m - 0.5) > 1e-10)\n"
" t = fma((real_t)(-1.0), m, sqrt(fma(m, m, ((real_t)(1.0) - (real_t)(2.0) * m) * x))) / ((real_t)(1.0) - (real_t)(2.0) * m);\n"
"\n"
" return a * fma(m - (real_t)(1.0), SQR(t), x);\n"
" }\n"
"\n"
" if ((1 < m) && (x <= 1))\n"
" {\n"
" t = x;\n"
"\n"
" if (fabs(m - 2) > 1e-10)\n"
" t = fma((real_t)(-1.0), iM, sqrt(fma(iM, iM, ((real_t)(1.0) - (real_t)(2.0) * iM) * x))) / ((real_t)(1.0) - (real_t)(2.0) * iM);\n"
"\n"
" return a * fma(m - (real_t)(1.0), SQR(t), x);\n"
" }\n"
"\n"
" if (m < 1)\n"
" {\n"
" t = sqrt((x - 1) / (L - 1));\n"
" return a * fma((m - 1), t * t, x + fma((real_t)(2.0), ((real_t)(1.0) - m) * t, (m - 1)));\n"
" }\n"
"\n"
" t = (1 - m) + sqrt(fma((m - (real_t)(1.0)), (m - (real_t)(1.0)), (x - (real_t)(1.0))));\n"
" return a * fma((m - (real_t)(1.0)), t * t, x - fma((real_t)(2.0), (m - (real_t)(1.0)) * t, (m - (real_t)(1.0))));\n"
"}\n"
"\n"
"static real_t Interpolate(real_t x, real_t m, int lerpType)\n"
"{\n"
" switch (lerpType)\n"
" {\n"
" case LERP_LINEAR:\n"
" return x * m;\n"
" case LERP_BEZIER:\n"
" return BezierQuadMap(x, m);\n"
" }\n"
"\n"
" return x * m;\n"
"}\n"
"\n"
"static void SynthSinCos(SynthStruct* synth, real_t theta, real_t* s, real_t* c, int sineType)\n"
"{\n"
" *s = sincos(theta, c);\n"
"\n"
" switch (sineType)\n"
" {\n"
" case SINCOS_MULTIPLY:\n"
" *s = *s * SynthValue(synth, theta);\n"
" *c = *c * SynthValue(synth, theta + MPI / (real_t)(2.0));\n"
" break;\n"
" case SINCOS_MIXIN:\n"
" *s = fma(((real_t)(1.0) - synth->SynthMix), *s, (SynthValue(synth, theta) - (real_t)(1.0)));\n"
" *c = fma(((real_t)(1.0) - synth->SynthMix), *c, (SynthValue(synth, theta + MPI / (real_t)(2.0)) - (real_t)(1.0)));\n"
" break;\n"
" }\n"
"\n"
" return;\n"
"}\n\n"
;
}
protected:
void Init()
{
string prefix = Prefix();
m_Params.clear();
m_Params.reserve(34);
m_Params.push_back(ParamWithName<T>(&m_SynthA, prefix + "synth_a"));
m_Params.push_back(ParamWithName<T>(&m_SynthMode, prefix + "synth_mode", 3, eParamType::INTEGER, MODE_SPHERICAL, MODE_SPHERICAL2));
m_Params.push_back(ParamWithName<T>(&m_SynthPower, prefix + "synth_power", -2));
m_Params.push_back(ParamWithName<T>(&m_SynthMix, prefix + "synth_mix"));
m_Params.push_back(ParamWithName<T>(&m_SynthSmooth, prefix + "synth_smooth", 0, eParamType::INTEGER, LERP_LINEAR, LERP_BEZIER));
m_Params.push_back(ParamWithName<T>(&m_SynthB, prefix + "synth_b"));
m_Params.push_back(ParamWithName<T>(&m_SynthBType, prefix + "synth_b_type", 0, eParamType::INTEGER, WAVE_SIN, WAVE_INGON));
m_Params.push_back(ParamWithName<T>(&m_SynthBSkew, prefix + "synth_b_skew"));
m_Params.push_back(ParamWithName<T>(&m_SynthBFrq, prefix + "synth_b_frq", 1, eParamType::REAL));
m_Params.push_back(ParamWithName<T>(&m_SynthBPhs, prefix + "synth_b_phs"));
m_Params.push_back(ParamWithName<T>(&m_SynthBLayer, prefix + "synth_b_layer", 0, eParamType::INTEGER, LAYER_ADD, LAYER_MIN));
m_Params.push_back(ParamWithName<T>(&m_SynthC, prefix + "synth_c"));
m_Params.push_back(ParamWithName<T>(&m_SynthCType, prefix + "synth_c_type", 0, eParamType::INTEGER, WAVE_SIN, WAVE_INGON));
m_Params.push_back(ParamWithName<T>(&m_SynthCSkew, prefix + "synth_c_skew"));
m_Params.push_back(ParamWithName<T>(&m_SynthCFrq, prefix + "synth_c_frq", 1, eParamType::REAL));
m_Params.push_back(ParamWithName<T>(&m_SynthCPhs, prefix + "synth_c_phs"));
m_Params.push_back(ParamWithName<T>(&m_SynthCLayer, prefix + "synth_c_layer", 0, eParamType::INTEGER, LAYER_ADD, LAYER_MIN));
m_Params.push_back(ParamWithName<T>(&m_SynthD, prefix + "synth_d"));
m_Params.push_back(ParamWithName<T>(&m_SynthDType, prefix + "synth_d_type", 0, eParamType::INTEGER, WAVE_SIN, WAVE_INGON));
m_Params.push_back(ParamWithName<T>(&m_SynthDSkew, prefix + "synth_d_skew"));
m_Params.push_back(ParamWithName<T>(&m_SynthDFrq, prefix + "synth_d_frq", 1, eParamType::REAL));
m_Params.push_back(ParamWithName<T>(&m_SynthDPhs, prefix + "synth_d_phs"));
m_Params.push_back(ParamWithName<T>(&m_SynthDLayer, prefix + "synth_d_layer", 0, eParamType::INTEGER, LAYER_ADD, LAYER_MIN));
m_Params.push_back(ParamWithName<T>(&m_SynthE, prefix + "synth_e"));
m_Params.push_back(ParamWithName<T>(&m_SynthEType, prefix + "synth_e_type", 0, eParamType::INTEGER, WAVE_SIN, WAVE_INGON));
m_Params.push_back(ParamWithName<T>(&m_SynthESkew, prefix + "synth_e_skew"));
m_Params.push_back(ParamWithName<T>(&m_SynthEFrq, prefix + "synth_e_frq", 1, eParamType::REAL));
m_Params.push_back(ParamWithName<T>(&m_SynthEPhs, prefix + "synth_e_phs"));
m_Params.push_back(ParamWithName<T>(&m_SynthELayer, prefix + "synth_e_layer", 0, eParamType::INTEGER, LAYER_ADD, LAYER_MIN));
m_Params.push_back(ParamWithName<T>(&m_SynthF, prefix + "synth_f"));
m_Params.push_back(ParamWithName<T>(&m_SynthFType, prefix + "synth_f_type", 0, eParamType::INTEGER, WAVE_SIN, WAVE_INGON));
m_Params.push_back(ParamWithName<T>(&m_SynthFSkew, prefix + "synth_f_skew"));
m_Params.push_back(ParamWithName<T>(&m_SynthFFrq, prefix + "synth_f_frq", 1, eParamType::REAL));
m_Params.push_back(ParamWithName<T>(&m_SynthFPhs, prefix + "synth_f_phs"));
m_Params.push_back(ParamWithName<T>(&m_SynthFLayer, prefix + "synth_f_layer", 0, eParamType::INTEGER, LAYER_ADD, LAYER_MIN));
}
private:
struct SynthStruct
{
T SynthA;
T SynthB;
T SynthBPhs;
T SynthBFrq;
T SynthBSkew;
int SynthBType;
int SynthBLayer;
T SynthC;
T SynthCPhs;
T SynthCFrq;
T SynthCSkew;
int SynthCType;
int SynthCLayer;
T SynthD;
T SynthDPhs;
T SynthDFrq;
T SynthDSkew;
int SynthDType;
int SynthDLayer;
T SynthE;
T SynthEPhs;
T SynthEFrq;
T SynthESkew;
int SynthEType;
int SynthELayer;
T SynthF;
T SynthFPhs;
T SynthFFrq;
T SynthFSkew;
int SynthFType;
int SynthFLayer;
T SynthMix;
};
inline void SynthValueProc(T& synthA, T& thetaFactor, T theta, T& synth, T& phs, T& frq, T& skew, T& x, T& y, T& z, int& type, int& layer)
{
if (synth != 0)
{
z = phs + theta * frq;
y = z / M_2PI;
y -= Floor<T>(y);
// y is in range 0 - 1. Now skew according to synth_f_skew
if (skew != 0)
{
z = T(0.5) + T(0.5) * skew;
if (y > z)
y = T(0.5) + T(0.5) * (y - z) / Zeps<T>(1 - z);// y is T(0.5) if equals z, up to 1.0
else
y = T(0.5) - T(0.5) * (z - y) / Zeps<T>(z);// y is T(0.5) if equals z, down to 0.0
}
switch (type)
{
case WAVE_SIN:
x = std::sin(y * M_2PI);
break;
case WAVE_COS:
x = std::cos(y * M_2PI);
break;
case WAVE_SQUARE:
x = y > T(0.5) ? T(1) : T(-1);
break;
case WAVE_SAW:
x = 1 - 2 * y;
break;
case WAVE_TRIANGLE:
x = y > T(0.5) ? 3 - 4 * y : 2 * y - 1;
break;
case WAVE_CONCAVE:
x = 8 * (y - T(0.5)) * (y - T(0.5)) - 1;
break;
case WAVE_CONVEX:
x = 2 * std::sqrt(y) - 1;
break;
case WAVE_NGON:
y -= T(0.5);
y *= M_2PI / frq;
x = 1 / Zeps<T>(std::cos(y)) - 1;
break;
default:
case WAVE_INGON:
y -= T(0.5);
y *= M_2PI / frq;
z = std::cos(y);
x = z / Zeps<T>(1 - z);
break;
}
switch (layer)
{
case LAYER_ADD:
thetaFactor += synth * x;
break;
case LAYER_MULT:
thetaFactor *= (1 + synth * x);
break;
case LAYER_MAX:
z = synthA + synth * x;
thetaFactor = (thetaFactor > z ? thetaFactor : z);
break;
default:
case LAYER_MIN:
z = synthA + synth * x;
thetaFactor = (thetaFactor < z ? thetaFactor : z);
break;
}
}
}
inline T SynthValue(SynthStruct& s, T theta)
{
T x, y, z;
T thetaFactor = s.SynthA;
SynthValueProc(s.SynthA, thetaFactor, theta, s.SynthB, s.SynthBPhs, s.SynthBFrq, s.SynthBSkew, x, y, z, s.SynthBType, s.SynthBLayer);
SynthValueProc(s.SynthA, thetaFactor, theta, s.SynthC, s.SynthCPhs, s.SynthCFrq, s.SynthCSkew, x, y, z, s.SynthCType, s.SynthCLayer);
SynthValueProc(s.SynthA, thetaFactor, theta, s.SynthD, s.SynthDPhs, s.SynthDFrq, s.SynthDSkew, x, y, z, s.SynthDType, s.SynthDLayer);
SynthValueProc(s.SynthA, thetaFactor, theta, s.SynthE, s.SynthEPhs, s.SynthEFrq, s.SynthESkew, x, y, z, s.SynthEType, s.SynthELayer);
SynthValueProc(s.SynthA, thetaFactor, theta, s.SynthF, s.SynthFPhs, s.SynthFFrq, s.SynthFSkew, x, y, z, s.SynthFType, s.SynthFLayer);
// Mix is applied here, assuming 1.0 to be the "flat" line for legacy support
return thetaFactor * s.SynthMix + (1 - s.SynthMix);
}
inline T BezierQuadMap(T x, T m)
{
T a = 1; // a is used to control sign of result
T t = 0; // t is the Bezier curve parameter
// Simply reflect in the y axis for negative values
if (m < 0) { m = -m; a = -1; }
if (x < 0) { x = -x; a = -a; }
// iM is "inverse m" used in a few places below
T iM = T(1e10);
if (m > 1.0e-10)
iM = 1 / m;
// L is the upper bound on our curves, where we have rejoined the y = x line
T L = iM < m * 2 ? m * 2 : iM;
// "Non Curved"
// Covers x >= L, or always true if m == 1.0
// y = x i.e. not distorted
if ((x > L) || (m == 1))
return a * x;
if ((m < 1) && (x <= 1))
{
// Bezier Curve #1
// Covers 0 <= $m <= 1.0, 0 <= $x <= 1.0
// Control points are (0,0), (m,m) and (1,m)
t = x; // Special case when m == 0.5
if (std::abs(m - T(0.5)) > 1e-10)
t = (-1 * m + std::sqrt(m * m + (1 - 2 * m) * x)) / (1 - 2 * m);
return a * (x + (m - 1) * t * t);
}
if ((1 < m) && (x <= 1))
{
// Bezier Curve #2
// Covers m >= 1.0, 0 <= x <= 1.0
// Control points are (0,0), (iM,iM) and (1,m)
t = x; // Special case when m == 2
if (std::abs(m - 2) > 1e-10)
t = (-1 * iM + std::sqrt(iM * iM + (1 - 2 * iM) * x)) / (1 - 2 * iM);
return a * (x + (m - 1) * t * t);
}
if (m < 1)
{
// Bezier Curve #3
// Covers 0 <= m <= 1.0, 1 <= x <= L
// Control points are (1,m), (1,1) and (L,L)
// (L is x value (>1) where we re-join y = x line, and is maximum( iM, 2 * m )
t = std::sqrt((x - 1) / (L - 1));
return a * (x + (m - 1) * t * t + 2 * (1 - m) * t + (m - 1));
}
// Curve #4
// Covers 1.0 <= m, 1 <= x <= L
// Control points are (1,m), (m,m) and (L,L)
// (L is x value (>1) where we re-join y = x line, and is maximum( iM, 2 * m )
t = (1 - m) + std::sqrt((m - 1) * (m - 1) + (x - 1));
return a * (x + (m - 1) * t * t - 2 * (m - 1) * t + (m - 1));
}
inline T Interpolate(T x, T m, int lerpType)
{
switch (lerpType)
{
case LERP_LINEAR:
return x * m;
default:
case LERP_BEZIER:
return BezierQuadMap(x, m);
}
}
inline void SynthSinCos(SynthStruct& synth, T theta, T& s, T& c, int sineType)
{
sincos(theta, &s, &c);
switch (sineType)
{
case SINCOS_MULTIPLY:
s = s * SynthValue(synth, theta);
c = c * SynthValue(synth, theta + T(M_PI) / 2);
break;
default:
case SINCOS_MIXIN:
s = (1 - m_SynthMix) * s + (SynthValue(synth, theta) - 1);
c = (1 - m_SynthMix) * c + (SynthValue(synth, theta + T(M_PI) / 2) - 1);
break;
}
return;
}
T m_SynthA;
T m_SynthMode;
T m_SynthPower;
T m_SynthMix;
T m_SynthSmooth;
T m_SynthB;
T m_SynthBType;
T m_SynthBSkew;
T m_SynthBFrq;
T m_SynthBPhs;
T m_SynthBLayer;
T m_SynthC;
T m_SynthCType;
T m_SynthCSkew;
T m_SynthCFrq;
T m_SynthCPhs;
T m_SynthCLayer;
T m_SynthD;
T m_SynthDType;
T m_SynthDSkew;
T m_SynthDFrq;
T m_SynthDPhs;
T m_SynthDLayer;
T m_SynthE;
T m_SynthEType;
T m_SynthESkew;
T m_SynthEFrq;
T m_SynthEPhs;
T m_SynthELayer;
T m_SynthF;
T m_SynthFType;
T m_SynthFSkew;
T m_SynthFFrq;
T m_SynthFPhs;
T m_SynthFLayer;
};
#define CACHE_NUM 10
#define CACHE_WIDTH 21
#define VORONOI_MAXPOINTS 10
/// <summary>
/// crackle.
/// </summary>
template <typename T>
class CrackleVariation : public ParametricVariation<T>
{
public:
CrackleVariation(T weight = 1.0) : ParametricVariation<T>("crackle", eVariationId::VAR_CRACKLE, weight)
{
Init();
}
PARVARCOPY(CrackleVariation)
virtual void Func(IteratorHelper<T>& helper, Point<T>& outPoint, QTIsaac<ISAAC_SIZE, ISAAC_INT>& rand) override
{
int i = 0;
T l, r, trgL;
v2T u, dO;
glm::ivec2 cv;
v2T p[VORONOI_MAXPOINTS] = { v2T(0), v2T(0), v2T(0), v2T(0), v2T(0), v2T(0), v2T(0), v2T(0), v2T(0), v2T(0) };
if (m_CellSize == 0)
return;
T blurr = (rand.Frand01<T>() + rand.Frand01<T>()) / 2 + (rand.Frand01<T>() - T(0.5)) / 4;
T theta = M_2PI * rand.Frand01<T>();
u.x = blurr * std::sin(theta);
u.y = blurr * std::cos(theta);
cv.x = int(std::floor(u.x / m_HalfCellSize));
cv.y = int(std::floor(u.y / m_HalfCellSize));
for (int di = -1; di < 2; di++)
{
for (int dj = -1; dj < 2; dj++)
{
CachedPosition(m_C, cv.x + di, cv.y + dj, m_Z, m_HalfCellSize, m_Distort, p[i]);
i++;
}
}
int q = m_VarFuncs->Closest(p, 9, u);
static glm::ivec2 offset[9] = { { -1, -1 }, { -1, 0 }, { -1, 1 },
{ 0, -1 }, { 0, 0 }, { 0, 1 },
{ 1, -1 }, { 1, 0 }, { 1, 1 }
};
cv += offset[q];
i = 0;
for (int di = -1; di < 2; di++)
{
for (int dj = -1; dj < 2; dj++)
{
CachedPosition(m_C, cv.x + di, cv.y + dj, m_Z, m_HalfCellSize, m_Distort, p[i]);
i++;
}
}
l = m_VarFuncs->Voronoi(p, 9, 4, u);
dO = u - p[4];
trgL = std::pow(std::abs(Zeps<T>(l)), m_Power) * m_Scale;
r = trgL / Zeps<T>(l);
dO *= r;
dO += p[4];
helper.Out.x = m_Weight * dO.x;
helper.Out.y = m_Weight * dO.y;
helper.Out.z = DefaultZ(helper);
}
virtual vector<string> OpenCLGlobalFuncNames() const override
{
return vector<string> { "Zeps", "Sqr", "Closest", "Vratio", "Voronoi", "SimplexNoise3D" };
}
virtual vector<string> OpenCLGlobalDataNames() const override
{
return vector<string> { "NOISE_INDEX", "NOISE_POINTS", "OFFSETS" };
}
virtual string OpenCLFuncsString() const override
{
ostringstream os;
os <<
"static void Position(__constant real_t* cache, __global real_t* p, __global real_t* grad, int x, int y, real_t z, real_t s, real_t d, real2* v)\n"
"{\n"
" if (abs(x) <= " << CACHE_NUM << " && abs(y) <= " << CACHE_NUM << ")\n"
" {\n"
" int index = (((x + " << CACHE_NUM << ") * " << CACHE_WIDTH << ") + (y + " << CACHE_NUM << ")) * 2;\n"
" (*v).x = cache[index];\n"
" (*v).y = cache[index + 1];\n"
" }\n"
" else\n"
" {\n"
" real4 e, f;\n"
" e.x = x * 2.5;\n"
" e.y = y * 2.5;\n"
" e.z = z * 2.5;\n"
" f.x = fma((real_t)y, (real_t)(2.5), (real_t)( 30.2));\n"
" f.y = fma((real_t)x, (real_t)(2.5), (real_t)(-12.1));\n"
" f.z = fma(z, (real_t)(2.5), (real_t)(19.8));\n"
" (*v).x = fma(d, SimplexNoise3D(&e, p, grad), (real_t)y) * s;\n"
" (*v).y = fma(d, SimplexNoise3D(&f, p, grad), (real_t)x) * s;\n"
" }\n"
"}\n"
"\n";
return os.str();
}
virtual string OpenCLString() const override
{
ostringstream ss, ss2;
intmax_t i = 0, varIndex = IndexInXform();
ss2 << "_" << XformIndexInEmber();
string weight = WeightDefineString();
string index = ss2.str() + "]";
string cellSize = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string power = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string distort = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string scale = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string z = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string halfCellSize = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string cache = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
ss << "\t{\n"
<< "\t\tint di = -1, dj = -1;\n"
<< "\t\tint i = 0;\n"
<< "\t\treal_t l, r, trgL;\n"
<< "\t\treal2 u, dO;\n"
<< "\t\tint2 cv;\n"
<< "\t\treal2 p[" << VORONOI_MAXPOINTS << "];\n"
<< "\t\t__global real2* offset = (__global real2*)(globalShared + OFFSETS);\n"
<< "\n"
<< "\t\tif (" << cellSize << " == 0)\n"
<< "\t\t return;\n"
<< "\n"
<< "\t\treal_t blurr = (MwcNext01(mwc) + MwcNext01(mwc)) / 2 + (MwcNext01(mwc) - 0.5) / 4;\n"
<< "\t\treal_t theta = M_2PI * MwcNext01(mwc);\n"
<< "\t\tu.x = blurr * sin(theta);\n"
<< "\t\tu.y = blurr * cos(theta);\n"
<< "\t\tcv.x = (int)floor(u.x / " << halfCellSize << ");\n"
<< "\t\tcv.y = (int)floor(u.y / " << halfCellSize << ");\n"
<< "\n"
<< "\t\tfor (di = -1; di < 2; di++)\n"
<< "\t\t{\n"
<< "\t\t for (dj = -1; dj < 2; dj++)\n"
<< "\t\t {\n"
<< "\t\t Position(&" << cache << ", globalShared + NOISE_INDEX, globalShared + NOISE_POINTS, cv.x + di, cv.y + dj, " << z << ", " << halfCellSize << ", " << distort << ", &p[i]); \n"
<< "\t\t i++;\n"
<< "\t\t }\n"
<< "\t\t}\n"
<< "\n"
<< "\t\tint q = Closest(p, 9, &u);\n"
<< "\t\tcv.x += (int)offset[q].x;\n"
<< "\t\tcv.y += (int)offset[q].y;\n"
<< "\t\ti = 0;\n"
<< "\n"
<< "\t\tfor (di = -1; di < 2; di++)\n"
<< "\t\t{\n"
<< "\t\t for (dj = -1; dj < 2; dj++)\n"
<< "\t\t {\n"
<< "\t\t Position(&" << cache << ", globalShared + NOISE_INDEX, globalShared + NOISE_POINTS, cv.x + di, cv.y + dj, " << z << ", " << halfCellSize << ", " << distort << ", &p[i]);\n"
<< "\t\t i++;\n"
<< "\t\t }\n"
<< "\t\t}\n"
<< "\n"
<< "\t\tl = Zeps(Voronoi(p, 9, 4, &u));\n"
<< "\t\tdO = u - p[4];\n"
<< "\t\ttrgL = pow(fabs(l), " << power << ") * " << scale << ";\n"
<< "\t\tr = trgL / l;\n"
<< "\t\tdO *= r;\n"
<< "\t\tdO += p[4];\n"
<< "\t\tvOut.x = " << weight << " * dO.x;\n"
<< "\t\tvOut.y = " << weight << " * dO.y;\n"
<< "\t\tvOut.z = " << DefaultZCl()
<< "\t}\n";
return ss.str();
}
virtual void Precalc() override
{
m_HalfCellSize = Zeps<T>(std::abs(m_CellSize) / 2);
for (int x = -CACHE_NUM; x <= CACHE_NUM; x++)
for (int y = -CACHE_NUM; y <= CACHE_NUM; y++)
Position(x, y, m_Z, m_HalfCellSize, m_Distort, m_C[x + CACHE_NUM][y + CACHE_NUM]);
}
protected:
void Init()
{
string prefix = Prefix();
m_Params.clear();
m_Params.reserve(8);
m_Params.push_back(ParamWithName<T>(&m_CellSize, prefix + "crackle_cellsize", 1, eParamType::REAL, T(0.0001)));
m_Params.push_back(ParamWithName<T>(&m_Power, prefix + "crackle_power", T(0.2)));
m_Params.push_back(ParamWithName<T>(&m_Distort, prefix + "crackle_distort"));
m_Params.push_back(ParamWithName<T>(&m_Scale, prefix + "crackle_scale", 1));
m_Params.push_back(ParamWithName<T>(&m_Z, prefix + "crackle_z"));
m_Params.push_back(ParamWithName<T>(true, &m_HalfCellSize, prefix + "crackle_half_cellsize"));
m_Params.push_back(ParamWithName<T>(true, &(m_C[0][0].x), prefix + "crackle_cache", sizeof(m_C)));
}
private:
void Position(int x, int y, T z, T s, T d, v2T& v)
{
v3T e, f;
// Values here are arbitrary, chosen simply to be far enough apart so they do not correlate
e.x = x * T(2.5);
e.y = y * T(2.5);
e.z = z * T(2.5);
// Cross-over between x and y is intentional
f.x = y * T(2.5) + T(30.2);
f.y = x * T(2.5) - T(12.1);
f.z = z * T(2.5) + T(19.8);
v.x = (x + d * m_VarFuncs->SimplexNoise3D(e)) * s;
v.y = (y + d * m_VarFuncs->SimplexNoise3D(f)) * s;
}
void CachedPosition(v2T cache[CACHE_WIDTH][CACHE_WIDTH], int x, int y, T z, T s, T d, v2T& v)
{
if (std::abs(x) <= CACHE_NUM && std::abs(y) <= CACHE_NUM)
v = cache[x + CACHE_NUM][y + CACHE_NUM];
else
Position(x, y, z, s, d, v);
}
T m_CellSize;
T m_Power;
T m_Distort;
T m_Scale;
T m_Z;
T m_HalfCellSize;//Precalc
v2T m_C[CACHE_WIDTH][CACHE_WIDTH];//Not kept as a precalc because it crashes Nvidia GPUs.
shared_ptr<VarFuncs<T>> m_VarFuncs = VarFuncs<T>::Instance();
};
/// <summary>
/// crackle2.
/// By tatasz.
/// </summary>
template <typename T>
class Crackle2Variation : public ParametricVariation<T>
{
public:
Crackle2Variation(T weight = 1.0) : ParametricVariation<T>("crackle2", eVariationId::VAR_CRACKLE2, weight)
{
Init();
}
PARVARCOPY(Crackle2Variation)
virtual void Func(IteratorHelper<T>& helper, Point<T>& outPoint, QTIsaac<ISAAC_SIZE, ISAAC_INT>& rand) override
{
T seed = 34554;
v2T cell(Floor(helper.In.x), Floor(helper.In.y));
v2T xy0(cell.x + m_OneOverCellsize * VarFuncs<T>::HashShadertoy(cell.x, cell.y, seed), cell.y + m_OneOverCellsize * VarFuncs<T>::HashShadertoy(cell.y, cell.x * 3, seed + 7));
v2T xy1_aux;
if (rand.Frand01<T>() < 0.5)
{
if (rand.Frand01<T>() < 0.5)
xy1_aux = v2T(cell.x, cell.y + 1);
else
xy1_aux = v2T(cell.x, cell.y - 1);
}
else
{
if (rand.Frand01<T>() < 0.5)
xy1_aux = v2T(cell.x + 1, cell.y);
else
xy1_aux = v2T(cell.x - 1, cell.y);
}
v2T xy1(xy1_aux.x + m_OneOverCellsize * VarFuncs<T>::HashShadertoy(xy1_aux.x, xy1_aux.y, seed), xy1_aux.y + m_OneOverCellsize * VarFuncs<T>::HashShadertoy(xy1_aux.y, xy1_aux.x * 3, seed + 7));
v2T v = xy1 - xy0;
v2T result = (xy0 + v * rand.Frand01<T>()) * m_Cellsize;
helper.Out.x = result.x;
helper.Out.y = result.y;
helper.Out.z = DefaultZ(helper);
}
virtual string OpenCLString() const override
{
ostringstream ss, ss2;
intmax_t i = 0, varIndex = IndexInXform();
ss2 << "_" << XformIndexInEmber() << "]";
string index = ss2.str();
string weight = WeightDefineString();
string cellsize = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string oneovercellsize = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
ss << "\t{\n"
<< "\t\treal_t seed = 34554.0;\n"
<< "\t\treal2 cell = (real2)(floor(vIn.x), floor(vIn.y));\n"
<< "\t\treal2 xy0 = (real2)(cell.x + " << oneovercellsize << " * HashShadertoy(cell.x, cell.y, seed), cell.y + " << oneovercellsize << " * HashShadertoy(cell.y, cell.x * 3.0, seed + 7.0));\n"
<< "\t\treal2 xy1_aux;\n"
<< "\t\t\n"
<< "\t\tif (MwcNext01(mwc) < 0.5)\n"
<< "\t\t{\n"
<< "\t\t if (MwcNext01(mwc) < 0.5)\n"
<< "\t\t xy1_aux = (real2)(cell.x, cell.y + 1);\n"
<< "\t\t else\n"
<< "\t\t xy1_aux = (real2)(cell.x, cell.y - 1);\n"
<< "\t\t}\n"
<< "\t\telse\n"
<< "\t\t{\n"
<< "\t\t if (MwcNext01(mwc) < 0.5)\n"
<< "\t\t xy1_aux = (real2)(cell.x + 1, cell.y);\n"
<< "\t\t else\n"
<< "\t\t xy1_aux = (real2)(cell.x - 1, cell.y);\n"
<< "\t\t}\n"
<< "\t\t\n"
<< "\t\treal2 xy1 = (real2)(xy1_aux.x + " << oneovercellsize << " * HashShadertoy(xy1_aux.x, xy1_aux.y, seed), xy1_aux.y + " << oneovercellsize << " * HashShadertoy(xy1_aux.y, xy1_aux.x * 3.0, seed + 7.0));\n"
<< "\t\treal2 v = xy1 - xy0;\n"
<< "\t\treal2 result = (xy0 + v * MwcNext01(mwc)) * " << cellsize << ";\n"
<< "\t\tvOut.x = result.x;\n"
<< "\t\tvOut.y = result.y;\n"
<< "\t\tvOut.z = " << DefaultZCl()
<< "\t}\n";
return ss.str();
}
virtual vector<string> OpenCLGlobalFuncNames() const override
{
return vector<string> { "Fract", "HashShadertoy" };
}
virtual void Precalc() override
{
m_OneOverCellsize = 1 / Zeps(m_Cellsize);
}
protected:
void Init()
{
string prefix = Prefix();
m_Params.clear();
m_Params.push_back(ParamWithName<T>(&m_Cellsize, prefix + "crackle2_cellsize", 1, eParamType::REAL, T(0.0001)));
m_Params.push_back(ParamWithName<T>(true, &m_OneOverCellsize, prefix + "crackle2_one_over_cellsize"));
}
private:
T m_Cellsize;
T m_OneOverCellsize;
};
/// <summary>
/// post_smartcrop.
/// This variation is special in that it only exists as a post_.
/// </summary>
template <typename T>
class PostSmartcropVariation : public ParametricVariation<T>
{
public:
PostSmartcropVariation(T weight = 1.0) : ParametricVariation<T>("post_smartcrop", eVariationId::VAR_POST_SMARTCROP, weight)
{
m_PrePostAssignType = eVariationAssignType::ASSIGNTYPE_SET;
m_VarType = eVariationType::VARTYPE_POST;//Very special usage, post only.
Init();
}
PARVARCOPY(PostSmartcropVariation)
virtual void Func(IteratorHelper<T>& helper, Point<T>& outPoint, QTIsaac<ISAAC_SIZE, ISAAC_INT>& rand) override
{
bool lastPart = true;
T xi, yi, zi;
int iMode = int(m_Mode);
if (m_Static > 1)
{
xi = helper.In.x;
yi = helper.In.y;
zi = helper.In.z;
}
else//Extremely strange usage, where a post variation wants the original affine transformed points.
{
xi = helper.m_TransX;
yi = helper.m_TransY;
zi = helper.m_TransZ;
}
T ang = std::atan2(yi, xi);
T rad = std::sqrt(SQR(xi) + SQR(yi));
if (m_Radial)
{
T edge = m_Edge * (rand.Frand01<T>() - T(0.5));
T xang = ang / M_2PI + 1 + edge;
xang = (xang - int(xang)) * M_2PI;
if (int(xang > m_WorkPower) == iMode)
{
if (m_Cropmode == 2)
{
if (m_Static > 1 || m_Static == -1)
{
helper.Out.x = m_X;//This is post only with an assign type of SET, so no need to set m_* to 0 after these (or any other) direct assignments.
helper.Out.y = m_Y;
helper.Out.z = m_Z;
}
else
{
helper.Out.x = helper.In.x + m_X;//Original specifically summed the running sum point.
helper.Out.y = helper.In.y + m_Y;
helper.Out.z = helper.In.z + m_Z;
}
outPoint.m_ColorX = m_C;
}
else
{
T x, s, c;
x = int(rand.Frand01<T>() * 2) ? m_WorkPower + (rand.Frand01<T>() * m_Scatter + m_Offset + edge) * T(M_PI) : -(rand.Frand01<T>() * m_Scatter + m_Offset + edge) * T(M_PI);
sincos(x, &s, &c);
if (m_Static > 1 || m_Static == -1)
{
helper.Out.x = m_Weight * rad * c;
helper.Out.y = m_Weight * rad * s;
helper.Out.z = m_Weight * zi;
}
else
{
helper.Out.x = helper.In.x + (m_Weight * rad * c);//Original specifically summed the running sum point.
helper.Out.y = helper.In.y + (m_Weight * rad * s);
helper.Out.z = helper.In.z + (m_Weight * zi);
}
}
lastPart = false;
}
}
else
{
T coeff;
if (m_Distortion == 0)
{
coeff = 1;
}
else
{
T xang = (ang + T(M_PI)) / m_Alpha;
xang = xang - int(xang);
xang = (xang < T(0.5)) ? xang : 1 - xang;
coeff = 1 / std::cos(xang * m_Alpha);
if (m_Roundstr != 0)
{
T wwidth = ((m_Roundwidth != 1) ? std::exp(std::log(xang * 2) * m_Roundwidth) : (xang * 2)) * m_RoundCoeff;
coeff = std::abs((1 - wwidth) * coeff + wwidth);
}
if (m_Distortion != 1)
coeff = std::exp(std::log(coeff) * m_Distortion);
}
T xr = coeff * ((m_Edge != 0) ? m_WorkRadius + m_Edge * (rand.Frand01<T>() - T(0.5)) : m_WorkRadius);
if ((rad > xr) == iMode)
{
if (m_Cropmode)
{
if (m_Cropmode == 2)
{
if (m_Static > 1 || m_Static == -1)
{
helper.Out.x = m_X;
helper.Out.y = m_Y;
helper.Out.z = m_Z;
}
else
{
helper.Out.x = helper.In.x + m_X;//Original specifically summed the running sum point.
helper.Out.y = helper.In.y + m_Y;
helper.Out.z = helper.In.z + m_Z;
}
outPoint.m_ColorX = m_C;
}
else
{
T rdc = (m_Cropmode == -1) ? rad : xr + coeff * (rand.Frand01<T>() * m_Scatter + m_Offset);
T x, s, c;
x = ang + m_WorkRotation;
sincos(x, &s, &c);
if (m_Static > 1 || m_Static == -1)
{
helper.Out.x = m_Weight * rdc * c;
helper.Out.y = m_Weight * rdc * s;
helper.Out.z = m_Weight * zi;
}
else
{
helper.Out.x = helper.In.x + (m_Weight * rdc * c);
helper.Out.y = helper.In.y + (m_Weight * rdc * s);
helper.Out.z = helper.In.z + (m_Weight * zi);
}
}
}
else
{
if (m_Static > 1 || m_Static == -1)
{
helper.Out.x = 0;
helper.Out.y = 0;
helper.Out.z = 0;
}
}
lastPart = false;
}
}
if (lastPart)
{
if (m_Static == 3)
{
m_X = m_Weight * helper.m_TransX;//Another case where it wants the original affine transformed points.
m_Y = m_Weight * helper.m_TransY;
m_Z = m_Weight * helper.m_TransZ;
}
else
{
m_X = m_Weight * xi;
m_Y = m_Weight * yi;
m_Z = m_Weight * zi;
}
if (m_Cropmode == 2)
m_C = outPoint.m_ColorX;
if (m_Static > 0)
{
helper.Out.x = m_X;
helper.Out.y = m_Y;
helper.Out.z = m_Z;
}
else
{
helper.Out.x = helper.In.x + m_X;//Original specifically summed the running sum point.
helper.Out.y = helper.In.y + m_Y;
helper.Out.z = helper.In.z + m_Z;
}
}
}
virtual string OpenCLString() const override
{
ostringstream ss, ss2;
intmax_t i = 0, varIndex = IndexInXform();
ss2 << "_" << XformIndexInEmber();
string weight = WeightDefineString();
string index = ss2.str() + "]";
string stateIndex = ss2.str();
string power = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string radius = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string roundstr = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string roundwidth = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string distortion = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string edge = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string scatter = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string offset = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string rotation = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string cropmode = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string staticc = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string mode = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string radial = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string workradius = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string workpower = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string alpha = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string roundcoeff = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string workrotation = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string x = "varState->" + m_Params[i++].Name() + stateIndex;//State.
string y = "varState->" + m_Params[i++].Name() + stateIndex;
string z = "varState->" + m_Params[i++].Name() + stateIndex;
string c = "varState->" + m_Params[i++].Name() + stateIndex;
ss << "\t{\n"
<< "\t\tint lastPart = 1;\n"
<< "\t\treal_t xi, yi, zi;\n"
<< "\t\tint iMode = (int)" << mode << ";\n"
<< "\n"
<< "\t\tif (" << staticc << " > 1)\n"
<< "\t\t{\n"
<< "\t\t xi = vIn.x;\n"
<< "\t\t yi = vIn.y;\n"
<< "\t\t zi = vIn.z;\n"
<< "\t\t}\n"
<< "\t\telse\n"
<< "\t\t{\n"
<< "\t\t xi = transX;\n"
<< "\t\t yi = transY;\n"
<< "\t\t zi = transZ;\n"
<< "\t\t}\n"
<< "\n"
<< "\t\treal_t ang = atan2(yi, xi);\n"
<< "\t\treal_t rad = sqrt(SQR(xi) + SQR(yi));\n"
<< "\n"
<< "\t\tif (" << radial << ")\n"
<< "\t\t{\n"
<< "\t\t real_t edge = " << edge << " * (MwcNext01(mwc) - 0.5);\n"
<< "\t\t real_t xang = ang / M_2PI + 1 + edge;\n"
<< "\t\t xang = (xang - (int)xang) * M_2PI;\n"
<< "\n"
<< "\t\t if ((int)(xang > " << workpower << ") == iMode)\n"
<< "\t\t {\n"
<< "\t\t if (" << cropmode << " == 2)\n"
<< "\t\t {\n"
<< "\t\t if (" << staticc << " > 1 || " << staticc << " == -1)\n"
<< "\t\t {\n"
<< "\t\t vOut.x = " << x << ";\n"
<< "\t\t vOut.y = " << y << ";\n"
<< "\t\t vOut.z = " << z << ";\n"
<< "\t\t }\n"
<< "\t\t else\n"
<< "\t\t {\n"
<< "\t\t vOut.x = vIn.x + " << x << ";\n"
<< "\t\t vOut.y = vIn.y + " << y << ";\n"
<< "\t\t vOut.z = vIn.z + " << z << ";\n"
<< "\t\t }\n"
<< "\n"
<< "\t\t outPoint->m_ColorX = " << c << ";\n"
<< "\t\t }\n"
<< "\t\t else\n"
<< "\t\t {\n"
<< "\t\t real_t x, s, c;\n"
<< "\t\t x = ((int)(MwcNext01(mwc) * 2)) ? " << workpower << " + (MwcNext01(mwc) * " << scatter << " + " << offset << " + edge) * MPI : -(MwcNext01(mwc) * " << scatter << " + " << offset << " + edge) * MPI;\n"
<< "\t\t s = sincos(x, &c);\n"
<< "\n"
<< "\t\t if (" << staticc << " > 1 || " << staticc << " == -1)\n"
<< "\t\t {\n"
<< "\t\t vOut.x = " << weight << " * rad * c;\n"
<< "\t\t vOut.y = " << weight << " * rad * s;\n"
<< "\t\t vOut.z = " << weight << " * zi;\n"
<< "\t\t }\n"
<< "\t\t else\n"
<< "\t\t {\n"
<< "\t\t vOut.x = vIn.x + (" << weight << " * rad * c);\n"
<< "\t\t vOut.y = vIn.y + (" << weight << " * rad * s);\n"
<< "\t\t vOut.z = vIn.z + (" << weight << " * zi);\n"
<< "\t\t }\n"
<< "\t\t }\n"
<< "\n"
<< "\t\t lastPart = 0;\n"
<< "\t\t }\n"
<< "\t\t}\n"
<< "\t\telse\n"
<< "\t\t{\n"
<< "\t\t real_t coeff;\n"
<< "\n"
<< "\t\t if (" << distortion << " == 0)\n"
<< "\t\t {\n"
<< "\t\t coeff = 1;\n"
<< "\t\t }\n"
<< "\t\t else\n"
<< "\t\t {\n"
<< "\t\t real_t xang = (ang + MPI) / " << alpha << ";\n"
<< "\t\t xang = xang - (int)xang;\n"
<< "\t\t xang = (xang < 0.5) ? xang : 1 - xang;\n"
<< "\t\t coeff = 1 / cos(xang * " << alpha << ");\n"
<< "\n"
<< "\t\t if (" << roundstr << " != 0)\n"
<< "\t\t {\n"
<< "\t\t real_t wwidth = ((" << roundwidth << " != 1) ? exp(log(xang * 2) * " << roundwidth << ") : (xang * 2)) * " << roundcoeff << ";\n"
<< "\t\t coeff = fabs((1 - wwidth) * coeff + wwidth);\n"
<< "\t\t }\n"
<< "\n"
<< "\t\t if (" << distortion << " != 1)\n"
<< "\t\t coeff = exp(log(coeff) * " << distortion << ");\n"
<< "\t\t }\n"
<< "\n"
<< "\t\t real_t xr = coeff * ((" << edge << " != 0) ? " << workradius << " + " << edge << " * (MwcNext01(mwc) - 0.5) : " << workradius << ");\n"
<< "\n"
<< "\t\t if ((int)(rad > xr) == iMode)\n"
<< "\t\t {\n"
<< "\t\t if (" << cropmode << ")\n"
<< "\t\t {\n"
<< "\t\t if (" << cropmode << " == 2)\n"
<< "\t\t {\n"
<< "\t\t if (" << staticc << " > 1 || " << staticc << " == -1)\n"
<< "\t\t {\n"
<< "\t\t vOut.x = " << x << ";\n"
<< "\t\t vOut.y = " << y << ";\n"
<< "\t\t vOut.z = " << z << ";\n"
<< "\t\t }\n"
<< "\t\t else\n"
<< "\t\t {\n"
<< "\t\t vOut.x = vIn.x + " << x << ";\n"
<< "\t\t vOut.y = vIn.y + " << y << ";\n"
<< "\t\t vOut.z = vIn.z + " << z << ";\n"
<< "\t\t }\n"
<< "\n"
<< "\t\t outPoint->m_ColorX = " << c << ";\n"
<< "\t\t }\n"
<< "\t\t else\n"
<< "\t\t {\n"
<< "\t\t real_t rdc = (" << cropmode << " == -1) ? rad : xr + coeff * (MwcNext01(mwc) * " << scatter << " + " << offset << ");\n"
<< "\t\t real_t x, s, c;\n"
<< "\t\t x = ang + " << workrotation << ";\n"
<< "\t\t s = sincos(x, &c);\n"
<< "\n"
<< "\t\t if (" << staticc << " > 1 || " << staticc << " == -1)\n"
<< "\t\t {\n"
<< "\t\t vOut.x = " << weight << " * rdc * c;\n"
<< "\t\t vOut.y = " << weight << " * rdc * s;\n"
<< "\t\t vOut.z = " << weight << " * zi;\n"
<< "\t\t }\n"
<< "\t\t else\n"
<< "\t\t {\n"
<< "\t\t vOut.x = vIn.x + (" << weight << " * rdc * c);\n"
<< "\t\t vOut.y = vIn.y + (" << weight << " * rdc * s);\n"
<< "\t\t vOut.z = vIn.z + (" << weight << " * zi);\n"
<< "\t\t }\n"
<< "\t\t }\n"
<< "\t\t }\n"
<< "\t\t else\n"
<< "\t\t {\n"
<< "\t\t if (" << staticc << " > 1 || " << staticc << " == -1)\n"
<< "\t\t {\n"
<< "\t\t vOut.x = 0;\n"
<< "\t\t vOut.y = 0;\n"
<< "\t\t vOut.z = 0;\n"
<< "\t\t }\n"
<< "\t\t }\n"
<< "\n"
<< "\t\t lastPart = 0;\n"
<< "\t\t }\n"
<< "\t\t}\n"
<< "\n"
<< "\t\tif (lastPart)\n"
<< "\t\t{\n"
<< "\t\t if (" << staticc << " == 3)\n"
<< "\t\t {\n"
<< "\t\t " << x << " = " << weight << " * transX;\n"
<< "\t\t " << y << " = " << weight << " * transY;\n"
<< "\t\t " << z << " = " << weight << " * transZ;\n"
<< "\t\t }\n"
<< "\t\t else\n"
<< "\t\t {\n"
<< "\t\t " << x << " = " << weight << " * xi;\n"
<< "\t\t " << y << " = " << weight << " * yi;\n"
<< "\t\t " << z << " = " << weight << " * zi;\n"
<< "\t\t }\n"
<< "\n"
<< "\t\t if (" << cropmode << " == 2)\n"
<< "\t\t " << c << " = outPoint->m_ColorX;\n"
<< "\n"
<< "\t\t if (" << staticc << " > 0)\n"
<< "\t\t {\n"
<< "\t\t vOut.x = " << x << ";\n"
<< "\t\t vOut.y = " << y << ";\n"
<< "\t\t vOut.z = " << z << ";\n"
<< "\t\t }\n"
<< "\t\t else\n"
<< "\t\t {\n"
<< "\t\t vOut.x = vIn.x + " << x << ";\n"
<< "\t\t vOut.y = vIn.y + " << y << ";\n"
<< "\t\t vOut.z = vIn.z + " << z << ";\n"
<< "\t\t }\n"
<< "\t\t}\n"
<< "\t}\n";
return ss.str();
}
virtual void Precalc() override
{
m_Mode = T(((m_Power > 0) == (m_Radius > 0)) ? 1 : 0);
m_WorkRadius = std::abs(m_Radius);
m_WorkPower = std::abs(Zeps<T>(m_Power));
if (m_WorkPower < 2)
{
m_WorkPower = m_WorkPower * T(M_PI);
m_Radial = 1;
}
else
{
m_Radial = 0;
m_Alpha = M_2PI / m_WorkPower;
m_RoundCoeff = m_Roundstr / Zeps<T>(std::sin(m_Alpha / 2)) / m_WorkPower * 2;
m_WorkRotation = m_Rotation * m_Alpha;
}
m_X = m_Y = m_Z = m_C = 0;
}
protected:
void Init()
{
string prefix = Prefix();
m_Params.clear();
m_Params.push_back(ParamWithName<T>(&m_Power, prefix + "smartcrop_power", 4)); //Original used a prefix of scrop_, which is incompatible with Ember's design.
m_Params.push_back(ParamWithName<T>(&m_Radius, prefix + "smartcrop_radius", 1));
m_Params.push_back(ParamWithName<T>(&m_Roundstr, prefix + "smartcrop_roundstr"));
m_Params.push_back(ParamWithName<T>(&m_Roundwidth, prefix + "smartcrop_roundwidth", 1));
m_Params.push_back(ParamWithName<T>(&m_Distortion, prefix + "smartcrop_distortion", 1));
m_Params.push_back(ParamWithName<T>(&m_Edge, prefix + "smartcrop_edge"));
m_Params.push_back(ParamWithName<T>(&m_Scatter, prefix + "smartcrop_scatter"));
m_Params.push_back(ParamWithName<T>(&m_Offset, prefix + "smartcrop_offset"));
m_Params.push_back(ParamWithName<T>(&m_Rotation, prefix + "smartcrop_rotation"));
m_Params.push_back(ParamWithName<T>(&m_Cropmode, prefix + "smartcrop_cropmode", 1, eParamType::INTEGER, -1, 2));
m_Params.push_back(ParamWithName<T>(&m_Static, prefix + "smartcrop_static", 1, eParamType::INTEGER, -1, 3));
m_Params.push_back(ParamWithName<T>(true, &m_Mode, prefix + "smartcrop_mode"));//Precalc.
m_Params.push_back(ParamWithName<T>(true, &m_Radial, prefix + "smartcrop_radial"));
m_Params.push_back(ParamWithName<T>(true, &m_WorkRadius, prefix + "smartcrop_work_radius"));
m_Params.push_back(ParamWithName<T>(true, &m_WorkPower, prefix + "smartcrop_work_power"));
m_Params.push_back(ParamWithName<T>(true, &m_Alpha, prefix + "smartcrop_alpha"));
m_Params.push_back(ParamWithName<T>(true, &m_RoundCoeff, prefix + "smartcrop_round_coeff"));
m_Params.push_back(ParamWithName<T>(true, &m_WorkRotation, prefix + "smartcrop_work_rotation"));
m_Params.push_back(ParamWithName<T>(true, true, &m_X, prefix + "smartcrop_x"));//State.
m_Params.push_back(ParamWithName<T>(true, true, &m_Y, prefix + "smartcrop_y"));
m_Params.push_back(ParamWithName<T>(true, true, &m_Z, prefix + "smartcrop_z"));
m_Params.push_back(ParamWithName<T>(true, true, &m_C, prefix + "smartcrop_c"));
}
private:
T m_Power;
T m_Radius;
T m_Roundstr;
T m_Roundwidth;
T m_Distortion;
T m_Edge;
T m_Scatter;
T m_Offset;
T m_Rotation;
T m_Cropmode;
T m_Static;
T m_Mode;//Precalc.
T m_Radial;
T m_WorkRadius;
T m_WorkPower;
T m_Alpha;
T m_RoundCoeff;
T m_WorkRotation;
T m_X;//State.
T m_Y;
T m_Z;
T m_C;
};
/// <summary>
/// erf.
/// </summary>
template <typename T>
class ErfVariation : public Variation<T>
{
public:
ErfVariation(T weight = 1.0) : Variation<T>("erf", eVariationId::VAR_ERF, weight) { }
VARCOPY(ErfVariation)
virtual void Func(IteratorHelper<T>& helper, Point<T>& outPoint, QTIsaac<ISAAC_SIZE, ISAAC_INT>& rand) override
{
helper.Out.x = m_Weight * std::erf(helper.In.x);
helper.Out.y = m_Weight * std::erf(helper.In.y);
helper.Out.z = DefaultZ(helper);
}
virtual string OpenCLString() const override
{
ostringstream ss;
intmax_t varIndex = IndexInXform();
string weight = WeightDefineString();
ss << "\t{\n"
<< "\t\tvOut.x = " << weight << " * erf(vIn.x);\n"
<< "\t\tvOut.y = " << weight << " * erf(vIn.y);\n"
<< "\t\tvOut.z = " << DefaultZCl()
<< "\t}\n";
return ss.str();
}
};
/// <summary>
/// xerf.
/// </summary>
template <typename T>
class XerfVariation : public Variation<T>
{
public:
XerfVariation(T weight = 1.0) : Variation<T>("xerf", eVariationId::VAR_XERF, weight, true) { }
VARCOPY(XerfVariation)
virtual void Func(IteratorHelper<T>& helper, Point<T>& outPoint, QTIsaac<ISAAC_SIZE, ISAAC_INT>& rand) override
{
T r2 = Sqr(std::sqrt(helper.m_PrecalcSumSquares + SQR(helper.In.z)));
helper.Out.x = m_Weight * (std::abs(helper.In.x) >= 2 ? helper.In.x / r2 : std::erf(helper.In.x));
helper.Out.y = m_Weight * (std::abs(helper.In.y) >= 2 ? helper.In.y / r2 : std::erf(helper.In.y));
helper.Out.z = m_Weight * (std::abs(helper.In.z) >= 2 ? helper.In.z / r2 : std::erf(helper.In.z));
}
virtual string OpenCLString() const override
{
ostringstream ss;
intmax_t varIndex = IndexInXform();
string weight = WeightDefineString();
ss << "\t{\n"
<< "\t\treal_t r2 = Sqr(sqrt(fma(vIn.z, vIn.z, precalcSumSquares)));\n"
<< "\t\tvOut.x = " << weight << " * (fabs(vIn.x) >= 2 ? vIn.x / r2 : erf(vIn.x));\n"
<< "\t\tvOut.y = " << weight << " * (fabs(vIn.y) >= 2 ? vIn.y / r2 : erf(vIn.y));\n"
<< "\t\tvOut.z = " << weight << " * (fabs(vIn.z) >= 2 ? vIn.z / r2 : erf(vIn.z));\n"
<< "\t}\n";
return ss.str();
}
virtual vector<string> OpenCLGlobalFuncNames() const override
{
return vector<string> { "Sqr" };
}
};
template <typename T>
class WVariation : public ParametricVariation<T>
{
public:
WVariation(T weight = 1.0) : ParametricVariation<T>("w", eVariationId::VAR_W, weight, true, true, false, false, true)
{
Init();
}
PARVARCOPY(WVariation)
virtual void Func(IteratorHelper<T>& helper, Point<T>& outPoint, QTIsaac<ISAAC_SIZE, ISAAC_INT>& rand) override
{
T a = helper.m_PrecalcAtanyx;
T r = helper.m_PrecalcSqrtSumSquares;
T a2 = a + m_Angle;
if (a2 < -T(M_PI))
a2 += M_2PI;
if (a2 > T(M_PI))
a2 -= M_2PI;
T s, c;
T total = 0;
T total2 = 0;
T temp1, temp2, temp4;
if (m_Hypergon != 0)
{
temp1 = fmod(std::abs(a), M_2PI / m_HypergonN) - T(M_PI) / m_HypergonN;
temp2 = Sqr(std::tan(temp1)) + 1;
if (temp2 >= Sqr(m_HypergonD))
{
total += m_Hypergon;
}
else
{
total += m_Hypergon * (m_HypergonD - std::sqrt(Sqr(m_HypergonD) - temp2)) / std::sqrt(temp2);
}
}
if (m_Star != 0)
{
temp1 = std::tan(std::abs(fmod(std::abs(a), M_2PI / m_StarN) - T(M_PI) / m_StarN));
total += m_Star * std::sqrt(Sqr(m_TanStarSlope) * (1 + Sqr(temp1)) / Sqr(temp1 + m_TanStarSlope));
}
if (m_Lituus != 0)
{
total += m_Lituus * std::pow(std::abs(a / T(M_PI) + 1), m_InvLituusA);
}
if (m_Super != 0)
{
temp4 = a * m_SuperM4th;
sincos(temp4, &s, &c);
total += m_Super * std::pow(std::pow(std::abs(c), m_SuperN2) + std::pow(std::abs(s), m_SuperN3), m_OneOverSuperN1);
}
if (r <= total)
{
if (m_Hypergon != 0.0)
{
temp1 = fmod(std::abs(a2), M_2PI / m_HypergonN) - T(M_PI) / m_HypergonN;
temp2 = Sqr(std::tan(temp1)) + 1;
if (temp2 >= Sqr(m_HypergonD))
{
total2 += m_Hypergon;
}
else
{
total2 += m_Hypergon * (m_HypergonD - std::sqrt(Sqr(m_HypergonD) - temp2)) / std::sqrt(temp2);
}
}
if (m_Star != 0)
{
temp1 = std::tan(std::abs(fmod(std::abs(a2), M_2PI / m_StarN) - T(M_PI) / m_StarN));
total2 += m_Star * std::sqrt(Sqr(m_TanStarSlope) * (1 + Sqr(temp1)) / Sqr(temp1 + m_TanStarSlope));
}
if (m_Lituus != 0)
{
total2 += m_Lituus * std::pow(std::abs(a2 / T(M_PI) + 1), m_InvLituusA);
}
if (m_Super != 0)
{
temp4 = a2 * m_SuperM4th;
sincos(temp4, &s, &c);
total2 += m_Super * std::pow(std::pow(std::abs(c), m_SuperN2) + std::pow(std::abs(s), m_SuperN3), m_OneOverSuperN1);
}
r = m_Weight * total2 * r / total;
sincos(a2, &s, &c);
helper.Out.x = r * c;
helper.Out.y = r * s;
}
else
{
helper.Out.x = m_Weight * helper.In.x;
helper.Out.y = m_Weight * helper.In.y;
}
helper.Out.z = DefaultZ(helper);
}
virtual string OpenCLString() const override
{
ostringstream ss, ss2;
intmax_t i = 0, varIndex = IndexInXform();
ss2 << "_" << XformIndexInEmber() << "]";
string index = ss2.str();
string weight = WeightDefineString();
string angle = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string hypergon = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string hypergonN = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string hypergonR = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string star = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string starN = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string starSlope = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string lituus = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string lituusA = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string super = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string superM = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string superN1 = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string superN2 = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string superN3 = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string invLituusA = "parVars[" + ToUpper(m_Params[i++].Name()) + index;//Precalc
string tanStarSlope = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string hypergonD = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string superM4th = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string oneOverSuperN1 = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
ss << "\t{\n"
<< "\t\treal_t a = precalcAtanyx;\n"
<< "\t\treal_t r = precalcSqrtSumSquares;\n"
<< "\t\treal_t a2 = a + " << angle << ";\n"
<< "\n"
<< "\t\tif (a2 < -MPI)\n"
<< "\t\t a2 += M_2PI;\n"
<< "\n"
<< "\t\tif (a2 > MPI)\n"
<< "\t\t a2 -= M_2PI;\n"
<< "\n"
<< "\t\treal_t s, c;\n"
<< "\t\treal_t total = 0;\n"
<< "\t\treal_t total2 = 0;\n"
<< "\t\treal_t temp1, temp2, temp4;\n"
<< "\n"
<< "\t\tif (" << hypergon << " != 0)\n"
<< "\t\t{\n"
<< "\t\t temp1 = fmod(fabs(a), (real_t)M_2PI / " << hypergonN << ") - MPI / " << hypergonN << ";\n"
<< "\t\t temp2 = Sqr(tan(temp1)) + 1;\n"
<< "\n"
<< "\t\t if (temp2 >= Sqr(" << hypergonD << "))\n"
<< "\t\t {\n"
<< "\t\t total += " << hypergon << ";\n"
<< "\t\t }\n"
<< "\t\t else\n"
<< "\t\t {\n"
<< "\t\t total += " << hypergon << " * (" << hypergonD << " - sqrt(fma(" << hypergonD << ", " << hypergonD << ", -temp2))) / sqrt(temp2);\n"
<< "\t\t }\n"
<< "\t\t}\n"
<< "\n"
<< "\t\tif (" << star << "!= 0)\n"
<< "\t\t{\n"
<< "\t\t temp1 = tan(fabs(fmod(fabs(a), (real_t)M_2PI / " << starN << ") - MPI / " << starN << "));\n"
<< "\t\t total += " << star << " * sqrt(Sqr(" << tanStarSlope << ") * fma(temp1, temp1, (real_t)(1.0)) / Sqr(temp1 + " << tanStarSlope << "));\n"
<< "\t\t}\n"
<< "\n"
<< "\t\tif (" << lituus << " != 0)\n"
<< "\t\t{\n"
<< "\t\t total += " << lituus << " * pow(fabs(a / MPI + 1), " << invLituusA << ");\n"
<< "\t\t}\n"
<< "\n"
<< "\t\tif (" << super << " != 0)\n"
<< "\t\t{\n"
<< "\t\t temp4 = a * " << superM4th << ";\n"
<< "\t\t s = sincos(temp4, &c);\n"
<< "\t\t total += " << super << " * pow(pow(fabs(c), " << superN2 << ") + pow(fabs(s), " << superN3 << "), " << oneOverSuperN1 << ");\n"
<< "\t\t}\n"
<< "\n"
<< "\t\tif (r <= total)\n"
<< "\t\t{\n"
<< "\t\t if (" << hypergon << " != 0.0)\n"
<< "\t\t {\n"
<< "\t\t temp1 = fmod(fabs(a2), (real_t)M_2PI / " << hypergonN << ") - MPI / " << hypergonN << ";\n"
<< "\t\t real_t tantemp = tan(temp1);\n"
<< "\t\t temp2 = fma(tantemp, tantemp, (real_t)(1.0));\n"
<< "\n"
<< "\t\t if (temp2 >= Sqr(" << hypergonD << "))\n"
<< "\t\t {\n"
<< "\t\t total2 += " << hypergon << ";\n"
<< "\t\t }\n"
<< "\t\t else\n"
<< "\t\t {\n"
<< "\t\t total2 += " << hypergon << " * (" << hypergonD << " - sqrt(fma(" << hypergonD << ", " << hypergonD << ", -temp2))) / sqrt(temp2);\n"
<< "\t\t }\n"
<< "\t\t }\n"
<< "\n"
<< "\t\t if (" << star << " != 0)\n"
<< "\t\t {\n"
<< "\t\t temp1 = tan(fabs(fmod(fabs(a2), (real_t)M_2PI / " << starN << ") - MPI / " << starN << "));\n"
<< "\t\t total2 += " << star << " * sqrt(Sqr(" << tanStarSlope << ") * fma(temp1, temp1, (real_t)(1.0)) / Sqr(temp1 + " << tanStarSlope << "));\n"
<< "\t\t }\n"
<< "\n"
<< "\t\t if (" << lituus << " != 0)\n"
<< "\t\t {\n"
<< "\t\t total2 += " << lituus << " * pow(fabs(a2 / MPI + 1), " << invLituusA << ");\n"
<< "\t\t }\n"
<< "\n"
<< "\t\t if (" << super << " != 0)\n"
<< "\t\t {\n"
<< "\t\t temp4 = a2 * " << superM4th << ";\n"
<< "\t\t s = sincos(temp4, &c);\n"
<< "\t\t total2 += " << super << " * pow(pow(fabs(c), " << superN2 << ") + pow(fabs(s), " << superN3 << "), " << oneOverSuperN1 << ");\n"
<< "\t\t }\n"
<< "\n"
<< "\t\t r = " << weight << " * total2 * r / total;\n"
<< "\t\t s = sincos(a2, &c);\n"
<< "\t\t vOut.x = r * c;\n"
<< "\t\t vOut.y = r * s;\n"
<< "\t\t}\n"
<< "\t\telse\n"
<< "\t\t{\n"
<< "\t\t vOut.x = " << weight << " * vIn.x;\n"
<< "\t\t vOut.y = " << weight << " * vIn.y;\n"
<< "\t\t}\n"
<< "\n"
<< "\t\tvOut.z = " << DefaultZCl()
<< "\t}\n";
return ss.str();
}
virtual vector<string> OpenCLGlobalFuncNames() const override
{
return vector<string> { "Sqr" };
}
virtual void Precalc() override
{
m_HypergonD = std::sqrt(1 + SQR(m_HypergonR));
m_InvLituusA = -m_LituusA;
if (IsClose(m_StarSlope, T(M_PI_2)))
m_TanStarSlope = std::tan(m_StarSlope - T(0.05));//Original did not do this, but it makes no sense to take tan(pi/2) because it's undefined.
else
m_TanStarSlope = std::tan(m_StarSlope);
m_SuperM4th = m_SuperM / 4;
m_OneOverSuperN1 = -1 / Zeps<T>(m_SuperN1);
}
protected:
void Init()
{
string prefix = Prefix();
m_Params.clear();
m_Params.push_back(ParamWithName<T>(&m_Angle, prefix + "w_angle", 0, eParamType::REAL_CYCLIC, T(-M_PI), T(M_PI)));
m_Params.push_back(ParamWithName<T>(&m_Hypergon, prefix + "w_hypergon"));
m_Params.push_back(ParamWithName<T>(&m_HypergonN, prefix + "w_hypergon_n", 4, eParamType::INTEGER, 3));
m_Params.push_back(ParamWithName<T>(&m_HypergonR, prefix + "w_hypergon_r", 1));
m_Params.push_back(ParamWithName<T>(&m_Star, prefix + "w_star"));
m_Params.push_back(ParamWithName<T>(&m_StarN, prefix + "w_star_n", 5, eParamType::INTEGER, 3));
m_Params.push_back(ParamWithName<T>(&m_StarSlope, prefix + "w_star_slope", 2, eParamType::REAL, EPS, T(M_PI_2)));
m_Params.push_back(ParamWithName<T>(&m_Lituus, prefix + "w_lituus"));
m_Params.push_back(ParamWithName<T>(&m_LituusA, prefix + "w_lituus_a", 1));
m_Params.push_back(ParamWithName<T>(&m_Super, prefix + "w_super"));
m_Params.push_back(ParamWithName<T>(&m_SuperM, prefix + "w_super_m", 1));
m_Params.push_back(ParamWithName<T>(&m_SuperN1, prefix + "w_super_n1", 1));
m_Params.push_back(ParamWithName<T>(&m_SuperN2, prefix + "w_super_n2", 1));
m_Params.push_back(ParamWithName<T>(&m_SuperN3, prefix + "w_super_n3", 1));
m_Params.push_back(ParamWithName<T>(true, &m_InvLituusA, prefix + "w_inv_lituus_a"));//Precalc
m_Params.push_back(ParamWithName<T>(true, &m_TanStarSlope, prefix + "w_tan_star_slope"));
m_Params.push_back(ParamWithName<T>(true, &m_HypergonD, prefix + "w_hypergon_d"));
m_Params.push_back(ParamWithName<T>(true, &m_SuperM4th, prefix + "w_super_m_4th"));
m_Params.push_back(ParamWithName<T>(true, &m_OneOverSuperN1, prefix + "w_one_over_super_n1"));
}
private:
T m_Angle;
T m_Hypergon;
T m_HypergonN;
T m_HypergonR;
T m_Star;
T m_StarN;
T m_StarSlope;
T m_Lituus;
T m_LituusA;
T m_Super;
T m_SuperM;
T m_SuperN1;
T m_SuperN2;
T m_SuperN3;
T m_InvLituusA;//Precalc
T m_TanStarSlope;
T m_HypergonD;
T m_SuperM4th;
T m_OneOverSuperN1;
};
template <typename T>
class XVariation : public ParametricVariation<T>
{
public:
XVariation(T weight = 1.0) : ParametricVariation<T>("x", eVariationId::VAR_X, weight, true, false, false, false, true)
{
Init();
}
PARVARCOPY(XVariation)
virtual void Func(IteratorHelper<T>& helper, Point<T>& outPoint, QTIsaac<ISAAC_SIZE, ISAAC_INT>& rand) override
{
T a = helper.m_PrecalcAtanyx;
T r;
T s, c;
T total = 0;
T temp1, temp2, temp4;
if (m_Hypergon != 0)
{
temp1 = fmod(std::abs(a), M_2PI / m_HypergonN) - T(M_PI) / m_HypergonN;
temp2 = Sqr(std::tan(temp1)) + 1;
if (temp2 >= Sqr(m_HypergonD))
{
total += m_Hypergon;
}
else
{
total += m_Hypergon * (m_HypergonD - std::sqrt(Sqr(m_HypergonD) - temp2)) / std::sqrt(temp2);
}
}
if (m_Star != 0)
{
temp1 = std::tan(std::abs(fmod(std::abs(a), M_2PI / m_StarN) - T(M_PI) / m_StarN));
total += m_Star * std::sqrt(Sqr(m_TanStarSlope) * (1 + Sqr(temp1)) / Sqr(temp1 + m_TanStarSlope));
}
if (m_Lituus != 0)
{
total += m_Lituus * std::pow(std::fabs(a / T(M_PI) + 1), m_InvLituusA);
}
if (m_Super != 0)
{
temp4 = a * m_SuperM4th;
sincos(temp4, &s, &c);
total += m_Super * std::pow(std::pow(std::abs(c), m_SuperN2) + std::pow(std::abs(s), m_SuperN3), m_OneOverSuperN1);
}
r = m_Weight * std::sqrt(helper.m_PrecalcSumSquares + Sqr(total));
sincos(a, &s, &c);
helper.Out.x = r * c;
helper.Out.y = r * s;
helper.Out.z = DefaultZ(helper);
}
virtual string OpenCLString() const override
{
ostringstream ss, ss2;
intmax_t i = 0, varIndex = IndexInXform();
ss2 << "_" << XformIndexInEmber() << "]";
string index = ss2.str();
string weight = WeightDefineString();
string hypergon = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string hypergonN = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string hypergonR = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string star = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string starN = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string starSlope = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string lituus = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string lituusA = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string super = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string superM = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string superN1 = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string superN2 = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string superN3 = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string invLituusA = "parVars[" + ToUpper(m_Params[i++].Name()) + index;//Precalc
string tanStarSlope = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string hypergonD = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string superM4th = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string oneOverSuperN1 = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
ss << "\t{\n"
<< "\t\treal_t a = precalcAtanyx;\n"
<< "\t\treal_t r;\n"
<< "\t\treal_t s, c;\n"
<< "\t\treal_t total = 0;\n"
<< "\t\treal_t temp1, temp2, temp4;\n"
<< "\n"
<< "\t\tif (" << hypergon << " != 0)\n"
<< "\t\t{\n"
<< "\t\t temp1 = fmod(fabs(a), M_2PI / " << hypergonN << ") - MPI / " << hypergonN << ";\n"
<< "\t\treal_t tantemp = tan(temp1);\n"
<< "\t\t temp2 = fma(tantemp, tantemp, (real_t)(1.0));\n"
<< "\n"
<< "\t\t if (temp2 >= Sqr(" << hypergonD << "))\n"
<< "\t\t {\n"
<< "\t\t total += " << hypergon << ";\n"
<< "\t\t }\n"
<< "\t\t else\n"
<< "\t\t {\n"
<< "\t\t total += " << hypergon << " * (" << hypergonD << " - sqrt(fma(" << hypergonD << ", " << hypergonD << ", -temp2))) / sqrt(temp2);\n"
<< "\t\t }\n"
<< "\t\t}\n"
<< "\n"
<< "\t\tif (" << star << " != 0)\n"
<< "\t\t{\n"
<< "\t\t temp1 = tan(fabs(fmod(fabs(a), M_2PI / " << starN << ") - MPI / " << starN << "));\n"
<< "\t\t total += " << star << " * sqrt(Sqr(" << tanStarSlope << ") * fma(temp1, temp1, (real_t)(1.0)) / Sqr(temp1 + " << tanStarSlope << "));\n"
<< "\t\t}\n"
<< "\n"
<< "\t\tif (" << lituus << " != 0)\n"
<< "\t\t{\n"
<< "\t\t total += " << lituus << " * pow(fabs(a / MPI + 1), " << invLituusA << ");\n"
<< "\t\t}\n"
<< "\n"
<< "\t\tif (" << super << " != 0)\n"
<< "\t\t{\n"
<< "\t\t temp4 = a * " << superM4th << ";\n"
<< "\t\t s = sincos(temp4, &c);\n"
<< "\t\t total += " << super << " * pow(pow(fabs(c), " << superN2 << ") + pow(fabs(s), " << superN3 << "), " << oneOverSuperN1 << ");\n"
<< "\t\t}\n"
<< "\n"
<< "\t\tr = " << weight << " * sqrt(fma(total, total, precalcSumSquares));\n"
<< "\t\ts = sincos(a, &c);\n"
<< "\t\tvOut.x = r * c;\n"
<< "\t\tvOut.y = r * s;\n"
<< "\t\tvOut.z = " << DefaultZCl()
<< "\t}\n";
return ss.str();
}
virtual vector<string> OpenCLGlobalFuncNames() const override
{
return vector<string> { "Sqr" };
}
virtual void Precalc() override
{
m_HypergonD = std::sqrt(1 + SQR(m_HypergonR));
m_InvLituusA = -m_LituusA;
if (IsClose(m_StarSlope, T(M_PI_2)))
m_TanStarSlope = std::tan(m_StarSlope - T(0.05));//Original did not do this, but it makes no sense to take tan(pi/2) because it's undefined.
else
m_TanStarSlope = std::tan(m_StarSlope);
m_SuperM4th = m_SuperM / 4;
m_OneOverSuperN1 = -1 / Zeps<T>(m_SuperN1);
}
protected:
void Init()
{
string prefix = Prefix();
m_Params.clear();
m_Params.push_back(ParamWithName<T>(&m_Hypergon, prefix + "x_hypergon"));
m_Params.push_back(ParamWithName<T>(&m_HypergonN, prefix + "x_hypergon_n", 4, eParamType::INTEGER, 3));
m_Params.push_back(ParamWithName<T>(&m_HypergonR, prefix + "x_hypergon_r", 1));
m_Params.push_back(ParamWithName<T>(&m_Star, prefix + "x_star"));
m_Params.push_back(ParamWithName<T>(&m_StarN, prefix + "x_star_n", 5, eParamType::INTEGER, 3));
m_Params.push_back(ParamWithName<T>(&m_StarSlope, prefix + "x_star_slope", 2, eParamType::REAL, EPS, T(M_PI_2)));
m_Params.push_back(ParamWithName<T>(&m_Lituus, prefix + "x_lituus"));
m_Params.push_back(ParamWithName<T>(&m_LituusA, prefix + "x_lituus_a", 1));
m_Params.push_back(ParamWithName<T>(&m_Super, prefix + "x_super"));
m_Params.push_back(ParamWithName<T>(&m_SuperM, prefix + "x_super_m", 1));
m_Params.push_back(ParamWithName<T>(&m_SuperN1, prefix + "x_super_n1", 1));
m_Params.push_back(ParamWithName<T>(&m_SuperN2, prefix + "x_super_n2", 1));
m_Params.push_back(ParamWithName<T>(&m_SuperN3, prefix + "x_super_n3", 1));
m_Params.push_back(ParamWithName<T>(true, &m_InvLituusA, prefix + "x_inv_lituus_a"));//Precalc
m_Params.push_back(ParamWithName<T>(true, &m_TanStarSlope, prefix + "x_tan_star_slope"));
m_Params.push_back(ParamWithName<T>(true, &m_HypergonD, prefix + "x_hypergon_d"));
m_Params.push_back(ParamWithName<T>(true, &m_SuperM4th, prefix + "x_super_m_4th"));
m_Params.push_back(ParamWithName<T>(true, &m_OneOverSuperN1, prefix + "x_one_over_super_n1"));
}
private:
T m_Hypergon;
T m_HypergonN;
T m_HypergonR;
T m_Star;
T m_StarN;
T m_StarSlope;
T m_Lituus;
T m_LituusA;
T m_Super;
T m_SuperM;
T m_SuperN1;
T m_SuperN2;
T m_SuperN3;
T m_InvLituusA;//Precalc
T m_TanStarSlope;
T m_HypergonD;
T m_SuperM4th;
T m_OneOverSuperN1;
};
template <typename T>
class YVariation : public ParametricVariation<T>
{
public:
YVariation(T weight = 1.0) : ParametricVariation<T>("y", eVariationId::VAR_Y, weight, true, true, false, false, true)
{
Init();
}
PARVARCOPY(YVariation)
virtual void Func(IteratorHelper<T>& helper, Point<T>& outPoint, QTIsaac<ISAAC_SIZE, ISAAC_INT>& rand) override
{
T a = helper.m_PrecalcAtanyx;
T r;
T s, c;
T total = 0;
T temp1, temp2, temp4;
if (m_Hypergon != 0)
{
temp1 = fmod(std::abs(a), M_2PI / m_HypergonN) - T(M_PI) / m_HypergonN;
temp2 = Sqr(std::tan(temp1)) + 1;
auto hd2 = SQR(m_HypergonD);
if (temp2 >= hd2)
{
total += m_Hypergon;
}
else
{
total += m_Hypergon * (m_HypergonD - std::sqrt(hd2 - temp2)) / std::sqrt(temp2);
}
}
if (m_Star != 0)
{
temp1 = std::tan(std::abs(fmod(std::abs(a), M_2PI / m_StarN) - T(M_PI) / m_StarN));
total += m_Star * std::sqrt(Sqr(m_TanStarSlope) * (1 + Sqr(temp1)) / Sqr(temp1 + m_TanStarSlope));
}
if (m_Lituus != 0)
{
total += m_Lituus * std::pow(std::abs(a / T(M_PI) + 1), m_InvLituusA);
}
if (m_Super != 0)
{
temp4 = a * m_SuperM4th;
sincos(temp4, &s, &c);
total += m_Super * std::pow(std::pow(std::abs(c), m_SuperN2) + std::pow(std::abs(s), m_SuperN3), m_OneOverSuperN1);
}
r = m_Weight * Sqr(total) / helper.m_PrecalcSqrtSumSquares;
sincos(a, &s, &c);
helper.Out.x = r * c;
helper.Out.y = r * s;
helper.Out.z = DefaultZ(helper);
}
virtual string OpenCLString() const override
{
ostringstream ss, ss2;
intmax_t i = 0, varIndex = IndexInXform();
ss2 << "_" << XformIndexInEmber() << "]";
string index = ss2.str();
string weight = WeightDefineString();
string hypergon = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string hypergonN = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string hypergonR = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string star = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string starN = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string starSlope = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string lituus = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string lituusA = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string super = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string superM = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string superN1 = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string superN2 = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string superN3 = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string invLituusA = "parVars[" + ToUpper(m_Params[i++].Name()) + index;//Precalc
string tanStarSlope = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string hypergonD = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string superM4th = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string oneOverSuperN1 = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
ss << "\t{\n"
<< "\t\treal_t a = precalcAtanyx;\n"
<< "\t\treal_t r;\n"
<< "\t\treal_t s, c;\n"
<< "\t\treal_t total = 0;\n"
<< "\t\treal_t temp1, temp2, temp4;\n"
<< "\n"
<< "\t\tif (" << hypergon << " != 0)\n"
<< "\t\t{\n"
<< "\t\t temp1 = fmod(fabs(a), M_2PI / " << hypergonN << ") - MPI / " << hypergonN << ";\n"
<< "\t\t temp2 = Sqr(tan(temp1)) + 1;\n"
<< "\t\t real_t hd2 = SQR(" << hypergonD << ");\n"
<< "\n"
<< "\t\t if (temp2 >= hd2)\n"
<< "\t\t {\n"
<< "\t\t total += " << hypergon << ";\n"
<< "\t\t }\n"
<< "\t\t else\n"
<< "\t\t {\n"
<< "\t\t total += " << hypergon << " * (" << hypergonD << " - sqrt(hd2 - temp2)) / sqrt(temp2);\n"
<< "\t\t }\n"
<< "\t\t}\n"
<< "\n"
<< "\t\tif (" << star << " != 0)\n"
<< "\t\t{\n"
<< "\t\t temp1 = tan(fabs(fmod(fabs(a), M_2PI / " << starN << ") - MPI / " << starN << "));\n"
<< "\t\t total += " << star << " * sqrt(Sqr(" << tanStarSlope << ") * fma(temp1, temp1, (real_t)(1.0)) / Sqr(temp1 + " << tanStarSlope << "));\n"
<< "\t\t}\n"
<< "\n"
<< "\t\tif (" << lituus << " != 0)\n"
<< "\t\t{\n"
<< "\t\t total += " << lituus << " * pow(fabs(a / MPI + 1), " << invLituusA << ");\n"
<< "\t\t}\n"
<< "\n"
<< "\t\tif (" << super << " != 0)\n"
<< "\t\t{\n"
<< "\t\t temp4 = a * " << superM4th << ";\n"
<< "\t\t s = sincos(temp4, &c);\n"
<< "\t\t total += " << super << " * pow(pow(fabs(c), " << superN2 << ") + pow(fabs(s), " << superN3 << "), " << oneOverSuperN1 << ");\n"
<< "\t\t}\n"
<< "\n"
<< "\t\tr = " << weight << " * Sqr(total) / precalcSqrtSumSquares;\n"
<< "\t\ts = sincos(a, &c);\n"
<< "\t\tvOut.x = r * c;\n"
<< "\t\tvOut.y = r * s;\n"
<< "\t\tvOut.z = " << DefaultZCl()
<< "\t}\n";
return ss.str();
}
virtual vector<string> OpenCLGlobalFuncNames() const override
{
return vector<string> { "Sqr" };
}
virtual void Precalc() override
{
m_HypergonD = std::sqrt(1 + SQR(m_HypergonR));
m_InvLituusA = -m_LituusA;
if (IsClose(m_StarSlope, T(M_PI_2)))
m_TanStarSlope = std::tan(m_StarSlope - T(0.05));//Original did not do this, but it makes no sense to take tan(pi/2) because it's undefined.
else
m_TanStarSlope = std::tan(m_StarSlope);
m_SuperM4th = m_SuperM / 4;
m_OneOverSuperN1 = -1 / Zeps<T>(m_SuperN1);
}
protected:
void Init()
{
string prefix = Prefix();
m_Params.clear();
m_Params.push_back(ParamWithName<T>(&m_Hypergon, prefix + "y_hypergon"));
m_Params.push_back(ParamWithName<T>(&m_HypergonN, prefix + "y_hypergon_n", 4, eParamType::INTEGER, 3));
m_Params.push_back(ParamWithName<T>(&m_HypergonR, prefix + "y_hypergon_r", 1));
m_Params.push_back(ParamWithName<T>(&m_Star, prefix + "y_star"));
m_Params.push_back(ParamWithName<T>(&m_StarN, prefix + "y_star_n", 5, eParamType::INTEGER, 3));
m_Params.push_back(ParamWithName<T>(&m_StarSlope, prefix + "y_star_slope", 2, eParamType::REAL, EPS, T(M_PI_2)));
m_Params.push_back(ParamWithName<T>(&m_Lituus, prefix + "y_lituus"));
m_Params.push_back(ParamWithName<T>(&m_LituusA, prefix + "y_lituus_a", 1));
m_Params.push_back(ParamWithName<T>(&m_Super, prefix + "y_super"));
m_Params.push_back(ParamWithName<T>(&m_SuperM, prefix + "y_super_m", 1));
m_Params.push_back(ParamWithName<T>(&m_SuperN1, prefix + "y_super_n1", 1));
m_Params.push_back(ParamWithName<T>(&m_SuperN2, prefix + "y_super_n2", 1));
m_Params.push_back(ParamWithName<T>(&m_SuperN3, prefix + "y_super_n3", 1));
m_Params.push_back(ParamWithName<T>(true, &m_InvLituusA, prefix + "y_inv_lituus_a"));//Precalc
m_Params.push_back(ParamWithName<T>(true, &m_TanStarSlope, prefix + "y_tan_star_slope"));
m_Params.push_back(ParamWithName<T>(true, &m_HypergonD, prefix + "y_hypergon_d"));
m_Params.push_back(ParamWithName<T>(true, &m_SuperM4th, prefix + "y_super_m_4th"));
m_Params.push_back(ParamWithName<T>(true, &m_OneOverSuperN1, prefix + "y_one_over_super_n1"));
}
private:
T m_Hypergon;
T m_HypergonN;
T m_HypergonR;
T m_Star;
T m_StarN;
T m_StarSlope;
T m_Lituus;
T m_LituusA;
T m_Super;
T m_SuperM;
T m_SuperN1;
T m_SuperN2;
T m_SuperN3;
T m_InvLituusA;//Precalc
T m_TanStarSlope;
T m_HypergonD;
T m_SuperM4th;
T m_OneOverSuperN1;
};
template <typename T>
class ZVariation : public ParametricVariation<T>
{
public:
ZVariation(T weight = 1.0) : ParametricVariation<T>("z", eVariationId::VAR_Z, weight, true, true, false, false, true)
{
Init();
}
PARVARCOPY(ZVariation)
virtual void Func(IteratorHelper<T>& helper, Point<T>& outPoint, QTIsaac<ISAAC_SIZE, ISAAC_INT>& rand) override
{
T a = helper.m_PrecalcAtanyx;
T r;
T s, c;
T total = 0;
T temp1, temp2, temp4;
if (m_Hypergon != 0)
{
temp1 = fmod(std::abs(a), M_2PI / m_HypergonN) - T(M_PI) / m_HypergonN;
temp2 = Sqr(std::tan(temp1)) + 1;
auto hd2 = SQR(m_HypergonD);
if (temp2 >= hd2)
{
total += m_Hypergon;
}
else
{
total += m_Hypergon * (m_HypergonD - std::sqrt(hd2 - temp2)) / std::sqrt(temp2);
}
}
if (m_Star != 0)
{
temp1 = std::tan(std::abs(fmod(std::abs(a), M_2PI / m_StarN) - T(M_PI) / m_StarN));
total += m_Star * std::sqrt(Sqr(m_TanStarSlope) * (1 + Sqr(temp1)) / Sqr(temp1 + m_TanStarSlope));
}
if (m_Lituus != 0)
{
total += m_Lituus * std::pow(std::abs(a / T(M_PI) + 1), m_InvLituusA);
}
if (m_Super != 0)
{
temp4 = a * m_SuperM4th;
sincos(temp4, &s, &c);
total += m_Super * std::pow(std::pow(std::abs(c), m_SuperN2) + std::pow(std::abs(s), m_SuperN3), m_OneOverSuperN1);
}
r = m_Weight * (helper.m_PrecalcSqrtSumSquares + total);
sincos(a, &s, &c);
helper.Out.x = r * c;
helper.Out.y = r * s;
helper.Out.z = DefaultZ(helper);
}
virtual string OpenCLString() const override
{
ostringstream ss, ss2;
intmax_t i = 0, varIndex = IndexInXform();
ss2 << "_" << XformIndexInEmber() << "]";
string index = ss2.str();
string weight = WeightDefineString();
string hypergon = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string hypergonN = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string hypergonR = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string star = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string starN = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string starSlope = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string lituus = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string lituusA = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string super = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string superM = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string superN1 = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string superN2 = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string superN3 = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string invLituusA = "parVars[" + ToUpper(m_Params[i++].Name()) + index;//Precalc
string tanStarSlope = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string hypergonD = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string superM4th = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string oneOverSuperN1 = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
ss << "\t{\n"
<< "\t\treal_t a = precalcAtanyx;\n"
<< "\t\treal_t a90 = atan2(vIn.x, -vIn.y);\n"
<< "\t\treal_t r;\n"
<< "\t\treal_t s, c;\n"
<< "\t\treal_t total = 0;\n"
<< "\t\treal_t temp1, temp2, temp4;\n"
<< "\n"
<< "\t\tif (" << hypergon << " != 0)\n"
<< "\t\t{\n"
<< "\t\t temp1 = fmod(fabs(a), M_2PI / " << hypergonN << ") - MPI / " << hypergonN << ";\n"
<< "\t\t temp2 = Sqr(tan(temp1)) + 1;\n"
<< "\t\t real_t hd2 = SQR(" << hypergonD << ");\n"
<< "\n"
<< "\t\t if (temp2 >= hd2)\n"
<< "\t\t {\n"
<< "\t\t total += " << hypergon << ";\n"
<< "\t\t }\n"
<< "\t\t else\n"
<< "\t\t {\n"
<< "\t\t total += " << hypergon << " * (" << hypergonD << " - sqrt(hd2 - temp2)) / sqrt(temp2);\n"
<< "\t\t }\n"
<< "\t\t}\n"
<< "\n"
<< "\t\tif (" << star << " != 0)\n"
<< "\t\t{\n"
<< "\t\t temp1 = tan(fabs(fmod(fabs(a), M_2PI / " << starN << ") - MPI / " << starN << "));\n"
<< "\t\t total += " << star << " * sqrt(Sqr(" << tanStarSlope << ") * fma(temp1, temp1, (real_t)(1.0)) / Sqr(temp1 + " << tanStarSlope << "));\n"
<< "\t\t}\n"
<< "\n"
<< "\t\tif (" << lituus << " != 0)\n"
<< "\t\t{\n"
<< "\t\t total += " << lituus << " * pow(fabs(a / MPI + 1), " << invLituusA << ");\n"
<< "\t\t}\n"
<< "\n"
<< "\t\tif (" << super << " != 0)\n"
<< "\t\t{\n"
<< "\t\t temp4 = a * " << superM4th << ";\n"
<< "\t\t s = sincos(temp4, &c);\n"
<< "\t\t total += " << super << " * pow(pow(fabs(c), " << superN2 << ") + pow(fabs(s), " << superN3 << "), " << oneOverSuperN1 << ");\n"
<< "\t\t}\n"
<< "\n"
<< "\t\tr = " << weight << " * (precalcSqrtSumSquares + total);\n"
<< "\t\ts = sincos(a, &c);\n"
<< "\t\tvOut.x = r * c;\n"
<< "\t\tvOut.y = r * s;\n"
<< "\t\tvOut.z = " << DefaultZCl()
<< "\t}\n";
return ss.str();
}
virtual vector<string> OpenCLGlobalFuncNames() const override
{
return vector<string> { "Sqr" };
}
virtual void Precalc() override
{
m_HypergonD = std::sqrt(1 + SQR(m_HypergonR));
m_InvLituusA = -m_LituusA;
if (IsClose(m_StarSlope, T(M_PI_2)))
m_TanStarSlope = std::tan(m_StarSlope - T(0.05));//Original did not do this, but it makes no sense to take tan(pi/2) because it's undefined.
else
m_TanStarSlope = std::tan(m_StarSlope);
m_SuperM4th = m_SuperM / 4;
m_OneOverSuperN1 = -1 / Zeps<T>(m_SuperN1);
}
protected:
void Init()
{
string prefix = Prefix();
m_Params.clear();
m_Params.push_back(ParamWithName<T>(&m_Hypergon, prefix + "z_hypergon"));
m_Params.push_back(ParamWithName<T>(&m_HypergonN, prefix + "z_hypergon_n", 4, eParamType::INTEGER, 3));
m_Params.push_back(ParamWithName<T>(&m_HypergonR, prefix + "z_hypergon_r", 1));
m_Params.push_back(ParamWithName<T>(&m_Star, prefix + "z_star"));
m_Params.push_back(ParamWithName<T>(&m_StarN, prefix + "z_star_n", 5, eParamType::INTEGER, 3));
m_Params.push_back(ParamWithName<T>(&m_StarSlope, prefix + "z_star_slope", 2, eParamType::REAL, EPS, T(M_PI_2)));
m_Params.push_back(ParamWithName<T>(&m_Lituus, prefix + "z_lituus"));
m_Params.push_back(ParamWithName<T>(&m_LituusA, prefix + "z_lituus_a", 1));
m_Params.push_back(ParamWithName<T>(&m_Super, prefix + "z_super"));
m_Params.push_back(ParamWithName<T>(&m_SuperM, prefix + "z_super_m", 1));
m_Params.push_back(ParamWithName<T>(&m_SuperN1, prefix + "z_super_n1", 1));
m_Params.push_back(ParamWithName<T>(&m_SuperN2, prefix + "z_super_n2", 1));
m_Params.push_back(ParamWithName<T>(&m_SuperN3, prefix + "z_super_n3", 1));
m_Params.push_back(ParamWithName<T>(true, &m_InvLituusA, prefix + "z_inv_lituus_a"));//Precalc
m_Params.push_back(ParamWithName<T>(true, &m_TanStarSlope, prefix + "z_tan_star_slope"));
m_Params.push_back(ParamWithName<T>(true, &m_HypergonD, prefix + "z_hypergon_d"));
m_Params.push_back(ParamWithName<T>(true, &m_SuperM4th, prefix + "z_super_m_4th"));
m_Params.push_back(ParamWithName<T>(true, &m_OneOverSuperN1, prefix + "z_one_over_super_n1"));
}
private:
T m_Hypergon;
T m_HypergonN;
T m_HypergonR;
T m_Star;
T m_StarN;
T m_StarSlope;
T m_Lituus;
T m_LituusA;
T m_Super;
T m_SuperM;
T m_SuperN1;
T m_SuperN2;
T m_SuperN3;
T m_InvLituusA;//Precalc
T m_TanStarSlope;
T m_HypergonD;
T m_SuperM4th;
T m_OneOverSuperN1;
};
MAKEPREPOSTPARVAR(Hexes, hexes, HEXES)
MAKEPREPOSTPARVAR(Nblur, nBlur, NBLUR)
MAKEPREPOSTPARVAR(Octapol, octapol, OCTAPOL)
MAKEPREPOSTPARVAR(Crob, crob, CROB)
MAKEPREPOSTPARVAR(BubbleT3D, bubbleT3D, BUBBLET3D)
MAKEPREPOSTPARVAR(Synth, synth, SYNTH)
MAKEPREPOSTPARVAR(Crackle, crackle, CRACKLE)
MAKEPREPOSTPARVAR(Crackle2, crackle2, CRACKLE2)
MAKEPREPOSTVAR(Erf, erf, ERF)
MAKEPREPOSTVAR(Xerf, xerf, XERF)
MAKEPREPOSTPARVAR(W, w, W)
MAKEPREPOSTPARVAR(X, x, X)
MAKEPREPOSTPARVAR(Y, y, Y)
MAKEPREPOSTPARVAR(Z, z, Z)
}