#pragma once
#include "Variation.h"
namespace EmberNs
{
///
/// bubble2.
///
template
class EMBER_API Bubble2Variation : public ParametricVariation
{
public:
Bubble2Variation(T weight = 1.0) : ParametricVariation("bubble2", VAR_BUBBLE2, weight, true)
{
Init();
}
PARVARCOPY(Bubble2Variation)
virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override
{
T t = T(0.25) * (helper.m_PrecalcSumSquares + SQR(helper.In.z)) + 1;
T r = m_Weight / t;
helper.Out.x = helper.In.x * r * m_X;
helper.Out.y = helper.In.y * r * m_Y;
if (helper.In.z >= 0)
helper.Out.z = m_Weight * (helper.In.z + m_Z);
else
helper.Out.z = m_Weight * (helper.In.z - m_Z);
helper.Out.z += helper.In.z * r * m_Z;//The += is intentional.
}
virtual string OpenCLString() const override
{
ostringstream ss, ss2;
intmax_t i = 0, varIndex = IndexInXform();
ss2 << "_" << XformIndexInEmber() << "]";
string index = ss2.str();
string x = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string y = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string z = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
ss << "\t{\n"
<< "\t\treal_t t = (real_t)(0.25) * (precalcSumSquares + SQR(vIn.z)) + 1;\n"
<< "\t\treal_t r = xform->m_VariationWeights[" << varIndex << "] / t;\n"
<< "\n"
<< "\t\tvOut.x = vIn.x * r * " << x << ";\n"
<< "\t\tvOut.y = vIn.y * r * " << y << ";\n"
<< "\n"
<< "\t\tif (vIn.z >= 0)\n"
<< "\t\t vOut.z = xform->m_VariationWeights[" << varIndex << "] * (vIn.z + " << z << ");\n"
<< "\t\telse\n"
<< "\t\t vOut.z = xform->m_VariationWeights[" << varIndex << "] * (vIn.z - " << z << ");\n"
<< "\n"
<< "\t\tvOut.z += vIn.z * r * " << z << ";\n"
<< "\t}\n";
return ss.str();
}
protected:
void Init()
{
string prefix = Prefix();
m_Params.clear();
m_Params.push_back(ParamWithName(&m_X, prefix + "bubble2_x", 1));//Original used a prefix of bubble_, which is incompatible with Ember's design.
m_Params.push_back(ParamWithName(&m_Y, prefix + "bubble2_y", 1));
m_Params.push_back(ParamWithName(&m_Z, prefix + "bubble2_z"));
}
private:
T m_X;
T m_Y;
T m_Z;
};
///
/// CircleLinear.
///
template
class EMBER_API CircleLinearVariation : public ParametricVariation
{
public:
CircleLinearVariation(T weight = 1.0) : ParametricVariation("CircleLinear", VAR_CIRCLELINEAR, weight)
{
Init();
}
PARVARCOPY(CircleLinearVariation)
virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override
{
int m = int(Floor(T(0.5) * helper.In.x / m_Sc));
int n = int(Floor(T(0.5) * helper.In.y / m_Sc));
T x = helper.In.x - (m * 2 + 1) * m_Sc;
T y = helper.In.y - (n * 2 + 1) * m_Sc;
T u = Zeps(Hypot(x, y));
T v = (T(0.3) + T(0.7) * DiscreteNoise2(m + 10, n + 3)) * m_Sc;
T z1 = DiscreteNoise2(int(m + m_Seed), n);
if ((z1 < m_Dens1) && (u < v))
{
if (m_Reverse > 0)
{
if (z1 < m_Dens1 * m_Dens2)
{
x *= m_K;
y *= m_K;
}
else
{
T z = v / u * (1 - m_K) + m_K;
x *= z;
y *= z;
}
}
else
{
if (z1 > m_Dens1 * m_Dens2)
{
x *= m_K;
y *= m_K;
}
else
{
T z = v / u * (1 - m_K) + m_K;
x *= z;
y *= z;
}
}
}
helper.Out.x = m_Weight * (x + (m * 2 + 1) * m_Sc);
helper.Out.y = m_Weight * (y + (n * 2 + 1) * m_Sc);
helper.Out.z = (m_VarType == VARTYPE_REG) ? 0 : helper.In.z;
}
virtual string OpenCLString() const override
{
ostringstream ss, ss2;
intmax_t i = 0, varIndex = IndexInXform();
ss2 << "_" << XformIndexInEmber() << "]";
string index = ss2.str();
string sc = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string k = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string dens1 = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string dens2 = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string reverse = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string x = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string y = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string seed = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
ss << "\t{\n"
<< "\t\tint m = (int)floor((real_t)(0.5) * vIn.x / " << sc << ");\n"
<< "\t\tint n = (int)floor((real_t)(0.5) * vIn.y / " << sc << ");\n"
<< "\t\treal_t x = vIn.x - (m * 2 + 1) * " << sc << ";\n"
<< "\t\treal_t y = vIn.y - (n * 2 + 1) * " << sc << ";\n"
<< "\t\treal_t u = Zeps(Hypot(x, y));\n"
<< "\t\treal_t v = ((real_t)(0.3) + (real_t)(0.7) * CircleLinearDiscreteNoise2(m + 10, n + 3)) * " << sc << ";\n"
<< "\t\treal_t z1 = CircleLinearDiscreteNoise2((int)(m + " << seed << "), n);\n"
<< "\n"
<< "\t\tif ((z1 < " << dens1 << ") && (u < v))\n"
<< "\t\t{\n"
<< "\t\t if (" << reverse << " > 0)\n"
<< "\t\t {\n"
<< "\t\t if (z1 < " << dens1 << " * " << dens2 << ")\n"
<< "\t\t {\n"
<< "\t\t x *= " << k << ";\n"
<< "\t\t y *= " << k << ";\n"
<< "\t\t }\n"
<< "\t\t else\n"
<< "\t\t {\n"
<< "\t\t real_t z = v / u * (1 - " << k << ") + " << k << ";\n"
<< "\n"
<< "\t\t x *= z;\n"
<< "\t\t y *= z;\n"
<< "\t\t }\n"
<< "\t\t }\n"
<< "\t\t else\n"
<< "\t\t {\n"
<< "\t\t if (z1 > " << dens1 << " * " << dens2 << ")\n"
<< "\t\t {\n"
<< "\t\t x *= " << k << ";\n"
<< "\t\t y *= " << k << ";\n"
<< "\t\t }\n"
<< "\t\t else\n"
<< "\t\t {\n"
<< "\t\t real_t z = v / u * (1 - " << k << ") + " << k << ";\n"
<< "\n"
<< "\t\t x *= z;\n"
<< "\t\t y *= z;\n"
<< "\t\t }\n"
<< "\t\t }\n"
<< "\t\t}\n"
<< "\n"
<< "\t\tvOut.x = xform->m_VariationWeights[" << varIndex << "] * (x + (m * 2 + 1) * " << sc << ");\n"
<< "\t\tvOut.y = xform->m_VariationWeights[" << varIndex << "] * (y + (n * 2 + 1) * " << sc << ");\n"
<< "\t\tvOut.z = " << ((m_VarType == VARTYPE_REG) ? "0" : "vIn.z") << ";\n"
<< "\t}\n";
return ss.str();
}
virtual vector OpenCLGlobalFuncNames() const override
{
return vector { "Hypot", "Zeps" };
}
virtual string OpenCLFuncsString() const override
{
return
"real_t CircleLinearDiscreteNoise2(int x, int y)\n"
"{\n"
" const real_t im = 2147483647;\n"
" const real_t am = 1 / im;\n"
"\n"
" int n = x + y * 57;\n"
" n = (n << 13) ^ n;\n"
" return ((n * (n * n * 15731 + 789221) + 1376312589) & 0x7fffffff) * am;\n"
"}\n"
"\n";
}
protected:
void Init()
{
string prefix = Prefix();
m_Params.clear();
m_Params.push_back(ParamWithName(&m_Sc, prefix + "CircleLinear_Sc", 1, REAL_NONZERO));
m_Params.push_back(ParamWithName(&m_K, prefix + "CircleLinear_K", T(0.5)));
m_Params.push_back(ParamWithName(&m_Dens1, prefix + "CircleLinear_Dens1", T(0.5)));
m_Params.push_back(ParamWithName(&m_Dens2, prefix + "CircleLinear_Dens2", T(0.5)));
m_Params.push_back(ParamWithName(&m_Reverse, prefix + "CircleLinear_Reverse", 1));
m_Params.push_back(ParamWithName(&m_X, prefix + "CircleLinear_X", 10));
m_Params.push_back(ParamWithName(&m_Y, prefix + "CircleLinear_Y", 10));
m_Params.push_back(ParamWithName(&m_Seed, prefix + "CircleLinear_Seed", 0, INTEGER));
}
private:
T DiscreteNoise2(int x, int y)
{
const T im = T(2147483647);
const T am = (1 / im);
int n = x + y * 57;
n = (n << 13) ^ n;
return ((n * (n * n * 15731 + 789221) + 1376312589) & 0x7fffffff) * am;
}
T m_Sc;
T m_K;
T m_Dens1;
T m_Dens2;
T m_Reverse;
T m_X;
T m_Y;
T m_Seed;
};
///
/// CircleRand.
/// The original would loop infinitely as x and y approached zero, so put a check for a max of 10 iters.
///
template
class EMBER_API CircleRandVariation : public ParametricVariation
{
public:
CircleRandVariation(T weight = 1.0) : ParametricVariation("CircleRand", VAR_CIRCLERAND, weight)
{
Init();
}
PARVARCOPY(CircleRandVariation)
virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override
{
intmax_t m, n, iters = 0;
T x, y, u;
do
{
x = m_X * (1 - 2 * rand.Frand01());
y = m_Y * (1 - 2 * rand.Frand01());
m = Floor(T(0.5) * x / m_Sc);
n = Floor(T(0.5) * y / m_Sc);
x -= (m * 2 + 1) * m_Sc;
y -= (n * 2 + 1) * m_Sc;
u = Hypot(x, y);
if (++iters > 10)
break;
}
while ((DiscreteNoise2(int(m + m_Seed), int(n)) > m_Dens) || (u > (T(0.3) + T(0.7) * DiscreteNoise2(int(m + 10), int(n + 3))) * m_Sc));
helper.Out.x = m_Weight * (x + (m * 2 + 1) * m_Sc);
helper.Out.y = m_Weight * (y + (n * 2 + 1) * m_Sc);
helper.Out.z = (m_VarType == VARTYPE_REG) ? 0 : helper.In.z;
}
virtual string OpenCLString() const override
{
ostringstream ss, ss2;
intmax_t i = 0, varIndex = IndexInXform();
ss2 << "_" << XformIndexInEmber() << "]";
string index = ss2.str();
string sc = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string dens = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string x = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string y = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string seed = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
ss << "\t{\n"
<< "\t\tint m, n, iters = 0;\n"
<< "\t\treal_t x, y, u;\n"
<< "\n"
<< "\t\tdo\n"
<< "\t\t{\n"
<< "\t\t x = " << x << " * (1 - 2 * MwcNext01(mwc));\n"
<< "\t\t y = " << y << " * (1 - 2 * MwcNext01(mwc));\n"
<< "\t\t m = (int)floor((real_t)(0.5) * x / " << sc << ");\n"
<< "\t\t n = (int)floor((real_t)(0.5) * y / " << sc << ");\n"
<< "\t\t x = x - (m * 2 + 1) * " << sc << ";\n"
<< "\t\t y = y - (n * 2 + 1) * " << sc << ";\n"
<< "\t\t u = Hypot(x, y);\n"
<< "\n"
<< "\t\t if (++iters > 10)\n"
<< "\t\t break;\n"
<< "\t\t}\n"
<< "\t\twhile ((CircleRandDiscreteNoise2((int)(m + " << seed << "), n) > " << dens << ") || (u > ((real_t)(0.3) + (real_t)(0.7) * CircleRandDiscreteNoise2(m + 10, n + 3)) * " << sc << "));\n"
<< "\n"
<< "\t\tvOut.x = xform->m_VariationWeights[" << varIndex << "] * (x + (m * 2 + 1) * " << sc << ");\n"
<< "\t\tvOut.y = xform->m_VariationWeights[" << varIndex << "] * (y + (n * 2 + 1) * " << sc << ");\n"
<< "\t\tvOut.z = " << ((m_VarType == VARTYPE_REG) ? "0" : "vIn.z") << ";\n"
<< "\t}\n";
return ss.str();
}
virtual vector OpenCLGlobalFuncNames() const override
{
return vector { "Hypot" };
}
virtual string OpenCLFuncsString() const override
{
return
"real_t CircleRandDiscreteNoise2(int x, int y)\n"
"{\n"
" const real_t im = 2147483647;\n"
" const real_t am = 1 / im;\n"
"\n"
" int n = x + y * 57;\n"
" n = (n << 13) ^ n;\n"
" return ((n * (n * n * 15731 + 789221) + 1376312589) & 0x7fffffff) * am;\n"
"}\n"
"\n";
}
protected:
void Init()
{
string prefix = Prefix();
m_Params.clear();
m_Params.push_back(ParamWithName(&m_Sc, prefix + "CircleRand_Sc", 1, REAL_NONZERO));
m_Params.push_back(ParamWithName(&m_Dens, prefix + "CircleRand_Dens", T(0.5)));
m_Params.push_back(ParamWithName(&m_X, prefix + "CircleRand_X", 10));
m_Params.push_back(ParamWithName(&m_Y, prefix + "CircleRand_Y", 10));
m_Params.push_back(ParamWithName(&m_Seed, prefix + "CircleRand_Seed", 0, INTEGER));
}
private:
T DiscreteNoise2(int x, int y)
{
const T im = T(2147483647);
const T am = (1 / im);
int n = x + y * 57;
n = (n << 13) ^ n;
return ((n * (n * n * 15731 + 789221) + 1376312589) & 0x7fffffff) * am;
}
T m_Sc;
T m_Dens;
T m_X;
T m_Y;
T m_Seed;
};
///
/// CircleTrans1.
/// The original would loop infinitely as x and y approached zero, so put a check for a max of 10 iters.
///
template
class EMBER_API CircleTrans1Variation : public ParametricVariation
{
public:
CircleTrans1Variation(T weight = 1.0) : ParametricVariation("CircleTrans1", VAR_CIRCLETRANS1, weight)
{
Init();
}
PARVARCOPY(CircleTrans1Variation)
virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override
{
T ux, uy, u, x, y;
Trans(m_X, m_Y, helper.In.x, helper.In.y, &ux, &uy);
intmax_t m = Floor(T(0.5) * ux / m_Sc);
intmax_t n = Floor(T(0.5) * uy / m_Sc);
x = ux - (m * 2 + 1) * m_Sc;
y = uy - (n * 2 + 1) * m_Sc;
u = Hypot(x, y);
if ((DiscreteNoise2(int(m + m_Seed), int(n)) > m_Dens) || (u > (T(0.3) + T(0.7) * DiscreteNoise2(int(m + 10), int(n + 3))) * m_Sc))
{
ux = ux;
uy = uy;
}
else
{
CircleR(&ux, &uy, rand);
}
helper.Out.x = m_Weight * ux;
helper.Out.y = m_Weight * uy;
helper.Out.z = (m_VarType == VARTYPE_REG) ? 0 : helper.In.z;
}
virtual string OpenCLString() const override
{
ostringstream ss, ss2;
intmax_t i = 0, varIndex = IndexInXform();
ss2 << "_" << XformIndexInEmber() << "]";
string index = ss2.str();
string sc = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string dens = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string x = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string y = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string seed = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
ss << "\t{\n"
<< "\t\treal_t ux, uy, u, x, y;\n"
<< "\n"
<< "\t\tCircleTrans1Trans(" << x << ", " << y << ", vIn.x, vIn.y, &ux, &uy);\n"
<< "\n"
<< "\t\tint m = (int)floor((real_t)(0.5) * ux / " << sc << ");\n"
<< "\t\tint n = (int)floor((real_t)(0.5) * uy / " << sc << ");\n"
<< "\n"
<< "\t\tx = ux - (m * 2 + 1) * " << sc << ";\n"
<< "\t\ty = uy - (n * 2 + 1) * " << sc << ";\n"
<< "\t\tu = Hypot(x, y);\n"
<< "\n"
<< "\t\tif ((CircleTrans1DiscreteNoise2((int)(m + " << seed << "), n) > " << dens << ") || (u > ((real_t)(0.3) + (real_t)(0.7) * CircleTrans1DiscreteNoise2(m + 10, n + 3)) * " << sc << "))\n"
<< "\t\t{\n"
<< "\t\t ux = ux;\n"
<< "\t\t uy = uy;\n"
<< "\t\t}\n"
<< "\t\telse\n"
<< "\t\t{\n"
<< "\t\t CircleTrans1CircleR(" << x << ", " << y << ", " << sc << ", " << seed << ", " << dens << ", &ux, &uy, mwc);\n"
<< "\t\t}\n"
<< "\n"
<< "\t\tvOut.x = xform->m_VariationWeights[" << varIndex << "] * ux;\n"
<< "\t\tvOut.y = xform->m_VariationWeights[" << varIndex << "] * uy;\n"
<< "\t\tvOut.z = " << ((m_VarType == VARTYPE_REG) ? "0" : "vIn.z") << ";\n"
<< "\t}\n";
return ss.str();
}
virtual string OpenCLFuncsString() const override
{
return
"real_t CircleTrans1DiscreteNoise2(int x, int y)\n"
"{\n"
" const real_t im = 2147483647;\n"
" const real_t am = 1 / im;\n"
"\n"
" int n = x + y * 57;\n"
" n = (n << 13) ^ n;\n"
" return ((n * (n * n * 15731 + 789221) + 1376312589) & 0x7fffffff) * am;\n"
"}\n"
"\n"
"void CircleTrans1Trans(real_t a, real_t b, real_t x, real_t y, real_t* x1, real_t* y1)\n"
"{\n"
" *x1 = (x - a) * (real_t)(0.5) + a;\n"
" *y1 = (y - b) * (real_t)(0.5) + b;\n"
"}\n"
"\n"
"void CircleTrans1CircleR(real_t mx, real_t my, real_t sc, real_t seed, real_t dens, real_t* ux, real_t* vy, uint2* mwc)\n"
"{\n"
" int m, n, iters = 0;\n"
" real_t x, y, alpha, u;\n"
"\n"
" do\n"
" {\n"
" x = fabs(mx) * (1 - 2 * MwcNext01(mwc));\n"
" y = fabs(my) * (1 - 2 * MwcNext01(mwc));\n"
" m = (int)floor((real_t)(0.5) * x / sc);\n"
" n = (int)floor((real_t)(0.5) * y / sc);\n"
" alpha = M_2PI * MwcNext01(mwc);\n"
" u = (real_t)(0.3) + (real_t)(0.7) * CircleTrans1DiscreteNoise2(m + 10, n + 3);\n"
" x = u * cos(alpha);\n"
" y = u * sin(alpha);\n"
"\n"
" if (++iters > 10)\n"
" break;\n"
" }\n"
" while (CircleTrans1DiscreteNoise2((int)(m + seed), n) > dens);\n"
"\n"
" *ux = x + (m * 2 + 1) * sc;\n"
" *vy = y + (n * 2 + 1) * sc;\n"
"}\n"
"\n";
}
virtual vector OpenCLGlobalFuncNames() const override
{
return vector { "Hypot" };
}
protected:
void Init()
{
string prefix = Prefix();
m_Params.clear();
m_Params.push_back(ParamWithName(&m_Sc, prefix + "CircleTrans1_Sc", 1, REAL_NONZERO));
m_Params.push_back(ParamWithName(&m_Dens, prefix + "CircleTrans1_Dens", T(0.5)));
m_Params.push_back(ParamWithName(&m_X, prefix + "CircleTrans1_X", 10));
m_Params.push_back(ParamWithName(&m_Y, prefix + "CircleTrans1_Y", 10));
m_Params.push_back(ParamWithName(&m_Seed, prefix + "CircleTrans1_Seed", 0, INTEGER));
}
private:
T DiscreteNoise2(int x, int y)
{
const T im = T(2147483647);
const T am = (1 / im);
int n = x + y * 57;
n = (n << 13) ^ n;
return ((n * (n * n * 15731 + 789221) + 1376312589) & 0x7fffffff) * am;
}
void Trans(T a, T b, T x, T y, T* x1, T* y1)
{
*x1 = (x - a) * T(0.5) + a;
*y1 = (y - b) * T(0.5) + b;
}
void CircleR(T* ux, T* vy, QTIsaac& rand)
{
intmax_t m, n, iters = 0;
T x, y, alpha, u;
do
{
x = fabs(m_X) * (1 - 2 * rand.Frand01());
y = fabs(m_Y) * (1 - 2 * rand.Frand01());
m = Floor(T(0.5) * x / m_Sc);
n = Floor(T(0.5) * y / m_Sc);
alpha = M_2PI * rand.Frand01();
u = T(0.3) + T(0.7) * DiscreteNoise2(int(m + 10), int(n + 3));
x = u * std::cos(alpha);
y = u * std::sin(alpha);
if (++iters > 10)
break;
}
while (DiscreteNoise2(int(m + m_Seed), int(n)) > m_Dens);
*ux = x + (m * 2 + 1) * m_Sc;
*vy = y + (n * 2 + 1) * m_Sc;
}
T m_Sc;
T m_Dens;
T m_X;
T m_Y;
T m_Seed;
};
///
/// cubic3D.
///
template
class EMBER_API Cubic3DVariation : public ParametricVariation
{
public:
Cubic3DVariation(T weight = 1.0) : ParametricVariation("cubic3D", VAR_CUBIC3D, weight)
{
Init();
}
PARVARCOPY(Cubic3DVariation)
virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override
{
int useNode = rand.Rand() & 7;//Faster than % 8.
T exnze, wynze, znxy;
T lattd = m_Weight * T(0.5);
T px, py, pz;
exnze = 1 - (m_SmoothStyle * (1 - (std::cos(std::atan2(helper.In.x, helper.In.z)))));
wynze = 1 - (m_SmoothStyle * (1 - (std::sin(std::atan2(helper.In.y, helper.In.z)))));
if (m_SmoothStyle > 1)
znxy = 1 - (m_SmoothStyle * (1 - ((exnze + wynze) / 2 * m_SmoothStyle)));
else
znxy = 1 - (m_SmoothStyle * (1 - ((exnze + wynze) * T(0.5))));
if (m_VarType == VARTYPE_PRE)
{
px = helper.In.x;
py = helper.In.y;
pz = helper.In.z;
}
else
{
px = outPoint.m_X;
py = outPoint.m_Y;
pz = outPoint.m_Z;
}
switch (useNode)
{
case 0 :
helper.Out.x = ((px - (m_Smooth * (1 - m_Fill) * px * exnze)) + (helper.In.x * m_Smooth * m_Fill * exnze)) + lattd;
helper.Out.y = ((py - (m_Smooth * (1 - m_Fill) * py * wynze)) + (helper.In.y * m_Smooth * m_Fill * wynze)) + lattd;
helper.Out.z = ((pz - (m_Smooth * (1 - m_Fill) * pz * znxy)) + (helper.In.z * m_Smooth * m_Fill * znxy)) + lattd;
break;
case 1 :
helper.Out.x = ((px - (m_Smooth * (1 - m_Fill) * px * exnze)) + (helper.In.x * m_Smooth * m_Fill * exnze)) + lattd;
helper.Out.y = ((py - (m_Smooth * (1 - m_Fill) * py * wynze)) + (helper.In.y * m_Smooth * m_Fill * wynze)) - lattd;
helper.Out.z = ((pz - (m_Smooth * (1 - m_Fill) * pz * znxy)) + (helper.In.z * m_Smooth * m_Fill * znxy)) + lattd;
break;
case 2 :
helper.Out.x = ((px - (m_Smooth * (1 - m_Fill) * px * exnze)) + (helper.In.x * m_Smooth * m_Fill * exnze)) + lattd;
helper.Out.y = ((py - (m_Smooth * (1 - m_Fill) * py * wynze)) + (helper.In.y * m_Smooth * m_Fill * wynze)) + lattd;
helper.Out.z = ((pz - (m_Smooth * (1 - m_Fill) * pz * znxy)) + (helper.In.z * m_Smooth * m_Fill * znxy)) - lattd;
break;
case 3 :
helper.Out.x = ((px - (m_Smooth * (1 - m_Fill) * px * exnze)) + (helper.In.x * m_Smooth * m_Fill * exnze)) + lattd;
helper.Out.y = ((py - (m_Smooth * (1 - m_Fill) * py * wynze)) + (helper.In.y * m_Smooth * m_Fill * wynze)) - lattd;
helper.Out.z = ((pz - (m_Smooth * (1 - m_Fill) * pz * znxy)) + (helper.In.z * m_Smooth * m_Fill * znxy)) - lattd;
break;
case 4 :
helper.Out.x = ((px - (m_Smooth * (1 - m_Fill) * px * exnze)) + (helper.In.x * m_Smooth * m_Fill * exnze)) - lattd;
helper.Out.y = ((py - (m_Smooth * (1 - m_Fill) * py * wynze)) + (helper.In.y * m_Smooth * m_Fill * wynze)) + lattd;
helper.Out.z = ((pz - (m_Smooth * (1 - m_Fill) * pz * znxy)) + (helper.In.z * m_Smooth * m_Fill * znxy)) + lattd;
break;
case 5 :
helper.Out.x = ((px - (m_Smooth * (1 - m_Fill) * px * exnze)) + (helper.In.x * m_Smooth * m_Fill * exnze)) - lattd;
helper.Out.y = ((py - (m_Smooth * (1 - m_Fill) * py * wynze)) + (helper.In.y * m_Smooth * m_Fill * wynze)) - lattd;
helper.Out.z = ((pz - (m_Smooth * (1 - m_Fill) * pz * znxy)) + (helper.In.z * m_Smooth * m_Fill * znxy)) + lattd;
break;
case 6 :
helper.Out.x = ((px - (m_Smooth * (1 - m_Fill) * px * exnze)) + (helper.In.x * m_Smooth * m_Fill * exnze)) - lattd;
helper.Out.y = ((py - (m_Smooth * (1 - m_Fill) * py * wynze)) + (helper.In.y * m_Smooth * m_Fill * wynze)) + lattd;
helper.Out.z = ((pz - (m_Smooth * (1 - m_Fill) * pz * znxy)) + (helper.In.z * m_Smooth * m_Fill * znxy)) - lattd;
break;
case 7 :
default:
helper.Out.x = ((px - (m_Smooth * (1 - m_Fill) * px * exnze)) + (helper.In.x * m_Smooth * m_Fill * exnze)) - lattd;
helper.Out.y = ((py - (m_Smooth * (1 - m_Fill) * py * wynze)) + (helper.In.y * m_Smooth * m_Fill * wynze)) - lattd;
helper.Out.z = ((pz - (m_Smooth * (1 - m_Fill) * pz * znxy)) + (helper.In.z * m_Smooth * m_Fill * znxy)) - lattd;
break;
}
}
virtual string OpenCLString() const override
{
ostringstream ss, ss2;
intmax_t i = 0, varIndex = IndexInXform();
ss2 << "_" << XformIndexInEmber() << "]";
string index = ss2.str();
string xpand = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string style = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string fill = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string smooth = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string smoothStyle = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
ss << "\t{\n"
<< "\t\tint useNode = MwcNext(mwc) & 7;\n"
<< "\t\treal_t exnze, wynze, znxy;\n"
<< "\t\treal_t lattd = xform->m_VariationWeights[" << varIndex << "] * (real_t)(0.5);\n"
<< "\t\treal_t px, py, pz;\n"
<< "\n"
<< "\t\texnze = 1 - (" << smoothStyle << " * (1 - (cos(atan2(vIn.x, vIn.z)))));\n"
<< "\t\twynze = 1 - (" << smoothStyle << " * (1 - (sin(atan2(vIn.y, vIn.z)))));\n"
<< "\n"
<< "\t\tif (" << smoothStyle << " > 1)\n"
<< "\t\t znxy = 1 - (" << smoothStyle << " * (1 - ((exnze + wynze) / 2 * " << smoothStyle << ")));\n"
<< "\t\telse\n"
<< "\t\t znxy = 1 - (" << smoothStyle << " * (1 - ((exnze + wynze) * (real_t)(0.5))));\n";
if (m_VarType == VARTYPE_PRE)
{
ss <<
"\t\tpx = vIn.x;\n"
"\t\tpy = vIn.y;\n"
"\t\tpz = vIn.z;\n";
}
else
{
ss <<
"\t\tpx = outPoint->m_X;\n"
"\t\tpy = outPoint->m_Y;\n"
"\t\tpz = outPoint->m_Z;\n";
}
ss <<
"\t\tswitch (useNode)\n"
"\t\t{\n"
"\t\t case 0 :\n"
"\t\t vOut.x = ((px - (" << smooth << " * (1 - " << fill << ") * px * exnze)) + (vIn.x * " << smooth << " * " << fill << " * exnze)) + lattd;\n"
"\t\t vOut.y = ((py - (" << smooth << " * (1 - " << fill << ") * py * wynze)) + (vIn.y * " << smooth << " * " << fill << " * wynze)) + lattd;\n"
"\t\t vOut.z = ((pz - (" << smooth << " * (1 - " << fill << ") * pz * znxy)) + (vIn.z * " << smooth << " * " << fill << " * znxy)) + lattd;\n"
"\t\t break;\n"
"\t\t case 1 :\n"
"\t\t vOut.x = ((px - (" << smooth << " *(1 - " << fill << ") * px * exnze)) + (vIn.x * " << smooth << " * " << fill << " * exnze)) + lattd;\n"
"\t\t vOut.y = ((py - (" << smooth << " *(1 - " << fill << ") * py * wynze)) + (vIn.y * " << smooth << " * " << fill << " * wynze)) - lattd;\n"
"\t\t vOut.z = ((pz - (" << smooth << " *(1 - " << fill << ") * pz * znxy)) + (vIn.z * " << smooth << " * " << fill << " * znxy)) + lattd;\n"
"\t\t break;\n"
"\t\t case 2 :\n"
"\t\t vOut.x = ((px - (" << smooth << " * (1 - " << fill << ") * px * exnze)) + (vIn.x * " << smooth << " * " << fill << " * exnze)) + lattd;\n"
"\t\t vOut.y = ((py - (" << smooth << " * (1 - " << fill << ") * py * wynze)) + (vIn.y * " << smooth << " * " << fill << " * wynze)) + lattd;\n"
"\t\t vOut.z = ((pz - (" << smooth << " * (1 - " << fill << ") * pz * znxy)) + (vIn.z * " << smooth << " * " << fill << " * znxy)) - lattd;\n"
"\t\t break;\n"
"\t\t case 3 :\n"
"\t\t vOut.x = ((px - (" << smooth << " * (1 - " << fill << ") * px * exnze)) + (vIn.x * " << smooth << " * " << fill << " * exnze)) + lattd;\n"
"\t\t vOut.y = ((py - (" << smooth << " * (1 - " << fill << ") * py * wynze)) + (vIn.y * " << smooth << " * " << fill << " * wynze)) - lattd;\n"
"\t\t vOut.z = ((pz - (" << smooth << " * (1 - " << fill << ") * pz * znxy)) + (vIn.z * " << smooth << " * " << fill << " * znxy)) - lattd;\n"
"\t\t break;\n"
"\t\t case 4 :\n"
"\t\t vOut.x = ((px - (" << smooth << " * (1 - " << fill << ") * px * exnze)) + (vIn.x * " << smooth << " * " << fill << " * exnze)) - lattd;\n"
"\t\t vOut.y = ((py - (" << smooth << " * (1 - " << fill << ") * py * wynze)) + (vIn.y * " << smooth << " * " << fill << " * wynze)) + lattd;\n"
"\t\t vOut.z = ((pz - (" << smooth << " * (1 - " << fill << ") * pz * znxy)) + (vIn.z * " << smooth << " * " << fill << " * znxy)) + lattd;\n"
"\t\t break;\n"
"\t\t case 5 :\n"
"\t\t vOut.x = ((px - (" << smooth << " * (1 - " << fill << ") * px * exnze)) + (vIn.x * " << smooth << " * " << fill << " * exnze)) - lattd;\n"
"\t\t vOut.y = ((py - (" << smooth << " * (1 - " << fill << ") * py * wynze)) + (vIn.y * " << smooth << " * " << fill << " * wynze)) - lattd;\n"
"\t\t vOut.z = ((pz - (" << smooth << " * (1 - " << fill << ") * pz * znxy)) + (vIn.z * " << smooth << " * " << fill << " * znxy)) + lattd;\n"
"\t\t break;\n"
"\t\t case 6 :\n"
"\t\t vOut.x = ((px - (" << smooth << " * (1 - " << fill << ") * px * exnze)) + (vIn.x * " << smooth << " * " << fill << " * exnze)) - lattd;\n"
"\t\t vOut.y = ((py - (" << smooth << " * (1 - " << fill << ") * py * wynze)) + (vIn.y * " << smooth << " * " << fill << " * wynze)) + lattd;\n"
"\t\t vOut.z = ((pz - (" << smooth << " * (1 - " << fill << ") * pz * znxy)) + (vIn.z * " << smooth << " * " << fill << " * znxy)) - lattd;\n"
"\t\t break;\n"
"\t\t case 7 :\n"
"\t\t vOut.x = ((px - (" << smooth << " * (1 - " << fill << ") * px * exnze)) + (vIn.x * " << smooth << " * " << fill << " * exnze)) - lattd;\n"
"\t\t vOut.y = ((py - (" << smooth << " * (1 - " << fill << ") * py * wynze)) + (vIn.y * " << smooth << " * " << fill << " * wynze)) - lattd;\n"
"\t\t vOut.z = ((pz - (" << smooth << " * (1 - " << fill << ") * pz * znxy)) + (vIn.z * " << smooth << " * " << fill << " * znxy)) - lattd;\n"
"\t\t break;\n"
"\t\t}\n"
"\t}\n";
return ss.str();
}
virtual void Precalc() override
{
if (fabs(m_Xpand) <= 1)
m_Fill = m_Xpand * T(0.5);
else
m_Fill = std::sqrt(m_Xpand) * T(0.5);
if (fabs(m_Weight) <= T(0.5))
m_Smooth = m_Weight * 2;//Causes full effect above m_Weight = 0.5.
else
m_Smooth = 1;
if (fabs(m_Style) <= 1)
{
m_SmoothStyle = m_Style;
}
else
{
if (m_Style > 1)
m_SmoothStyle = 1 + (m_Style - 1) * T(0.25);
else
m_SmoothStyle = (m_Style + 1) * T(0.25) - 1;
}
}
protected:
void Init()
{
string prefix = Prefix();
m_Params.clear();
m_Params.push_back(ParamWithName(&m_Xpand, prefix + "cubic3D_xpand", T(0.25)));
m_Params.push_back(ParamWithName(&m_Style, prefix + "cubic3D_style"));
m_Params.push_back(ParamWithName(true, &m_Fill, prefix + "cubic3D_fill"));//Precalc.
m_Params.push_back(ParamWithName(true, &m_Smooth, prefix + "cubic3D_smooth"));
m_Params.push_back(ParamWithName(true, &m_SmoothStyle, prefix + "cubic3D_smooth_style"));
}
private:
T m_Xpand;
T m_Style;
T m_Fill;//Precalc.
T m_Smooth;
T m_SmoothStyle;
};
///
/// cubicLattice_3D.
///
template
class EMBER_API CubicLattice3DVariation : public ParametricVariation
{
public:
CubicLattice3DVariation(T weight = 1.0) : ParametricVariation("cubicLattice_3D", VAR_CUBIC_LATTICE3D, weight)
{
Init();
}
PARVARCOPY(CubicLattice3DVariation)
virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override
{
int useNode = rand.Rand() & 7;//Faster than % 8.
T exnze, wynze, znxy, px, py, pz, lattd = m_Weight;
if (m_Style == 2)
{
exnze = std::cos(std::atan2(helper.In.x, helper.In.z));
wynze = std::sin(std::atan2(helper.In.y, helper.In.z));
znxy = (exnze + wynze) * T(0.5);
}
else
{
exnze = 1;
wynze = 1;
znxy = 1;
}
if (m_VarType == VARTYPE_PRE)
{
px = helper.In.x;
py = helper.In.y;
pz = helper.In.z;
}
else
{
px = outPoint.m_X;
py = outPoint.m_Y;
pz = outPoint.m_Z;
}
T pxtx = px + helper.In.x;
T pyty = py + helper.In.y;
T pztz = pz + helper.In.z;
switch (useNode)
{
case 0 :
helper.Out.x = pxtx * m_Fill * exnze + lattd;
helper.Out.y = pyty * m_Fill * wynze + lattd;
helper.Out.z = pztz * m_Fill * znxy + lattd;
break;
case 1 :
helper.Out.x = pxtx * m_Fill * exnze + lattd;
helper.Out.y = pyty * m_Fill * wynze - lattd;
helper.Out.z = pztz * m_Fill * znxy + lattd;
break;
case 2 :
helper.Out.x = pxtx * m_Fill * exnze + lattd;
helper.Out.y = pyty * m_Fill * wynze + lattd;
helper.Out.z = pztz * m_Fill * znxy - lattd;
break;
case 3 :
helper.Out.x = pxtx * m_Fill * exnze + lattd;
helper.Out.y = pyty * m_Fill * wynze - lattd;
helper.Out.z = pztz * m_Fill * znxy - lattd;
break;
case 4 :
helper.Out.x = pxtx * m_Fill * exnze - lattd;
helper.Out.y = pyty * m_Fill * wynze + lattd;
helper.Out.z = pztz * m_Fill * znxy + lattd;
break;
case 5 :
helper.Out.x = pxtx * m_Fill * exnze - lattd;
helper.Out.y = pyty * m_Fill * wynze - lattd;
helper.Out.z = pztz * m_Fill * znxy + lattd;
break;
case 6 :
helper.Out.x = pxtx * m_Fill * exnze - lattd;
helper.Out.y = pyty * m_Fill * wynze + lattd;
helper.Out.z = pztz * m_Fill * znxy - lattd;
break;
case 7 :
default:
helper.Out.x = pxtx * m_Fill * exnze - lattd;
helper.Out.y = pyty * m_Fill * wynze - lattd;
helper.Out.z = pztz * m_Fill * znxy - lattd;
break;
}
}
virtual string OpenCLString() const override
{
ostringstream ss, ss2;
intmax_t i = 0, varIndex = IndexInXform();
ss2 << "_" << XformIndexInEmber() << "]";
string index = ss2.str();
string xpand = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string style = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string fill = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
ss << "\t{\n"
<< "\t\tint useNode = MwcNext(mwc) & 7;\n"
<< "\t\treal_t exnze, wynze, znxy, px, py, pz, lattd = xform->m_VariationWeights[" << varIndex << "];\n"
<< "\n"
<< "\t\tif (" << style << " == 2)\n"
<< "\t\t{\n"
<< "\t\t exnze = cos(atan2(vIn.x, vIn.z));\n"
<< "\t\t wynze = sin(atan2(vIn.y, vIn.z));\n"
<< "\t\t znxy = (exnze + wynze) * (real_t)(0.5);\n"
<< "\t\t}\n"
<< "\t\telse\n"
<< "\t\t{\n"
<< "\t\t exnze = 1;\n"
<< "\t\t wynze = 1;\n"
<< "\t\t znxy = 1;\n"
<< "\t\t}\n";
if (m_VarType == VARTYPE_PRE)
{
ss <<
"\t\tpx = vIn.x;\n"
"\t\tpy = vIn.y;\n"
"\t\tpz = vIn.z;\n";
}
else
{
ss <<
"\t\tpx = outPoint->m_X;\n"
"\t\tpy = outPoint->m_Y;\n"
"\t\tpz = outPoint->m_Z;\n";
}
ss << "\t\treal_t pxtx = px + vIn.x;\n"
<< "\t\treal_t pyty = py + vIn.y;\n"
<< "\t\treal_t pztz = pz + vIn.z;\n"
<< "\n"
<< "\t\tswitch (useNode)\n"
<< "\t\t{\n"
<< "\t\t case 0 :\n"
<< "\t\t vOut.x = pxtx * " << fill << " * exnze + lattd;\n"
<< "\t\t vOut.y = pyty * " << fill << " * wynze + lattd;\n"
<< "\t\t vOut.z = pztz * " << fill << " * znxy + lattd;\n"
<< "\t\t break;\n"
<< "\t\t case 1 :\n"
<< "\t\t vOut.x = pxtx * " << fill << " * exnze + lattd;\n"
<< "\t\t vOut.y = pyty * " << fill << " * wynze - lattd;\n"
<< "\t\t vOut.z = pztz * " << fill << " * znxy + lattd;\n"
<< "\t\t break;\n"
<< "\t\t case 2 :\n"
<< "\t\t vOut.x = pxtx * " << fill << " * exnze + lattd;\n"
<< "\t\t vOut.y = pyty * " << fill << " * wynze + lattd;\n"
<< "\t\t vOut.z = pztz * " << fill << " * znxy - lattd;\n"
<< "\t\t break;\n"
<< "\t\t case 3 :\n"
<< "\t\t vOut.x = pxtx * " << fill << " * exnze + lattd;\n"
<< "\t\t vOut.y = pyty * " << fill << " * wynze - lattd;\n"
<< "\t\t vOut.z = pztz * " << fill << " * znxy - lattd;\n"
<< "\t\t break;\n"
<< "\t\t case 4 :\n"
<< "\t\t vOut.x = pxtx * " << fill << " * exnze - lattd;\n"
<< "\t\t vOut.y = pyty * " << fill << " * wynze + lattd;\n"
<< "\t\t vOut.z = pztz * " << fill << " * znxy + lattd;\n"
<< "\t\t break;\n"
<< "\t\t case 5 :\n"
<< "\t\t vOut.x = pxtx * " << fill << " * exnze - lattd;\n"
<< "\t\t vOut.y = pyty * " << fill << " * wynze - lattd;\n"
<< "\t\t vOut.z = pztz * " << fill << " * znxy + lattd;\n"
<< "\t\t break;\n"
<< "\t\t case 6 :\n"
<< "\t\t vOut.x = pxtx * " << fill << " * exnze - lattd;\n"
<< "\t\t vOut.y = pyty * " << fill << " * wynze + lattd;\n"
<< "\t\t vOut.z = pztz * " << fill << " * znxy - lattd;\n"
<< "\t\t break;\n"
<< "\t\t case 7 :\n"
<< "\t\t vOut.x = pxtx * " << fill << " * exnze - lattd;\n"
<< "\t\t vOut.y = pyty * " << fill << " * wynze - lattd;\n"
<< "\t\t vOut.z = pztz * " << fill << " * znxy - lattd;\n"
<< "\t\t break;\n"
<< "\t\t}\n"
<< "\t}\n";
return ss.str();
}
virtual void Precalc() override
{
if (fabs(m_Xpand) <= 1)
m_Fill = m_Xpand * T(0.5);
else
m_Fill = std::sqrt(m_Xpand) * T(0.5);
}
protected:
void Init()
{
string prefix = Prefix();
m_Params.clear();
m_Params.push_back(ParamWithName(&m_Xpand, prefix + "cubicLattice_3D_xpand", T(0.2)));//Original used a prefix of cubic3D_, which is incompatible with Ember's design.
m_Params.push_back(ParamWithName(&m_Style, prefix + "cubicLattice_3D_style", 1, INTEGER, 1, 2));
m_Params.push_back(ParamWithName(true, &m_Fill, prefix + "cubicLattice_3D_fill"));//Precalc.
}
private:
T m_Xpand;
T m_Style;
T m_Fill;//Precalc.
};
///
/// foci_3D.
///
template
class EMBER_API Foci3DVariation : public Variation
{
public:
Foci3DVariation(T weight = 1.0) : Variation("foci_3D", VAR_FOCI3D, weight, false, false, false, false, true) { }
VARCOPY(Foci3DVariation)
virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override
{
T expx = std::exp(helper.In.x) * T(0.5);
T expnx = T(0.25) / expx;
T boot = helper.In.z == 0 ? helper.m_PrecalcAtanyx : helper.In.z;
T tmp = m_Weight / (expx + expnx - (std::cos(helper.In.y) * std::cos(boot)));
helper.Out.x = (expx - expnx) * tmp;
helper.Out.y = std::sin(helper.In.y) * tmp;
helper.Out.z = std::sin(boot) * tmp;
}
virtual string OpenCLString() const override
{
ostringstream ss;
intmax_t varIndex = IndexInXform();
ss << "\t{\n"
<< "\t\treal_t expx = exp(vIn.x) * (real_t)(0.5);\n"
<< "\t\treal_t expnx = (real_t)(0.25) / expx;\n"
<< "\t\treal_t boot = vIn.z == 0 ? precalcAtanyx : vIn.z;\n"
<< "\t\treal_t tmp = xform->m_VariationWeights[" << varIndex << "] / (expx + expnx - (cos(vIn.y) * cos(boot)));\n"
<< "\n"
<< "\t\tvOut.x = (expx - expnx) * tmp;\n"
<< "\t\tvOut.y = sin(vIn.y) * tmp;\n"
<< "\t\tvOut.z = sin(boot) * tmp;\n"
<< "\t}\n";
return ss.str();
}
};
///
/// ho.
///
template
class EMBER_API HoVariation : public ParametricVariation
{
public:
HoVariation(T weight = 1.0) : ParametricVariation("ho", VAR_HO, weight)
{
Init();
}
PARVARCOPY(HoVariation)
virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override
{
T uu = SQR(helper.In.x);
T vv = SQR(helper.In.y);
T ww = SQR(helper.In.z);
T atOmegaX = atan2(vv, ww);
T atOmegaY = atan2(uu, ww);
T su = std::sin(helper.In.x);
T cu = std::cos(helper.In.x);
T sv = std::sin(helper.In.y);
T cv = std::cos(helper.In.y);
T cucv = cu * cv;
T sucv = su * cv;
T x = std::pow(fabs(cucv), m_XPow) + (cucv * m_XPow) + (T(0.25) * atOmegaX);//Must fabs first argument to pow, because negative values will return NaN.
T y = std::pow(fabs(sucv), m_YPow) + (sucv * m_YPow) + (T(0.25) * atOmegaY);//Original did not do this and would frequently return bad values.
T z = std::pow(fabs(sv), m_ZPow) + sv * m_ZPow;
helper.Out.x = m_Weight * x;
helper.Out.y = m_Weight * y;
helper.Out.z = m_Weight * z;
}
virtual string OpenCLString() const override
{
ostringstream ss, ss2;
intmax_t i = 0, varIndex = IndexInXform();
ss2 << "_" << XformIndexInEmber() << "]";
string index = ss2.str();
string xpow = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string ypow = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string zpow = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
ss << "\t{\n"
<< "\t\treal_t uu = SQR(vIn.x);\n"
<< "\t\treal_t vv = SQR(vIn.y);\n"
<< "\t\treal_t ww = SQR(vIn.z);\n"
<< "\t\treal_t atOmegaX = atan2(vv, ww);\n"
<< "\t\treal_t atOmegaY = atan2(uu, ww);\n"
<< "\t\treal_t su = sin(vIn.x);\n"
<< "\t\treal_t cu = cos(vIn.x);\n"
<< "\t\treal_t sv = sin(vIn.y);\n"
<< "\t\treal_t cv = cos(vIn.y);\n"
<< "\t\treal_t cucv = cu * cv;\n"
<< "\t\treal_t sucv = su * cv;\n"
<< "\t\treal_t x = pow(fabs(cucv), " << xpow << ") + (cucv * " << xpow << ") + ((real_t)(0.25) * atOmegaX);\n"
<< "\t\treal_t y = pow(fabs(sucv), " << ypow << ") + (sucv * " << ypow << ") + ((real_t)(0.25) * atOmegaY);\n"
<< "\t\treal_t z = pow(fabs(sv), " << zpow << ") + sv * " << zpow << ";\n"
<< "\n"
<< "\t\tvOut.x = xform->m_VariationWeights[" << varIndex << "] * x;\n"
<< "\t\tvOut.y = xform->m_VariationWeights[" << varIndex << "] * y;\n"
<< "\t\tvOut.z = xform->m_VariationWeights[" << varIndex << "] * z;\n"
<< "\t}\n";
return ss.str();
}
protected:
void Init()
{
string prefix = Prefix();
m_Params.clear();
m_Params.push_back(ParamWithName(&m_XPow, prefix + "ho_xpow", 3));
m_Params.push_back(ParamWithName(&m_YPow, prefix + "ho_ypow", 3));
m_Params.push_back(ParamWithName(&m_ZPow, prefix + "ho_zpow", 3));
}
private:
T m_XPow;
T m_YPow;
T m_ZPow;
};
///
/// Julia3Dq.
///
template
class EMBER_API Julia3DqVariation : public ParametricVariation
{
public:
Julia3DqVariation(T weight = 1.0) : ParametricVariation("julia3Dq", VAR_JULIA3DQ, weight, true, true, false, false, true)
{
Init();
}
PARVARCOPY(Julia3DqVariation)
virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override
{
T temp = helper.m_PrecalcAtanyx * m_InvPower + rand.Rand() * m_InvPower2pi;
T sina = std::sin(temp);
T cosa = std::cos(temp);
T z = helper.In.z * m_AbsInvPower;
T r2d = helper.m_PrecalcSumSquares;
T r = m_Weight * std::pow(r2d + SQR(z), m_HalfInvPower);
T rsss = r * helper.m_PrecalcSqrtSumSquares;
helper.Out.x = rsss * cosa;
helper.Out.y = rsss * sina;
helper.Out.z = r * z;
}
virtual string OpenCLString() const override
{
ostringstream ss, ss2;
intmax_t i = 0, varIndex = IndexInXform();
ss2 << "_" << XformIndexInEmber() << "]";
string index = ss2.str();
string power = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string divisor = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string invPower = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string absInvPower = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string halfInvPower = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string invPower2pi = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
ss << "\t{\n"
<< "\t\treal_t temp = precalcAtanyx * " << invPower << " + MwcNext(mwc) * " << invPower2pi << ";\n"
<< "\t\treal_t sina = sin(temp);\n"
<< "\t\treal_t cosa = cos(temp);\n"
<< "\t\treal_t z = vIn.z * " << absInvPower << ";\n"
<< "\t\treal_t r2d = precalcSumSquares;\n"
<< "\t\treal_t r = xform->m_VariationWeights[" << varIndex << "] * pow(r2d + SQR(z), " << halfInvPower << ");\n"
<< "\t\treal_t rsss = r * precalcSqrtSumSquares;\n"
<< "\n"
<< "\t\tvOut.x = rsss * cosa;\n"
<< "\t\tvOut.y = rsss * sina;\n"
<< "\t\tvOut.z = r * z;\n"
<< "\t}\n";
return ss.str();
}
virtual void Precalc() override
{
m_InvPower = m_Divisor / m_Power;
m_AbsInvPower = fabs(m_InvPower);
m_HalfInvPower = T(0.5) * m_InvPower - T(0.5);
m_InvPower2pi = M_2PI / m_Power;
}
protected:
void Init()
{
string prefix = Prefix();
m_Params.clear();
m_Params.push_back(ParamWithName(&m_Power, prefix + "julia3Dq_power", 3, INTEGER_NONZERO));
m_Params.push_back(ParamWithName(&m_Divisor, prefix + "julia3Dq_divisor", 2, INTEGER_NONZERO));
m_Params.push_back(ParamWithName(true, &m_InvPower, prefix + "julia3Dq_inv_power"));//Precalc.
m_Params.push_back(ParamWithName(true, &m_AbsInvPower, prefix + "julia3Dq_abs_inv_power"));
m_Params.push_back(ParamWithName(true, &m_HalfInvPower, prefix + "julia3Dq_half_inv_power"));
m_Params.push_back(ParamWithName(true, &m_InvPower2pi, prefix + "julia3Dq_inv_power_2pi"));
}
private:
T m_Power;
T m_Divisor;
T m_InvPower;//Precalc.
T m_AbsInvPower;
T m_HalfInvPower;
T m_InvPower2pi;
};
///
/// line.
///
template
class EMBER_API LineVariation : public ParametricVariation
{
public:
LineVariation(T weight = 1.0) : ParametricVariation("line", VAR_LINE, weight)
{
Init();
}
PARVARCOPY(LineVariation)
virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override
{
T r = rand.Frand01() * m_Weight;
helper.Out.x = m_Ux * r;
helper.Out.y = m_Uy * r;
helper.Out.z = m_Uz * r;
}
virtual string OpenCLString() const override
{
ostringstream ss, ss2;
intmax_t i = 0, varIndex = IndexInXform();
ss2 << "_" << XformIndexInEmber() << "]";
string index = ss2.str();
string delta = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string phi = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string ux = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string uy = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string uz = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
ss << "\t{\n"
<< "\t\treal_t r = MwcNext01(mwc) * xform->m_VariationWeights[" << varIndex << "];\n"
<< "\n"
<< "\t\tvOut.x = " << ux << " * r;\n"
<< "\t\tvOut.y = " << uy << " * r;\n"
<< "\t\tvOut.z = " << uz << " * r;\n"
<< "\t}\n";
return ss.str();
}
virtual void Precalc() override
{
//Unit vector of the line.
m_Ux = std::cos(m_Delta * T(M_PI)) * std::cos(m_Phi * T(M_PI));
m_Uy = std::sin(m_Delta * T(M_PI)) * std::cos(m_Phi * T(M_PI));
m_Uz = std::sin(m_Phi * T(M_PI));
T r = std::sqrt(SQR(m_Ux) + SQR(m_Uy) + SQR(m_Uz));
//Normalize.
m_Ux /= r;
m_Uy /= r;
m_Uz /= r;
}
protected:
void Init()
{
string prefix = Prefix();
m_Params.clear();
m_Params.push_back(ParamWithName(&m_Delta, prefix + "line_delta"));
m_Params.push_back(ParamWithName(&m_Phi, prefix + "line_phi"));
m_Params.push_back(ParamWithName(true, &m_Ux, prefix + "line_ux"));//Precalc.
m_Params.push_back(ParamWithName(true, &m_Uy, prefix + "line_uy"));
m_Params.push_back(ParamWithName(true, &m_Uz, prefix + "line_uz"));
}
private:
T m_Delta;
T m_Phi;
T m_Ux;//Precalc.
T m_Uy;
T m_Uz;
};
///
/// Loonie2.
///
template
class EMBER_API Loonie2Variation : public ParametricVariation
{
public:
Loonie2Variation(T weight = 1.0) : ParametricVariation("loonie2", VAR_LOONIE2, weight, true, true)
{
Init();
}
PARVARCOPY(Loonie2Variation)
virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override
{
int i;
T xrt = helper.In.x, yrt = helper.In.y, swp;
T r2 = xrt * m_Coss + fabs(yrt) * m_Sins;
T circle = helper.m_PrecalcSqrtSumSquares;
for (i = 0; i < m_Sides - 1; i++)
{
swp = xrt * m_Cosa - yrt * m_Sina;
yrt = xrt * m_Sina + yrt * m_Cosa;
xrt = swp;
r2 = std::max(r2, xrt * m_Coss + fabs(yrt) * m_Sins);
}
r2 = r2 * m_Cosc + circle * m_Sinc;
if (i > 1)
r2 = SQR(r2);
else
r2 = fabs(r2) * r2;
if (r2 > 0 && (r2 < m_W2))
{
T r = m_Weight * std::sqrt(fabs(m_W2 / r2 - 1));
helper.Out.x = r * helper.In.x;
helper.Out.y = r * helper.In.y;
}
else if (r2 < 0)
{
T r = m_Weight / std::sqrt(fabs(m_W2 / r2) - 1);
helper.Out.x = r * helper.In.x;
helper.Out.y = r * helper.In.y;
}
else
{
helper.Out.x = m_Weight * helper.In.x;
helper.Out.y = m_Weight * helper.In.y;
}
helper.Out.z = (m_VarType == VARTYPE_REG) ? 0 : helper.In.z;
}
virtual string OpenCLString() const override
{
ostringstream ss, ss2;
intmax_t i = 0, varIndex = IndexInXform();
ss2 << "_" << XformIndexInEmber() << "]";
string index = ss2.str();
string sides = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string star = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string circle = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string w2 = "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 sins = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string coss = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string sinc = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string cosc = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
ss << "\t{\n"
<< "\t\tint i;\n"
<< "\t\treal_t xrt = vIn.x, yrt = vIn.y, swp;\n"
<< "\t\treal_t r2 = xrt * " << coss << " + fabs(yrt) * " << sins << ";\n"
<< "\t\treal_t circle = precalcSqrtSumSquares;\n"
<< "\n"
<< "\t\tfor (i = 0; i < " << sides << " - 1; i++)\n"
<< "\t\t{\n"
<< "\t\t swp = xrt * " << cosa << " - yrt * " << sina << ";\n"
<< "\t\t yrt = xrt * " << sina << " + yrt * " << cosa << ";\n"
<< "\t\t xrt = swp;\n"
<< "\n"
<< "\t\t r2 = max(r2, xrt * " << coss << " + fabs(yrt) * " << sins << ");\n"
<< "\t\t}\n"
<< "\n"
<< "\t\tr2 = r2 * " << cosc << " + circle * " << sinc << ";\n"
<< "\n"
<< "\t\tif (i > 1)\n"
<< "\t\t r2 = SQR(r2);\n"
<< "\t\telse\n"
<< "\t\t r2 = fabs(r2) * r2;\n"
<< "\n"
<< "\t\tif (r2 > 0 && (r2 < " << w2 << "))\n"
<< "\t\t{\n"
<< "\t\t real_t r = xform->m_VariationWeights[" << varIndex << "] * sqrt(fabs(" << w2 << " / r2 - 1));\n"
<< "\n"
<< "\t\t vOut.x = r * vIn.x;\n"
<< "\t\t vOut.y = r * vIn.y;\n"
<< "\t\t}\n"
<< "\t\telse if (r2 < 0)\n"
<< "\t\t{\n"
<< "\t\t real_t r = xform->m_VariationWeights[" << varIndex << "] / sqrt(fabs(" << w2 << " / r2) - 1);\n"
<< "\n"
<< "\t\t vOut.x = r * vIn.x;\n"
<< "\t\t vOut.y = r * vIn.y;\n"
<< "\t\t}\n"
<< "\t\telse\n"
<< "\t\t{\n"
<< "\t\t vOut.x = xform->m_VariationWeights[" << varIndex << "] * vIn.x;\n"
<< "\t\t vOut.y = xform->m_VariationWeights[" << varIndex << "] * vIn.y;\n"
<< "\t\t}\n"
<< "\n"
<< "\t\tvOut.z = " << ((m_VarType == VARTYPE_REG) ? "0" : "vIn.z") << ";\n"
<< "\t}\n";
return ss.str();
}
virtual void Precalc() override
{
auto a = M_2PI / m_Sides;
auto s = T(-M_PI_2) * m_Star;
auto c = T(M_PI_2) * m_Circle;
m_W2 = SQR(m_Weight);
sincos(a, &m_Sina, &m_Cosa);
sincos(s, &m_Sins, &m_Coss);
sincos(c, &m_Sinc, &m_Cosc);
}
protected:
void Init()
{
string prefix = Prefix();
m_Params.clear();
m_Params.push_back(ParamWithName(&m_Sides, prefix + "loonie2_sides", 4, INTEGER, 1, 50));
m_Params.push_back(ParamWithName(&m_Star, prefix + "loonie2_star", 0, REAL, -1, 1));
m_Params.push_back(ParamWithName(&m_Circle, prefix + "loonie2_circle", 0, REAL, -1, 1));
m_Params.push_back(ParamWithName(true, &m_W2, prefix + "loonie2_w2"));//Precalc.
m_Params.push_back(ParamWithName(true, &m_Sina, prefix + "loonie2_sina"));
m_Params.push_back(ParamWithName(true, &m_Cosa, prefix + "loonie2_cosa"));
m_Params.push_back(ParamWithName(true, &m_Sins, prefix + "loonie2_sins"));
m_Params.push_back(ParamWithName(true, &m_Coss, prefix + "loonie2_coss"));
m_Params.push_back(ParamWithName(true, &m_Sinc, prefix + "loonie2_sinc"));
m_Params.push_back(ParamWithName(true, &m_Cosc, prefix + "loonie2_cosc"));
}
private:
T m_Sides;
T m_Star;
T m_Circle;
T m_W2;//Precalc.
T m_Sina;
T m_Cosa;
T m_Sins;
T m_Coss;
T m_Sinc;
T m_Cosc;
};
///
/// Loonie3.
///
template
class EMBER_API Loonie3Variation : public ParametricVariation
{
public:
Loonie3Variation(T weight = 1.0) : ParametricVariation("loonie3", VAR_LOONIE3, weight, true)
{
Init();
}
PARVARCOPY(Loonie3Variation)
virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override
{
T r2;
if (helper.In.x > EPS)
r2 = SQR(helper.m_PrecalcSumSquares / helper.In.x);
else
r2 = 2 * m_W2;
if (r2 < m_W2)
{
T r = m_Weight * std::sqrt(m_W2 / r2 - 1);
helper.Out.x = r * helper.In.x;
helper.Out.y = r * helper.In.y;
}
else
{
helper.Out.x = m_Weight * helper.In.x;
helper.Out.y = m_Weight * helper.In.y;
}
helper.Out.z = (m_VarType == VARTYPE_REG) ? 0 : helper.In.z;
}
virtual string OpenCLString() const override
{
ostringstream ss, ss2;
intmax_t i = 0, varIndex = IndexInXform();
ss2 << "_" << XformIndexInEmber() << "]";
string index = ss2.str();
string w2 = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
ss << "\t{\n"
<< "\t\treal_t r2;\n"
<< "\n"
<< "\t\tif (vIn.x > EPS)\n"
<< "\t\t r2 = SQR(precalcSumSquares / vIn.x);\n"
<< "\t\telse\n"
<< "\t\t r2 = 2 * " << w2 << ";\n"
<< "\n"
<< "\t\tif (r2 < " << w2 << ")\n"
<< "\t\t{\n"
<< "\t\t real_t r = xform->m_VariationWeights[" << varIndex << "] * sqrt(" << w2 << " / r2 - 1);\n"
<< "\n"
<< "\t\t vOut.x = r * vIn.x;\n"
<< "\t\t vOut.y = r * vIn.y;\n"
<< "\t\t}\n"
<< "\t\telse\n"
<< "\t\t{\n"
<< "\t\t vOut.x = xform->m_VariationWeights[" << varIndex << "] * vIn.x;\n"
<< "\t\t vOut.y = xform->m_VariationWeights[" << varIndex << "] * vIn.y;\n"
<< "\t\t}\n"
<< "\n"
<< "\t\tvOut.z = " << ((m_VarType == VARTYPE_REG) ? "0" : "vIn.z") << ";\n"
<< "\t}\n";
return ss.str();
}
virtual void Precalc() override
{
m_W2 = SQR(m_Weight);
}
protected:
void Init()
{
string prefix = Prefix();
m_Params.clear();
m_Params.push_back(ParamWithName(true, &m_W2, prefix + "loonie3_w2"));//Precalc.
}
private:
T m_W2;//Precalc.
};
///
/// loonie_3D.
///
template
class EMBER_API Loonie3DVariation : public ParametricVariation
{
public:
Loonie3DVariation(T weight = 1.0) : ParametricVariation("loonie_3D", VAR_LOONIE3D, weight, true, false, false, false, true)
{
Init();
}
PARVARCOPY(Loonie3DVariation)
virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override
{
T kikr = helper.m_PrecalcAtanyx;
T efTez = helper.In.z == 0 ? kikr : helper.In.z;
T r2 = helper.m_PrecalcSumSquares + SQR(efTez);
if (r2 < m_Vv)
{
T r = m_Weight * std::sqrt(m_Vv / r2 - 1);
helper.Out.x = r * helper.In.x;
helper.Out.y = r * helper.In.y;
helper.Out.z = r * efTez * T(0.5);
}
else
{
helper.Out.x = m_Weight * helper.In.x;
helper.Out.y = m_Weight * helper.In.y;
helper.Out.z = m_Weight * efTez * T(0.5);
}
}
virtual string OpenCLString() const override
{
ostringstream ss, ss2;
intmax_t i = 0, varIndex = IndexInXform();
ss2 << "_" << XformIndexInEmber() << "]";
string index = ss2.str();
string vv = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
ss << "\t{\n"
<< "\t\treal_t kikr = precalcAtanyx;\n"
<< "\t\treal_t efTez = vIn.z == 0 ? kikr : vIn.z;\n"
<< "\t\treal_t r2 = precalcSumSquares + SQR(efTez);\n"
<< "\n"
<< "\t\tif (r2 < " << vv << ")\n"
<< "\t\t{\n"
<< "\t\t real_t r = xform->m_VariationWeights[" << varIndex << "] * sqrt(" << vv << " / r2 - 1);\n"
<< "\n"
<< "\t\t vOut.x = r * vIn.x;\n"
<< "\t\t vOut.y = r * vIn.y;\n"
<< "\t\t vOut.z = r * efTez * (real_t)(0.5);\n"
<< "\t\t}\n"
<< "\t\telse\n"
<< "\t\t{\n"
<< "\t\t vOut.x = xform->m_VariationWeights[" << varIndex << "] * vIn.x;\n"
<< "\t\t vOut.y = xform->m_VariationWeights[" << varIndex << "] * vIn.y;\n"
<< "\t\t vOut.z = xform->m_VariationWeights[" << varIndex << "] * efTez * (real_t)(0.5);\n"
<< "\t\t}\n"
<< "\t}\n";
return ss.str();
}
virtual void Precalc() override
{
m_Vv = SQR(m_Weight);
}
protected:
void Init()
{
string prefix = Prefix();
m_Params.clear();
m_Params.push_back(ParamWithName(true, &m_Vv, prefix + "loonie_3D_vv"));//Precalcs only, no params.
}
private:
T m_Vv;//Precalcs only, no params.
};
///
/// mcarpet.
///
template
class EMBER_API McarpetVariation : public ParametricVariation
{
public:
McarpetVariation(T weight = 1.0) : ParametricVariation("mcarpet", VAR_MCARPET, weight, true)
{
Init();
}
PARVARCOPY(McarpetVariation)
virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override
{
T t = helper.m_PrecalcSumSquares * T(0.25) + 1;
T r = m_Weight / t;
helper.Out.x = helper.In.x * r * m_X;
helper.Out.y = helper.In.y * r * m_Y;
helper.Out.x += (1 - (m_Twist * SQR(helper.In.x)) + helper.In.y) * m_Weight;//The += is intentional.
helper.Out.y += m_Tilt * helper.In.x * m_Weight;
helper.Out.z = (m_VarType == VARTYPE_REG) ? 0 : helper.In.z;
}
virtual string OpenCLString() const override
{
ostringstream ss, ss2;
intmax_t i = 0, varIndex = IndexInXform();
ss2 << "_" << XformIndexInEmber() << "]";
string index = ss2.str();
string x = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string y = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string twist = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string tilt = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
ss << "\t{\n"
<< "\t\treal_t t = precalcSumSquares * (real_t)(0.25) + 1;\n"
<< "\t\treal_t r = xform->m_VariationWeights[" << varIndex << "] / t;\n"
<< "\n"
<< "\t\tvOut.x = vIn.x * r * " << x << ";\n"
<< "\t\tvOut.y = vIn.y * r * " << y << ";\n"
<< "\t\tvOut.x += (1 - (" << twist << " * SQR(vIn.x)) + vIn.y) * xform->m_VariationWeights[" << varIndex << "];\n"
<< "\t\tvOut.y += " << tilt << " * vIn.x * xform->m_VariationWeights[" << varIndex << "];\n"
<< "\t\tvOut.z = " << ((m_VarType == VARTYPE_REG) ? "0" : "vIn.z") << ";\n"
<< "\t}\n";
return ss.str();
}
protected:
void Init()
{
string prefix = Prefix();
m_Params.clear();
m_Params.push_back(ParamWithName(&m_X, prefix + "mcarpet_x"));
m_Params.push_back(ParamWithName(&m_Y, prefix + "mcarpet_y"));
m_Params.push_back(ParamWithName(&m_Twist, prefix + "mcarpet_twist"));
m_Params.push_back(ParamWithName(&m_Tilt, prefix + "mcarpet_tilt"));
}
private:
T m_X;
T m_Y;
T m_Twist;
T m_Tilt;
};
///
/// waves2_3D.
/// Original used a precalc for the input points, but it doesn't
/// work with Ember's design, so it gets calculated on every iter
/// which is slightly slower.
///
template
class EMBER_API Waves23DVariation : public ParametricVariation
{
public:
Waves23DVariation(T weight = 1.0) : ParametricVariation("waves2_3D", VAR_WAVES23D, weight)
{
Init();
}
PARVARCOPY(Waves23DVariation)
virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override
{
T avgxy = (helper.In.x + helper.In.y) * T(0.5);
helper.Out.x = m_Weight * (helper.In.x + m_Scale * std::sin(helper.In.y * m_Freq));
helper.Out.y = m_Weight * (helper.In.y + m_Scale * std::sin(helper.In.x * m_Freq));
helper.Out.z = m_Weight * (helper.In.z + m_Scale * std::sin(avgxy * m_Freq));//Averages the XY to get Z.
}
virtual string OpenCLString() const override
{
ostringstream ss, ss2;
intmax_t i = 0, varIndex = IndexInXform();
ss2 << "_" << XformIndexInEmber() << "]";
string index = ss2.str();
string freq = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string scale = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
ss << "\t{\n"
<< "\t\treal_t avgxy = (vIn.x + vIn.y) * (real_t)(0.5);\n"
<< "\n"
<< "\t\tvOut.x = xform->m_VariationWeights[" << varIndex << "] * (vIn.x + " << scale << " * sin(vIn.y * " << freq << "));\n"
<< "\t\tvOut.y = xform->m_VariationWeights[" << varIndex << "] * (vIn.y + " << scale << " * sin(vIn.x * " << freq << "));\n"
<< "\t\tvOut.z = xform->m_VariationWeights[" << varIndex << "] * (vIn.z + " << scale << " * sin(avgxy * " << freq << "));\n"
<< "\t}\n";
return ss.str();
}
protected:
void Init()
{
string prefix = Prefix();
m_Params.clear();
m_Params.push_back(ParamWithName(&m_Freq, prefix + "waves2_3D_freq", 2));
m_Params.push_back(ParamWithName(&m_Scale, prefix + "waves2_3D_scale", 1));
}
private:
T m_Freq;
T m_Scale;
};
///
/// Pie3D.
///
template
class EMBER_API Pie3DVariation : public ParametricVariation
{
public:
Pie3DVariation(T weight = 1.0) : ParametricVariation("pie3D", VAR_PIE3D, weight)
{
Init();
}
PARVARCOPY(Pie3DVariation)
virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override
{
int sl = int(rand.Frand01() * m_Slices + T(0.5));
T a = m_Rotation + M_2PI * (sl + rand.Frand01() * m_Thickness) / m_Slices;
T r = m_Weight * rand.Frand01();
helper.Out.x = r * std::cos(a);
helper.Out.y = r * std::sin(a);
helper.Out.z = m_Weight * std::sin(r);
}
virtual string OpenCLString() const override
{
ostringstream ss, ss2;
intmax_t i = 0, varIndex = IndexInXform();
ss2 << "_" << XformIndexInEmber() << "]";
string index = ss2.str();
string slices = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string rotation = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string thickness = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
ss << "\t{\n"
<< "\t\tint sl = (int)(MwcNext01(mwc) * " << slices << " + (real_t)(0.5));\n"
<< "\t\treal_t a = " << rotation << " + M_2PI * (sl + MwcNext01(mwc) * " << thickness << ") / " << slices << ";\n"
<< "\t\treal_t r = xform->m_VariationWeights[" << varIndex << "] * MwcNext01(mwc);\n"
<< "\n"
<< "\t\tvOut.x = r * cos(a);\n"
<< "\t\tvOut.y = r * sin(a);\n"
<< "\t\tvOut.z = xform->m_VariationWeights[" << varIndex << "] * sin(r);\n"
<< "\t}\n";
return ss.str();
}
virtual void Random(QTIsaac& rand) override
{
m_Params[0].Set(10 * rand.Frand01());//Slices.
m_Params[1].Set(M_2PI * rand.Frand11());//Rotation.
m_Thickness = rand.Frand01();
}
protected:
void Init()
{
string prefix = Prefix();
m_Params.clear();
m_Params.push_back(ParamWithName(&m_Slices, prefix + "pie3D_slices", 6, INTEGER_NONZERO, 1));
m_Params.push_back(ParamWithName(&m_Rotation, prefix + "pie3D_rotation", T(0.5), REAL_CYCLIC, 0, M_2PI));
m_Params.push_back(ParamWithName(&m_Thickness, prefix + "pie3D_thickness", T(0.5), REAL, 0, 1));
}
private:
T m_Slices;
T m_Rotation;
T m_Thickness;
};
///
/// popcorn2_3D.
///
template
class EMBER_API Popcorn23DVariation : public ParametricVariation
{
public:
Popcorn23DVariation(T weight = 1.0) : ParametricVariation("popcorn2_3D", VAR_POPCORN23D, weight, false, false, false, false, true)
{
Init();
}
PARVARCOPY(Popcorn23DVariation)
virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override
{
T otherZ, tempPZ = 0;
T tempTZ = helper.In.z == 0 ? m_Vv * m_SinTanC * helper.m_PrecalcAtanyx : helper.In.z;
if (m_VarType == VARTYPE_PRE)
otherZ = helper.In.z;
else
otherZ = outPoint.m_Z;
if (otherZ == 0)
tempPZ = m_Vv * m_SinTanC * helper.m_PrecalcAtanyx;
helper.Out.x = m_HalfWeight * (helper.In.x + m_X * std::sin(SafeTan(m_C * helper.In.y)));
helper.Out.y = m_HalfWeight * (helper.In.y + m_Y * std::sin(SafeTan(m_C * helper.In.x)));
helper.Out.z = tempPZ + m_Vv * (m_Z * m_SinTanC * tempTZ);
}
virtual string OpenCLString() const override
{
ostringstream ss, ss2;
int i = 0;
ss2 << "_" << XformIndexInEmber() << "]";
string index = ss2.str();
string x = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string y = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string z = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string c = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string stc = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string hw = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string vv = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
ss << "\t{\n"
<< "\t\treal_t otherZ, tempPZ = 0;\n"
<< "\t\treal_t tempTZ = vIn.z == 0 ? " << vv << " * " << stc << " * precalcAtanyx : vIn.z;\n";
if (m_VarType == VARTYPE_PRE)
ss << "\t\totherZ = vIn.z;\n";
else
ss << "\t\totherZ = outPoint->m_Z;\n";
ss << "\t\tif (otherZ == 0)\n"
<< "\t\t tempPZ = " << vv << " * " << stc << " * precalcAtanyx;\n"
<< "\n"
<< "\t\tvOut.x = " << hw << " * (vIn.x + " << x << " * sin(tan(" << c << " * vIn.y)));\n"
<< "\t\tvOut.y = " << hw << " * (vIn.y + " << y << " * sin(tan(" << c << " * vIn.x)));\n"
<< "\t\tvOut.z = tempPZ + " << vv << " * (" << z << " * " << stc << " * tempTZ);\n"
<< "\t}\n";
return ss.str();
}
virtual vector OpenCLGlobalFuncNames() const override
{
return vector { "Sqr" };
}
virtual void Precalc() override
{
m_SinTanC = std::sin(SafeTan(m_C));
m_HalfWeight = m_Weight * T(0.5);
if (fabs(m_Weight) <= 1)
m_Vv = fabs(m_Weight) * m_Weight;//Sqr(m_Weight) value retaining sign.
else
m_Vv = m_Weight;
}
virtual void Random(QTIsaac& rand) override
{
m_X = T(0.2) + rand.Frand01();
m_Y = T(0.2) * rand.Frand01();
m_Z = T(0.2) * rand.Frand01();
m_C = 5 * rand.Frand01();
}
protected:
void Init()
{
string prefix = Prefix();
m_Params.clear();
m_Params.push_back(ParamWithName(&m_X, prefix + "popcorn2_3D_x", T(0.1)));
m_Params.push_back(ParamWithName(&m_Y, prefix + "popcorn2_3D_y", T(0.1)));
m_Params.push_back(ParamWithName(&m_Z, prefix + "popcorn2_3D_z", T(0.1)));
m_Params.push_back(ParamWithName(&m_C, prefix + "popcorn2_3D_c", 3));
m_Params.push_back(ParamWithName(true, &m_SinTanC, prefix + "popcorn2_3D_sintanc"));
m_Params.push_back(ParamWithName(true, &m_HalfWeight, prefix + "popcorn2_3D_half_weight"));
m_Params.push_back(ParamWithName(true, &m_Vv, prefix + "popcorn2_3D_vv"));
}
private:
T m_X;
T m_Y;
T m_Z;
T m_C;
T m_SinTanC;//Precalcs.
T m_HalfWeight;
T m_Vv;
};
///
/// sinusoidal3d.
///
template
class EMBER_API Sinusoidal3DVariation : public Variation
{
public:
Sinusoidal3DVariation(T weight = 1.0) : Variation("sinusoidal3D", VAR_SINUSOIDAL3D, weight) { }
VARCOPY(Sinusoidal3DVariation)
virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override
{
helper.Out.x = m_Weight * std::sin(helper.In.x);
helper.Out.y = m_Weight * std::sin(helper.In.y);
helper.Out.z = m_Weight * (std::atan2(SQR(helper.In.x), SQR(helper.In.y)) * std::cos(helper.In.z));
}
virtual string OpenCLString() const override
{
ostringstream ss;
intmax_t varIndex = IndexInXform();
ss << "\t{\n"
<< "\t\tvOut.x = xform->m_VariationWeights[" << varIndex << "] * sin(vIn.x);\n"
<< "\t\tvOut.y = xform->m_VariationWeights[" << varIndex << "] * sin(vIn.y);\n"
<< "\t\tvOut.z = xform->m_VariationWeights[" << varIndex << "] * (atan2(SQR(vIn.x), SQR(vIn.y)) * cos(vIn.z));\n"
<< "\t}\n";
return ss.str();
}
};
///
/// scry_3D.
///
template
class EMBER_API Scry3DVariation : public ParametricVariation
{
public:
Scry3DVariation(T weight = 1.0) : ParametricVariation("scry_3D", VAR_SCRY3D, weight, true, false, false, false, true)
{
Init();
}
PARVARCOPY(Scry3DVariation)
virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override
{
T t = helper.m_PrecalcSumSquares + SQR(helper.In.z);
T r = 1 / (std::sqrt(t) * (t + m_InvWeight));
T z = helper.In.z == 0 ? helper.m_PrecalcAtanyx : helper.In.z;
helper.Out.x = helper.In.x * r;
helper.Out.y = helper.In.y * r;
helper.Out.z = z * r;
}
virtual string OpenCLString() const override
{
ostringstream ss, ss2;
int i = 0;
ss2 << "_" << XformIndexInEmber() << "]";
string index = ss2.str();
string invWeight = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
ss << "\t{\n"
<< "\t\treal_t t = precalcSumSquares + SQR(vIn.z);\n"
<< "\t\treal_t r = 1 / (sqrt(t) * (t + " << invWeight << "));\n"
<< "\t\treal_t z = vIn.z == 0 ? precalcAtanyx : vIn.z;\n"
<< "\n"
<< "\t\tvOut.x = vIn.x * r;\n"
<< "\t\tvOut.y = vIn.y * r;\n"
<< "\t\tvOut.z = z * r;\n"
<< "\t}\n";
return ss.str();
}
virtual void Precalc() override
{
m_InvWeight = 1 / Zeps(m_Weight);
}
protected:
void Init()
{
string prefix = Prefix();
m_Params.clear();
m_Params.push_back(ParamWithName(true, &m_InvWeight, prefix + "scry_3D_inv_weight"));//Precalcs only, no params.
}
private:
T m_InvWeight;//Precalcs only, no params.
};
///
/// shredlin.
///
template
class EMBER_API ShredlinVariation : public ParametricVariation
{
public:
ShredlinVariation(T weight = 1.0) : ParametricVariation("shredlin", VAR_SHRED_LIN, weight)
{
Init();
}
PARVARCOPY(ShredlinVariation)
virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override
{
const int xpos = helper.In.x < 0;
const int ypos = helper.In.y < 0;
const T xrng = helper.In.x / m_XDistance;
const T yrng = helper.In.y / m_YDistance;
helper.Out.x = m_Xw * ((xrng - int(xrng)) * m_XWidth + int(xrng) + (T(0.5) - xpos) * m_1mX);
helper.Out.y = m_Yw * ((yrng - int(yrng)) * m_YWidth + int(yrng) + (T(0.5) - ypos) * m_1mY);
helper.Out.z = m_Weight * helper.In.z;
}
virtual string OpenCLString() const override
{
ostringstream ss, ss2;
intmax_t i = 0, varIndex = IndexInXform();
ss2 << "_" << XformIndexInEmber() << "]";
string index = ss2.str();
string xdist = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string xwidth = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string ydist = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string ywidth = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string xw = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string yw = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string onemx = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string onemy = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
ss << "\t{\n"
<< "\t\tconst int xpos = vIn.x < 0;\n"
<< "\t\tconst int ypos = vIn.y < 0;\n"
<< "\t\tconst real_t xrng = vIn.x / " << xdist << ";\n"
<< "\t\tconst real_t yrng = vIn.y / " << ydist << ";\n"
<< "\n"
<< "\t\tvOut.x = " << xw << " * ((xrng - (int)xrng) * " << xwidth << " + (int)xrng + ((real_t)(0.5) - xpos) * " << onemx << ");\n"
<< "\t\tvOut.y = " << yw << " * ((yrng - (int)yrng) * " << ywidth << " + (int)yrng + ((real_t)(0.5) - ypos) * " << onemy << ");\n"
<< "\t\tvOut.z = xform->m_VariationWeights[" << varIndex << "] * vIn.z;\n"
<< "\t}\n";
return ss.str();
}
virtual void Precalc() override
{
m_Xw = m_Weight * m_XDistance;
m_Yw = m_Weight * m_YDistance;
m_1mX = 1 - m_XWidth;
m_1mY = 1 - m_YWidth;
}
protected:
void Init()
{
string prefix = Prefix();
m_Params.clear();
m_Params.push_back(ParamWithName(&m_XDistance, prefix + "shredlin_xdistance", 1, REAL_NONZERO));
m_Params.push_back(ParamWithName(&m_XWidth, prefix + "shredlin_xwidth", T(0.5), REAL, -1, 1));
m_Params.push_back(ParamWithName(&m_YDistance, prefix + "shredlin_ydistance", 1, REAL_NONZERO));
m_Params.push_back(ParamWithName(&m_YWidth, prefix + "shredlin_ywidth", T(0.5), REAL, -1, 1));
m_Params.push_back(ParamWithName(true, &m_Xw, prefix + "shredlin_xw"));
m_Params.push_back(ParamWithName(true, &m_Yw, prefix + "shredlin_yw"));
m_Params.push_back(ParamWithName(true, &m_1mX, prefix + "shredlin_1mx"));
m_Params.push_back(ParamWithName(true, &m_1mY, prefix + "shredlin_1my"));
}
private:
T m_XDistance;
T m_XWidth;
T m_YDistance;
T m_YWidth;
T m_Xw;//Precalc.
T m_Yw;
T m_1mX;
T m_1mY;
};
///
/// splitbrdr.
///
template
class EMBER_API SplitBrdrVariation : public ParametricVariation
{
public:
SplitBrdrVariation(T weight = 1.0) : ParametricVariation("SplitBrdr", VAR_SPLIT_BRDR, weight, true)
{
Init();
}
PARVARCOPY(SplitBrdrVariation)
virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override
{
T b = m_Weight / (helper.m_PrecalcSumSquares * T(0.25) + 1);
T roundX = Rint(helper.In.x);
T roundY = Rint(helper.In.y);
T offsetX = helper.In.x - roundX;
T offsetY = helper.In.y - roundY;
helper.Out.x = helper.In.x * b;
helper.Out.y = helper.In.y * b;
if (rand.Frand01() >= T(0.75))
{
helper.Out.x += m_Weight * (offsetX * T(0.5) + roundX);
helper.Out.y += m_Weight * (offsetY * T(0.5) + roundY);
}
else
{
if (fabs(offsetX) >= fabs(offsetY))
{
if (offsetX >= 0)
{
helper.Out.x += m_Weight * (offsetX * T(0.5) + roundX + m_X);
helper.Out.y += m_Weight * (offsetY * T(0.5) + roundY + m_Y * offsetY / offsetX);
}
else
{
helper.Out.x += m_Weight * (offsetX * T(0.5) + roundX - m_Y);
helper.Out.y += m_Weight * (offsetY * T(0.5) + roundY - m_Y * offsetY / offsetX);
}
}
else
{
if (offsetY >= 0)
{
helper.Out.y += m_Weight * (offsetY * T(0.5) + roundY + m_Y);
helper.Out.x += m_Weight * (offsetX * T(0.5) + roundX + offsetX / offsetY * m_Y);
}
else
{
helper.Out.y += m_Weight * (offsetY * T(0.5) + roundY - m_Y);
helper.Out.x += m_Weight * (offsetX * T(0.5) + roundX - offsetX / offsetY * m_X);
}
}
}
helper.Out.x += helper.In.x * m_Px;
helper.Out.y += helper.In.y * m_Py;
helper.Out.z = (m_VarType == VARTYPE_REG) ? 0 : helper.In.z;
}
virtual string OpenCLString() const override
{
ostringstream ss, ss2;
intmax_t i = 0, varIndex = IndexInXform();
ss2 << "_" << XformIndexInEmber() << "]";
string index = ss2.str();
string x = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string y = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string px = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string py = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
ss << "\t{\n"
<< "\t\treal_t b = xform->m_VariationWeights[" << varIndex << "] / (precalcSumSquares * (real_t)(0.25) + 1);\n"
<< "\t\treal_t roundX = rint(vIn.x);\n"
<< "\t\treal_t roundY = rint(vIn.y);\n"
<< "\t\treal_t offsetX = vIn.x - roundX;\n"
<< "\t\treal_t offsetY = vIn.y - roundY;\n"
<< "\n"
<< "\t\tvOut.x = vIn.x * b;\n"
<< "\t\tvOut.y = vIn.y * b;\n"
<< "\n"
<< "\t\tif (MwcNext01(mwc) >= (real_t)(0.75))\n"
<< "\t\t{\n"
<< "\t\t vOut.x += xform->m_VariationWeights[" << varIndex << "] * (offsetX * (real_t)(0.5) + roundX);\n"
<< "\t\t vOut.y += xform->m_VariationWeights[" << varIndex << "] * (offsetY * (real_t)(0.5) + roundY);\n"
<< "\t\t}\n"
<< "\t\telse\n"
<< "\t\t{\n"
<< "\t\t if (fabs(offsetX) >= fabs(offsetY))\n"
<< "\t\t {\n"
<< "\t\t if (offsetX >= 0)\n"
<< "\t\t {\n"
<< "\t\t vOut.x += xform->m_VariationWeights[" << varIndex << "] * (offsetX * (real_t)(0.5) + roundX + " << x << ");\n"
<< "\t\t vOut.y += xform->m_VariationWeights[" << varIndex << "] * (offsetY * (real_t)(0.5) + roundY + " << y << " * offsetY / offsetX);\n"
<< "\t\t }\n"
<< "\t\t else\n"
<< "\t\t {\n"
<< "\t\t vOut.x += xform->m_VariationWeights[" << varIndex << "] * (offsetX * (real_t)(0.5) + roundX - " << y << ");\n"
<< "\t\t vOut.y += xform->m_VariationWeights[" << varIndex << "] * (offsetY * (real_t)(0.5) + roundY - " << y << " * offsetY / offsetX);\n"
<< "\t\t }\n"
<< "\t\t }\n"
<< "\t\t else\n"
<< "\t\t {\n"
<< "\t\t if (offsetY >= 0)\n"
<< "\t\t {\n"
<< "\t\t vOut.y += xform->m_VariationWeights[" << varIndex << "] * (offsetY * (real_t)(0.5) + roundY + " << y << ");\n"
<< "\t\t vOut.x += xform->m_VariationWeights[" << varIndex << "] * (offsetX * (real_t)(0.5) + roundX + offsetX / offsetY * " << y << ");\n"
<< "\t\t }\n"
<< "\t\t else\n"
<< "\t\t {\n"
<< "\t\t vOut.y += xform->m_VariationWeights[" << varIndex << "] * (offsetY * (real_t)(0.5) + roundY - " << y << ");\n"
<< "\t\t vOut.x += xform->m_VariationWeights[" << varIndex << "] * (offsetX * (real_t)(0.5) + roundX - offsetX / offsetY * " << x << ");\n"
<< "\t\t }\n"
<< "\t\t }\n"
<< "\t\t}\n"
<< "\n"
<< "\t\tvOut.x += vIn.x * " << px << ";\n"
<< "\t\tvOut.y += vIn.y * " << py << ";\n"
<< "\t\tvOut.z = " << ((m_VarType == VARTYPE_REG) ? "0" : "vIn.z") << ";\n"
<< "\t}\n";
return ss.str();
}
protected:
void Init()
{
string prefix = Prefix();
m_Params.clear();
m_Params.push_back(ParamWithName(&m_X, prefix + "SplitBrdr_x", T(0.25)));//Original used a prefix of splitb_, which is incompatible with Ember's design.
m_Params.push_back(ParamWithName(&m_Y, prefix + "SplitBrdr_y", T(0.25)));
m_Params.push_back(ParamWithName(&m_Px, prefix + "SplitBrdr_px"));
m_Params.push_back(ParamWithName(&m_Py, prefix + "SplitBrdr_py"));
}
private:
T m_X;
T m_Y;
T m_Px;
T m_Py;
};
///
/// wdisc.
///
template
class EMBER_API WdiscVariation : public Variation
{
public:
WdiscVariation(T weight = 1.0) : Variation("wdisc", VAR_WDISC, weight, true, true, false, false, true) { }
VARCOPY(WdiscVariation)
virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac