fractorium/Source/Ember/Variations06.h
Person c3078f018a --User changes
-Update various tooltips.
 -Increase precision of affine and xaos spinners.
 -Increase precision of fields written in Xml files to 8.

--Bug fixes
 -When rendering on the CPU, if the number of threads didn't divide evenly into the number of rows, it would leave a blank spot on the last few rows.
 -Fix numerous parsing bugs when reading .chaos files.
 -Added compatibility fixes and/or optimizations to the following variations: asteria, bcircle, bcollide, bipolar, blob2, btransform, cell, circlecrop, circlecrop2, collideoscope, cpow2, cropn, cross, curl, depth_ngon2, depth_sine2, edisc, eRotate, escher, fan2, hex_rand, hypershift, hypershift2, hypertile1, julia, julian, julian2, juliaq, juliascope, lazyjess, log, loonie2, murl, murl2, npolar, oscilloscope2, perspective, phoenix_julia, sphericaln, squish, starblur, starblur2, truchet, truchet_glyph, waffle, wavesn.
2023-11-29 15:47:31 -07:00

5523 lines
192 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;
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 * 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;
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"));//Precalc.
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;
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;
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(Floor(u.x / m_HalfCellSize));
cv.y = int(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;
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"));//Precalc.
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;
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"));//Precalc.
}
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;
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::REAL, -1, 2));
m_Params.push_back(ParamWithName<T>(&m_Static, prefix + "smartcrop_static", 1, eParamType::REAL, -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;
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;
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;
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;
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;
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;
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)
}