#pragma once
#include "Variation.h"
namespace EmberNs
{
///
/// Linear:
/// nx = tx;
/// ny = ty;
/// p[0] += weight * nx;
/// p[1] += weight * ny;
///
template
class EMBER_API LinearVariation : public Variation
{
public:
LinearVariation(T weight = 1.0) : Variation("linear", VAR_LINEAR, weight) { }
VARCOPY(LinearVariation)
virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override
{
helper.Out.x = m_Weight * helper.In.x;
helper.Out.y = m_Weight * helper.In.y;
helper.Out.z = m_Weight * helper.In.z;
}
virtual string OpenCLString() override
{
ostringstream ss;
intmax_t varIndex = IndexInXform();
ss << "\t{\n"
<< "\t\tvOut.x = xform->m_VariationWeights[" << varIndex << "] * vIn.x;\n"
<< "\t\tvOut.y = xform->m_VariationWeights[" << varIndex << "] * vIn.y;\n"
<< "\t\tvOut.z = xform->m_VariationWeights[" << varIndex << "] * vIn.z;\n"
<< "\t}\n";
return ss.str();
}
};
///
/// Sinusoidal:
/// nx = sin(tx);
/// ny = sin(ty);
/// p[0] += weight * nx;
/// p[1] += weight * ny;
///
template
class EMBER_API SinusoidalVariation : public Variation
{
public:
SinusoidalVariation(T weight = 1.0) : Variation("sinusoidal", VAR_SINUSOIDAL, weight) { }
VARCOPY(SinusoidalVariation)
virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override
{
helper.Out.x = m_Weight * sin(helper.In.x);
helper.Out.y = m_Weight * sin(helper.In.y);
helper.Out.z = m_Weight * helper.In.z;
}
virtual string OpenCLString() 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 << "] * vIn.z;\n"
<< "\t}\n";
return ss.str();
}
};
///
/// Spherical:
/// T r2 = tx * tx + ty * ty + 1e-6;
/// nx = tx / r2;
/// ny = ty / r2;
/// p[0] += weight * nx;
/// p[1] += weight * ny;
///
template
class EMBER_API SphericalVariation : public Variation
{
public:
SphericalVariation(T weight = 1.0) : Variation("spherical", VAR_SPHERICAL, weight, true) { }
VARCOPY(SphericalVariation)
virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override
{
T r2 = m_Weight / Zeps(helper.m_PrecalcSumSquares);
helper.Out.x = r2 * helper.In.x;
helper.Out.y = r2 * helper.In.y;
helper.Out.z = m_Weight * helper.In.z;
}
virtual string OpenCLString() override
{
ostringstream ss;
intmax_t varIndex = IndexInXform();
ss << "\t{\n"
<< "\t\treal_t r2 = xform->m_VariationWeights[" << varIndex << "] / Zeps(precalcSumSquares);\n"
<< "\n"
<< "\t\tvOut.x = r2 * vIn.x;\n"
<< "\t\tvOut.y = r2 * vIn.y;\n"
<< "\t\tvOut.z = xform->m_VariationWeights[" << varIndex << "] * vIn.z;\n"
<< "\t}\n";
return ss.str();
}
};
///
/// Swirl:
/// double r2 = tx * tx + ty * ty;
/// double c1 = sin(r2);
/// double c2 = cos(r2);
/// nx = c1 * tx - c2 * ty;
/// ny = c2 * tx + c1 * ty;
/// p[0] += weight * nx;
/// p[1] += weight * ny;
///
template
class EMBER_API SwirlVariation : public Variation
{
public:
SwirlVariation(T weight = 1.0) : Variation("swirl", VAR_SWIRL, weight, true) { }
VARCOPY(SwirlVariation)
virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override
{
T c1, c2;
sincos(helper.m_PrecalcSumSquares, &c1, &c2);
helper.Out.x = m_Weight * (c1 * helper.In.x - c2 * helper.In.y);
helper.Out.y = m_Weight * (c2 * helper.In.x + c1 * helper.In.y);
helper.Out.z = m_Weight * helper.In.z;
}
virtual string OpenCLString() override
{
ostringstream ss;
intmax_t varIndex = IndexInXform();
ss << "\t{\n"
<< "\t\treal_t c1 = sin(precalcSumSquares);\n"
<< "\t\treal_t c2 = cos(precalcSumSquares);\n"
<< "\n"
<< "\t\tvOut.x = xform->m_VariationWeights[" << varIndex << "] * (c1 * vIn.x - c2 * vIn.y);\n"
<< "\t\tvOut.y = xform->m_VariationWeights[" << varIndex << "] * (c2 * vIn.x + c1 * vIn.y);\n"
<< "\t\tvOut.z = xform->m_VariationWeights[" << varIndex << "] * vIn.z;\n"
<< "\t}\n";
return ss.str();
}
};
///
/// Horseshoe:
/// a = atan2(tx, ty);
/// c1 = sin(a);
/// c2 = cos(a);
/// nx = c1 * tx - c2 * ty;
/// ny = c2 * tx + c1 * ty;
/// p[0] += weight * nx;
/// p[1] += weight * ny;
///
template
class EMBER_API HorseshoeVariation : public Variation
{
public:
HorseshoeVariation(T weight = 1.0) : Variation("horseshoe", VAR_HORSESHOE, weight, true, true) { }
VARCOPY(HorseshoeVariation)
virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override
{
T r = m_Weight / Zeps(helper.m_PrecalcSqrtSumSquares);
helper.Out.x = (helper.In.x - helper.In.y) * (helper.In.x + helper.In.y) * r;
helper.Out.y = 2 * helper.In.x * helper.In.y * r;
helper.Out.z = m_Weight * helper.In.z;
}
virtual string OpenCLString() override
{
ostringstream ss;
intmax_t varIndex = IndexInXform();
ss << "\t{\n"
<< "\t\treal_t r = xform->m_VariationWeights[" << varIndex << "] / Zeps(precalcSqrtSumSquares);\n"
<< "\n"
<< "\t\tvOut.x = (vIn.x - vIn.y) * (vIn.x + vIn.y) * r;\n"
<< "\t\tvOut.y = 2.0 * vIn.x * vIn.y * r;\n"
<< "\t\tvOut.z = xform->m_VariationWeights[" << varIndex << "] * vIn.z;\n"
<< "\t}\n";
return ss.str();
}
};
///
/// Polar:
/// nx = atan2(tx, ty) / M_PI;
/// ny = sqrt(tx * tx + ty * ty) - 1.0;
/// p[0] += weight * nx;
/// p[1] += weight * ny;
///
template
class EMBER_API PolarVariation : public Variation
{
public:
PolarVariation(T weight = 1.0) : Variation("polar", VAR_POLAR, weight, true, true, false, true, false) { }
VARCOPY(PolarVariation)
virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override
{
helper.Out.x = m_Weight * (helper.m_PrecalcAtanxy * T(M_1_PI));
helper.Out.y = m_Weight * (helper.m_PrecalcSqrtSumSquares - 1);
helper.Out.z = m_Weight * helper.In.z;
}
virtual string OpenCLString() override
{
ostringstream ss;
intmax_t varIndex = IndexInXform();
ss << "\t{\n"
<< "\t\tvOut.x = xform->m_VariationWeights[" << varIndex << "] * (precalcAtanxy * M_1_PI);\n"
<< "\t\tvOut.y = xform->m_VariationWeights[" << varIndex << "] * (precalcSqrtSumSquares - 1.0);\n"
<< "\t\tvOut.z = xform->m_VariationWeights[" << varIndex << "] * vIn.z;\n"
<< "\t}\n";
return ss.str();
}
};
///
/// Handkerchief:
/// a = atan2(tx, ty);
/// r = sqrt(tx * tx + ty * ty);
/// p[0] += weight * sin(a + r) * r;
/// p[1] += weight * cos(a - r) * r;
///
template
class EMBER_API HandkerchiefVariation : public Variation
{
public:
HandkerchiefVariation(T weight = 1.0) : Variation("handkerchief", VAR_HANDKERCHIEF, weight, true, true, false, true) { }
VARCOPY(HandkerchiefVariation)
virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override
{
helper.Out.x = m_Weight * helper.m_PrecalcSqrtSumSquares * sin(helper.m_PrecalcAtanxy + helper.m_PrecalcSqrtSumSquares);
helper.Out.y = m_Weight * helper.m_PrecalcSqrtSumSquares * cos(helper.m_PrecalcAtanxy - helper.m_PrecalcSqrtSumSquares);
helper.Out.z = m_Weight * helper.In.z;
}
virtual string OpenCLString() override
{
ostringstream ss;
intmax_t varIndex = IndexInXform();
ss << "\t{\n"
<< "\t\tvOut.x = xform->m_VariationWeights[" << varIndex << "] * precalcSqrtSumSquares * sin(precalcAtanxy + precalcSqrtSumSquares);\n"
<< "\t\tvOut.y = xform->m_VariationWeights[" << varIndex << "] * precalcSqrtSumSquares * cos(precalcAtanxy - precalcSqrtSumSquares);\n"
<< "\t\tvOut.z = xform->m_VariationWeights[" << varIndex << "] * vIn.z;\n"
<< "\t}\n";
return ss.str();
}
};
///
/// Heart:
/// a = atan2(tx, ty);
/// r = sqrt(tx * tx + ty * ty);
/// a *= r;
/// p[0] += weight * sin(a) * r;
/// p[1] += weight * cos(a) * -r;
///
template
class EMBER_API HeartVariation : public Variation
{
public:
HeartVariation(T weight = 1.0) : Variation("heart", VAR_HEART, weight, true, true, false, true) { }
VARCOPY(HeartVariation)
virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override
{
T a = helper.m_PrecalcSqrtSumSquares * helper.m_PrecalcAtanxy;
T r = m_Weight * helper.m_PrecalcSqrtSumSquares;
helper.Out.x = r * sin(a);
helper.Out.y = (-r) * cos(a);
helper.Out.z = m_Weight * helper.In.z;
}
virtual string OpenCLString() override
{
ostringstream ss;
intmax_t varIndex = IndexInXform();
ss << "\t{\n"
<< "\t\treal_t a = precalcSqrtSumSquares * precalcAtanxy;\n"
<< "\t\treal_t r = xform->m_VariationWeights[" << varIndex << "] * precalcSqrtSumSquares;\n"
<< "\n"
<< "\t\tvOut.x = r * sin(a);\n"
<< "\t\tvOut.y = (-r) * cos(a);\n"
<< "\t\tvOut.z = xform->m_VariationWeights[" << varIndex << "] * vIn.z;\n"
<< "\t}\n";
return ss.str();
}
};
///
/// Disc:
/// nx = tx * M_PI;
/// ny = ty * M_PI;
/// a = atan2(nx, ny);
/// r = sqrt(nx * nx + ny * ny);
/// p[0] += weight * sin(r) * a / M_PI;
/// p[1] += weight * cos(r) * a / M_PI;
///
template
class EMBER_API DiscVariation : public ParametricVariation
{
public:
DiscVariation(T weight = 1.0) : ParametricVariation("disc", VAR_DISC, weight, true, true, false, true)
{
Init();
}
PARVARCOPY(DiscVariation)
virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override
{
T val = T(M_PI) * helper.m_PrecalcSqrtSumSquares;
T r = m_WeightByPI * helper.m_PrecalcAtanxy;
helper.Out.x = sin(val) * r;
helper.Out.y = cos(val) * r;
helper.Out.z = m_Weight * helper.In.z;
}
virtual string OpenCLString() override
{
ostringstream ss, ss2;
intmax_t i = 0, varIndex = IndexInXform();
ss2 << "_" << XformIndexInEmber() << "]";
string index = ss2.str();
string weightByPI = "parVars[" + ToUpper(m_Params[i++].Name()) + index;//Precalcs only, no params.
ss << "\t{\n"
<< "\t\treal_t val = M_PI * precalcSqrtSumSquares;\n"
<< "\t\treal_t r = " << weightByPI << " * precalcAtanxy;\n"
<< "\n"
<< "\t\tvOut.x = sin(val) * r;\n"
<< "\t\tvOut.y = cos(val) * r;\n"
<< "\t\tvOut.z = xform->m_VariationWeights[" << varIndex << "] * vIn.z;\n"
<< "\t}\n";
return ss.str();
}
virtual void Precalc() override
{
m_WeightByPI = m_Weight * T(M_1_PI);
}
protected:
void Init()
{
string prefix = Prefix();
m_Params.clear();
m_Params.push_back(ParamWithName(true, &m_WeightByPI, prefix + "disc_weight_by_pi"));//Precalcs only, no params.
}
private:
T m_WeightByPI;//Precalcs only, no params.
};
///
/// Spiral:
/// a = atan2(tx, ty);
/// r = sqrt(tx * tx + ty * ty) + 1e-6;
/// p[0] += weight * (cos(a) + sin(r)) / r;
/// p[1] += weight * (sin(a) - cos(r)) / r;
///
template
class EMBER_API SpiralVariation : public Variation
{
public:
SpiralVariation(T weight = 1.0) : Variation("spiral", VAR_SPIRAL, weight, true, true, true) { }
VARCOPY(SpiralVariation)
virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override
{
T r = Zeps(helper.m_PrecalcSqrtSumSquares);
T r1 = m_Weight / r;
helper.Out.x = r1 * (helper.m_PrecalcCosa + sin(r));
helper.Out.y = r1 * (helper.m_PrecalcSina - cos(r));
helper.Out.z = m_Weight * helper.In.z;
}
virtual string OpenCLString() override
{
ostringstream ss;
intmax_t varIndex = IndexInXform();
ss << "\t{\n"
<< "\t\treal_t r = Zeps(precalcSqrtSumSquares);\n"
<< "\t\treal_t r1 = xform->m_VariationWeights[" << varIndex << "] / r;\n"
<< "\n"
<< "\t\tvOut.x = r1 * (precalcCosa + sin(r));\n"
<< "\t\tvOut.y = r1 * (precalcSina - cos(r));\n"
<< "\t\tvOut.z = xform->m_VariationWeights[" << varIndex << "] * vIn.z;\n"
<< "\t}\n";
return ss.str();
}
};
///
/// Hyperbolic:
/// a = atan2(tx, ty);
/// r = sqrt(tx * tx + ty * ty) + 1e-6;
/// p[0] += weight * sin(a) / r;
/// p[1] += weight * cos(a) * r;
///
template
class EMBER_API HyperbolicVariation : public Variation
{
public:
HyperbolicVariation(T weight = 1.0) : Variation("hyperbolic", VAR_HYPERBOLIC, weight, true, true, true) { }
VARCOPY(HyperbolicVariation)
virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override
{
T r = Zeps(helper.m_PrecalcSqrtSumSquares);
helper.Out.x = m_Weight * helper.m_PrecalcSina / r;
helper.Out.y = m_Weight * helper.m_PrecalcCosa * r;
helper.Out.z = m_Weight * helper.In.z;
}
virtual string OpenCLString() override
{
ostringstream ss;
intmax_t varIndex = IndexInXform();
ss << "\t{\n"
<< "\t\treal_t r = Zeps(precalcSqrtSumSquares);\n"
<< "\n"
<< "\t\tvOut.x = xform->m_VariationWeights[" << varIndex << "] * precalcSina / r;\n"
<< "\t\tvOut.y = xform->m_VariationWeights[" << varIndex << "] * precalcCosa * r;\n"
<< "\t\tvOut.z = xform->m_VariationWeights[" << varIndex << "] * vIn.z;\n"
<< "\t}\n";
return ss.str();
}
};
///
/// Diamond:
/// a = atan2(tx, ty);
/// r = sqrt(tx * tx + ty * ty);
/// p[0] += weight * sin(a) * cos(r);
/// p[1] += weight * cos(a) * sin(r);
///
template
class EMBER_API DiamondVariation : public Variation
{
public:
DiamondVariation(T weight = 1.0) : Variation("diamond", VAR_DIAMOND, weight, true, true, true) { }
VARCOPY(DiamondVariation)
virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override
{
helper.Out.x = m_Weight * helper.m_PrecalcSina * cos(helper.m_PrecalcSqrtSumSquares);
helper.Out.y = m_Weight * helper.m_PrecalcCosa * sin(helper.m_PrecalcSqrtSumSquares);
helper.Out.z = m_Weight * helper.In.z;
}
virtual string OpenCLString() override
{
ostringstream ss;
intmax_t varIndex = IndexInXform();
ss << "\t{\n"
<< "\t\tvOut.x = xform->m_VariationWeights[" << varIndex << "] * precalcSina * cos(precalcSqrtSumSquares);\n"
<< "\t\tvOut.y = xform->m_VariationWeights[" << varIndex << "] * precalcCosa * sin(precalcSqrtSumSquares);\n"
<< "\t\tvOut.z = xform->m_VariationWeights[" << varIndex << "] * vIn.z;\n"
<< "\t}\n";
return ss.str();
}
};
///
/// Ex:
/// a = atan2(tx, ty);
/// r = sqrt(tx * tx + ty * ty);
/// n0 = sin(a + r);
/// n1 = cos(a - r);
/// m0 = n0 * n0 * n0 * r;
/// m1 = n1 * n1 * n1 * r;
/// p[0] += weight * (m0 + m1);
/// p[1] += weight * (m0 - m1);
///
template
class EMBER_API ExVariation : public Variation
{
public:
ExVariation(T weight = 1.0) : Variation("ex", VAR_EX, weight, true, true, false, true) { }
VARCOPY(ExVariation)
virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override
{
T a = helper.m_PrecalcAtanxy;
T r = helper.m_PrecalcSqrtSumSquares;
T n0 = sin(a + r);
T n1 = cos(a - r);
T m0 = n0 * n0 * n0 * r;
T m1 = n1 * n1 * n1 * r;
helper.Out.x = m_Weight * (m0 + m1);
helper.Out.y = m_Weight * (m0 - m1);
helper.Out.z = m_Weight * helper.In.z;
}
virtual string OpenCLString() override
{
ostringstream ss;
intmax_t varIndex = IndexInXform();
ss << "\t{\n"
<< "\t\treal_t a = precalcAtanxy;\n"
<< "\t\treal_t r = precalcSqrtSumSquares;\n"
<< "\t\treal_t n0 = sin(a + r);\n"
<< "\t\treal_t n1 = cos(a - r);\n"
<< "\t\treal_t m0 = n0 * n0 * n0 * r;\n"
<< "\t\treal_t m1 = n1 * n1 * n1 * r;\n"
<< "\n"
<< "\t\tvOut.x = xform->m_VariationWeights[" << varIndex << "] * (m0 + m1);\n"
<< "\t\tvOut.y = xform->m_VariationWeights[" << varIndex << "] * (m0 - m1);\n"
<< "\t\tvOut.z = xform->m_VariationWeights[" << varIndex << "] * vIn.z;\n"
<< "\t}\n";
return ss.str();
}
};
///
/// Julia:
/// a = atan2(tx, ty)/2.0;
/// if (random bit()) a += M_PI;
/// r = pow(tx*tx + ty*ty, 0.25);
/// nx = r * cos(a);
/// ny = r * sin(a);
/// p[0] += v * nx;
/// p[1] += v * ny;
///
template
class EMBER_API JuliaVariation : public Variation
{
public:
JuliaVariation(T weight = 1.0) : Variation("julia", VAR_JULIA, weight, true, true, false, true) { }
VARCOPY(JuliaVariation)
virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override
{
T r = m_Weight * sqrt(helper.m_PrecalcSqrtSumSquares);
T a = T(0.5) * helper.m_PrecalcAtanxy;
if (rand.RandBit())
a += T(M_PI);
helper.Out.x = r * cos(a);
helper.Out.y = r * sin(a);
helper.Out.z = m_Weight * helper.In.z;
}
virtual string OpenCLString() override
{
ostringstream ss;
intmax_t varIndex = IndexInXform();
ss << "\t{\n"
<< "\t\treal_t r = xform->m_VariationWeights[" << varIndex << "] * sqrt(precalcSqrtSumSquares);\n"
<< "\t\treal_t a = 0.5 * precalcAtanxy;\n"
<< "\n"
<< "\t\tif (MwcNext(mwc) & 1)\n"
<< "\t\t a += M_PI;\n"
<< "\n"
<< "\t\tvOut.x = r * cos(a);\n"
<< "\t\tvOut.y = r * sin(a);\n"
<< "\t\tvOut.z = xform->m_VariationWeights[" << varIndex << "] * vIn.z;\n"
<< "\t}\n";
return ss.str();
}
};
///
/// Bent:
/// nx = tx;
/// ny = ty;
/// if (nx < 0.0) nx = nx * 2.0;
/// if (ny < 0.0) ny = ny / 2.0;
/// p[0] += weight * nx;
/// p[1] += weight * ny;
///
template
class EMBER_API BentVariation : public Variation
{
public:
BentVariation(T weight = 1.0) : Variation("bent", VAR_BENT, weight) { }
VARCOPY(BentVariation)
virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override
{
T nx = helper.In.x < T(0.0) ? helper.In.x * 2 : helper.In.x;
T ny = helper.In.y < T(0.0) ? helper.In.y / 2 : helper.In.y;
helper.Out.x = m_Weight * nx;
helper.Out.y = m_Weight * ny;
helper.Out.z = m_Weight * helper.In.z;
}
virtual string OpenCLString() override
{
ostringstream ss;
intmax_t varIndex = IndexInXform();
ss << "\t{\n"
<< "\t\treal_t nx = vIn.x < 0.0 ? (vIn.x * 2.0) : vIn.x;\n"
<< "\t\treal_t ny = vIn.y < 0.0 ? (vIn.y / 2.0) : vIn.y;\n"
<< "\n"
<< "\t\tvOut.x = xform->m_VariationWeights[" << varIndex << "] * nx;\n"
<< "\t\tvOut.y = xform->m_VariationWeights[" << varIndex << "] * ny;\n"
<< "\t\tvOut.z = xform->m_VariationWeights[" << varIndex << "] * vIn.z;\n"
<< "\t}\n";
return ss.str();
}
};
///
/// Waves:
/// dx = coef[2][0];
/// dy = coef[2][1];
/// nx = tx + coef[1][0] * sin(ty / ((dx * dx) + EPS));
/// ny = ty + coef[1][1] * sin(tx / ((dy * dy) + EPS));
/// p[0] += weight * nx;
/// p[1] += weight * ny;
/// Special case here, use parametric for precalcs, but no regular params.
///
template
class EMBER_API WavesVariation : public ParametricVariation
{
public:
WavesVariation(T weight = 1.0) : ParametricVariation("waves", VAR_WAVES, weight)
{
Init();
}
PARVARCOPY(WavesVariation)
virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override
{
T c10 = m_Xform->m_Affine.B();
T c11 = m_Xform->m_Affine.E();
T nx = helper.In.x + c10 * sin(helper.In.y * m_Dx2);
T ny = helper.In.y + c11 * sin(helper.In.x * m_Dy2);
helper.Out.x = m_Weight * nx;
helper.Out.y = m_Weight * ny;
helper.Out.z = m_Weight * helper.In.z;
}
virtual string OpenCLString() override
{
ostringstream ss, ss2;
intmax_t i = 0, varIndex = IndexInXform();
ss2 << "_" << XformIndexInEmber() << "]";
string index = ss2.str();
string dx2 = "parVars[" + ToUpper(m_Params[i++].Name()) + index;//Precalcs only, no params.
string dy2 = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
ss << "\t{\n"
<< "\t\treal_t c10 = xform->m_B;\n"
<< "\t\treal_t c11 = xform->m_E;\n"
<< "\t\treal_t nx = vIn.x + c10 * sin(vIn.y * " << dx2 << ");\n"
<< "\t\treal_t ny = vIn.y + c11 * sin(vIn.x * " << dy2 << ");\n"
<< "\n"
<< "\t\tvOut.x = (xform->m_VariationWeights[" << varIndex << "] * nx);\n"
<< "\t\tvOut.y = (xform->m_VariationWeights[" << varIndex << "] * ny);\n"
<< "\t\tvOut.z = xform->m_VariationWeights[" << varIndex << "] * vIn.z;\n"
<< "\t}\n";
return ss.str();
}
virtual void Precalc() override
{
if (m_Xform)//If this variation exists by itself and hasn't been added to an xform yet, m_Xform will be nullptr.
{
T dx = m_Xform->m_Affine.C();
T dy = m_Xform->m_Affine.F();
m_Dx2 = 1 / Zeps(dx * dx);
m_Dy2 = 1 / Zeps(dy * dy);
}
}
protected:
void Init()
{
string prefix = Prefix();
m_Params.clear();
m_Params.push_back(ParamWithName(true, &m_Dx2, prefix + "waves_dx2"));//Precalcs only, no params.
m_Params.push_back(ParamWithName(true, &m_Dy2, prefix + "waves_dy2"));
}
private:
T m_Dx2;//Precalcs only, no params.
T m_Dy2;
};
///
/// Fisheye:
/// a = atan2(tx, ty);
/// r = sqrt(tx * tx + ty * ty);
/// r = 2 * r / (r + 1);
/// nx = r * cos(a);
/// ny = r * sin(a);
/// p[0] += weight * nx;
/// p[1] += weight * ny;
///
template
class EMBER_API FisheyeVariation : public Variation
{
public:
FisheyeVariation(T weight = 1.0) : Variation("fisheye", VAR_FISHEYE, weight, true, true) { }
VARCOPY(FisheyeVariation)
virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override
{
T r = 2 * m_Weight / (helper.m_PrecalcSqrtSumSquares + 1);
helper.Out.x = r * helper.In.y;
helper.Out.y = r * helper.In.x;
helper.Out.z = m_Weight * helper.In.z;
}
virtual string OpenCLString() override
{
ostringstream ss;
intmax_t varIndex = IndexInXform();
ss << "\t{\n"
<< "\t\treal_t r = 2 * xform->m_VariationWeights[" << varIndex << "] / (precalcSqrtSumSquares + 1);\n"
<< "\n"
<< "\t\tvOut.x = r * vIn.y;\n"
<< "\t\tvOut.y = r * vIn.x;\n"
<< "\t\tvOut.z = xform->m_VariationWeights[" << varIndex << "] * vIn.z;\n"
<< "\t}\n";
return ss.str();
}
};
///
/// Popcorn:
/// dx = tan(3 * ty);
/// dy = tan(3 * tx);
/// nx = tx + coef[2][0] * sin(dx);
/// ny = ty + coef[2][1] * sin(dy);
/// p[0] += weight * nx;
/// p[1] += weight * ny;
///
template
class EMBER_API PopcornVariation : public Variation
{
public:
PopcornVariation(T weight = 1.0) : Variation("popcorn", VAR_POPCORN, weight) { }
VARCOPY(PopcornVariation)
virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override
{
T dx = SafeTan(3 * helper.In.y);
T dy = SafeTan(3 * helper.In.x);
T nx = helper.In.x + m_Xform->m_Affine.C() * sin(dx);
T ny = helper.In.y + m_Xform->m_Affine.F() * sin(dy);
helper.Out.x = m_Weight * nx;
helper.Out.y = m_Weight * ny;
helper.Out.z = m_Weight * helper.In.z;
}
virtual string OpenCLString() override
{
ostringstream ss;
intmax_t varIndex = IndexInXform();
ss << "\t{\n"
<< "\t\treal_t dx = tan(3 * vIn.y);\n"
<< "\t\treal_t dy = tan(3 * vIn.x);\n"
<< "\t\treal_t nx = vIn.x + xform->m_C * sin(dx);\n"
<< "\t\treal_t ny = vIn.y + xform->m_F * sin(dy);\n"
<< "\n"
<< "\t\tvOut.x = xform->m_VariationWeights[" << varIndex << "] * nx;\n"
<< "\t\tvOut.y = xform->m_VariationWeights[" << varIndex << "] * ny;\n"
<< "\t\tvOut.z = xform->m_VariationWeights[" << varIndex << "] * vIn.z;\n"
<< "\t}\n";
return ss.str();
}
};
///
/// Exponential:
/// dx = exp(tx - 1.0);
/// dy = M_PI * ty;
/// nx = cos(dy) * dx;
/// ny = sin(dy) * dx;
/// p[0] += weight * nx;
/// p[1] += weight * ny;
///
template
class EMBER_API ExponentialVariation : public Variation
{
public:
ExponentialVariation(T weight = 1.0) : Variation("exponential", VAR_EXPONENTIAL, weight) { }
VARCOPY(ExponentialVariation)
virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override
{
T dx = m_Weight * exp(helper.In.x - 1);
T dy = T(M_PI) * helper.In.y;
helper.Out.x = dx * cos(dy);
helper.Out.y = dx * sin(dy);
helper.Out.z = m_Weight * helper.In.z;
}
virtual string OpenCLString() override
{
ostringstream ss;
intmax_t varIndex = IndexInXform();
ss << "\t{\n"
<< "\t\treal_t dx = xform->m_VariationWeights[" << varIndex << "] * exp(vIn.x - 1.0);\n"
<< "\t\treal_t dy = M_PI * vIn.y;\n"
<< "\n"
<< "\t\tvOut.x = dx * cos(dy);\n"
<< "\t\tvOut.y = dx * sin(dy);\n"
<< "\t\tvOut.z = xform->m_VariationWeights[" << varIndex << "] * vIn.z;\n"
<< "\t}\n";
return ss.str();
}
};
///
/// Power:
/// a = atan2(tx, ty);
/// sa = sin(a);
/// r = sqrt(tx * tx + ty * ty);
/// r = pow(r, sa);
/// nx = r * precalc_cosa;
/// ny = r * sa;
/// p[0] += weight * nx;
/// p[1] += weight * ny;
///
template
class EMBER_API PowerVariation : public Variation
{
public:
PowerVariation(T weight = 1.0) : Variation("power", VAR_POWER, weight, true, true, true) { }
VARCOPY(PowerVariation)
virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override
{
T r = m_Weight * pow(helper.m_PrecalcSqrtSumSquares, helper.m_PrecalcSina);
helper.Out.x = r * helper.m_PrecalcCosa;
helper.Out.y = r * helper.m_PrecalcSina;
helper.Out.z = m_Weight * helper.In.z;
}
virtual string OpenCLString() override
{
ostringstream ss;
intmax_t varIndex = IndexInXform();
ss << "\t{\n"
<< "\t\treal_t r = xform->m_VariationWeights[" << varIndex << "] * pow(precalcSqrtSumSquares, precalcSina);\n"
<< "\n"
<< "\t\tvOut.x = r * precalcCosa;\n"
<< "\t\tvOut.y = r * precalcSina;\n"
<< "\t\tvOut.z = xform->m_VariationWeights[" << varIndex << "] * vIn.z;\n"
<< "\t}\n";
return ss.str();
}
};
///
/// Cosine:
/// nx = cos(tx * M_PI) * cosh(ty);
/// ny = -sin(tx * M_PI) * sinh(ty);
/// p[0] += weight * nx;
/// p[1] += weight * ny;
///
template
class EMBER_API CosineVariation : public Variation
{
public:
CosineVariation(T weight = 1.0) : Variation("cosine", VAR_COSINE, weight) { }
VARCOPY(CosineVariation)
virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override
{
T a = helper.In.x * T(M_PI);
T nx = cos(a) * cosh(helper.In.y);
T ny = -sin(a) * sinh(helper.In.y);
helper.Out.x = m_Weight * nx;
helper.Out.y = m_Weight * ny;
helper.Out.z = m_Weight * helper.In.z;
}
virtual string OpenCLString() override
{
ostringstream ss;
intmax_t varIndex = IndexInXform();
ss << "\t{\n"
<< "\t\treal_t a = vIn.x * M_PI;\n"
<< "\t\treal_t nx = cos(a) * cosh(vIn.y);\n"
<< "\t\treal_t ny = -sin(a) * sinh(vIn.y);\n"
<< "\n"
<< "\t\tvOut.x = xform->m_VariationWeights[" << varIndex << "] * nx;\n"
<< "\t\tvOut.y = xform->m_VariationWeights[" << varIndex << "] * ny;\n"
<< "\t\tvOut.z = xform->m_VariationWeights[" << varIndex << "] * vIn.z;\n"
<< "\t}\n";
return ss.str();
}
};
///
/// Rings:
/// dx = coef[2][0];
/// dx = dx * dx + EPS;
/// r = sqrt(tx * tx + ty * ty);
/// r = fmod(r + dx, 2 * dx) - dx + r * (1 - dx);
/// a = atan2(tx, ty);
/// nx = cos(a) * r;
/// ny = sin(a) * r;
/// p[0] += weight * nx;
/// p[1] += weight * ny;
///
template
class EMBER_API RingsVariation : public Variation
{
public:
RingsVariation(T weight = 1.0) : Variation("rings", VAR_RINGS, weight, true, true, true) { }
VARCOPY(RingsVariation)
virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override
{
T dx = Zeps(m_Xform->m_Affine.C() * m_Xform->m_Affine.C());
T r = helper.m_PrecalcSqrtSumSquares;
r = m_Weight * (fmod(r + dx, 2 * dx) - dx + r * (1 - dx));
helper.Out.x = r * helper.m_PrecalcCosa;
helper.Out.y = r * helper.m_PrecalcSina;
helper.Out.z = m_Weight * helper.In.z;
}
virtual string OpenCLString() override
{
ostringstream ss;
intmax_t varIndex = IndexInXform();
ss << "\t{\n"
<< "\t\treal_t dx = Zeps(xform->m_C * xform->m_C);\n"
<< "\t\treal_t r = precalcSqrtSumSquares;\n"
<< "\n"
<< "\t\tr = xform->m_VariationWeights[" << varIndex << "] * (fmod(r + dx, 2 * dx) - dx + r * (1 - dx));\n"
<< "\t\tvOut.x = r * precalcCosa;\n"
<< "\t\tvOut.y = r * precalcSina;\n"
<< "\t\tvOut.z = xform->m_VariationWeights[" << varIndex << "] * vIn.z;\n"
<< "\t}\n";
return ss.str();
}
};
///
/// Fan:
/// dx = coef[2][0];
/// dy = coef[2][1];
/// dx = M_PI * (dx * dx + EPS);
/// dx2 = dx / 2;
/// a = atan(tx, ty);
/// r = sqrt(tx * tx + ty * ty);
/// a += (fmod(a + dy, dx) > dx2) ? -dx2 : dx2;
/// nx = cos(a) * r;
/// ny = sin(a) * r;
/// p[0] += weight * nx;
/// p[1] += weight * ny;
///
template
class EMBER_API FanVariation : public Variation
{
public:
FanVariation(T weight = 1.0) : Variation("fan", VAR_FAN, weight, true, true, false, true) { }
VARCOPY(FanVariation)
virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override
{
T dx = T(M_PI) * Zeps(m_Xform->m_Affine.C() * m_Xform->m_Affine.C());
T dy = m_Xform->m_Affine.F();
T dx2 = T(0.5) * dx;
T a = helper.m_PrecalcAtanxy;
T r = m_Weight * helper.m_PrecalcSqrtSumSquares;
a += (fmod(a + dy, dx) > dx2) ? -dx2 : dx2;
helper.Out.x = r * cos(a);
helper.Out.y = r * sin(a);
helper.Out.z = m_Weight * helper.In.z;
}
virtual string OpenCLString() override
{
ostringstream ss;
intmax_t varIndex = IndexInXform();
ss << "\t{\n"
<< "\t\treal_t dx = M_PI * Zeps(xform->m_C * xform->m_C);\n"
<< "\t\treal_t dy = xform->m_F;\n"
<< "\t\treal_t dx2 = 0.5 * dx;\n"
<< "\t\treal_t a = precalcAtanxy + ((fmod(precalcAtanxy + dy, dx) > dx2) ? -dx2 : dx2);\n"
<< "\t\treal_t r = xform->m_VariationWeights[" << varIndex << "] * precalcSqrtSumSquares;\n"
<< "\n"
<< "\t\tvOut.x = r * cos(a);\n"
<< "\t\tvOut.y = r * sin(a);\n"
<< "\t\tvOut.z = xform->m_VariationWeights[" << varIndex << "] * vIn.z;\n"
<< "\t}\n";
return ss.str();
}
};
///
/// Blob:
/// a = atan2(tx, ty);
/// r = sqrt(tx * tx + ty * ty);
/// r = r * (bloblow + (blobhigh - bloblow) * (0.5 + 0.5 * sin(blobwaves * a)));
/// nx = sin(a) * r;
/// ny = cos(a) * r;
///
/// p[0] += weight * nx;
/// p[1] += weight * ny;
///
template
class EMBER_API BlobVariation : public ParametricVariation
{
public:
BlobVariation(T weight = 1.0) : ParametricVariation("blob", VAR_BLOB, weight, true, true, true, true)
{
Init();
}
PARVARCOPY(BlobVariation)
virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override
{
T r = helper.m_PrecalcSqrtSumSquares * (m_BlobLow + m_BlobDiff * (T(0.5) + T(0.5) * sin(m_BlobWaves * helper.m_PrecalcAtanxy)));
helper.Out.x = m_Weight * helper.m_PrecalcSina * r;
helper.Out.y = m_Weight * helper.m_PrecalcCosa * r;
helper.Out.z = (m_VarType == VARTYPE_REG) ? 0 : helper.In.z;
}
virtual string OpenCLString() override
{
ostringstream ss, ss2;
intmax_t i = 0, varIndex = IndexInXform();
ss2 << "_" << XformIndexInEmber() << "]";
string index = ss2.str();
string blobLow = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string blobHigh = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string blobWaves = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string blobDiff = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
ss << "\t{\n"
<< "\t\treal_t r = precalcSqrtSumSquares * (" << blobLow << " + " << blobDiff << " * (0.5 + 0.5 * sin(" << blobWaves << " * precalcAtanxy)));\n"
<< "\n"
<< "\t\tvOut.x = (xform->m_VariationWeights[" << varIndex << "] * precalcSina * r);\n"
<< "\t\tvOut.y = (xform->m_VariationWeights[" << varIndex << "] * precalcCosa * r);\n"
<< "\t\tvOut.z = " << ((m_VarType == VARTYPE_REG) ? "0" : "vIn.z") << ";\n"
<< "\t}\n";
return ss.str();
}
virtual void Precalc() override
{
m_BlobDiff = m_BlobHigh - m_BlobLow;
}
virtual void Random(QTIsaac& rand) override
{
m_BlobLow = T(0.2) + T(0.5) * rand.Frand01();
m_BlobHigh = T(0.8) + T(0.4) * rand.Frand01();
m_BlobWaves = T(int(2 + 5 * rand.Frand01()));
}
protected:
void Init()
{
string prefix = Prefix();
m_Params.clear();
m_Params.push_back(ParamWithName(&m_BlobLow, prefix + "blob_low"));
m_Params.push_back(ParamWithName(&m_BlobHigh, prefix + "blob_high", 1));
m_Params.push_back(ParamWithName(&m_BlobWaves, prefix + "blob_waves", 1));
m_Params.push_back(ParamWithName(true, &m_BlobDiff, prefix + "blob_diff"));//Precalc.
}
private:
T m_BlobLow;
T m_BlobHigh;
T m_BlobWaves;
T m_BlobDiff;//Precalc.
};
///
/// Pdj:
/// nx1 = cos(pdjb * tx);
/// nx2 = sin(pdjc * tx);
/// ny1 = sin(pdja * ty);
/// ny2 = cos(pdjd * ty);
///
/// p[0] += weight * (ny1 - nx1);
/// p[1] += weight * (nx2 - ny2);
///
template
class EMBER_API PdjVariation : public ParametricVariation
{
public:
PdjVariation(T weight = 1.0) : ParametricVariation("pdj", VAR_PDJ, weight)
{
Init();
}
PARVARCOPY(PdjVariation)
virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override
{
T nx1 = cos(m_PdjB * helper.In.x);
T nx2 = sin(m_PdjC * helper.In.x);
T ny1 = sin(m_PdjA * helper.In.y);
T ny2 = cos(m_PdjD * helper.In.y);
helper.Out.x = m_Weight * (ny1 - nx1);
helper.Out.y = m_Weight * (nx2 - ny2);
helper.Out.z = m_Weight * helper.In.z;
}
virtual string OpenCLString() override
{
ostringstream ss, ss2;
intmax_t i = 0, varIndex = IndexInXform();
ss2 << "_" << XformIndexInEmber() << "]";
string index = ss2.str();
string pdjA = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string pdjB = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string pdjC = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string pdjD = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
ss << "\t{\n"
<< "\t\treal_t nx1 = cos(" << pdjB << " * vIn.x)" << ";\n"
<< "\t\treal_t nx2 = sin(" << pdjC << " * vIn.x)" << ";\n"
<< "\t\treal_t ny1 = sin(" << pdjA << " * vIn.y)" << ";\n"
<< "\t\treal_t ny2 = cos(" << pdjD << " * vIn.y)" << ";\n"
<< "\n"
<< "\t\tvOut.x = (xform->m_VariationWeights[" << varIndex << "] * (ny1 - nx1));\n"
<< "\t\tvOut.y = (xform->m_VariationWeights[" << varIndex << "] * (nx2 - ny2));\n"
<< "\t\tvOut.z = xform->m_VariationWeights[" << varIndex << "] * vIn.z;\n"
<< "\t}\n";
return ss.str();
}
virtual void Random(QTIsaac& rand) override
{
m_PdjA = 3 * rand.Frand11();
m_PdjB = 3 * rand.Frand11();
m_PdjC = 3 * rand.Frand11();
m_PdjD = 3 * rand.Frand11();
}
protected:
void Init()
{
string prefix = Prefix();
m_Params.clear();
m_Params.push_back(ParamWithName(&m_PdjA, prefix + "pdj_a"));
m_Params.push_back(ParamWithName(&m_PdjB, prefix + "pdj_b"));
m_Params.push_back(ParamWithName(&m_PdjC, prefix + "pdj_c"));
m_Params.push_back(ParamWithName(&m_PdjD, prefix + "pdj_d"));
}
private:
T m_PdjA;
T m_PdjB;
T m_PdjC;
T m_PdjD;
};
///
/// Fan2:
/// a = precalc_atan;
/// r = precalc_sqrt;
///
/// dy = fan2y;
/// dx = M_PI * (fan2x * fan2x + EPS);
/// dx2 = dx / 2.0;
///
/// t = a + dy - dx * (int)((a + dy) / dx);
///
/// if (t > dx2)
/// a = a - dx2;
/// else
/// a = a + dx2;
///
/// nx = sin(a) * r;
/// ny = cos(a) * r;
///
/// p[0] += weight * nx;
/// p[1] += weight * ny;
///
template
class EMBER_API Fan2Variation : public ParametricVariation
{
public:
Fan2Variation(T weight = 1.0) : ParametricVariation("fan2", VAR_FAN2, weight, true, true, false, true)
{
Init();
}
PARVARCOPY(Fan2Variation)
virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override
{
T a = helper.m_PrecalcAtanxy;
T r = m_Weight * helper.m_PrecalcSqrtSumSquares;
T t = a + m_Fan2Y - m_Fan2Dx * int((a + m_Fan2Y) / m_Fan2Dx);
if (t > m_Fan2Dx2)
a = a - m_Fan2Dx2;
else
a = a + m_Fan2Dx2;
helper.Out.x = r * sin(a);
helper.Out.y = r * cos(a);
helper.Out.z = m_Weight * helper.In.z;
}
virtual string OpenCLString() override
{
ostringstream ss, ss2;
intmax_t i = 0, varIndex = IndexInXform();
ss2 << "_" << XformIndexInEmber() << "]";
string index = ss2.str();
string fan2X = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string fan2Y = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string dx = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string dx2 = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
ss << "\t{\n"
<< "\t\treal_t a = precalcAtanxy;\n"
<< "\t\treal_t r = xform->m_VariationWeights[" << varIndex << "] * precalcSqrtSumSquares;\n"
<< "\t\treal_t t = a + " << fan2Y << " - " << dx << " * (int)((a + " << fan2Y << ") / " << dx << ");\n"
<< "\n"
<< "\t\tif (t > " << dx2 << ")\n"
<< "\t\t a = a - " << dx2 << ";\n"
<< "\t\telse\n"
<< "\t\t a = a + " << dx2 << ";\n"
<< "\n"
<< "\t\tvOut.x = r * sin(a);\n"
<< "\t\tvOut.y = r * cos(a);\n"
<< "\t\tvOut.z = xform->m_VariationWeights[" << varIndex << "] * vIn.z;\n"
<< "\t}\n";
return ss.str();
}
virtual void Precalc() override
{
m_Fan2Dx = T(M_PI) * Zeps(SQR(m_Fan2X));
m_Fan2Dx2 = T(0.5) * m_Fan2Dx;
}
virtual void Random(QTIsaac& rand) override
{
m_Fan2X = rand.Frand11();
m_Fan2Y = rand.Frand11();
}
protected:
void Init()
{
string prefix = Prefix();
m_Params.clear();
m_Params.push_back(ParamWithName(&m_Fan2X, prefix + "fan2_x"));
m_Params.push_back(ParamWithName(&m_Fan2Y, prefix + "fan2_y"));
m_Params.push_back(ParamWithName(true, &m_Fan2Dx, prefix + "fan2_dx"));//Precalc.
m_Params.push_back(ParamWithName(true, &m_Fan2Dx2, prefix + "fan2_dx2"));
}
private:
T m_Fan2X;
T m_Fan2Y;
T m_Fan2Dx;//Precalc.
T m_Fan2Dx2;
};
///
/// Rings2:
/// r = precalc_sqrt;
/// dx = rings2val * rings2val + EPS;
/// r += dx - 2.0 * dx * (int)((r + dx)/(2.0 * dx)) - dx + r * (1.0 - dx);
/// nx = precalc_sina * r;
/// ny = precalc_cosa * r;
/// p[0] += weight * nx;
/// p[1] += weight * ny;
///
template
class EMBER_API Rings2Variation : public ParametricVariation
{
public:
Rings2Variation(T weight = 1.0) : ParametricVariation("rings2", VAR_RINGS2, weight, true, true, true)
{
Init();
}
PARVARCOPY(Rings2Variation)
virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override
{
T r = helper.m_PrecalcSqrtSumSquares;
r += -2 * m_Rings2Val2 * int((r + m_Rings2Val2) / (2 * m_Rings2Val2)) + r * (1 - m_Rings2Val2);
helper.Out.x = m_Weight * helper.m_PrecalcSina * r;
helper.Out.y = m_Weight * helper.m_PrecalcCosa * r;
helper.Out.z = m_Weight * helper.In.z;
}
virtual string OpenCLString() override
{
ostringstream ss, ss2;
intmax_t i = 0, varIndex = IndexInXform();
ss2 << "_" << XformIndexInEmber() << "]";
string index = ss2.str();
string rings2Val = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string rings2Val2 = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
ss << "\t{\n"
<< "\t\treal_t r = precalcSqrtSumSquares;\n"
<< "\n"
<< "\t\tr += -2.0 * " << rings2Val2 << " * (int)((r + " << rings2Val2 << ") / (2.0 * " << rings2Val2 << ")) + r * (1.0 - " << rings2Val2 << ");\n"
<< "\t\tvOut.x = (xform->m_VariationWeights[" << varIndex << "] * precalcSina * r);\n"
<< "\t\tvOut.y = (xform->m_VariationWeights[" << varIndex << "] * precalcCosa * r);\n"
<< "\t\tvOut.z = xform->m_VariationWeights[" << varIndex << "] * vIn.z;\n"
<< "\t}\n";
return ss.str();
}
virtual void Precalc() override
{
m_Rings2Val2 = Zeps(SQR(m_Rings2Val));
}
virtual void Random(QTIsaac& rand) override
{
m_Rings2Val = 2 * rand.Frand01();
}
protected:
void Init()
{
string prefix = Prefix();
m_Params.clear();
m_Params.push_back(ParamWithName(&m_Rings2Val, prefix + "rings2_val", 1));//This differs from the original which used zero. Use 1 instead to avoid getting too close to dividing by zero.
m_Params.push_back(ParamWithName(true, &m_Rings2Val2, prefix + "rings2_val2"));//Precalc.
}
private:
T m_Rings2Val;
T m_Rings2Val2;//Precalc.
};
///
/// Eyefish:
/// r = 2.0 * weight / (precalc_sqrt + 1.0);
/// p[0] += r * tx;
/// p[1] += r * ty;
///
template
class EMBER_API EyefishVariation : public Variation
{
public:
EyefishVariation(T weight = 1.0) : Variation("eyefish", VAR_EYEFISH, weight, true, true) { }
VARCOPY(EyefishVariation)
virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override
{
T r = 2 * m_Weight / (helper.m_PrecalcSqrtSumSquares + 1);
helper.Out.x = r * helper.In.x;
helper.Out.y = r * helper.In.y;
helper.Out.z = m_Weight * helper.In.z;
}
virtual string OpenCLString() override
{
ostringstream ss;
intmax_t varIndex = IndexInXform();
ss << "\t{\n"
<< "\t\treal_t r = (xform->m_VariationWeights[" << varIndex << "] * 2.0) / (precalcSqrtSumSquares + 1.0);\n"
<< "\n"
<< "\t\tvOut.x = r * vIn.x;\n"
<< "\t\tvOut.y = r * vIn.y;\n"
<< "\t\tvOut.z = xform->m_VariationWeights[" << varIndex << "] * vIn.z;\n"
<< "\t}\n";
return ss.str();
}
};
///
/// Bubble.
///
template
class EMBER_API BubbleVariation : public Variation
{
public:
BubbleVariation(T weight = 1.0) : Variation("bubble", VAR_BUBBLE, weight, true) { }
VARCOPY(BubbleVariation)
virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override
{
T denom = T(0.25) * helper.m_PrecalcSumSquares + 1;
T r = m_Weight / denom;
helper.Out.x = r * helper.In.x;
helper.Out.y = r * helper.In.y;
helper.Out.z = m_Weight * (2 / denom - 1);
}
virtual string OpenCLString() override
{
ostringstream ss;
intmax_t varIndex = IndexInXform();
ss << "\t{\n"
<< "\t\treal_t denom = 0.25 * precalcSumSquares + 1;\n"
<< "\t\treal_t r = xform->m_VariationWeights[" << varIndex << "] / denom;\n"
<< "\n"
<< "\t\tvOut.x = r * vIn.x;\n"
<< "\t\tvOut.y = r * vIn.y;\n"
<< "\t\tvOut.z = xform->m_VariationWeights[" << varIndex << "] * (2 / denom - 1);\n"
<< "\t}\n";
return ss.str();
}
};
///
/// Cylinder.
///
template
class EMBER_API CylinderVariation : public Variation
{
public:
CylinderVariation(T weight = 1.0) : Variation("cylinder", VAR_CYLINDER, weight) { }
VARCOPY(CylinderVariation)
virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override
{
helper.Out.x = m_Weight * sin(helper.In.x);
helper.Out.y = m_Weight * helper.In.y;
helper.Out.z = m_Weight * cos(helper.In.x);
}
virtual string OpenCLString() 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 << "] * vIn.y;\n"
<< "\t\tvOut.z = xform->m_VariationWeights[" << varIndex << "] * cos(vIn.x);\n"
<< "\t}\n";
return ss.str();
}
};
///
/// Perspective.
///
template
class EMBER_API PerspectiveVariation : public ParametricVariation
{
public:
PerspectiveVariation(T weight = 1.0) : ParametricVariation("perspective", VAR_PERSPECTIVE, weight)
{
Init();
}
PARVARCOPY(PerspectiveVariation)
virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override
{
T d = Zeps(m_Dist - helper.In.y * m_Vsin);
T t = 1 / d;
helper.Out.x = m_Weight * m_Dist * helper.In.x * t;
helper.Out.y = m_Weight * m_VfCos * helper.In.y * t;
helper.Out.z = m_Weight * helper.In.z;
}
virtual string OpenCLString() override
{
ostringstream ss, ss2;
intmax_t i = 0, varIndex = IndexInXform();
ss2 << "_" << XformIndexInEmber() << "]";
string index = ss2.str();
string angle = "parVars[" + ToUpper(m_Params[i++].Name()) + index;//Params.
string dist = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string vSin = "parVars[" + ToUpper(m_Params[i++].Name()) + index;//Precalc.
string vfCos = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
ss << "\t{\n"
<< "\t\treal_t d = Zeps(" << dist << " - vIn.y * " << vSin << ");\n"
<< "\t\treal_t t = 1.0 / d;\n"
<< "\n"
<< "\t\tvOut.x = (xform->m_VariationWeights[" << varIndex << "] * " << dist << " * vIn.x * t);\n"
<< "\t\tvOut.y = (xform->m_VariationWeights[" << varIndex << "] * " << vfCos << " * vIn.y * t);\n"
<< "\t\tvOut.z = xform->m_VariationWeights[" << varIndex << "] * vIn.z;\n"
<< "\t}\n";
return ss.str();
}
virtual void Precalc() override
{
T angle = m_Angle * T(M_PI) / 2;
m_Vsin = sin(angle);
m_VfCos = m_Dist * cos(angle);
}
virtual void Random(QTIsaac& rand) override
{
m_Angle = rand.Frand01();
m_Dist = 2 * rand.Frand01() + 1;
}
protected:
void Init()
{
string prefix = Prefix();
m_Params.clear();
m_Params.push_back(ParamWithName(&m_Angle, prefix + "perspective_angle"));//Params.
m_Params.push_back(ParamWithName(&m_Dist, prefix + "perspective_dist"));
m_Params.push_back(ParamWithName(true, &m_Vsin, prefix + "perspective_vsin"));//Precalc.
m_Params.push_back(ParamWithName(true, &m_VfCos, prefix + "perspective_vfcos"));
}
private:
T m_Angle;//Params.
T m_Dist;
T m_Vsin;//Precalc.
T m_VfCos;
};
///
/// Noise.
///
template
class EMBER_API NoiseVariation : public Variation
{
public:
NoiseVariation(T weight = 1.0) : Variation("noise", VAR_NOISE, weight) { }
VARCOPY(NoiseVariation)
virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override
{
T tempr = rand.Frand01() * M_2PI;
T r = m_Weight * rand.Frand01();
helper.Out.x = helper.In.x * r * cos(tempr);
helper.Out.y = helper.In.y * r * sin(tempr);
helper.Out.z = m_Weight * helper.In.z;
}
virtual string OpenCLString() override
{
ostringstream ss;
intmax_t varIndex = IndexInXform();
ss << "\t{\n"
<< "\t\treal_t tempr = MwcNext01(mwc) * M_2PI;\n"
<< "\t\treal_t r = xform->m_VariationWeights[" << varIndex << "] * MwcNext01(mwc);\n"
<< "\n"
<< "\t\tvOut.x = vIn.x * r * cos(tempr);\n"
<< "\t\tvOut.y = vIn.y * r * sin(tempr);\n"
<< "\t\tvOut.z = xform->m_VariationWeights[" << varIndex << "] * vIn.z;\n"
<< "\t}\n";
return ss.str();
}
};
///
/// JuliaN.
///
template
class EMBER_API JuliaNGenericVariation : public ParametricVariation
{
public:
JuliaNGenericVariation(T weight = 1.0) : ParametricVariation("julian", VAR_JULIAN, weight, true, false, false, false, true)
{
Init();
}
PARVARCOPY(JuliaNGenericVariation)
virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override
{
T tempr = (helper.m_PrecalcAtanyx + M_2PI * rand.Rand(ISAAC_INT(m_Rn))) / m_Power;
T r = m_Weight * pow(helper.m_PrecalcSumSquares, m_Cn);
helper.Out.x = r * cos(tempr);
helper.Out.y = r * sin(tempr);
helper.Out.z = m_Weight * helper.In.z;
}
virtual string OpenCLString() override
{
ostringstream ss, ss2;
intmax_t i = 0, varIndex = IndexInXform();
ss2 << "_" << XformIndexInEmber() << "]";
string index = ss2.str();
string dist = "parVars[" + ToUpper(m_Params[i++].Name()) + index;//Params.
string power = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
string rn = "parVars[" + ToUpper(m_Params[i++].Name()) + index;//Precalc.
string cn = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
ss << "\t{\n"
<< "\t\tint tRnd = (int)(" << rn << " * MwcNext01(mwc));\n"
<< "\t\treal_t tempr = (precalcAtanyx + M_2PI * tRnd) / " << power << ";\n"
<< "\t\treal_t r = xform->m_VariationWeights[" << varIndex << "] * pow(precalcSumSquares, " << cn << ");\n"
<< "\n"
<< "\t\tvOut.x = r * cos(tempr);\n"
<< "\t\tvOut.y = r * sin(tempr);\n"
<< "\t\tvOut.z = xform->m_VariationWeights[" << varIndex << "] * vIn.z;\n"
<< "\t}\n";
return ss.str();
}
virtual void Precalc() override
{
m_Power = Zeps(m_Power);
m_Rn = fabs(m_Power);
m_Cn = m_Dist / m_Power / 2;
}
virtual void Random(QTIsaac& rand) override
{
m_Dist = 1;
m_Power = T(int(5 * rand.Frand01() + 2));
}
protected:
void Init()
{
string prefix = Prefix();
m_Params.clear();
m_Params.push_back(ParamWithName(&m_Dist, prefix + "julian_dist", 1));//Params.
m_Params.push_back(ParamWithName(&m_Power, prefix + "julian_power", 1, INTEGER_NONZERO));
m_Params.push_back(ParamWithName(true, &m_Rn, prefix + "julian_rn"));//Precalc.
m_Params.push_back(ParamWithName(true, &m_Cn, prefix + "julian_cn"));
}
private:
T m_Dist;//Params.
T m_Power;
T m_Rn;//Precalc.
T m_Cn;
};
///
/// JuliaScope.
///
template
class EMBER_API JuliaScopeVariation : public ParametricVariation
{
public:
JuliaScopeVariation(T weight = 1.0) : ParametricVariation("juliascope", VAR_JULIASCOPE, weight, true, false, false, false, true)
{
Init();
}
PARVARCOPY(JuliaScopeVariation)
virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override
{
int rnd = int(m_Rn * rand.Frand01());
T tempr, r = m_Weight * pow(helper.m_PrecalcSumSquares, m_Cn);
if ((rnd & 1) == 0)
tempr = (M_2PI * rnd + helper.m_PrecalcAtanyx) / m_Power;
else
tempr = (M_2PI * rnd - helper.m_PrecalcAtanyx) / m_Power;
helper.Out.x = r * cos(tempr);
helper.Out.y = r * sin(tempr);
helper.Out.z = m_Weight * helper.In.z;
//int rnd = (int)(m_Rn * rand.Frand01());
//T tempr, r;
//if ((rnd & 1) == 0)
// tempr = (2 * T(M_PI) * (int)(m_Rn * rand.Frand01