#pragma once #include "Variation.h" #include "Xform.h" namespace EmberNs { //template class Xform; /// /// Linear: /// nx = tx; /// ny = ty; /// p[0] += weight * nx; /// p[1] += weight * ny; /// template class LinearVariation : public Variation { public: LinearVariation(T weight = 1.0) : Variation("linear", eVariationId::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() const override { ostringstream ss; string weight = WeightDefineString(); ss << "\t{\n" << "\t\tvOut.x = " << weight << " * vIn.x;\n" << "\t\tvOut.y = " << weight << " * vIn.y;\n" << "\t\tvOut.z = " << weight << " * 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 SinusoidalVariation : public Variation { public: SinusoidalVariation(T weight = 1.0) : Variation("sinusoidal", eVariationId::VAR_SINUSOIDAL, weight) { } VARCOPY(SinusoidalVariation) 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 * helper.In.z; } virtual string OpenCLString() const override { ostringstream ss; string weight = WeightDefineString(); ss << "\t{\n" << "\t\tvOut.x = " << weight << " * sin(vIn.x);\n" << "\t\tvOut.y = " << weight << " * sin(vIn.y);\n" << "\t\tvOut.z = " << weight << " * 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 SphericalVariation : public Variation { public: SphericalVariation(T weight = 1.0) : Variation("spherical", eVariationId::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() const override { ostringstream ss; string weight = WeightDefineString(); ss << "\t{\n" << "\t\treal_t r2 = " << weight << " / Zeps(precalcSumSquares);\n" << "\n" << "\t\tvOut.x = r2 * vIn.x;\n" << "\t\tvOut.y = r2 * vIn.y;\n" << "\t\tvOut.z = " << weight << " * vIn.z;\n" << "\t}\n"; return ss.str(); } virtual vector OpenCLGlobalFuncNames() const override { return vector { "Zeps" }; } }; /// /// 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 SwirlVariation : public Variation { public: SwirlVariation(T weight = 1.0) : Variation("swirl", eVariationId::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() const override { ostringstream ss; string weight = WeightDefineString(); ss << "\t{\n" << "\t\treal_t c1 = sin(precalcSumSquares);\n" << "\t\treal_t c2 = cos(precalcSumSquares);\n" << "\n" << "\t\tvOut.x = " << weight << " * fma(c1, vIn.x, -(c2 * vIn.y));\n" << "\t\tvOut.y = " << weight << " * fma(c2, vIn.x, c1 * vIn.y);\n" << "\t\tvOut.z = " << weight << " * vIn.z;\n" << "\t}\n"; return ss.str(); } }; /// /// swirl3. /// By Zy0rg. /// template class Swirl3Variation : public ParametricVariation { public: Swirl3Variation(T weight = 1.0) : ParametricVariation("swirl3", eVariationId::VAR_SWIRL3, weight, true, true, false, false, true) { Init(); } PARVARCOPY(Swirl3Variation) virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { T rad = helper.m_PrecalcSqrtSumSquares; T ang = helper.m_PrecalcAtanyx + std::log(rad) * m_Shift; helper.Out.x = m_Weight * rad * std::cos(ang); helper.Out.y = m_Weight * rad * std::sin(ang); helper.Out.z = DefaultZ(helper); } virtual string OpenCLString() const override { ostringstream ss, ss2; intmax_t i = 0; ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string weight = WeightDefineString(); string shift = "parVars[" + ToUpper(m_Params[i++].Name()) + index; ss << "\t{\n" << "\t\treal_t rad = precalcSqrtSumSquares;\n" << "\t\treal_t ang = fma(log(rad), " << shift << ", precalcAtanyx);\n" << "\t\tvOut.x = " << weight << " * rad * cos(ang);\n" << "\t\tvOut.y = " << weight << " * rad * sin(ang);\n" << "\t\tvOut.z = " << DefaultZCl() << "\t}\n"; return ss.str(); } protected: void Init() { string prefix = Prefix(); m_Params.clear(); m_Params.push_back(ParamWithName(&m_Shift, prefix + "swirl3_shift", T(0.5))); } private: T m_Shift; }; /// /// swirl3r. /// By Zy0rg. /// template class Swirl3rVariation : public ParametricVariation { public: Swirl3rVariation(T weight = 1.0) : ParametricVariation("swirl3r", eVariationId::VAR_SWIRL3R, weight, true, true, false, false, true) { Init(); } PARVARCOPY(Swirl3rVariation) virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { T rad = helper.m_PrecalcSqrtSumSquares; T ang = helper.m_PrecalcAtanyx; T ang2; if (rad < m_Minr) ang2 = ang + m_Mina; else if (rad > m_Maxr) ang2 = ang + m_Maxa; else ang2 = ang + std::log(rad) * m_Shift; helper.Out.x = m_Weight * rad * std::cos(ang2); helper.Out.y = m_Weight * rad * std::sin(ang2); helper.Out.z = DefaultZ(helper); } virtual string OpenCLString() const override { ostringstream ss, ss2; intmax_t i = 0; ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string weight = WeightDefineString(); string shift = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string mmin = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string mmax = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string minr = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string maxr = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string mina = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string maxa = "parVars[" + ToUpper(m_Params[i++].Name()) + index; ss << "\t{\n" << "\t\treal_t rad = precalcSqrtSumSquares;\n" << "\t\treal_t ang2, ang = precalcAtanyx;\n" << "\n" << "\t\tif (rad < " << minr << ")\n" << "\t\t ang2 = ang + " << mina << ";\n" << "\t\telse if (rad > " << maxr << ")\n" << "\t\t ang2 = ang + " << maxa << ";\n" << "\t\telse\n" << "\t\t ang2 = ang + log(rad) * " << shift << ";\n" << "\n" << "\t\tvOut.x = " << weight << " * rad * cos(ang);\n" << "\t\tvOut.y = " << weight << " * rad * sin(ang);\n" << "\t\tvOut.z = " << DefaultZCl() << "\t}\n"; return ss.str(); } virtual void Precalc() override { m_Minr = std::min(m_Min, m_Max); m_Maxr = std::max(m_Min, m_Max); m_Mina = m_Minr > 0 ? std::log(m_Minr) * m_Shift : 0; m_Maxa = m_Maxr > 0 ? std::log(m_Maxr) * m_Shift : 0; } protected: void Init() { string prefix = Prefix(); m_Params.clear(); m_Params.push_back(ParamWithName(&m_Shift, prefix + "swirl3r_shift", T(0.5))); m_Params.push_back(ParamWithName(&m_Min, prefix + "swirl3r_min", T(0.5), eParamType::REAL, 0)); m_Params.push_back(ParamWithName(&m_Max, prefix + "swirl3r_max", 1, eParamType::REAL, 0)); m_Params.push_back(ParamWithName(true, &m_Minr, prefix + "swirl3r_minr"));//Precalc. m_Params.push_back(ParamWithName(true, &m_Maxr, prefix + "swirl3r_maxr")); m_Params.push_back(ParamWithName(true, &m_Mina, prefix + "swirl3r_mina")); m_Params.push_back(ParamWithName(true, &m_Maxa, prefix + "swirl3r_maxa")); } private: T m_Shift; T m_Min; T m_Max; T m_Minr;//Precalc. T m_Maxr; T m_Mina; T m_Maxa; }; /// /// 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 HorseshoeVariation : public Variation { public: HorseshoeVariation(T weight = 1.0) : Variation("horseshoe", eVariationId::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() const override { ostringstream ss; string weight = WeightDefineString(); ss << "\t{\n" << "\t\treal_t r = " << weight << " / Zeps(precalcSqrtSumSquares);\n" << "\n" << "\t\tvOut.x = (vIn.x - vIn.y) * (vIn.x + vIn.y) * r;\n" << "\t\tvOut.y = (real_t)(2.0) * vIn.x * vIn.y * r;\n" << "\t\tvOut.z = " << weight << " * vIn.z;\n" << "\t}\n"; return ss.str(); } virtual vector OpenCLGlobalFuncNames() const override { return vector { "Zeps" }; } }; /// /// Polar: /// nx = atan2(tx, ty) / M_PI; /// ny = std::sqrt(tx * tx + ty * ty) - 1.0; /// p[0] += weight * nx; /// p[1] += weight * ny; /// template class PolarVariation : public Variation { public: PolarVariation(T weight = 1.0) : Variation("polar", eVariationId::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() const override { ostringstream ss; string weight = WeightDefineString(); ss << "\t{\n" << "\t\tvOut.x = " << weight << " * (precalcAtanxy * M1PI);\n" << "\t\tvOut.y = " << weight << " * (precalcSqrtSumSquares - (real_t)(1.0));\n" << "\t\tvOut.z = " << weight << " * vIn.z;\n" << "\t}\n"; return ss.str(); } }; /// /// Handkerchief: /// a = atan2(tx, ty); /// r = std::sqrt(tx * tx + ty * ty); /// p[0] += weight * sin(a + r) * r; /// p[1] += weight * cos(a - r) * r; /// template class HandkerchiefVariation : public Variation { public: HandkerchiefVariation(T weight = 1.0) : Variation("handkerchief", eVariationId::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 * std::sin(helper.m_PrecalcAtanxy + helper.m_PrecalcSqrtSumSquares); helper.Out.y = m_Weight * helper.m_PrecalcSqrtSumSquares * std::cos(helper.m_PrecalcAtanxy - helper.m_PrecalcSqrtSumSquares); helper.Out.z = DefaultZ(helper); } virtual string OpenCLString() const override { ostringstream ss; string weight = WeightDefineString(); ss << "\t{\n" << "\t\tvOut.x = " << weight << " * precalcSqrtSumSquares * sin(precalcAtanxy + precalcSqrtSumSquares);\n" << "\t\tvOut.y = " << weight << " * precalcSqrtSumSquares * cos(precalcAtanxy - precalcSqrtSumSquares);\n" << "\t\tvOut.z = " << DefaultZCl() << "\t}\n"; return ss.str(); } }; /// /// Heart: /// a = atan2(tx, ty); /// r = std::sqrt(tx * tx + ty * ty); /// a *= r; /// p[0] += weight * sin(a) * r; /// p[1] += weight * cos(a) * -r; /// template class HeartVariation : public Variation { public: HeartVariation(T weight = 1.0) : Variation("heart", eVariationId::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 * std::sin(a); helper.Out.y = (-r) * std::cos(a); helper.Out.z = DefaultZ(helper); } virtual string OpenCLString() const override { ostringstream ss; string weight = WeightDefineString(); ss << "\t{\n" << "\t\treal_t a = precalcSqrtSumSquares * precalcAtanxy;\n" << "\t\treal_t r = " << weight << " * precalcSqrtSumSquares;\n" << "\n" << "\t\tvOut.x = r * sin(a);\n" << "\t\tvOut.y = (-r) * cos(a);\n" << "\t\tvOut.z = " << DefaultZCl() << "\t}\n"; return ss.str(); } }; /// /// Disc: /// nx = tx * M_PI; /// ny = ty * M_PI; /// a = atan2(nx, ny); /// r = std::sqrt(nx * nx + ny * ny); /// p[0] += weight * sin(r) * a / M_PI; /// p[1] += weight * cos(r) * a / M_PI; /// template class DiscVariation : public ParametricVariation { public: DiscVariation(T weight = 1.0) : ParametricVariation("disc", eVariationId::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 = std::sin(val) * r; helper.Out.y = std::cos(val) * r; helper.Out.z = m_Weight * helper.In.z; } virtual string OpenCLString() const override { ostringstream ss, ss2; intmax_t i = 0; ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string weight = WeightDefineString(); string weightByPI = "parVars[" + ToUpper(m_Params[i++].Name()) + index;//Precalcs only, no params. ss << "\t{\n" << "\t\treal_t val = MPI * 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 = " << weight << " * 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 = std::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 SpiralVariation : public Variation { public: SpiralVariation(T weight = 1.0) : Variation("spiral", eVariationId::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_PrecalcSina + std::sin(r));//Intentionally flipped. helper.Out.y = r1 * (helper.m_PrecalcCosa - std::cos(r)); helper.Out.z = m_Weight * helper.In.z; } virtual string OpenCLString() const override { ostringstream ss; string weight = WeightDefineString(); ss << "\t{\n" << "\t\treal_t r = Zeps(precalcSqrtSumSquares);\n" << "\t\treal_t r1 = " << weight << " / r;\n" << "\n" << "\t\tvOut.x = r1 * (precalcSina + sin(r));\n" << "\t\tvOut.y = r1 * (precalcCosa - cos(r));\n" << "\t\tvOut.z = " << weight << " * vIn.z;\n" << "\t}\n"; return ss.str(); } virtual vector OpenCLGlobalFuncNames() const override { return vector { "Zeps" }; } }; /// /// Hyperbolic: /// a = atan2(tx, ty); /// r = std::sqrt(tx * tx + ty * ty) + 1e-6; /// p[0] += weight * sin(a) / r; /// p[1] += weight * cos(a) * r; /// template class HyperbolicVariation : public Variation { public: HyperbolicVariation(T weight = 1.0) : Variation("hyperbolic", eVariationId::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_PrecalcCosa / r;//Flipped from flam3 because flam3 had them erroneously flipped. helper.Out.y = m_Weight * helper.m_PrecalcSina * r; helper.Out.z = m_Weight * helper.In.z; } virtual string OpenCLString() const override { ostringstream ss; string weight = WeightDefineString(); ss << "\t{\n" << "\t\treal_t r = Zeps(precalcSqrtSumSquares);\n" << "\n" << "\t\tvOut.x = " << weight << " * precalcCosa / r;\n" << "\t\tvOut.y = " << weight << " * precalcSina * r;\n" << "\t\tvOut.z = " << weight << " * vIn.z;\n" << "\t}\n"; return ss.str(); } virtual vector OpenCLGlobalFuncNames() const override { return vector { "Zeps" }; } }; /// /// Diamond: /// a = atan2(tx, ty); /// r = std::sqrt(tx * tx + ty * ty); /// p[0] += weight * sin(a) * cos(r); /// p[1] += weight * cos(a) * sin(r); /// template class DiamondVariation : public Variation { public: DiamondVariation(T weight = 1.0) : Variation("diamond", eVariationId::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_PrecalcCosa * std::cos(helper.m_PrecalcSqrtSumSquares);//Flipped from flam3 because flam3 had them erroneously flipped. helper.Out.y = m_Weight * helper.m_PrecalcSina * std::sin(helper.m_PrecalcSqrtSumSquares); helper.Out.z = DefaultZ(helper); } virtual string OpenCLString() const override { ostringstream ss; string weight = WeightDefineString(); ss << "\t{\n" << "\t\tvOut.x = " << weight << " * precalcCosa * cos(precalcSqrtSumSquares);\n" << "\t\tvOut.y = " << weight << " * precalcSina * sin(precalcSqrtSumSquares);\n" << "\t\tvOut.z = " << DefaultZCl() << "\t}\n"; return ss.str(); } }; /// /// Ex: /// a = atan2(tx, ty); /// r = std::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 ExVariation : public Variation { public: ExVariation(T weight = 1.0) : Variation("ex", eVariationId::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 = std::sin(a + r); T n1 = std::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 = DefaultZ(helper); } virtual string OpenCLString() const override { ostringstream ss; string weight = WeightDefineString(); 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 = " << weight << " * (m0 + m1);\n" << "\t\tvOut.y = " << weight << " * (m0 - m1);\n" << "\t\tvOut.z = " << DefaultZCl() << "\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 JuliaVariation : public Variation { public: JuliaVariation(T weight = 1.0) : Variation("julia", eVariationId::VAR_JULIA, weight, true, true, false, true) { } VARCOPY(JuliaVariation) virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { T r = m_Weight * std::sqrt(helper.m_PrecalcSqrtSumSquares); T a = T(0.5) * helper.m_PrecalcAtanxy; if (rand.RandBit()) a += T(M_PI); helper.Out.x = r * std::cos(a); helper.Out.y = r * std::sin(a); helper.Out.z = DefaultZ(helper); } virtual string OpenCLString() const override { ostringstream ss; string weight = WeightDefineString(); ss << "\t{\n" << "\t\treal_t r = " << weight << " * sqrt(precalcSqrtSumSquares);\n" << "\t\treal_t a = (real_t)(0.5) * precalcAtanxy;\n" << "\n" << "\t\tif (MwcNext(mwc) & 1)\n" << "\t\t a += MPI;\n" << "\n" << "\t\tvOut.x = r * cos(a);\n" << "\t\tvOut.y = r * sin(a);\n" << "\t\tvOut.z = " << DefaultZCl() << "\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 BentVariation : public Variation { public: BentVariation(T weight = 1.0) : Variation("bent", eVariationId::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 = DefaultZ(helper); } virtual string OpenCLString() const override { ostringstream ss; string weight = WeightDefineString(); ss << "\t{\n" << "\t\treal_t nx = vIn.x < (real_t)(0.0) ? (vIn.x * (real_t)(2.0)) : vIn.x;\n" << "\t\treal_t ny = vIn.y < (real_t)(0.0) ? (vIn.y / (real_t)(2.0)) : vIn.y;\n" << "\n" << "\t\tvOut.x = " << weight << " * nx;\n" << "\t\tvOut.y = " << weight << " * ny;\n" << "\t\tvOut.z = " << DefaultZCl() << "\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 WavesVariation : public ParametricVariation { public: WavesVariation(T weight = 1.0) : ParametricVariation("waves", eVariationId::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 * std::sin(helper.In.y * m_Dx2); T ny = helper.In.y + c11 * std::sin(helper.In.x * m_Dy2); helper.Out.x = m_Weight * nx; helper.Out.y = m_Weight * ny; helper.Out.z = DefaultZ(helper); } virtual string OpenCLString() const override { ostringstream ss, ss2; intmax_t i = 0; ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string weight = WeightDefineString(); string 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 = fma(c10, sin(vIn.y * " << dx2 << "), vIn.x);\n" << "\t\treal_t ny = fma(c11, sin(vIn.x * " << dy2 << "), vIn.y);\n" << "\n" << "\t\tvOut.x = (" << weight << " * nx);\n" << "\t\tvOut.y = (" << weight << " * ny);\n" << "\t\tvOut.z = " << DefaultZCl() << "\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 = std::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 FisheyeVariation : public Variation { public: FisheyeVariation(T weight = 1.0) : Variation("fisheye", eVariationId::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 = DefaultZ(helper); } virtual string OpenCLString() const override { ostringstream ss; string weight = WeightDefineString(); ss << "\t{\n" << "\t\treal_t r = 2 * " << weight << " / (precalcSqrtSumSquares + 1);\n" << "\n" << "\t\tvOut.x = r * vIn.y;\n" << "\t\tvOut.y = r * vIn.x;\n" << "\t\tvOut.z = " << DefaultZCl() << "\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 PopcornVariation : public Variation { public: PopcornVariation(T weight = 1.0) : Variation("popcorn", eVariationId::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() * std::sin(dx); T ny = helper.In.y + m_Xform->m_Affine.F() * std::sin(dy); helper.Out.x = m_Weight * nx; helper.Out.y = m_Weight * ny; helper.Out.z = DefaultZ(helper); } virtual string OpenCLString() const override { ostringstream ss; string weight = WeightDefineString(); 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 = fma(xform->m_C, sin(dx), vIn.x);\n" << "\t\treal_t ny = fma(xform->m_F, sin(dy), vIn.y);\n" << "\n" << "\t\tvOut.x = " << weight << " * nx;\n" << "\t\tvOut.y = " << weight << " * ny;\n" << "\t\tvOut.z = " << DefaultZCl() << "\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 ExponentialVariation : public Variation { public: ExponentialVariation(T weight = 1.0) : Variation("exponential", eVariationId::VAR_EXPONENTIAL, weight) { } VARCOPY(ExponentialVariation) virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { T dx = m_Weight * std::exp(helper.In.x - 1); T dy = T(M_PI) * helper.In.y; helper.Out.x = dx * std::cos(dy); helper.Out.y = dx * std::sin(dy); helper.Out.z = DefaultZ(helper); } virtual string OpenCLString() const override { ostringstream ss; string weight = WeightDefineString(); ss << "\t{\n" << "\t\treal_t dx = " << weight << " * exp(vIn.x - (real_t)(1.0));\n" << "\t\treal_t dy = MPI * vIn.y;\n" << "\n" << "\t\tvOut.x = dx * cos(dy);\n" << "\t\tvOut.y = dx * sin(dy);\n" << "\t\tvOut.z = " << DefaultZCl() << "\t}\n"; return ss.str(); } }; /// /// Power: /// a = atan2(tx, ty); /// sa = sin(a); /// r = std::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 PowerVariation : public Variation { public: PowerVariation(T weight = 1.0) : Variation("power", eVariationId::VAR_POWER, weight, true, true, true) { } VARCOPY(PowerVariation) virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { T r = m_Weight * std::pow(helper.m_PrecalcSqrtSumSquares, helper.m_PrecalcCosa);//Flipped from flam3. helper.Out.x = r * helper.m_PrecalcSina;//Intentionally flipped. helper.Out.y = r * helper.m_PrecalcCosa; helper.Out.z = DefaultZ(helper); } virtual string OpenCLString() const override { ostringstream ss; string weight = WeightDefineString(); ss << "\t{\n" << "\t\treal_t r = " << weight << " * pow(precalcSqrtSumSquares, precalcCosa);\n" << "\n" << "\t\tvOut.x = r * precalcSina;\n" << "\t\tvOut.y = r * precalcCosa;\n" << "\t\tvOut.z = " << DefaultZCl() << "\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 CosineVariation : public Variation { public: CosineVariation(T weight = 1.0) : Variation("cosine", eVariationId::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 = std::cos(a) * std::cosh(helper.In.y); T ny = -std::sin(a) * std::sinh(helper.In.y); helper.Out.x = m_Weight * nx; helper.Out.y = m_Weight * ny; helper.Out.z = DefaultZ(helper); } virtual string OpenCLString() const override { ostringstream ss; string weight = WeightDefineString(); ss << "\t{\n" << "\t\treal_t a = vIn.x * MPI;\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 = " << weight << " * nx;\n" << "\t\tvOut.y = " << weight << " * ny;\n" << "\t\tvOut.z = " << DefaultZCl() << "\t}\n"; return ss.str(); } }; /// /// Rings: /// dx = coef[2][0]; /// dx = dx * dx + EPS; /// r = std::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 RingsVariation : public Variation { public: RingsVariation(T weight = 1.0) : Variation("rings", eVariationId::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_PrecalcSina;//Intentionally flipped, also flipped from flam3 because flam3 had them erroneously flipped. helper.Out.y = r * helper.m_PrecalcCosa; helper.Out.z = DefaultZ(helper); } virtual string OpenCLString() const override { ostringstream ss; string weight = WeightDefineString(); ss << "\t{\n" << "\t\treal_t dx = Zeps(xform->m_C * xform->m_C);\n" << "\t\treal_t r = precalcSqrtSumSquares;\n" << "\n" << "\t\tr = " << weight << " * (fmod(r + dx, 2 * dx) + fma(r, ((real_t)(1.0) - dx), -dx));\n" << "\t\tvOut.x = r * precalcSina;\n" << "\t\tvOut.y = r * precalcCosa;\n" << "\t\tvOut.z = " << DefaultZCl() << "\t}\n"; return ss.str(); } virtual vector OpenCLGlobalFuncNames() const override { return vector { "Zeps" }; } }; /// /// Fan: /// dx = coef[2][0]; /// dy = coef[2][1]; /// dx = M_PI * (dx * dx + EPS); /// dx2 = dx / 2; /// a = atan(tx, ty); /// r = std::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 FanVariation : public Variation { public: FanVariation(T weight = 1.0) : Variation("fan", eVariationId::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 * std::cos(a); helper.Out.y = r * std::sin(a); helper.Out.z = DefaultZ(helper); } virtual string OpenCLString() const override { ostringstream ss; string weight = WeightDefineString(); ss << "\t{\n" << "\t\treal_t dx = MPI * Zeps(xform->m_C * xform->m_C);\n" << "\t\treal_t dy = xform->m_F;\n" << "\t\treal_t dx2 = (real_t)(0.5) * dx;\n" << "\t\treal_t a = precalcAtanxy + ((fmod(precalcAtanxy + dy, dx) > dx2) ? -dx2 : dx2);\n" << "\t\treal_t r = " << weight << " * precalcSqrtSumSquares;\n" << "\n" << "\t\tvOut.x = r * cos(a);\n" << "\t\tvOut.y = r * sin(a);\n" << "\t\tvOut.z = " << DefaultZCl() << "\t}\n"; return ss.str(); } virtual vector OpenCLGlobalFuncNames() const override { return vector { "Zeps" }; } }; /// /// Blob: /// a = atan2(tx, ty); /// r = std::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 BlobVariation : public ParametricVariation { public: BlobVariation(T weight = 1.0) : ParametricVariation("blob", eVariationId::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) * std::sin(m_BlobWaves * helper.m_PrecalcAtanxy))); helper.Out.x = m_Weight * helper.m_PrecalcCosa * r;//Flipped from flam3 because flam3 had them erroneously flipped. helper.Out.y = m_Weight * helper.m_PrecalcSina * r; helper.Out.z = DefaultZ(helper); } virtual string OpenCLString() const override { ostringstream ss, ss2; intmax_t i = 0; ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string weight = WeightDefineString(); string 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 * fma(" << blobDiff << ", fma((real_t)(0.5), sin(" << blobWaves << " * precalcAtanxy), (real_t)(0.5)), " << blobLow << ");\n" << "\n" << "\t\tvOut.x = " << weight << " * precalcCosa * r;\n" << "\t\tvOut.y = " << weight << " * precalcSina * r;\n" << "\t\tvOut.z = " << DefaultZCl() << "\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 PdjVariation : public ParametricVariation { public: PdjVariation(T weight = 1.0) : ParametricVariation("pdj", eVariationId::VAR_PDJ, weight) { Init(); } PARVARCOPY(PdjVariation) virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { T nx1 = std::cos(m_PdjB * helper.In.x); T nx2 = std::sin(m_PdjC * helper.In.x); T ny1 = std::sin(m_PdjA * helper.In.y); T ny2 = std::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() const override { ostringstream ss, ss2; intmax_t i = 0; ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string weight = WeightDefineString(); 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 = (" << weight << " * (ny1 - nx1));\n" << "\t\tvOut.y = (" << weight << " * (nx2 - ny2));\n" << "\t\tvOut.z = " << weight << " * 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 Fan2Variation : public ParametricVariation { public: Fan2Variation(T weight = 1.0) : ParametricVariation("fan2", eVariationId::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 * std::sin(a); helper.Out.y = r * std::cos(a); helper.Out.z = m_Weight * helper.In.z; } virtual string OpenCLString() const override { ostringstream ss, ss2; intmax_t i = 0; ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string weight = WeightDefineString(); 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 = " << weight << " * 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 = " << weight << " * 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 Rings2Variation : public ParametricVariation { public: Rings2Variation(T weight = 1.0) : ParametricVariation("rings2", eVariationId::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_PrecalcCosa * r;//Flipped from flam3 because flam3 had them erroneously flipped. helper.Out.y = m_Weight * helper.m_PrecalcSina * r; helper.Out.z = m_Weight * helper.In.z; } virtual string OpenCLString() const override { ostringstream ss, ss2; intmax_t i = 0; ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string weight = WeightDefineString(); 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 += fma((real_t)(-2.0) * " << rings2Val2 << ", (real_t)(int)((r + " << rings2Val2 << ") / ((real_t)(2.0) * " << rings2Val2 << ")), r * ((real_t)(1.0) - " << rings2Val2 << "));\n" //<< "\t\tr += -(real_t)(2.0) * " << rings2Val2 << " * (int)((r + " << rings2Val2 << ") / ((real_t)(2.0) * " << rings2Val2 << ")) + r * ((real_t)(1.0) - " << rings2Val2 << ");\n" << "\t\tvOut.x = (" << weight << " * precalcCosa * r);\n" << "\t\tvOut.y = (" << weight << " * precalcSina * r);\n" << "\t\tvOut.z = " << weight << " * 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 EyefishVariation : public Variation { public: EyefishVariation(T weight = 1.0) : Variation("eyefish", eVariationId::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() const override { ostringstream ss; string weight = WeightDefineString(); ss << "\t{\n" << "\t\treal_t r = (" << weight << " * (real_t)(2.0)) / (precalcSqrtSumSquares + (real_t)(1.0));\n" << "\n" << "\t\tvOut.x = r * vIn.x;\n" << "\t\tvOut.y = r * vIn.y;\n" << "\t\tvOut.z = " << weight << " * vIn.z;\n" << "\t}\n"; return ss.str(); } }; /// /// Bubble. /// template class BubbleVariation : public Variation { public: BubbleVariation(T weight = 1.0) : Variation("bubble", eVariationId::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 / Zeps(denom - 1)); } virtual string OpenCLString() const override { ostringstream ss; string weight = WeightDefineString(); ss << "\t{\n" << "\t\treal_t denom = fma((real_t)(0.25), precalcSumSquares, (real_t)(1.0));\n" << "\t\treal_t r = " << weight << " / denom;\n" << "\n" << "\t\tvOut.x = r * vIn.x;\n" << "\t\tvOut.y = r * vIn.y;\n" << "\t\tvOut.z = " << weight << " * (2 / Zeps(denom - 1));\n" << "\t}\n"; return ss.str(); } virtual vector OpenCLGlobalFuncNames() const override { return vector { "Zeps" }; } }; /// /// Cylinder. /// template class CylinderVariation : public Variation { public: CylinderVariation(T weight = 1.0) : Variation("cylinder", eVariationId::VAR_CYLINDER, weight) { } VARCOPY(CylinderVariation) 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 * helper.In.y; helper.Out.z = m_Weight * std::cos(helper.In.x); } virtual string OpenCLString() const override { ostringstream ss; string weight = WeightDefineString(); ss << "\t{\n" << "\t\tvOut.x = " << weight << " * sin(vIn.x);\n" << "\t\tvOut.y = " << weight << " * vIn.y;\n" << "\t\tvOut.z = " << weight << " * cos(vIn.x);\n" << "\t}\n"; return ss.str(); } }; /// /// Perspective. /// template class PerspectiveVariation : public ParametricVariation { public: PerspectiveVariation(T weight = 1.0) : ParametricVariation("perspective", eVariationId::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 = DefaultZ(helper); } virtual string OpenCLString() const override { ostringstream ss, ss2; intmax_t i = 0; ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string weight = WeightDefineString(); string angle = "parVars[" + ToUpper(m_Params[i++].Name()) + index;//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 = (real_t)(1.0) / d;\n" << "\n" << "\t\tvOut.x = (" << weight << " * " << dist << " * vIn.x * t);\n" << "\t\tvOut.y = (" << weight << " * " << vfCos << " * vIn.y * t);\n" << "\t\tvOut.z = " << DefaultZCl() << "\t}\n"; return ss.str(); } virtual vector OpenCLGlobalFuncNames() const override { return vector { "Zeps" }; } virtual void Precalc() override { T angle = m_Angle * T(M_PI) / 2; m_Vsin = std::sin(angle); m_VfCos = m_Dist * std::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 NoiseVariation : public Variation { public: NoiseVariation(T weight = 1.0) : Variation("noise", eVariationId::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 * std::cos(tempr); helper.Out.y = helper.In.y * r * std::sin(tempr); helper.Out.z = m_Weight * helper.In.z; } virtual string OpenCLString() const override { ostringstream ss; string weight = WeightDefineString(); ss << "\t{\n" << "\t\treal_t tempr = MwcNext01(mwc) * M_2PI;\n" << "\t\treal_t r = " << weight << " * 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 = " << weight << " * vIn.z;\n" << "\t}\n"; return ss.str(); } }; /// /// JuliaN. /// template class JuliaNGenericVariation : public ParametricVariation { public: JuliaNGenericVariation(T weight = 1.0) : ParametricVariation("julian", eVariationId::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(size_t(m_Rn))) / m_Power; T r = m_Weight * std::pow(helper.m_PrecalcSumSquares, m_Cn); helper.Out.x = r * std::cos(tempr); helper.Out.y = r * std::sin(tempr); helper.Out.z = m_Weight * helper.In.z; } virtual string OpenCLString() const override { ostringstream ss, ss2; intmax_t i = 0; ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string weight = WeightDefineString(); 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 = fma(M_2PI, (real_t)tRnd, precalcAtanyx) / " << power << ";\n" << "\t\treal_t r = " << weight << " * pow(precalcSumSquares, " << cn << ");\n" << "\n" << "\t\tvOut.x = r * cos(tempr);\n" << "\t\tvOut.y = r * sin(tempr);\n" << "\t\tvOut.z = " << weight << " * vIn.z;\n" << "\t}\n"; return ss.str(); } virtual void Precalc() override { m_Power = Zeps(m_Power); m_Rn = std::abs(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, eParamType::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 JuliaScopeVariation : public ParametricVariation { public: JuliaScopeVariation(T weight = 1.0) : ParametricVariation("juliascope", eVariationId::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 * std::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 * std::cos(tempr); helper.Out.y = r * std::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()) + helper.m_PrecalcAtanyx) / m_Power;//Fixed to get new random rather than use rnd from above.//SMOULDER //else // tempr = (2 * T(M_PI) * (int)(m_Rn * rand.Frand01()) - helper.m_PrecalcAtanyx) / m_Power; //r = m_Weight * pow(helper.m_PrecalcSumSquares, m_Cn); //helper.Out.x = r * cos(tempr); //helper.Out.y = r * sin(tempr); } virtual string OpenCLString() const override { ostringstream ss, ss2; intmax_t i = 0; ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string weight = WeightDefineString(); 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 rnd = (int)(" << rn << " * MwcNext01(mwc));\n" << "\t\treal_t tempr, r;\n" << "\n" << "\t\tif ((rnd & 1) == 0)\n" << "\t\t tempr = fma(M_2PI, (real_t)rnd, precalcAtanyx) / " << power << ";\n" << "\t\telse\n" << "\t\t tempr = fma(M_2PI, (real_t)rnd, -precalcAtanyx) / " << power << ";\n" << "\n" << "\t\tr = " << weight << " * pow(precalcSumSquares, " << cn << ");\n" << "\n" << "\t\tvOut.x = r * cos(tempr);\n" << "\t\tvOut.y = r * sin(tempr);\n" << "\t\tvOut.z = " << weight << " * vIn.z;\n" << "\t}\n"; //ss << "\t{\n" // << "\t\tint rnd = (int)(" << rn << " * MwcNext01(mwc));\n" // << "\t\treal_t tempr, r;\n" // << "\n" // << "\t\tif ((rnd & 1) == 0)\n" // << "\t\t tempr = (2 * M_PI * (int)(" << rn << " * MwcNext01(mwc)) + precalcAtanyx) / " << power << ";\n"//Fixed to get new random rather than use rnd from above.//SMOULDER // << "\t\telse\n" // << "\t\t tempr = (2 * M_PI * (int)(" << rn << " * MwcNext01(mwc)) - precalcAtanyx) / " << power << ";\n" // << "\n" // << "\t\tr = " << weight << " * pow(precalcSumSquares, " << cn << ");\n" // << "\n" // << "\t\tvOut.x = r * cos(tempr);\n" // << "\t\tvOut.y = r * sin(tempr);\n" // << "\t\tvOut.z = " << weight << " * vIn.z;\n" // << "\t}\n"; return ss.str(); } virtual void Precalc() override { m_Rn = std::abs(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 + "juliascope_dist", 1));//Params. m_Params.push_back(ParamWithName(&m_Power, prefix + "juliascope_power", 1, eParamType::REAL_NONZERO)); m_Params.push_back(ParamWithName(true, &m_Rn, prefix + "juliascope_rn"));//Precalc. m_Params.push_back(ParamWithName(true, &m_Cn, prefix + "juliascope_cn")); } private: T m_Dist;//Params. T m_Power; T m_Rn;//Precalc. T m_Cn; }; /// /// Blur. /// This is somewhat different than the original functionality in that blur used /// the code below, but pre_blur used gaussian_blur. /// If the original pre_blur functionality is needed, use pre_gaussian_blur. /// template class BlurVariation : public Variation { public: BlurVariation(T weight = 1.0) : Variation("blur", eVariationId::VAR_BLUR, weight) { } VARCOPY(BlurVariation) 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 = r * std::cos(tempr); helper.Out.y = r * std::sin(tempr); helper.Out.z = m_Weight * helper.In.z; } virtual string OpenCLString() const override { ostringstream ss; string weight = WeightDefineString(); ss << "\t{\n" << "\t\treal_t tmpr = MwcNext01(mwc) * M_2PI;\n" << "\t\treal_t r = " << weight << " * MwcNext01(mwc);\n" << "\n" << "\t\tvOut.x = r * cos(tmpr);\n" << "\t\tvOut.y = r * sin(tmpr);\n" << "\t\tvOut.z = " << weight << " * vIn.z;\n" << "\t}\n"; return ss.str(); } }; /// /// Gaussian blur. /// template class GaussianBlurVariation : public Variation { public: GaussianBlurVariation(T weight = 1.0) : Variation("gaussian_blur", eVariationId::VAR_GAUSSIAN_BLUR, weight) { } VARCOPY(GaussianBlurVariation) virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { T angle = rand.Frand01() * M_2PI; T r = m_Weight * (rand.Frand01() + rand.Frand01() + rand.Frand01() + rand.Frand01() - 2); helper.Out.x = r * std::cos(angle); helper.Out.y = r * std::sin(angle); helper.Out.z = m_Weight * helper.In.z; } virtual string OpenCLString() const override { ostringstream ss; string weight = WeightDefineString(); ss << "\t{\n" << "\t\treal_t angle = MwcNext01(mwc) * M_2PI;\n" << "\t\treal_t r = " << weight << " * (MwcNext01(mwc) + MwcNext01(mwc) + MwcNext01(mwc) + MwcNext01(mwc) - (real_t)(2.0));\n" << "\n" << "\t\tvOut.x = r * cos(angle);\n" << "\t\tvOut.y = r * sin(angle);\n" << "\t\tvOut.z = " << weight << " * vIn.z;\n" << "\t}\n"; return ss.str(); } }; /// /// Gaussian. /// template class GaussianVariation : public Variation { public: GaussianVariation(T weight = 1.0) : Variation("gaussian", eVariationId::VAR_GAUSSIAN, weight) { } VARCOPY(GaussianVariation) virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { T angle = rand.Frand01() * M_2PI; T r = m_Weight * (rand.Frand01() + rand.Frand01() + rand.Frand01() + rand.Frand01() - 2); helper.Out.x = r * std::cos(angle) + helper.In.x; helper.Out.y = r * std::sin(angle) + helper.In.y; helper.Out.z = DefaultZ(helper); } virtual string OpenCLString() const override { ostringstream ss; string weight = WeightDefineString(); ss << "\t{\n" << "\t\treal_t angle = MwcNext01(mwc) * M_2PI;\n" << "\t\treal_t r = " << weight << " * (MwcNext01(mwc) + MwcNext01(mwc) + MwcNext01(mwc) + MwcNext01(mwc) - (real_t)(2.0));\n" << "\n" << "\t\tvOut.x = fma(r, cos(angle), vIn.x);\n" << "\t\tvOut.y = fma(r, sin(angle), vIn.y);\n" << "\t\tvOut.z = " << DefaultZCl() << "\t}\n"; return ss.str(); } }; /// /// Radial blur. /// template class RadialBlurVariation : public ParametricVariation { public: RadialBlurVariation(T weight = 1.0) : ParametricVariation("radial_blur", eVariationId::VAR_RADIAL_BLUR, weight, true, true, false, false, true) { Init(); } PARVARCOPY(RadialBlurVariation) virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { //Get pseudo-gaussian. T rndG = m_Weight * (rand.Frand01() + rand.Frand01() + rand.Frand01() + rand.Frand01() - 2); //Calculate angle & zoom. T ra = helper.m_PrecalcSqrtSumSquares; T tempa = helper.m_PrecalcAtanyx + m_Spin * rndG; T rz = m_Zoom * rndG - 1; helper.Out.x = ra * std::cos(tempa) + rz * helper.In.x; helper.Out.y = ra * std::sin(tempa) + rz * helper.In.y; helper.Out.z = m_Weight * helper.In.z; } virtual string OpenCLString() const override { ostringstream ss, ss2; intmax_t i = 0; ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string weight = WeightDefineString(); string angle = "parVars[" + ToUpper(m_Params[i++].Name()) + index;//Params. string spin = "parVars[" + ToUpper(m_Params[i++].Name()) + index;//Precalc. string zoom = "parVars[" + ToUpper(m_Params[i++].Name()) + index; ss << "\t{\n" << "\t\treal_t rndG = " << weight << " * (MwcNext01(mwc) + MwcNext01(mwc) + MwcNext01(mwc) + MwcNext01(mwc) - (real_t)(2.0));\n" << "\t\treal_t ra = precalcSqrtSumSquares;\n" << "\t\treal_t tempa = fma(" << spin << ", rndG, precalcAtanyx);\n" << "\t\treal_t rz = fma(" << zoom << ", rndG, (real_t)(-1.0));\n" << "\n" << "\t\tvOut.x = fma(ra, cos(tempa), rz * vIn.x);\n" << "\t\tvOut.y = fma(ra, sin(tempa), rz * vIn.y);\n" << "\t\tvOut.z = " << weight << " * vIn.z;\n" << "\t}\n"; return ss.str(); } virtual void Precalc() override { sincos(m_Angle * T(M_PI) / 2, &m_Spin, &m_Zoom); } virtual void Random(QTIsaac& rand) override { m_Angle = (2 * rand.Frand01() - 1); } protected: void Init() { string prefix = Prefix(); m_Params.clear(); m_Params.push_back(ParamWithName(&m_Angle, prefix + "radial_blur_angle"));//Params. m_Params.push_back(ParamWithName(true, &m_Spin, prefix + "radial_blur_spin"));//Precalc. m_Params.push_back(ParamWithName(true, &m_Zoom, prefix + "radial_blur_zoom")); } private: T m_Angle;//Params. T m_Spin;//Precalc. T m_Zoom; }; /// /// Pie. /// template class PieVariation : public ParametricVariation { public: PieVariation(T weight = 1.0) : ParametricVariation("pie", eVariationId::VAR_PIE, weight) { Init(); } PARVARCOPY(PieVariation) virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { auto sl = rand.Rand(size_t(m_Slices)); T a = m_Rotation + m_Pi2Slices * (sl + m_Thickness * rand.Frand01()); T r = m_Weight * rand.Frand01(); helper.Out.x = r * std::cos(a); helper.Out.y = r * std::sin(a); helper.Out.z = DefaultZ(helper); } virtual string OpenCLString() const override { ostringstream ss, ss2; intmax_t i = 0; ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string weight = WeightDefineString(); string 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; string pi2Slices = "parVars[" + ToUpper(m_Params[i++].Name()) + index; ss << "\t{\n" << "\t\tuint sl = MwcNextRange(mwc, (uint)" << slices << ");\n" << "\t\treal_t a = fma(" << pi2Slices << ", fma(" << thickness << ", MwcNext01(mwc), sl), " << rotation << ");\n" << "\t\treal_t r = " << weight << " * MwcNext01(mwc);\n" << "\n" << "\t\tvOut.x = r * cos(a);\n" << "\t\tvOut.y = r * sin(a);\n" << "\t\tvOut.z = " << DefaultZCl() << "\t}\n"; return ss.str(); } virtual void Precalc() override { m_Pi2Slices = M_2PI / m_Slices; } 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 + "pie_slices", 6, eParamType::INTEGER_NONZERO, 1)); m_Params.push_back(ParamWithName(&m_Rotation, prefix + "pie_rotation", T(0.5), eParamType::REAL_CYCLIC, 0, M_2PI)); m_Params.push_back(ParamWithName(&m_Thickness, prefix + "pie_thickness", T(0.5), eParamType::REAL, 0, 1)); m_Params.push_back(ParamWithName(true, &m_Pi2Slices, prefix + "pie_pi2_slices")); } private: T m_Slices; T m_Rotation; T m_Thickness; T m_Pi2Slices;//Precalc }; /// /// Ngon. /// template class NgonVariation : public ParametricVariation { public: NgonVariation(T weight = 1.0) : ParametricVariation("ngon", eVariationId::VAR_NGON, weight, true, false, false, false, true) { Init(); } PARVARCOPY(NgonVariation) virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { T rFactor; if ((helper.In.x == 0) && (helper.In.y == 0)) rFactor = 0; else rFactor = std::pow(helper.m_PrecalcSumSquares, m_CPower); T phi = helper.m_PrecalcAtanyx - m_CSides * Floor(helper.m_PrecalcAtanyx * m_CSidesInv); if (phi > T(0.5) * m_CSides) phi -= m_CSides; T amp = (m_Corners * (1 / std::cos(phi) - 1) + m_Circle) * m_Weight * rFactor; helper.Out.x = amp * helper.In.x; helper.Out.y = amp * helper.In.y; helper.Out.z = m_Weight * helper.In.z; } virtual string OpenCLString() const override { ostringstream ss, ss2; intmax_t i = 0; ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string weight = WeightDefineString(); string sides = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string power = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string circle = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string corners = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string csides = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string csidesinv = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string cpower = "parVars[" + ToUpper(m_Params[i++].Name()) + index; ss << "\t{\n" << "\t\treal_t rFactor;\n" << "\n" << "\t\tif ((vIn.x == (real_t)(0.0)) && (vIn.y == (real_t)(0.0)))\n" << "\t\t rFactor = (real_t)(0.0);\n" << "\t\telse\n" << "\t\t rFactor = pow(precalcSumSquares, " << cpower << ");\n" << "\n" << "\t\treal_t phi = precalcAtanyx - " << csides << " * floor(precalcAtanyx * " << csidesinv << ");\n" << "\n" << "\t\tif (phi > (real_t)(0.5) * " << csides << ")\n" << "\t\t phi -= " << csides << ";\n" << "\n" << "\t\treal_t amp = fma(" << corners << ", (1 / cos(phi) - 1), " << circle << ") * " << weight << " * rFactor;\n" << "\n" << "\t\tvOut.x = amp * vIn.x;\n" << "\t\tvOut.y = amp * vIn.y;\n" << "\t\tvOut.z = " << weight << " * vIn.z;\n" << "\t}\n"; return ss.str(); } virtual void Precalc() override { m_CPower = -T(0.5) * m_Power; m_CSides = 2 * T(M_PI) / m_Sides; m_CSidesInv = 1 / m_CSides; } virtual void Random(QTIsaac& rand) override { m_Sides = T(int(rand.Frand01() * 10 + 3)); m_Power = 3 * rand.Frand01() + 1; m_Circle = 3 * rand.Frand01(); m_Corners = 2 * rand.Frand01() * m_Circle; } protected: void Init() { string prefix = Prefix(); m_Params.clear(); m_Params.push_back(ParamWithName(&m_Sides, prefix + "ngon_sides", 5, eParamType::INTEGER_NONZERO)); m_Params.push_back(ParamWithName(&m_Power, prefix + "ngon_power", 3)); m_Params.push_back(ParamWithName(&m_Circle, prefix + "ngon_circle", 1)); m_Params.push_back(ParamWithName(&m_Corners, prefix + "ngon_corners", 2)); m_Params.push_back(ParamWithName(true, &m_CSides, prefix + "ngon_csides")); m_Params.push_back(ParamWithName(true, &m_CSidesInv, prefix + "ngon_csides_inv")); m_Params.push_back(ParamWithName(true, &m_CPower, prefix + "ngon_cpower")); } private: T m_Sides; T m_Power; T m_Circle; T m_Corners; T m_CSides; T m_CSidesInv; T m_CPower; }; /// /// Curl. /// Note that in Apophysis, curl and post_curl differed slightly. /// Using what post_curl did here gave bad results, so sticking with the original /// curl code. /// template class CurlVariation : public ParametricVariation { public: CurlVariation(T weight = 1.0) : ParametricVariation("curl", eVariationId::VAR_CURL, weight) { Init(); } PARVARCOPY(CurlVariation) virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { T re = 1 + m_C1 * helper.In.x + m_C2 * (SQR(helper.In.x) - SQR(helper.In.y)); T im = m_C1 * helper.In.y + m_C22 * helper.In.x * helper.In.y; T r = m_Weight / Zeps(SQR(re) + SQR(im)); helper.Out.x = (helper.In.x * re + helper.In.y * im) * r; helper.Out.y = (helper.In.y * re - helper.In.x * im) * r; helper.Out.z = DefaultZ(helper); } virtual string OpenCLString() const override { ostringstream ss, ss2; intmax_t i = 0; ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string weight = WeightDefineString(); string c1 = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string c2 = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string c22 = "parVars[" + ToUpper(m_Params[i++].Name()) + index; ss << "\t{\n" << "\t\treal_t re = (real_t)(1.0) + " << c1 << " * vIn.x + " << c2 << " * fma(vIn.x, vIn.x, -SQR(vIn.y));\n" << "\t\treal_t im = fma(" << c1 << ", vIn.y, " << c22 << " * vIn.x * vIn.y);\n" << "\t\treal_t r = " << weight << " / Zeps(fma(re, re, SQR(im)));\n" << "\n" << "\t\tvOut.x = fma(vIn.x, re, vIn.y * im) * r;\n" << "\t\tvOut.y = fma(vIn.y, re, -(vIn.x * im)) * r;\n" << "\t\tvOut.z = " << DefaultZCl() << "\t}\n"; return ss.str(); } virtual vector OpenCLGlobalFuncNames() const override { return vector { "Zeps" }; } virtual void Precalc() override { m_C22 = 2 * m_C2; } virtual void Random(QTIsaac& rand) override { m_C1 = rand.Frand01(); m_C2 = rand.Frand01(); } protected: void Init() { string prefix = Prefix(); m_Params.clear(); m_Params.push_back(ParamWithName(&m_C1, prefix + "curl_c1", 1)); m_Params.push_back(ParamWithName(&m_C2, prefix + "curl_c2")); m_Params.push_back(ParamWithName(true, &m_C22, prefix + "curl_c22"));//Precalc. } private: T m_C1; T m_C2; T m_C22;//Precalc. }; /// /// Rectangles. /// template class RectanglesVariation : public ParametricVariation { public: RectanglesVariation(T weight = 1.0) : ParametricVariation("rectangles", eVariationId::VAR_RECTANGLES, weight) { Init(); } PARVARCOPY(RectanglesVariation) virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { if (m_X == 0) helper.Out.x = m_Weight * helper.In.x; else helper.Out.x = m_Weight * ((2 * Floor(helper.In.x / m_X) + 1) * m_X - helper.In.x); if (m_Y == 0) helper.Out.y = m_Weight * helper.In.y; else helper.Out.y = m_Weight * ((2 * Floor(helper.In.y / m_Y) + 1) * m_Y - helper.In.y); helper.Out.z = m_Weight * helper.In.z; } virtual string OpenCLString() const override { ostringstream ss, ss2; intmax_t i = 0; ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string weight = WeightDefineString(); string x = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string y = "parVars[" + ToUpper(m_Params[i++].Name()) + index; ss << "\t{\n" << "\t\tif (" << x << " == 0)\n" << "\t\t vOut.x = " << weight << " * vIn.x;\n" << "\t\telse\n" << "\t\t vOut.x = " << weight << " * fma(fma((real_t)(2.0), floor(vIn.x / " << x << "), 1), " << x << ", -vIn.x);\n" << "\n" << "\t\tif (" << y << " == 0)\n" << "\t\t vOut.y = " << weight << " * vIn.y;\n" << "\t\telse\n" << "\t\t vOut.y = " << weight << " * fma(fma((real_t)(2.0), floor(vIn.y / " << y << "), 1), " << y << ", -vIn.y);\n" << "\n" << "\t\tvOut.z = " << weight << " * vIn.z;\n" << "\t}\n"; return ss.str(); } virtual void Random(QTIsaac& rand) override { m_X = rand.Frand01(); m_Y = rand.Frand01(); } protected: void Init() { string prefix = Prefix(); m_Params.clear(); m_Params.push_back(ParamWithName(&m_X, prefix + "rectangles_x", 1)); m_Params.push_back(ParamWithName(&m_Y, prefix + "rectangles_y", 1)); } private: T m_X; T m_Y; }; /// /// Arch. /// template class ArchVariation : public Variation { public: ArchVariation(T weight = 1.0) : Variation("arch", eVariationId::VAR_ARCH, weight) { } VARCOPY(ArchVariation) virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { T angle = rand.Frand01() * m_Weight * T(M_PI); T sinr, cosr; sincos(angle, &sinr, &cosr); helper.Out.x = m_Weight * sinr; helper.Out.y = m_Weight * (sinr * sinr) / cosr; helper.Out.z = DefaultZ(helper); } virtual string OpenCLString() const override { ostringstream ss; string weight = WeightDefineString(); ss << "\t{\n" << "\t\treal_t angle = MwcNext01(mwc) * " << weight << " * MPI;\n" << "\t\treal_t sinr = sin(angle);\n" << "\t\treal_t cosr = cos(angle);\n" << "\n" << "\t\tvOut.x = " << weight << " * sinr;\n" << "\t\tvOut.y = " << weight << " * (sinr * sinr) / cosr;\n" << "\t\tvOut.z = " << DefaultZCl() << "\t}\n"; return ss.str(); } }; /// /// Tangent. /// template class TangentVariation : public Variation { public: TangentVariation(T weight = 1.0) : Variation("tangent", eVariationId::VAR_TANGENT, weight) { } VARCOPY(TangentVariation) virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { helper.Out.x = m_Weight * std::sin(helper.In.x) / std::cos(helper.In.y); helper.Out.y = m_Weight * SafeTan(helper.In.y); helper.Out.z = DefaultZ(helper); } virtual string OpenCLString() const override { ostringstream ss; string weight = WeightDefineString(); ss << "\t{\n" << "\t\tvOut.x = " << weight << " * sin(vIn.x) / cos(vIn.y);\n" << "\t\tvOut.y = " << weight << " * tan(vIn.y);\n" << "\t\tvOut.z = " << DefaultZCl() << "\t}\n"; return ss.str(); } }; /// /// Square. /// template class SquareVariation : public Variation { public: SquareVariation(T weight = 1.0) : Variation("square", eVariationId::VAR_SQUARE, weight) { } VARCOPY(SquareVariation) virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { helper.Out.x = m_Weight * (rand.Frand01() - T(0.5)); helper.Out.y = m_Weight * (rand.Frand01() - T(0.5)); helper.Out.z = m_Weight * helper.In.z; } virtual string OpenCLString() const override { ostringstream ss; string weight = WeightDefineString(); ss << "\t{\n" << "\t\tvOut.x = " << weight << " * (MwcNext01(mwc) - (real_t)(0.5));\n" << "\t\tvOut.y = " << weight << " * (MwcNext01(mwc) - (real_t)(0.5));\n" << "\t\tvOut.z = " << weight << " * vIn.z;\n" << "\t}\n"; return ss.str(); } }; /// /// Rays. /// template class RaysVariation : public Variation { public: RaysVariation(T weight = 1.0) : Variation("rays", eVariationId::VAR_RAYS, weight, true) { } VARCOPY(RaysVariation) virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { T ang = m_Weight * rand.Frand01() * T(M_PI); T r = m_Weight / Zeps(helper.m_PrecalcSumSquares); T tanr = m_Weight * SafeTan(ang) * r; helper.Out.x = tanr * std::cos(helper.In.x); helper.Out.y = tanr * std::sin(helper.In.y); helper.Out.z = DefaultZ(helper); } virtual string OpenCLString() const override { ostringstream ss; string weight = WeightDefineString(); ss << "\t{\n" << "\t\treal_t ang = " << weight << " * MwcNext01(mwc) * MPI;\n" << "\t\treal_t r = " << weight << " / Zeps(precalcSumSquares);\n" << "\t\treal_t tanr = " << weight << " * tan(ang) * r;\n" << "\n" << "\t\tvOut.x = tanr * cos(vIn.x);\n" << "\t\tvOut.y = tanr * sin(vIn.y);\n" << "\t\tvOut.z = " << DefaultZCl() << "\t}\n"; return ss.str(); } virtual vector OpenCLGlobalFuncNames() const override { return vector { "Zeps" }; } }; /// /// Rays1 from JWildfire by Raykoid666. /// template class Rays1Variation : public Variation { public: Rays1Variation(T weight = 1.0) : Variation("rays1", eVariationId::VAR_RAYS1, weight, true, true) { } VARCOPY(Rays1Variation) virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { T u = 1 / Zeps(SafeTan(helper.m_PrecalcSqrtSumSquares)) + (m_Weight * T(SQR(M_2_PI))); if (m_VarType == eVariationType::VARTYPE_REG) outPoint.m_X = outPoint.m_Y = 0;//This variation assigns, instead of summing, so order will matter. helper.Out.x = m_Weight * u * helper.m_PrecalcSumSquares / Zeps(helper.In.x); helper.Out.y = m_Weight * u * helper.m_PrecalcSumSquares / Zeps(helper.In.y); helper.Out.z = m_Weight * helper.In.z; } virtual string OpenCLString() const override { ostringstream ss; string weight = WeightDefineString(); ss << "\t{\n" << "\t\treal_t u = fma(" << weight << ", SQR(M2PI), 1 / Zeps(tan(precalcSqrtSumSquares)));\n"; if (m_VarType == eVariationType::VARTYPE_REG) ss << "\t\toutPoint->m_X = outPoint->m_Y = 0;\n"; ss << "\t\tvOut.x = " << weight << " * u * precalcSumSquares / Zeps(vIn.x);\n" << "\t\tvOut.y = " << weight << " * u * precalcSumSquares / Zeps(vIn.y);\n" << "\t\tvOut.z = " << weight << " * vIn.z;\n" << "\t}\n"; return ss.str(); } virtual vector OpenCLGlobalFuncNames() const override { return vector { "Zeps" }; } }; /// /// Rays2 from JWildfire by Raykoid666. /// template class Rays2Variation : public Variation { public: Rays2Variation(T weight = 1.0) : Variation("rays2", eVariationId::VAR_RAYS2, weight, true) { } VARCOPY(Rays2Variation) virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { T u = 1 / std::cos(helper.m_PrecalcSumSquares * std::tan(1 / Zeps(helper.m_PrecalcSumSquares))); if (m_VarType == eVariationType::VARTYPE_REG) outPoint.m_X = outPoint.m_Y = 0;//This variation assigns, instead of summing, so order will matter. helper.Out.x = (m_Weight / 10) * u * helper.m_PrecalcSumSquares / Zeps(helper.In.x); helper.Out.y = (m_Weight / 10) * u * helper.m_PrecalcSumSquares / Zeps(helper.In.y); helper.Out.z = m_Weight * helper.In.z; } virtual string OpenCLString() const override { ostringstream ss; string weight = WeightDefineString(); ss << "\t{\n" << "\t\treal_t u = 1 / cos(precalcSumSquares * tan(1 / Zeps(precalcSumSquares)));\n"; if (m_VarType == eVariationType::VARTYPE_REG) ss << "\t\toutPoint->m_X = outPoint->m_Y = 0;\n"; ss << "\t\tvOut.x = (" << weight << " / 10) * u * precalcSumSquares / Zeps(vIn.x);\n" << "\t\tvOut.y = (" << weight << " / 10) * u * precalcSumSquares / Zeps(vIn.y);\n" << "\t\tvOut.z = " << weight << " * vIn.z;\n" << "\t}\n"; return ss.str(); } virtual vector OpenCLGlobalFuncNames() const override { return vector { "Zeps" }; } }; /// /// Rays3 from JWildfire by Raykoid666. /// template class Rays3Variation : public Variation { public: Rays3Variation(T weight = 1.0) : Variation("rays3", eVariationId::VAR_RAYS3, weight, true) { } VARCOPY(Rays3Variation) virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { T sq = SQR(helper.m_PrecalcSumSquares); T u = 1 / std::sqrt(std::cos(std::sin(sq) * std::sin(1 / Zeps(sq)))); if (m_VarType == eVariationType::VARTYPE_REG) outPoint.m_X = outPoint.m_Y = 0;//This variation assigns, instead of summing, so order will matter. helper.Out.x = (m_Weight / 10) * u * std::cos(helper.m_PrecalcSumSquares) * helper.m_PrecalcSumSquares / Zeps(helper.In.x); helper.Out.y = (m_Weight / 10) * u * std::tan(helper.m_PrecalcSumSquares) * helper.m_PrecalcSumSquares / Zeps(helper.In.y); helper.Out.z = m_Weight * helper.In.z; } virtual string OpenCLString() const override { ostringstream ss; string weight = WeightDefineString(); ss << "\t{\n" << "\t\treal_t sq = SQR(precalcSumSquares);\n" << "\t\treal_t u = 1 / sqrt(cos(sin(sq) * sin(1 / Zeps(sq))));\n"; if (m_VarType == eVariationType::VARTYPE_REG) ss << "\t\toutPoint->m_X = outPoint->m_Y = 0;\n"; ss << "\t\tvOut.x = (" << weight << " / 10) * u * cos(precalcSumSquares) * precalcSumSquares / Zeps(vIn.x);\n" << "\t\tvOut.y = (" << weight << " / 10) * u * tan(precalcSumSquares) * precalcSumSquares / Zeps(vIn.y);\n" << "\t\tvOut.z = " << weight << " * vIn.z;\n" << "\t}\n"; return ss.str(); } virtual vector OpenCLGlobalFuncNames() const override { return vector { "Zeps" }; } }; /// /// Blade. /// template class BladeVariation : public Variation { public: BladeVariation(T weight = 1.0) : Variation("blade", eVariationId::VAR_BLADE, weight, true, true) { } VARCOPY(BladeVariation) virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { T r = rand.Frand01() * m_Weight * helper.m_PrecalcSqrtSumSquares; T sinr, cosr; sincos(r, &sinr, &cosr); helper.Out.x = m_Weight * helper.In.x * (cosr + sinr); helper.Out.y = m_Weight * helper.In.x * (cosr - sinr); helper.Out.z = DefaultZ(helper); } virtual string OpenCLString() const override { ostringstream ss; string weight = WeightDefineString(); ss << "\t{\n" << "\t\treal_t r = MwcNext01(mwc) * " << weight << " * precalcSqrtSumSquares;\n" << "\t\treal_t sinr = sin(r);\n" << "\t\treal_t cosr = cos(r);\n" << "\n" << "\t\tvOut.x = " << weight << " * vIn.x * (cosr + sinr);\n" << "\t\tvOut.y = " << weight << " * vIn.x * (cosr - sinr);\n" << "\t\tvOut.z = " << DefaultZCl() << "\t}\n"; return ss.str(); } }; /// /// Secant2. /// template class Secant2Variation : public Variation { public: Secant2Variation(T weight = 1.0) : Variation("secant2", eVariationId::VAR_SECANT2, weight, true, true) { } VARCOPY(Secant2Variation) virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { T r = m_Weight * helper.m_PrecalcSqrtSumSquares; T cr = std::cos(r); T icr = 1 / cr; helper.Out.x = m_Weight * helper.In.x; if (cr < 0) helper.Out.y = m_Weight * (icr + 1); else helper.Out.y = m_Weight * (icr - 1); helper.Out.z = DefaultZ(helper); } virtual string OpenCLString() const override { ostringstream ss; string weight = WeightDefineString(); ss << "\t{\n" << "\t\treal_t r = " << weight << " * precalcSqrtSumSquares;\n" << "\t\treal_t cr = cos(r);\n" << "\t\treal_t icr = (real_t)(1.0) / cr;\n" << "\n" << "\t\tvOut.x = " << weight << " * vIn.x;\n" << "\n" << "\t\tif (cr < (real_t)(0.0))\n" << "\t\t vOut.y = " << weight << " * (icr + (real_t)(1.0));\n" << "\t\telse\n" << "\t\t vOut.y = " << weight << " * (icr - (real_t)(1.0));\n" << "\n" << "\t\tvOut.z = " << DefaultZCl() << "\t}\n"; return ss.str(); } }; /// /// TwinTrian. /// template class TwinTrianVariation : public Variation { public: TwinTrianVariation(T weight = 1.0) : Variation("TwinTrian", eVariationId::VAR_TWINTRIAN, weight, true, true) { } VARCOPY(TwinTrianVariation) virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { T r = rand.Frand01() * m_Weight * helper.m_PrecalcSqrtSumSquares; T sinr, cosr, diff; sincos(r, &sinr, &cosr); diff = std::log10(SQR(sinr)) + cosr; if (BadVal(diff)) diff = -30.0; helper.Out.x = m_Weight * helper.In.x * diff; helper.Out.y = m_Weight * helper.In.x * (diff - sinr * T(M_PI)); helper.Out.z = DefaultZ(helper); } virtual string OpenCLString() const override { ostringstream ss; string weight = WeightDefineString(); ss << "\t{\n" << "\t\treal_t r = MwcNext01(mwc) * " << weight << " * precalcSqrtSumSquares;\n" << "\t\treal_t sinr = sin(r);\n" << "\t\treal_t cosr = cos(r);\n" << "\t\treal_t diff = log10(SQR(sinr)) + cosr;\n" << "\n" << "\t\tif (BadVal(diff))\n" << "\t\t diff = -(real_t)(30.0);\n" << "\n" << "\t\tvOut.x = " << weight << " * vIn.x * diff;\n" << "\t\tvOut.y = " << weight << " * vIn.x * (diff - sinr * MPI);\n" << "\t\tvOut.z = " << DefaultZCl() << "\t}\n"; return ss.str(); } }; /// /// Cross. /// template class CrossVariation : public Variation { public: CrossVariation(T weight = 1.0) : Variation("cross", eVariationId::VAR_CROSS, weight) { } VARCOPY(CrossVariation) virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { T r = m_Weight / Zeps(std::abs((helper.In.x - helper.In.y) * (helper.In.x + helper.In.y))); helper.Out.x = helper.In.x * r; helper.Out.y = helper.In.y * r; helper.Out.z = m_Weight * helper.In.z; } virtual string OpenCLString() const override { ostringstream ss; string weight = WeightDefineString(); ss << "\t{\n" << "\t\treal_t r = " << weight << " /Zeps(fabs((vIn.x - vIn.y) * (vIn.x + vIn.y)));\n" << "\n" << "\t\tvOut.x = vIn.x * r;\n" << "\t\tvOut.y = vIn.y * r;\n" << "\t\tvOut.z = " << weight << " * vIn.z;\n" << "\t}\n"; return ss.str(); } virtual vector OpenCLGlobalFuncNames() const override { return vector { "Zeps" }; } }; /// /// Disc2. /// template class Disc2Variation : public ParametricVariation { public: Disc2Variation(T weight = 1.0) : ParametricVariation("disc2", eVariationId::VAR_DISC2, weight, false, false, false, true) { Init(); } PARVARCOPY(Disc2Variation) virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { T r, t, sinr, cosr; t = m_RotTimesPi * (helper.In.x + helper.In.y); sincos(t, &sinr, &cosr); r = m_Weight * helper.m_PrecalcAtanxy / T(M_PI); helper.Out.x = (sinr + m_CosAdd) * r; helper.Out.y = (cosr + m_SinAdd) * r; helper.Out.z = DefaultZ(helper); } virtual string OpenCLString() const override { ostringstream ss, ss2; intmax_t i = 0; ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string weight = WeightDefineString(); string rot = "parVars[" + ToUpper(m_Params[i++].Name()) + index;//Params. string twist = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string sinAdd = "parVars[" + ToUpper(m_Params[i++].Name()) + index;//Precalc. string cosAdd = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string rotTimesPi = "parVars[" + ToUpper(m_Params[i++].Name()) + index; ss << "\t{\n" << "\t\treal_t t = " << rotTimesPi << " * (vIn.x + vIn.y);\n" << "\t\treal_t sinr = sin(t);\n" << "\t\treal_t cosr = cos(t);\n" << "\t\treal_t r = " << weight << " * precalcAtanxy / MPI;\n" << "\n" << "\t\tvOut.x = (sinr + " << cosAdd << ") * r;\n" << "\t\tvOut.y = (cosr + " << sinAdd << ") * r;\n" << "\t\tvOut.z = " << DefaultZCl() << "\t}\n"; return ss.str(); } virtual void Precalc() override { T k, add = m_Twist; m_RotTimesPi = m_Rot * T(M_PI); sincos(add, &m_SinAdd, &m_CosAdd); m_CosAdd -= 1; if (add > 2 * M_PI) { k = (1 + add - 2 * T(M_PI)); m_CosAdd *= k; m_SinAdd *= k; } if (add < -2 * M_PI) { k = (1 + add + 2 * T(M_PI)); m_CosAdd *= k; m_SinAdd *= k; } } virtual void Random(QTIsaac& rand) override { m_Rot = T(0.5) * rand.Frand01(); m_Twist = T(0.5) * rand.Frand01(); } protected: void Init() { string prefix = Prefix(); m_Params.clear(); m_Params.push_back(ParamWithName(&m_Rot, prefix + "disc2_rot"));//Params. m_Params.push_back(ParamWithName(&m_Twist, prefix + "disc2_twist")); m_Params.push_back(ParamWithName(true, &m_SinAdd, prefix + "disc2_sin_add"));//Precalc. m_Params.push_back(ParamWithName(true, &m_CosAdd, prefix + "disc2_cos_add")); m_Params.push_back(ParamWithName(true, &m_RotTimesPi, prefix + "disc2_rot_times_pi")); } private: T m_Rot;//Params. T m_Twist; T m_SinAdd;//Precalc. T m_CosAdd; T m_RotTimesPi; }; /// /// SuperShape. /// template class SuperShapeVariation : public ParametricVariation { public: SuperShapeVariation(T weight = 1.0) : ParametricVariation("super_shape", eVariationId::VAR_SUPER_SHAPE, weight, true, true, false, false, true) { Init(); } PARVARCOPY(SuperShapeVariation) virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { T theta = m_Pm4 * helper.m_PrecalcAtanyx + T(M_PI_4); T t1 = std::abs(std::cos(theta)); t1 = std::pow(t1, m_N2); T t2 = std::abs(std::sin(theta)); t2 = std::pow(t2, m_N3); T r = m_Weight * ((m_Rnd * rand.Frand01() + (1 - m_Rnd) * helper.m_PrecalcSqrtSumSquares) - m_Holes) * std::pow(t1 + t2, m_PNeg1N1) / helper.m_PrecalcSqrtSumSquares; helper.Out.x = r * helper.In.x; helper.Out.y = r * helper.In.y; helper.Out.z = DefaultZ(helper); } virtual string OpenCLString() const override { ostringstream ss, ss2; intmax_t i = 0; ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string weight = WeightDefineString(); string m = "parVars[" + ToUpper(m_Params[i++].Name()) + index;//Params. string n1 = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string n2 = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string n3 = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string rnd = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string holes = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string pm4 = "parVars[" + ToUpper(m_Params[i++].Name()) + index;//Precalc. string pNeg1N1 = "parVars[" + ToUpper(m_Params[i++].Name()) + index; ss << "\t{\n" << "\t\treal_t theta = " << pm4 << " * precalcAtanyx + MPI4;\n" << "\t\treal_t t1 = fabs(cos(theta));\n" << "\t\tt1 = pow(t1, " << n2 << ");\n" << "\t\treal_t t2 = fabs(sin(theta));\n" << "\t\tt2 = pow(t2, " << n3 << ");\n" << "\t\treal_t r = " << weight << " * (fma(" << rnd << ", MwcNext01(mwc), ((real_t)(1.0) - " << rnd << ") * precalcSqrtSumSquares) - " << holes << ") * pow(t1 + t2, " << pNeg1N1 << ") / precalcSqrtSumSquares;\n" << "\n" << "\t\tvOut.x = r * vIn.x;\n" << "\t\tvOut.y = r * vIn.y;\n" << "\t\tvOut.z = " << DefaultZCl() << "\t}\n"; return ss.str(); } virtual void Precalc() override { m_Pm4 = m_M / T(4.0); m_PNeg1N1 = T(-1.0) / m_N1; } virtual void Random(QTIsaac& rand) override { m_Rnd = rand.Frand01(); m_M = T(int(rand.Frand01() * 6)); m_N1 = rand.Frand01() * 40; m_N2 = rand.Frand01() * 20; m_N3 = m_N2; m_Holes = 0.0; } protected: void Init() { string prefix = Prefix(); m_Params.clear(); m_Params.push_back(ParamWithName(&m_M, prefix + "super_shape_m"));//Params. m_Params.push_back(ParamWithName(&m_N1, prefix + "super_shape_n1", 1)); m_Params.push_back(ParamWithName(&m_N2, prefix + "super_shape_n2", 1)); m_Params.push_back(ParamWithName(&m_N3, prefix + "super_shape_n3", 1)); m_Params.push_back(ParamWithName(&m_Rnd, prefix + "super_shape_rnd")); m_Params.push_back(ParamWithName(&m_Holes, prefix + "super_shape_holes")); m_Params.push_back(ParamWithName(true, &m_Pm4, prefix + "super_shape_pm4"));//Precalc. m_Params.push_back(ParamWithName(true, &m_PNeg1N1, prefix + "super_shape_pneg1n1")); } private: T m_M;//Params. T m_N1; T m_N2; T m_N3; T m_Rnd; T m_Holes; T m_Pm4;//Precalc. T m_PNeg1N1; }; /// /// Flower. /// template class FlowerVariation : public ParametricVariation { public: FlowerVariation(T weight = 1.0) : ParametricVariation("flower", eVariationId::VAR_FLOWER, weight, true, true, false, false, true) { Init(); } PARVARCOPY(FlowerVariation) virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { T theta = helper.m_PrecalcAtanyx; T r = m_Weight * (rand.Frand01() - m_Holes) * std::cos(m_Petals * theta) / helper.m_PrecalcSqrtSumSquares; helper.Out.x = r * helper.In.x; helper.Out.y = r * helper.In.y; helper.Out.z = DefaultZ(helper); } virtual string OpenCLString() const override { ostringstream ss, ss2; intmax_t i = 0; ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string weight = WeightDefineString(); string petals = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string holes = "parVars[" + ToUpper(m_Params[i++].Name()) + index; ss << "\t{\n" << "\t\treal_t theta = precalcAtanyx;\n" << "\t\treal_t r = " << weight << " * (MwcNext01(mwc) - " << holes << ") * cos(" << petals << " * theta) / precalcSqrtSumSquares;\n" << "\n" << "\t\tvOut.x = r * vIn.x;\n" << "\t\tvOut.y = r * vIn.y;\n" << "\t\tvOut.z = " << DefaultZCl() << "\t}\n"; return ss.str(); } virtual void Random(QTIsaac& rand) override { m_Petals = 4 * rand.Frand01(); m_Holes = rand.Frand01(); } protected: void Init() { string prefix = Prefix(); m_Params.clear(); m_Params.push_back(ParamWithName(&m_Petals, prefix + "flower_petals")); m_Params.push_back(ParamWithName(&m_Holes, prefix + "flower_holes")); } private: T m_Petals; T m_Holes; }; /// /// flowerdb. /// By dark-beam. /// template class FlowerDbVariation : public ParametricVariation { public: FlowerDbVariation(T weight = 1.0) : ParametricVariation("flowerdb", eVariationId::VAR_FLOWER_DB, weight, true, true, false, false, true) { Init(); } PARVARCOPY(FlowerDbVariation) virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { T r = m_Weight * helper.m_PrecalcSqrtSumSquares; T t = helper.m_PrecalcAtanyx; T r2 = r * (std::abs((m_Spread + std::sin(m_Petals * t)) * cos(m_PetalsSplit * t))); helper.Out.x = r2 * std::cos(t); helper.Out.y = r2 * std::sin(t); helper.Out.z = DefaultZ(helper); } virtual string OpenCLString() const override { ostringstream ss, ss2; intmax_t i = 0; ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string weight = WeightDefineString(); string petals = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string split = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string spread = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string petalssplit = "parVars[" + ToUpper(m_Params[i++].Name()) + index; ss << "\t{\n" << "\t\treal_t r = " << weight << " * precalcSqrtSumSquares;\n" << "\t\treal_t t = precalcAtanyx;\n" << "\t\treal_t r2 = r * (fabs((" << spread << " + sin(" << petals << " * t)) * cos(" << petalssplit << " * t)));\n" << "\n" << "\t\tvOut.x = r * cos(t);\n" << "\t\tvOut.y = r * sin(t);\n" << "\t\tvOut.z = " << DefaultZCl() << "\t}\n"; return ss.str(); } virtual void Precalc() override { m_PetalsSplit = m_Petals * m_Split; } protected: void Init() { string prefix = Prefix(); m_Params.clear(); m_Params.push_back(ParamWithName(&m_Petals, prefix + "flowerdb_petals", 6)); m_Params.push_back(ParamWithName(&m_Split, prefix + "flowerdb_petal_split")); m_Params.push_back(ParamWithName(&m_Spread, prefix + "flowerdb_petal_spread", 1)); m_Params.push_back(ParamWithName(true, &m_PetalsSplit, prefix + "flowerdb_petal_split_petals"));//Precalc. } private: T m_Petals; T m_Split; T m_Spread; T m_PetalsSplit;//Precalc. }; /// /// Conic. /// template class ConicVariation : public ParametricVariation { public: ConicVariation(T weight = 1.0) : ParametricVariation("conic", eVariationId::VAR_CONIC, weight, true, true) { Init(); } PARVARCOPY(ConicVariation) virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { T z = Zeps(helper.m_PrecalcSqrtSumSquares); T ct = helper.In.x / z; T r = m_Weight * (rand.Frand01() - m_Holes) * m_Eccentricity / (1 + m_Eccentricity * ct) / z; helper.Out.x = r * helper.In.x; helper.Out.y = r * helper.In.y; helper.Out.z = DefaultZ(helper); } virtual string OpenCLString() const override { ostringstream ss, ss2; intmax_t i = 0; ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string weight = WeightDefineString(); string eccentricity = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string holes = "parVars[" + ToUpper(m_Params[i++].Name()) + index; ss << "\t{\n" << "\t\treal_t z = Zeps(precalcSqrtSumSquares);\n" << "\t\treal_t ct = vIn.x / precalcSqrtSumSquares;\n" << "\t\treal_t r = " << weight << " * (MwcNext01(mwc) - " << holes << ") * " << eccentricity << " / fma(" << eccentricity << ", ct, 1) / z;\n" << "\n" << "\t\tvOut.x = r * vIn.x;\n" << "\t\tvOut.y = r * vIn.y;\n" << "\t\tvOut.z = " << DefaultZCl() << "\t}\n"; return ss.str(); } virtual vector OpenCLGlobalFuncNames() const override { return vector { "Zeps" }; } virtual void Random(QTIsaac& rand) override { m_Eccentricity = rand.Frand01(); m_Holes = rand.Frand01(); } protected: void Init() { string prefix = Prefix(); m_Params.clear(); m_Params.push_back(ParamWithName(&m_Eccentricity, prefix + "conic_eccentricity", 1)); m_Params.push_back(ParamWithName(&m_Holes, prefix + "conic_holes")); } private: T m_Eccentricity; T m_Holes; }; /// /// Parabola. /// template class ParabolaVariation : public ParametricVariation { public: ParabolaVariation(T weight = 1.0) : ParametricVariation("parabola", eVariationId::VAR_PARABOLA, weight, true, true) { Init(); } PARVARCOPY(ParabolaVariation) virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { T sr, cr; sincos(helper.m_PrecalcSqrtSumSquares, &sr, &cr); helper.Out.x = m_Height * m_Weight * sr * sr * rand.Frand01(); helper.Out.y = m_Width * m_Weight * cr * rand.Frand01(); helper.Out.z = DefaultZ(helper); } virtual string OpenCLString() const override { ostringstream ss, ss2; intmax_t i = 0; ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string weight = WeightDefineString(); string height = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string width = "parVars[" + ToUpper(m_Params[i++].Name()) + index; ss << "\t{\n" << "\t\treal_t sr = sin(precalcSqrtSumSquares);\n" << "\t\treal_t cr = cos(precalcSqrtSumSquares);\n" << "\n" << "\t\tvOut.x = " << height << " * (" << weight << " * sr * sr * MwcNext01(mwc));\n" << "\t\tvOut.y = " << width << " * (" << weight << " * cr * MwcNext01(mwc));\n" << "\t\tvOut.z = " << DefaultZCl() << "\t}\n"; return ss.str(); } virtual void Random(QTIsaac& rand) override { m_Height = T(0.5) * rand.Frand01(); m_Width = T(0.5) * rand.Frand01(); } protected: void Init() { string prefix = Prefix(); m_Params.clear(); m_Params.push_back(ParamWithName(&m_Height, prefix + "parabola_height")); m_Params.push_back(ParamWithName(&m_Width, prefix + "parabola_width")); } private: T m_Height; T m_Width; }; /// /// Bent2. /// template class Bent2Variation : public ParametricVariation { public: Bent2Variation(T weight = 1.0) : ParametricVariation("bent2", eVariationId::VAR_BENT2, weight) { Init(); } PARVARCOPY(Bent2Variation) virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { if (helper.In.x >= 0) helper.Out.x = m_Weight * helper.In.x; else helper.Out.x = m_Vx * helper.In.x; if (helper.In.y >= 0) helper.Out.y = m_Weight * helper.In.y; else helper.Out.y = m_Vy * helper.In.y; helper.Out.z = DefaultZ(helper); } virtual string OpenCLString() const override { ostringstream ss, ss2; intmax_t i = 0; ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string weight = WeightDefineString(); string x = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string y = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string vx = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string vy = "parVars[" + ToUpper(m_Params[i++].Name()) + index; ss << "\t{\n" << "\t\tif (vIn.x >= 0)\n" << "\t\t vOut.x = " << weight << " * vIn.x;\n" << "\t\telse\n" << "\t\t vOut.x = " << vx << " * vIn.x;\n" << "\n" << "\t\tif (vIn.y >= 0)\n" << "\t\t vOut.y = " << weight << " * vIn.y;\n" << "\t\telse\n" << "\t\tvOut.y = " << vy << " * vIn.y;\n" << "\n" << "\t\tvOut.z = " << DefaultZCl() << "\t}\n"; return ss.str(); } virtual void Precalc() override { m_Vx = m_X * m_Weight; m_Vy = m_Y * m_Weight; } virtual void Random(QTIsaac& rand) override { m_X = 3 * (T(-0.5) + rand.Frand01()); m_Y = 3 * (T(-0.5) + rand.Frand01()); } protected: void Init() { string prefix = Prefix(); m_Params.clear(); m_Params.push_back(ParamWithName(&m_X, prefix + "bent2_x", 1));//Params. m_Params.push_back(ParamWithName(&m_Y, prefix + "bent2_y", 1)); m_Params.push_back(ParamWithName(true, &m_Vx, prefix + "bent2_vx"));//Precalc. m_Params.push_back(ParamWithName(true, &m_Vy, prefix + "bent2_vy")); } private: T m_X;//Params. T m_Y; T m_Vx;//Precalc. T m_Vy; }; /// /// Bipolar. /// template class BipolarVariation : public ParametricVariation { public: BipolarVariation(T weight = 1.0) : ParametricVariation("bipolar", eVariationId::VAR_BIPOLAR, weight, true) { Init(); } PARVARCOPY(BipolarVariation) virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { const T x2y2 = helper.m_PrecalcSumSquares; const T t = x2y2 + 1; const T x2 = 2 * helper.In.x; T y = T(0.5) * std::atan2(2 * helper.In.y, x2y2 - 1) + m_S; if (y > T(M_PI_2)) y = -T(M_PI_2) + fmod(y + T(M_PI_2), T(M_PI)); else if (y < -T(M_PI_2)) y = T(M_PI_2) - fmod(T(M_PI_2) - y, T(M_PI)); const T f = t + x2; const T g = t - x2; if ((g == 0) || (f / g <= 0)) { if (m_VarType == eVariationType::VARTYPE_REG) { helper.Out.x = 0; helper.Out.y = 0; helper.Out.z = 0; } else { helper.Out.x = helper.In.x; helper.Out.y = helper.In.y; helper.Out.z = helper.In.z; } } else { helper.Out.x = m_V4 * std::log((t + x2) / Zeps(t - x2)); helper.Out.y = m_V * y; helper.Out.z = m_Weight * helper.In.z; } } virtual string OpenCLString() const override { ostringstream ss, ss2; intmax_t i = 0; ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string weight = WeightDefineString(); string shift = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string s = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string v = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string v4 = "parVars[" + ToUpper(m_Params[i++].Name()) + index; ss << "\t{\n" << "\t\treal_t x2y2 = precalcSumSquares;\n" << "\t\treal_t t = x2y2 + 1;\n" << "\t\treal_t x2 = 2 * vIn.x;\n" << "\t\treal_t ps = " << s << ";\n" << "\t\treal_t y = (real_t)(0.5) * atan2((real_t)(2.0) * vIn.y, x2y2 - (real_t)(1.0)) + ps;\n" << "\n" << "\t\tif (y > MPI2)\n" << "\t\t y = -MPI2 + fmod(y + MPI2, MPI);\n" << "\t\telse if (y < -MPI2)\n" << "\t\t y = MPI2 - fmod(MPI2 - y, MPI);\n" << "\n" << "\t\treal_t f = t + x2;\n" << "\t\treal_t g = t - x2;\n" << "\n"; if (m_VarType == eVariationType::VARTYPE_REG) { ss << "\t\tif ((g == 0) || (f / g <= 0))\n" << "\t\t{\n" << "\t\t vOut.x = 0;\n" << "\t\t vOut.y = 0;\n" << "\t\t vOut.z = 0;\n" << "\t\t}\n"; } else { ss << "\t\tif ((g == 0) || (f / g <= 0))\n" << "\t\t{\n" << "\t\t vOut.x = vIn.x;\n" << "\t\t vOut.y = vIn.y;\n" << "\t\t vOut.z = vIn.z;\n" << "\t\t}\n"; } ss << "\t\telse\n" << "\t\t{\n" << "\t\t vOut.x = (" << v4 << " * log((t + x2) / Zeps(t - x2)));\n" << "\t\t vOut.y = (" << v << " * y);\n" << "\t\t vOut.z = " << weight << " * vIn.z;\n" << "\t\t}\n" << "\t}\n"; return ss.str(); } virtual void Precalc() override { m_S = -T(M_PI_2) * m_Shift;; m_V = m_Weight * T(M_2_PI); m_V4 = m_Weight * T(0.25) * T(M_2_PI); } virtual void Random(QTIsaac& rand) override { m_Shift = 2 * rand.Frand01() - 1; } virtual vector OpenCLGlobalFuncNames() const override { return vector { "Zeps" }; } virtual bool SetParamVal(const char* name, T val) override { if (!_stricmp(name, "bipolar_shift")) { T temp = VarFuncs::Fabsmod(T(0.5) * (val + 1)); m_Shift = 2 * temp - 1; Precalc(); return true; } return ParametricVariation::SetParamVal(name, val); } protected: void Init() { string prefix = Prefix(); m_Params.clear(); m_Params.push_back(ParamWithName(&m_Shift, prefix + "bipolar_shift"));//Params. m_Params.push_back(ParamWithName(true, &m_S, prefix + "bipolar_s"));//Precalc. m_Params.push_back(ParamWithName(true, &m_V, prefix + "bipolar_v")); m_Params.push_back(ParamWithName(true, &m_V4, prefix + "bipolar_v4")); } private: T m_Shift;//Params. T m_S;//Precalc. T m_V; T m_V4; }; /// /// Boarders. /// template class BoardersVariation : public Variation { public: BoardersVariation(T weight = 1.0) : Variation("boarders", eVariationId::VAR_BOARDERS, weight) { } VARCOPY(BoardersVariation) virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { T roundX = std::rint(helper.In.x); T roundY = std::rint(helper.In.y); T offsetX = helper.In.x - roundX; T offsetY = helper.In.y - roundY; 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 (std::abs(offsetX) >= std::abs(offsetY)) { if (offsetX >= 0) { helper.Out.x = m_Weight * (offsetX * T(0.5) + roundX + T(0.25)); helper.Out.y = m_Weight * (offsetY * T(0.5) + roundY + T(0.25) * offsetY / offsetX); } else { helper.Out.x = m_Weight * (offsetX * T(0.5) + roundX - T(0.25)); helper.Out.y = m_Weight * (offsetY * T(0.5) + roundY - T(0.25) * offsetY / offsetX); } } else { if (offsetY >= 0) { helper.Out.y = m_Weight * (offsetY * T(0.5) + roundY + T(0.25)); helper.Out.x = m_Weight * (offsetX * T(0.5) + roundX + offsetX / offsetY * T(0.25)); } else { helper.Out.y = m_Weight * (offsetY * T(0.5) + roundY - T(0.25)); helper.Out.x = m_Weight * (offsetX * T(0.5) + roundX - offsetX / offsetY * T(0.25)); } } } helper.Out.z = DefaultZ(helper); } virtual string OpenCLString() const override { ostringstream ss; string weight = WeightDefineString(); ss << "\t{\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\tif (MwcNext01(mwc) >= (real_t)(0.75))\n" << "\t\t{\n" << "\t\t vOut.x = " << weight << " * fma(offsetX, (real_t)(0.5), roundX);\n" << "\t\t vOut.y = " << weight << " * fma(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 >= (real_t)(0.0))\n" << "\t\t {\n" << "\t\t vOut.x = " << weight << " * fma(offsetX, (real_t)(0.5), roundX + (real_t)(0.25));\n" << "\t\t vOut.y = " << weight << " * (fma(offsetY, (real_t)(0.5), roundY) + (real_t)(0.25) * offsetY / offsetX);\n" << "\t\t }\n" << "\t\t else\n" << "\t\t {\n" << "\t\t vOut.x = " << weight << " * fma(offsetX, (real_t)(0.5), roundX - (real_t)(0.25));\n" << "\t\t vOut.y = " << weight << " * (fma(offsetY, (real_t)(0.5), roundY) - (real_t)(0.25) * offsetY / offsetX);\n" << "\t\t }\n" << "\t\t }\n" << "\t\t else\n" << "\t\t {\n" << "\t\t if (offsetY >= (real_t)(0.0))\n" << "\t\t {\n" << "\t\t vOut.y = " << weight << " * fma(offsetY, (real_t)(0.5), roundY + (real_t)(0.25));\n" << "\t\t vOut.x = " << weight << " * (fma(offsetX, (real_t)(0.5), roundX) + offsetX / offsetY * (real_t)(0.25));\n" << "\t\t }\n" << "\t\t else\n" << "\t\t {\n" << "\t\t vOut.y = " << weight << " * fma(offsetY, (real_t)(0.5), roundY - (real_t)(0.25));\n" << "\t\t vOut.x = " << weight << " * (fma(offsetX, (real_t)(0.5), roundX) - offsetX / offsetY * (real_t)(0.25));\n" << "\t\t }\n" << "\t\t }\n" << "\t\t}\n" << "\n" << "\t\tvOut.z = " << DefaultZCl() << "\t}\n"; return ss.str(); } }; /// /// Butterfly. /// template class ButterflyVariation : public Variation { public: ButterflyVariation(T weight = 1.0) : Variation("butterfly", eVariationId::VAR_BUTTERFLY, weight) { } VARCOPY(ButterflyVariation) virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { T wx = m_Weight * T(1.3029400317411197908970256609023);//This precision came from the original. T y2 = helper.In.y * 2; T r = wx * std::sqrt(std::abs(helper.In.y * helper.In.x) / Zeps(SQR(helper.In.x) + SQR(y2))); helper.Out.x = r * helper.In.x; helper.Out.y = r * y2; helper.Out.z = DefaultZ(helper); } virtual string OpenCLString() const override { ostringstream ss; string weight = WeightDefineString(); ss << "\t{\n" << "\t\treal_t wx = " << weight << " * (real_t)(1.3029400317411197908970256609023);\n" << "\t\treal_t y2 = vIn.y * (real_t)(2.0);\n" << "\t\treal_t r = wx * sqrt(fabs(vIn.y * vIn.x) / Zeps(fma(vIn.x, vIn.x, SQR(y2))));\n" << "\n" << "\t\tvOut.x = r * vIn.x;\n" << "\t\tvOut.y = r * y2;\n" << "\t\tvOut.z = " << DefaultZCl() << "\t}\n"; return ss.str(); } virtual vector OpenCLGlobalFuncNames() const override { return vector { "Zeps" }; } }; /// /// Cell. /// template class CellVariation : public ParametricVariation { public: CellVariation(T weight = 1.0) : ParametricVariation("cell", eVariationId::VAR_CELL, weight) { Init(); } PARVARCOPY(CellVariation) virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { T invCellSize = 1 / m_Size; T x = std::floor(helper.In.x * invCellSize);//Calculate input cell. Note that int cast is omitted here. See below. T y = std::floor(helper.In.y * invCellSize); T dx = helper.In.x - x * m_Size;//Offset from cell origin. T dy = helper.In.y - y * m_Size; //Interleave cells. if (y >= 0) { if (x >= 0) { y *= 2; x *= 2; } else { y *= 2; x = -(2 * x + 1); } } else { if (x >= 0) { y = -(2 * y + 1); x *= 2; } else { y = -(2 * y + 1); x = -(2 * x + 1); } } helper.Out.x = m_Weight * (dx + x * m_Size); helper.Out.y = -(m_Weight * (dy + y * m_Size)); helper.Out.z = DefaultZ(helper); } /// /// Cell is very strange and will not run using integers. /// When using floats, it at least gives some output, however /// that output is slightly different than the CPU. But not by enough /// to change the shape of the final image. /// virtual string OpenCLString() const override { ostringstream ss, ss2; intmax_t i = 0; ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string weight = WeightDefineString(); string size = "parVars[" + ToUpper(m_Params[i++].Name()) + index; ss << "\t{\n" << "\t\treal_t invCellSize = (real_t)(1.0) / " << size << ";\n" //Float to int, orig. //<< "\t\tint x = (int)floor(vIn.x * invCellSize);\n" //<< "\t\tint y = (int)floor(vIn.y * invCellSize);\n" //For some reason, OpenCL renders nothing if these are ints, so use floats. //Note that Cuburn also omits the usage of ints. << "\t\treal_t x = floor(vIn.x * invCellSize);\n" << "\t\treal_t y = floor(vIn.y * invCellSize);\n" << "\t\treal_t dx = vIn.x - x * " << size << ";\n" << "\t\treal_t dy = vIn.y - y * " << size << ";\n" << "\n" << "\t\tif (y >= 0)\n" << "\t\t{\n" << "\t\t if (x >= 0)\n" << "\t\t {\n" << "\t\t y *= 2;\n" << "\t\t x *= 2;\n" << "\t\t }\n" << "\t\t else\n" << "\t\t {\n" << "\t\t y *= 2;\n" << "\t\t x = -fma((real_t)(2.0), x, (real_t)(1.0));\n" << "\t\t }\n" << "\t\t}\n" << "\t\telse\n" << "\t\t{\n" << "\t\t if (x >= 0)\n" << "\t\t {\n" << "\t\t y = -fma((real_t)(2.0), y, (real_t)(1.0));\n" << "\t\t x *= 2;\n" << "\t\t }\n" << "\t\t else\n" << "\t\t {\n" << "\t\t y = -fma((real_t)(2.0), y, (real_t)(1.0));\n" << "\t\t x = -fma((real_t)(2.0), x, (real_t)(1.0));\n" << "\t\t }\n" << "\t\t}\n" << "\n" << "\t\tvOut.x = " << weight << " * fma(x, " << size << ", dx);\n" << "\t\tvOut.y = -(" << weight << " * fma(y, " << size << ", dy));\n" << "\t\tvOut.z = " << DefaultZCl() << "\t}\n"; return ss.str(); } virtual void Random(QTIsaac& rand) override { m_Size = 2 * rand.Frand01() + T(0.5); } protected: void Init() { string prefix = Prefix(); m_Params.clear(); m_Params.push_back(ParamWithName(&m_Size, prefix + "cell_size", 1)); } private: T m_Size; }; /// /// Cpow. /// template class CpowVariation : public ParametricVariation { public: CpowVariation(T weight = 1.0) : ParametricVariation("cpow", eVariationId::VAR_CPOW, weight, true, false, false, false, true) { Init(); } PARVARCOPY(CpowVariation) virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { T a = helper.m_PrecalcAtanyx; T lnr = T(0.5) * std::log(helper.m_PrecalcSumSquares); T angle = m_C * a + m_D * lnr + m_Ang * rand.Rand(size_t(m_Power)); T m = m_Weight * std::exp(m_C * lnr - m_D * a); helper.Out.x = m * std::cos(angle); helper.Out.y = m * std::sin(angle); helper.Out.z = DefaultZ(helper); } virtual string OpenCLString() const override { ostringstream ss, ss2; intmax_t i = 0; ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string weight = WeightDefineString(); string powerR = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string powerI = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string power = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string c = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string d = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string ang = "parVars[" + ToUpper(m_Params[i++].Name()) + index; ss << "\t{\n" << "\t\treal_t a = precalcAtanyx;\n" << "\t\treal_t lnr = (real_t)(0.5) * log(precalcSumSquares);\n" << "\t\treal_t angle = fma(" << c << ", a, fma(" << d << ", lnr, " << ang << " * (real_t)MwcNextRange(mwc, (uint)" << power << ")));\n" << "\t\treal_t m = " << weight << " * exp(fma(" << c << ", lnr, -(" << d << " * a)));\n" << "\n" << "\t\tvOut.x = m * cos(angle);\n" << "\t\tvOut.y = m * sin(angle);\n" << "\t\tvOut.z = " << DefaultZCl() << "\t}\n"; return ss.str(); } virtual void Precalc() override { m_C = m_PowerR / m_Power; m_D = m_PowerI / m_Power; m_Ang = 2 * T(M_PI) / m_Power; } virtual void Random(QTIsaac& rand) override { m_PowerR = 3 * rand.Frand01(); m_PowerI = rand.Frand01() - T(0.5); m_Params[2].Set(5 * rand.Frand01());//Power. } protected: void Init() { string prefix = Prefix(); m_Params.clear(); m_Params.push_back(ParamWithName(&m_PowerR, prefix + "cpow_r", 1));//Params. m_Params.push_back(ParamWithName(&m_PowerI, prefix + "cpow_i")); m_Params.push_back(ParamWithName(&m_Power, prefix + "cpow_power", 1, eParamType::INTEGER_NONZERO)); m_Params.push_back(ParamWithName(true, &m_C, prefix + "cpow_c"));//Precalc. m_Params.push_back(ParamWithName(true, &m_D, prefix + "cpow_d")); m_Params.push_back(ParamWithName(true, &m_Ang, prefix + "cpow_ang")); } private: T m_PowerR;//Params. T m_PowerI; T m_Power; T m_C;//Precalc. T m_D; T m_Ang; }; /// /// Curve. /// template class CurveVariation : public ParametricVariation { public: CurveVariation(T weight = 1.0) : ParametricVariation("curve", eVariationId::VAR_CURVE, weight) { Init(); } PARVARCOPY(CurveVariation) virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { helper.Out.x = m_Weight * helper.In.x + m_XAmpV * std::exp(-helper.In.y * helper.In.y * m_XLengthV); helper.Out.y = m_Weight * helper.In.y + m_YAmpV * std::exp(-helper.In.x * helper.In.x * m_YLengthV); helper.Out.z = DefaultZ(helper); } virtual string OpenCLString() const override { ostringstream ss, ss2; intmax_t i = 0; ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string weight = WeightDefineString(); string xAmp = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string yAmp = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string xLength = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string yLength = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string xAmpV = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string yAmpV = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string xLengthV = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string yLengthV = "parVars[" + ToUpper(m_Params[i++].Name()) + index; ss << "\t{\n" << "\t\tvOut.x = fma(" << weight << ", vIn.x, " << xAmpV << " * exp(-vIn.y * vIn.y * " << xLengthV << "));\n" << "\t\tvOut.y = fma(" << weight << ", vIn.y, " << yAmpV << " * exp(-vIn.x * vIn.x * " << yLengthV << "));\n" << "\t\tvOut.z = " << DefaultZCl() << "\t}\n"; return ss.str(); } virtual void Precalc() override { m_XAmpV = m_Weight * m_XAmp; m_YAmpV = m_Weight * m_YAmp; m_XLengthV = 1 / std::max(SQR(m_XLength), T(1e-20)); m_YLengthV = 1 / std::max(SQR(m_YLength), T(1e-20)); } virtual void Random(QTIsaac& rand) override { m_XAmp = 5 * (rand.Frand01() - T(0.5)); m_YAmp = 4 * (rand.Frand01() - T(0.5)); m_XLength = 2 * (rand.Frand01() + T(0.5)); m_YLength = 2 * (rand.Frand01() + T(0.5)); } protected: void Init() { string prefix = Prefix(); m_Params.clear(); m_Params.push_back(ParamWithName(&m_XAmp, prefix + "curve_xamp"));//Params. m_Params.push_back(ParamWithName(&m_YAmp, prefix + "curve_yamp")); m_Params.push_back(ParamWithName(&m_XLength, prefix + "curve_xlength", 1)); m_Params.push_back(ParamWithName(&m_YLength, prefix + "curve_ylength", 1)); m_Params.push_back(ParamWithName(true, &m_XAmpV, prefix + "curve_xampv"));//Precalc. m_Params.push_back(ParamWithName(true, &m_YAmpV, prefix + "curve_yampv")); m_Params.push_back(ParamWithName(true, &m_XLengthV, prefix + "curve_xlenv")); m_Params.push_back(ParamWithName(true, &m_YLengthV, prefix + "curve_ylenv")); } private: T m_XAmp;//Params. T m_YAmp; T m_XLength; T m_YLength; T m_XAmpV;//Precalc. T m_YAmpV; T m_XLengthV; T m_YLengthV; }; /// /// Edisc. /// template class EdiscVariation : public Variation { public: EdiscVariation(T weight = 1.0) : Variation("edisc", eVariationId::VAR_EDISC, weight, true) { } VARCOPY(EdiscVariation) virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { T tmp = helper.m_PrecalcSumSquares + 1; T tmp2 = 2 * helper.In.x; T r1 = std::sqrt(tmp + tmp2); T r2 = std::sqrt(tmp - tmp2); T xmax = Zeps((r1 + r2) * T(0.5)); T a1 = std::log(xmax + std::sqrt(xmax - 1)); T a2 = -std::acos(Clamp(helper.In.x / xmax, -1, 1)); T w = m_Weight / T(11.57034632);//This is an interesting magic number. T snv, csv, snhu, cshu; sincos(a1, &snv, &csv); snhu = std::sinh(a2); cshu = std::cosh(a2); if (helper.In.y > 0.0) snv = -snv; helper.Out.x = w * cshu * csv; helper.Out.y = w * snhu * snv; helper.Out.z = DefaultZ(helper); } virtual string OpenCLString() const override { ostringstream ss; string weight = WeightDefineString(); ss << "\t{\n" << "\t\treal_t tmp = precalcSumSquares + (real_t)(1.0);\n" << "\t\treal_t tmp2 = (real_t)(2.0) * vIn.x;\n" << "\t\treal_t r1 = sqrt(tmp + tmp2);\n" << "\t\treal_t r2 = sqrt(tmp - tmp2);\n" << "\t\treal_t xmax = Zeps((r1 + r2) * (real_t)(0.5));\n" << "\t\treal_t a1 = log(xmax + sqrt(xmax - (real_t)(1.0)));\n" << "\t\treal_t a2 = -acos(clamp(vIn.x / xmax, -(real_t)(1.0), (real_t)(1.0)));\n" << "\t\treal_t w = " << weight << " / (real_t)(11.57034632);\n" << "\t\treal_t snv = sin(a1);\n" << "\t\treal_t csv = cos(a1);\n" << "\t\treal_t snhu = sinh(a2);\n" << "\t\treal_t cshu = cosh(a2);\n" << "\t\tif (vIn.y > 0)\n" << "\t\t snv = -snv;\n" << "\t\tvOut.x = w * cshu * csv;\n" << "\t\tvOut.y = w * snhu * snv;\n" << "\t\tvOut.z = " << DefaultZCl() << "\t}\n"; return ss.str(); } virtual vector OpenCLGlobalFuncNames() const override { return vector { "Zeps" }; } }; /// /// Elliptic. /// template class EllipticVariation : public ParametricVariation { public: EllipticVariation(T weight = 1.0) : ParametricVariation("elliptic", eVariationId::VAR_ELLIPTIC, weight, true) { Init(); } PARVARCOPY(EllipticVariation) //An improved version which was posted in the Discord chat by user Claude which was helps with rounding errors. //Note that for this to work, a "bad value" had to be changed from 1e10 and -1e10 to 1e50 and -1e50. //For this to be correct, it must always use double. So there is no point in switching precisions when using this variation. virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { if (typeid(T) == typeid(float)) { T tmp = helper.m_PrecalcSumSquares + 1; T x2 = 2 * helper.In.x; T xmax = T(0.5) * (std::sqrt(tmp + x2) + std::sqrt(tmp - x2)); T a = helper.In.x / xmax; T b = 1 - a * a; T ssx = xmax - 1; const T w = m_WeightDivPiDiv2; if (b < 0) b = 0; else b = std::sqrt(b); if (ssx < 0) ssx = 0; else ssx = std::sqrt(ssx); helper.Out.x = w * std::atan2(a, b); if (helper.In.y > 0) helper.Out.y = w * std::log(xmax + ssx); else helper.Out.y = -(w * std::log(xmax + ssx)); helper.Out.z = DefaultZ(helper); } else { double x2 = 2 * helper.In.x; double u = helper.m_PrecalcSumSquares + x2; double v = helper.m_PrecalcSumSquares - x2; double xmaxm1 = 0.5 * (Sqrt1pm1(u) + Sqrt1pm1(v)); double a = helper.In.x / (1 + xmaxm1); double ssx = xmaxm1 < 0 ? 0 : std::sqrt(xmaxm1); helper.Out.x = T(m_WeightDivPiDiv2 * std::asin(Clamp(a, -1.0, 1.0))); if (helper.In.y > 0) helper.Out.y = T(m_WeightDivPiDiv2 * std::log1p(xmaxm1 + ssx)); else helper.Out.y = T(-(m_WeightDivPiDiv2 * std::log1p(xmaxm1 + ssx))); helper.Out.z = DefaultZ(helper); } } virtual string OpenCLString() const override { ostringstream ss, ss2; intmax_t i = 0; ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string weight = WeightDefineString(); string weightDivPiDiv2 = "parVars[" + ToUpper(m_Params[i++].Name()) + index; if (typeid(T) == typeid(float)) { ss << "\t{\n" << "\t\treal_t tmp = precalcSumSquares + (real_t)(1.0);\n" << "\t\treal_t x2 = (real_t)(2.0) * vIn.x;\n" << "\t\treal_t xmax = (real_t)(0.5) * (sqrt(tmp + x2) + sqrt(tmp - x2));\n" << "\t\treal_t a = vIn.x / xmax;\n" << "\t\treal_t b = (real_t)(1.0) - a * a;\n" << "\t\treal_t ssx = xmax - (real_t)(1.0);\n" << "\t\tconst real_t w = " << weightDivPiDiv2 << ";\n" << "\n" << "\t\tif (b < 0)\n" << "\t\t b = 0;\n" << "\t\telse\n" << "\t\t b = sqrt(b);\n" << "\n" << "\t\tif (ssx < 0)\n" << "\t\t ssx = 0;\n" << "\t\telse\n" << "\t\t ssx = sqrt(ssx);\n" << "\n" << "\t\tvOut.x = w * atan2(a, b);\n" << "\n" << "\t\tif (vIn.y > 0)\n" << "\t\t vOut.y = w * log(xmax + ssx);\n" << "\t\telse\n" << "\t\t vOut.y = -(w * log(xmax + ssx));\n" << "\n" << "\t\tvOut.z = " << DefaultZCl() << "\t}\n"; } else { ss << "\t{\n" << "\t\tdouble x2 = 2.0 * vIn.x;\n" << "\t\tdouble u = precalcSumSquares + x2;\n" << "\t\tdouble v = precalcSumSquares - x2;\n" << "\t\tdouble xmaxm1 = 0.5 * (Sqrt1pm1(u) + Sqrt1pm1(v));\n" << "\t\tdouble a = vIn.x / (1 + xmaxm1);\n" << "\t\tdouble ssx = xmaxm1 < 0 ? 0.0 : sqrt(xmaxm1);\n" << "\t\tvOut.x = (" << weightDivPiDiv2 << " * asin(clamp(a, (double)-1.0, (double)1.0)));\n" << "\n" << "\t\tif (vIn.y > 0)\n" << "\t\t\tvOut.y = " << weightDivPiDiv2 << " * log1p(xmaxm1 + ssx);\n" << "\t\telse\n" << "\t\t\tvOut.y = -(" << weightDivPiDiv2 << " * log1p(xmaxm1 + ssx));\n" << "\n" << "\t\tvOut.z = " << DefaultZCl() << "\t}\n"; } return ss.str(); } virtual string OpenCLFuncsString() const override { return "double Sqrt1pm1(double x)\n" "{\n" " if (-0.0625 < x && x < 0.0625)\n" " {\n" " double num = 0;\n" " double den = 0;\n" " num += 1.0 / 32.0;\n" " den += 1.0 / 256.0;\n" " num *= x;\n" " den *= x;\n" " num += 5.0 / 16.0;\n" " den += 5.0 / 32.0;\n" " num *= x;\n" " den *= x;\n" " num += 3.0 / 4.0;\n" " den += 15.0 / 16.0;\n" " num *= x;\n" " den *= x;\n" " num += 1.0 / 2.0;\n" " den += 7.0 / 4.0;\n" " num *= x;\n" " den *= x;\n" " den += 1;\n" " return num / den;\n" " }\n" "\n" " return sqrt(1 + x) - 1;\n" "}\n\n"; } virtual void Precalc() override { m_WeightDivPiDiv2 = m_Weight / T(M_PI_2); } protected: void Init() { string prefix = Prefix(); m_Params.clear(); m_Params.push_back(ParamWithName(true, &m_WeightDivPiDiv2, prefix + "elliptic_weight_div_pi_div_2"));//Precalc. } private: //An improved version which was posted in the Discord chat by user Claude which was helps with rounding errors. //Note that for this to work, a "bad value" had to be changed from 1e10 and -1e10 to 1e50 and -1e50. //For this to be correct, it must always use double. So there is no point in switching precisions when using this variation. double Sqrt1pm1(double x) { if (-0.0625 < x && x < 0.0625) { double num = 0; double den = 0; num += 1.0 / 32; den += 1.0 / 256; num *= x; den *= x; num += 5.0 / 16; den += 5.0 / 32; num *= x; den *= x; num += 3.0 / 4; den += 15.0 / 16; num *= x; den *= x; num += 1.0 / 2; den += 7.0 / 4; num *= x; den *= x; den += 1; return num / den; } return std::sqrt(1 + x) - 1; } T m_WeightDivPiDiv2;//Precalc. }; /// /// Escher. /// template class EscherVariation : public ParametricVariation { public: EscherVariation(T weight = 1.0) : ParametricVariation("escher", eVariationId::VAR_ESCHER, weight, true, false, false, false, true) { Init(); } PARVARCOPY(EscherVariation) virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { T a = helper.m_PrecalcAtanyx; T lnr = T(0.5) * std::log(helper.m_PrecalcSumSquares); T m = m_Weight * std::exp(m_C * lnr - m_D * a); T n = m_C * a + m_D * lnr; helper.Out.x = m * std::cos(n); helper.Out.y = m * std::sin(n); helper.Out.z = m_Weight * helper.In.z; } virtual string OpenCLString() const override { ostringstream ss, ss2; intmax_t i = 0; ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string weight = WeightDefineString(); string beta = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string c = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string d = "parVars[" + ToUpper(m_Params[i++].Name()) + index; ss << "\t{\n" << "\t\treal_t a = precalcAtanyx;\n" << "\t\treal_t lnr = (real_t)(0.5) * log(precalcSumSquares);\n" << "\t\treal_t m = " << weight << " * exp(fma(" << c << ", lnr, -(" << d << " * a)));\n" << "\t\treal_t n = fma(" << c << ", a, " << d << " * lnr);\n" << "\n" << "\t\tvOut.x = m * cos(n);\n" << "\t\tvOut.y = m * sin(n);\n" << "\t\tvOut.z = " << weight << " * vIn.z;\n" << "\t}\n"; return ss.str(); } virtual void Precalc() override { sincos(m_Beta, &m_D, &m_C); m_C = T(0.5) * (1 + m_C); m_D = T(0.5) * m_D; } virtual void Random(QTIsaac& rand) override { SetParamVal("escher_beta", T(M_PI) * rand.Frand01()); } virtual bool SetParamVal(const char* name, T val) override { if (!_stricmp(name, "escher_beta")) { m_Beta = VarFuncs::Fabsmod((val + T(M_PI)) / (2 * T(M_PI))) * 2 * T(M_PI) - T(M_PI); Precalc(); return true; } return ParametricVariation::SetParamVal(name, val); } protected: void Init() { string prefix = Prefix(); m_Params.clear(); m_Params.push_back(ParamWithName(&m_Beta, prefix + "escher_beta"));//Params. m_Params.push_back(ParamWithName(true, &m_C, prefix + "escher_beta_c"));//Precalc. m_Params.push_back(ParamWithName(true, &m_D, prefix + "escher_beta_d")); } private: T m_Beta;//Params. T m_C;//Precalc. T m_D; }; /// /// Foci. /// template class FociVariation : public Variation { public: FociVariation(T weight = 1.0) : Variation("foci", eVariationId::VAR_FOCI, weight) { } VARCOPY(FociVariation) 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) / Zeps(expx); T sn, cn, tmp; sincos(helper.In.y, &sn, &cn); tmp = m_Weight / Zeps(expx + expnx - cn); helper.Out.x = tmp * (expx - expnx); helper.Out.y = tmp * sn; helper.Out.z = m_Weight * helper.In.z; } virtual string OpenCLString() const override { ostringstream ss; string weight = WeightDefineString(); ss << "\t{\n" << "\t\treal_t expx = exp(vIn.x) * (real_t)(0.5);\n" << "\t\treal_t expnx = (real_t)(0.25) / Zeps(expx);\n" << "\t\treal_t sn = sin(vIn.y);\n" << "\t\treal_t cn = cos(vIn.y);\n" << "\t\treal_t tmp = Zeps(expx + expnx - cn);\n" << "\n" << "\t\ttmp = " << weight << " / tmp;\n" << "\n" << "\t\tvOut.x = tmp * (expx - expnx);\n" << "\t\tvOut.y = tmp * sn;\n" << "\t\tvOut.z = " << weight << " * vIn.z;\n" << "\t}\n"; return ss.str(); } virtual vector OpenCLGlobalFuncNames() const override { return vector { "Zeps" }; } }; /// /// LazySusan. /// template class LazySusanVariation : public ParametricVariation { public: LazySusanVariation(T weight = 1.0) : ParametricVariation("lazysusan", eVariationId::VAR_LAZYSUSAN, weight) { Init(); } PARVARCOPY(LazySusanVariation) virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { T x = helper.In.x - m_X; T y = helper.In.y + m_Y; T r = std::sqrt(x * x + y * y); if (r < m_Weight) { T a = std::atan2(y, x) + m_Spin + m_Twist * (m_Weight - r); helper.Out.x = m_Weight * (r * std::cos(a) + m_X);//Fix to make it colapse to 0 when weight is 0.//SMOULDER helper.Out.y = m_Weight * (r * std::sin(a) - m_Y); } else { r = 1 + m_Space / Zeps(r); helper.Out.x = m_Weight * (r * x + m_X);//Fix to make it colapse to 0 when weight is 0.//SMOULDER helper.Out.y = m_Weight * (r * y - m_Y); } helper.Out.z = m_Weight * helper.In.z; } virtual string OpenCLString() const override { ostringstream ss, ss2; intmax_t i = 0; ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string weight = WeightDefineString(); string spin = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string space = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string twist = "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; ss << "\t{\n" << "\t\treal_t x = vIn.x - " << x << ";\n" << "\t\treal_t y = vIn.y + " << y << ";\n" << "\t\treal_t r = sqrt(fma(x, x, SQR(y)));\n" << "\n" << "\t\tif (r < " << weight << ")\n" << "\t\t{\n" << "\t\t real_t a = fma(" << twist << ", " << weight << " - r, atan2(y, x) + " << spin << ");\n" << "\n" << "\t\t vOut.x = " << weight << " * fma(r, cos(a), " << x << ");\n" << "\t\t vOut.y = " << weight << " * fma(r, sin(a), -" << y << ");\n" << "\t\t}\n" << "\t\telse\n" << "\t\t{\n" << "\t\t r = (real_t)(1.0) + " << space << " / Zeps(r);\n" << "\n" << "\t\t vOut.x = " << weight << " * fma(r, x, " << x << ");\n" << "\t\t vOut.y = " << weight << " * fma(r, y, -" << y << ");\n" << "\t\t}\n" << "\n" << "\t\tvOut.z = " << weight << " * vIn.z;\n" << "\t}\n"; return ss.str(); } virtual vector OpenCLGlobalFuncNames() const override { return vector { "Zeps" }; } virtual bool SetParamVal(const char* name, T val) override { if (!_stricmp(name, "lazysusan_spin")) { m_Spin = VarFuncs::Fabsmod(val / T(M_2PI)) * T(M_2PI); this->Precalc(); return true; } return ParametricVariation::SetParamVal(name, val); } virtual void Random(QTIsaac& rand) override { m_X = 2 * rand.Frand11(); m_Y = 2 * rand.Frand11(); m_Spin = T(M_PI) * rand.Frand11(); m_Space = 2 * rand.Frand11(); m_Twist = 2 * rand.Frand11(); } protected: void Init() { string prefix = Prefix(); m_Params.clear(); m_Params.push_back(ParamWithName(&m_Spin, prefix + "lazysusan_spin", T(M_PI))); m_Params.push_back(ParamWithName(&m_Space, prefix + "lazysusan_space")); m_Params.push_back(ParamWithName(&m_Twist, prefix + "lazysusan_twist")); m_Params.push_back(ParamWithName(&m_X, prefix + "lazysusan_x")); m_Params.push_back(ParamWithName(&m_Y, prefix + "lazysusan_y")); } private: T m_Spin; T m_Space; T m_Twist; T m_X; T m_Y; }; /// /// Loonie. /// template class LoonieVariation : public ParametricVariation { public: LoonieVariation(T weight = 1.0) : ParametricVariation("loonie", eVariationId::VAR_LOONIE, weight, true) { Init(); } PARVARCOPY(LoonieVariation) virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { if (helper.m_PrecalcSumSquares < m_W2 && helper.m_PrecalcSumSquares != 0) { T r = m_Weight * std::sqrt((m_W2 / helper.m_PrecalcSumSquares) - 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_Weight * helper.In.z; } virtual string OpenCLString() const override { ostringstream ss, ss2; intmax_t i = 0; ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string weight = WeightDefineString(); string w2 = "parVars[" + ToUpper(m_Params[i++].Name()) + index; ss << "\t{\n" << "\t\tif (precalcSumSquares < " << w2 << " && precalcSumSquares != 0)\n" << "\t\t{\n" << "\t\t real_t r = " << weight << " * sqrt((" << w2 << " / precalcSumSquares) - (real_t)(1.0));\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 = " << weight << " * vIn.x;\n" << "\t\t vOut.y = " << weight << " * vIn.y;\n" << "\t\t}\n" << "\n" << "\t\tvOut.z = " << weight << " * 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 + "loonie_w2"));//Precalc. } private: T m_W2;//Precalc. }; /// /// Modulus. /// template class ModulusVariation : public ParametricVariation { public: ModulusVariation(T weight = 1.0) : ParametricVariation("modulus", eVariationId::VAR_MODULUS, weight) { Init(); } PARVARCOPY(ModulusVariation) virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { if (helper.In.x > m_X) helper.Out.x = m_Weight * (-m_X + fmod(helper.In.x + m_X, m_XRange)); else if (helper.In.x < -m_X) helper.Out.x = m_Weight * (m_X - fmod(m_X - helper.In.x, m_XRange)); else helper.Out.x = m_Weight * helper.In.x; if (helper.In.y > m_Y) helper.Out.y = m_Weight * (-m_Y + fmod(helper.In.y + m_Y, m_YRange)); else if (helper.In.y < -m_Y) helper.Out.y = m_Weight * (m_Y - fmod(m_Y - helper.In.y, m_YRange)); else helper.Out.y = m_Weight * helper.In.y; helper.Out.z = DefaultZ(helper); } virtual string OpenCLString() const override { ostringstream ss, ss2; intmax_t i = 0; ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string weight = WeightDefineString(); string x = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string y = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string xr = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string yr = "parVars[" + ToUpper(m_Params[i++].Name()) + index; ss << "\t{\n" << "\t\tif (vIn.x > " << x << ")\n" << "\t\t vOut.x = " << weight << " * (-" << x << " + fmod(vIn.x + " << x << ", " << xr << "));\n" << "\t\telse if (vIn.x < -" << x << ")\n" << "\t\t vOut.x = " << weight << " * ( " << x << " - fmod(" << x << " - vIn.x, " << xr << "));\n" << "\t\telse\n" << "\t\t vOut.x = " << weight << " * vIn.x;\n" << "\n" << "\t\tif (vIn.y > " << y << ")\n" << "\t\t vOut.y = " << weight << " * (-" << y << " + fmod(vIn.y + " << y << ", " << yr << "));\n" << "\t\telse if (vIn.y < -" << y << ")\n" << "\t\t vOut.y = " << weight << " * ( " << y << " - fmod(" << y << " - vIn.y, " << yr << "));\n" << "\t\telse\n" << "\t\t vOut.y = " << weight << " * vIn.y;\n" << "\n" << "\t\tvOut.z = " << DefaultZCl() << "\t}\n"; return ss.str(); } virtual void Precalc() override { m_XRange = 2 * m_X; m_YRange = 2 * m_Y; } virtual void Random(QTIsaac& rand) override { m_X = rand.Frand11(); m_Y = rand.Frand11(); } protected: void Init() { string prefix = Prefix(); m_Params.clear(); m_Params.push_back(ParamWithName(&m_X, prefix + "modulus_x", 1));//Params. m_Params.push_back(ParamWithName(&m_Y, prefix + "modulus_y", 1)); m_Params.push_back(ParamWithName(true, &m_XRange, prefix + "modulus_xrange"));//Precalc. m_Params.push_back(ParamWithName(true, &m_YRange, prefix + "modulus_yrange")); } private: T m_X;//Params. T m_Y; T m_XRange;//Precalc. T m_YRange; }; /// /// Oscilloscope. /// template class OscilloscopeVariation : public ParametricVariation { public: OscilloscopeVariation(T weight = 1.0) : ParametricVariation("oscilloscope", eVariationId::VAR_OSCILLOSCOPE, weight) { Init(); } PARVARCOPY(OscilloscopeVariation) virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { T t; if (m_Damping == 0.0) t = m_Amplitude * std::cos(m_2PiFreq * helper.In.x) + m_Separation; else t = m_Amplitude * std::exp(-std::abs(helper.In.x) * m_Damping) * std::cos(m_2PiFreq * helper.In.x) + m_Separation; if (std::abs(helper.In.y) <= t) { helper.Out.x = m_Weight * helper.In.x; helper.Out.y = -(m_Weight * helper.In.y); } else { helper.Out.x = m_Weight * helper.In.x; helper.Out.y = m_Weight * helper.In.y; } helper.Out.z = DefaultZ(helper); } virtual string OpenCLString() const override { ostringstream ss, ss2; intmax_t i = 0; ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string weight = WeightDefineString(); string separation = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string frequency = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string amplitude = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string damping = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string tpf = "parVars[" + ToUpper(m_Params[i++].Name()) + index; ss << "\t{\n" << "\t\treal_t t;\n" << "\n" << "\t\tif (" << damping << " == (real_t)(0.0))\n" << "\t\t t = fma(" << amplitude << ", cos(" << tpf << " * vIn.x), " << separation << ");\n" << "\t\telse\n" << "\t\t t = fma(" << amplitude << ", exp(-fabs(vIn.x) * " << damping << ") * cos(" << tpf << " * vIn.x), " << separation << ");\n" << "\n" << "\t\tif (fabs(vIn.y) <= t)\n" << "\t\t{\n" << "\t\t vOut.x = " << weight << " * vIn.x;\n" << "\t\t vOut.y = -(" << weight << " * vIn.y);\n" << "\t\t}\n" << "\t\telse\n" << "\t\t{\n" << "\t\t vOut.x = " << weight << " * vIn.x;\n" << "\t\t vOut.y = " << weight << " * vIn.y;\n" << "\t\t}\n" << "\n" << "\t\tvOut.z = " << DefaultZCl() << "\t}\n"; return ss.str(); } virtual void Precalc() override { m_2PiFreq = m_Frequency * T(M_2PI); } virtual void Random(QTIsaac& rand) override { m_Separation = 1 + rand.Frand11(); m_Frequency = T(M_PI) * rand.Frand11(); m_Amplitude = 1 + 2 * rand.Frand01(); m_Damping = rand.Frand01(); } protected: void Init() { string prefix = Prefix(); m_Params.clear(); m_Params.push_back(ParamWithName(&m_Separation, prefix + "oscilloscope_separation", 1));//Params. m_Params.push_back(ParamWithName(&m_Frequency, prefix + "oscilloscope_frequency", T(M_PI))); m_Params.push_back(ParamWithName(&m_Amplitude, prefix + "oscilloscope_amplitude", 1)); m_Params.push_back(ParamWithName(&m_Damping, prefix + "oscilloscope_damping")); m_Params.push_back(ParamWithName(true, &m_2PiFreq, prefix + "oscilloscope_2pifreq"));//Precalc. } private: T m_Separation;//Params. T m_Frequency; T m_Amplitude; T m_Damping; T m_2PiFreq;//Precalc. }; /// /// Oscilloscope2. /// By dark-beam. /// template class Oscilloscope2Variation : public ParametricVariation { public: Oscilloscope2Variation(T weight = 1.0) : ParametricVariation("oscilloscope2", eVariationId::VAR_OSCILLOSCOPE2, weight) { Init(); } PARVARCOPY(Oscilloscope2Variation) virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { T t; T pt = m_Perturbation * std::sin(m_Tpf2 * helper.In.y); if (!m_Damping) t = m_Amplitude * std::cos(m_Tpf * helper.In.x + pt) + m_Separation; else t = m_Amplitude * std::exp(-std::abs(helper.In.x) * m_Damping) * std::cos(m_Tpf * helper.In.x + pt) + m_Separation; if (std::abs(helper.In.y) <= t) { helper.Out.x = -(m_Weight * helper.In.x); helper.Out.y = -(m_Weight * helper.In.y); } else { helper.Out.x = m_Weight * helper.In.x; helper.Out.y = m_Weight * helper.In.y; } helper.Out.z = DefaultZ(helper); } virtual string OpenCLString() const override { ostringstream ss, ss2; intmax_t i = 0; ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string weight = WeightDefineString(); string separation = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string frequencyx = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string frequencyy = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string amplitude = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string perturbation = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string damping = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string tpf = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string tpf2 = "parVars[" + ToUpper(m_Params[i++].Name()) + index; ss << "\t{\n" << "\t\treal_t t;\n" << "\t\treal_t pt = " << perturbation << " * sin(" << tpf2 << " * vIn.y);\n" << "\n" << "\t\tif (" << damping << " == 0)\n" << "\t\t t = fma(" << amplitude << ", cos(fma(" << tpf << ", vIn.x, pt)), " << separation << ");\n" << "\t\telse\n" << "\t\t t = fma(" << amplitude << ", exp(-fabs(vIn.x) * " << damping << ") * cos(fma(" << tpf << ", vIn.x, pt)), " << separation << ");\n" << "\n" << "\t\tif (fabs(vIn.y) <= t)\n" << "\t\t{\n" << "\t\t vOut.x = -(" << weight << " * vIn.x);\n" << "\t\t vOut.y = -(" << weight << " * vIn.y);\n" << "\t\t}\n" << "\t\telse\n" << "\t\t{\n" << "\t\t vOut.x = " << weight << " * vIn.x;\n" << "\t\t vOut.y = " << weight << " * vIn.y;\n" << "\t\t}\n" << "\n" << "\t\tvOut.z = " << DefaultZCl() << "\t}\n"; return ss.str(); } virtual void Precalc() override { m_Tpf = M_2PI * m_FrequencyX; m_Tpf2 = M_2PI * m_FrequencyY; } protected: void Init() { string prefix = Prefix(); m_Params.clear(); m_Params.push_back(ParamWithName(&m_Separation, prefix + "oscilloscope2_separation", 1, eParamType::REAL, 0));//Params. m_Params.push_back(ParamWithName(&m_FrequencyX, prefix + "oscilloscope2_frequencyx", T(M_PI))); m_Params.push_back(ParamWithName(&m_FrequencyY, prefix + "oscilloscope2_frequencyy", T(M_PI))); m_Params.push_back(ParamWithName(&m_Amplitude, prefix + "oscilloscope2_amplitude", 1)); m_Params.push_back(ParamWithName(&m_Perturbation, prefix + "oscilloscope2_perturbation", 1)); m_Params.push_back(ParamWithName(&m_Damping, prefix + "oscilloscope2_damping", 0, eParamType::INTEGER, 0, 1)); m_Params.push_back(ParamWithName(true, &m_Tpf, prefix + "oscilloscope2_tpf"));//Precalc. m_Params.push_back(ParamWithName(true, &m_Tpf2, prefix + "oscilloscope2_tpf2")); } private: T m_Separation;//Params. T m_FrequencyX; T m_FrequencyY; T m_Amplitude; T m_Perturbation; T m_Damping; T m_Tpf;//Precalc. T m_Tpf2; }; /// /// Polar2. /// template class Polar2Variation : public ParametricVariation { public: Polar2Variation(T weight = 1.0) : ParametricVariation("polar2", eVariationId::VAR_POLAR2, weight, true, false, false, true) { Init(); } PARVARCOPY(Polar2Variation) virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { helper.Out.x = m_Vvar * helper.m_PrecalcAtanxy; helper.Out.y = m_Vvar2 * std::log(helper.m_PrecalcSumSquares); helper.Out.z = m_Weight * helper.In.z; } virtual string OpenCLString() const override { ostringstream ss, ss2; intmax_t i = 0; ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string weight = WeightDefineString(); string vvar = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string vvar2 = "parVars[" + ToUpper(m_Params[i++].Name()) + index; ss << "\t{\n" << "\t\tvOut.x = " << vvar << " * precalcAtanxy;\n" << "\t\tvOut.y = " << vvar2 << " * log(precalcSumSquares);\n" << "\t\tvOut.z = " << weight << " * vIn.z;\n" << "\t}\n"; return ss.str(); } virtual void Precalc() override { m_Vvar = m_Weight / T(M_PI); m_Vvar2 = m_Vvar * T(0.5); } protected: void Init() { string prefix = Prefix(); m_Params.clear(); m_Params.push_back(ParamWithName(true, &m_Vvar, prefix + "polar2_vvar"));//Precalc. m_Params.push_back(ParamWithName(true, &m_Vvar2, prefix + "polar2_vvar2")); } private: T m_Vvar; T m_Vvar2; }; /// /// Popcorn2. /// template class Popcorn2Variation : public ParametricVariation { public: Popcorn2Variation(T weight = 1.0) : ParametricVariation("popcorn2", eVariationId::VAR_POPCORN2, weight) { Init(); } PARVARCOPY(Popcorn2Variation) virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { helper.Out.x = m_Weight * (helper.In.x + m_X * std::sin(SafeTan(helper.In.y * m_C))); helper.Out.y = m_Weight * (helper.In.y + m_Y * std::sin(SafeTan(helper.In.x * m_C))); helper.Out.z = DefaultZ(helper); } virtual string OpenCLString() const override { ostringstream ss, ss2; intmax_t i = 0; ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string weight = WeightDefineString(); string x = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string y = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string c = "parVars[" + ToUpper(m_Params[i++].Name()) + index; ss << "\t{\n" << "\t\tvOut.x = " << weight << " * fma(" << x << ", sin(tan(vIn.y * " << c << ")), vIn.x);\n" << "\t\tvOut.y = " << weight << " * fma(" << y << ", sin(tan(vIn.x * " << c << ")), vIn.y);\n" << "\t\tvOut.z = " << DefaultZCl() << "\t}\n"; return ss.str(); } virtual void Random(QTIsaac& rand) override { m_X = T(0.2) + rand.Frand01(); m_Y = 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_x", T(0.1))); m_Params.push_back(ParamWithName(&m_Y, prefix + "popcorn2_y", T(0.1))); m_Params.push_back(ParamWithName(&m_C, prefix + "popcorn2_c", 3)); } private: T m_X; T m_Y; T m_C; }; /// /// Scry. /// Note that scry does not multiply by weight, but as the /// values still approach 0 as the weight approaches 0, it /// should be ok. /// template class ScryVariation : public ParametricVariation { public: ScryVariation(T weight = 1.0) : ParametricVariation("scry", eVariationId::VAR_SCRY, weight, true, true) { Init(); } PARVARCOPY(ScryVariation) virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { T t = helper.m_PrecalcSumSquares; T r = 1 / Zeps(helper.m_PrecalcSqrtSumSquares * (t + m_InvWeight)); helper.Out.x = helper.In.x * r; helper.Out.y = helper.In.y * r; helper.Out.z = DefaultZ(helper); } virtual string OpenCLString() const override { ostringstream ss, ss2; int i = 0; ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string weight = WeightDefineString(); string invWeight = "parVars[" + ToUpper(m_Params[i++].Name()) + index; ss << "\t{\n" << "\t\treal_t t = precalcSumSquares;\n" << "\t\treal_t r = (real_t)(1.0) / Zeps(precalcSqrtSumSquares * (t + " << invWeight << "));\n" << "\n" << "\t\tvOut.x = vIn.x * r;\n" << "\t\tvOut.y = vIn.y * r;\n" << "\t\tvOut.z = " << DefaultZCl() << "\t}\n"; return ss.str(); } virtual vector OpenCLGlobalFuncNames() const override { return vector { "Zeps" }; } 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_inv_weight"));//Precalcs only, no params. } private: T m_InvWeight;//Precalcs only, no params. }; /// /// scry2. /// By dark-beam, modified by tatasz to increase the speed. /// template class Scry2Variation : public ParametricVariation { public: Scry2Variation(T weight = 1.0) : ParametricVariation("scry2", eVariationId::VAR_SCRY2, weight, true) { Init(); } PARVARCOPY(Scry2Variation) virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { T r2 = helper.m_PrecalcSumSquares; T s = 1 / Zeps(std::sqrt(r2) * (r2 + 1)); T newX = helper.In.x * s; T newY = helper.In.y * s; T dang = (std::atan2(newY, newX) + T(M_PI)) / m_2PiOverPower; T rad = std::sqrt(SQR(newX) + SQR(newY)); T zang1 = T(Floor(dang)); T xang1 = dang - zang1; T xang2 = xang1 > 0.5 ? 1 - xang1 : xang1; T zang = xang1 > 0.5 ? zang1 + 1 : zang1; T sign = T(xang1 > 0.5 ? -1 : 1); T xang = std::atan(xang2 * std::tan(m_2PiOverPower * T(0.5)) * 2) / m_2PiOverPower; T coeff = 1 / std::cos(xang * m_2PiOverPower); T ang = (zang + sign * xang) * m_2PiOverPower - T(M_PI); helper.Out.x = m_Weight * coeff * rad * std::cos(ang); helper.Out.y = m_Weight * coeff * rad * std::sin(ang); helper.Out.z = DefaultZ(helper); } virtual string OpenCLString() const override { ostringstream ss, ss2; int i = 0; ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string weight = WeightDefineString(); string power = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string twopioverpower = "parVars[" + ToUpper(m_Params[i++].Name()) + index; ss << "\t{\n" << "\t\treal_t r2 = precalcSumSquares;\n" << "\t\treal_t s = 1 / Zeps(sqrt(r2) * (r2 + 1));\n" << "\t\treal_t newX = vIn.x * s;\n" << "\t\treal_t newY = vIn.y * s;\n" << "\t\treal_t dang = (atan2(newY, newX) + MPI) / " << twopioverpower << ";\n" << "\t\treal_t rad = sqrt(SQR(newX) + SQR(newY));\n" << "\t\treal_t zang1 = floor(dang);\n" << "\t\treal_t xang1 = dang - zang1;\n" << "\t\treal_t xang2 = xang1 > 0.5 ? 1 - xang1 : xang1;\n" << "\t\treal_t zang = xang1 > 0.5 ? zang1 + 1 : zang1;\n" << "\t\treal_t sign = xang1 > 0.5 ? -1.0 : 1.0;\n" << "\t\treal_t xang = atan(xang2 * tan(" << twopioverpower << " * 0.5) * 2) / " << twopioverpower << ";\n" << "\t\treal_t coeff = 1 / cos(xang * " << twopioverpower << ");\n" << "\t\treal_t ang = (zang + sign * xang) * " << twopioverpower << " - MPI;\n" << "\t\tvOut.x = " << weight << " * coeff * rad * cos(ang);\n" << "\t\tvOut.y = " << weight << " * coeff * rad * sin(ang);\n" << "\t\tvOut.z = " << DefaultZCl() << "\t}\n"; return ss.str(); } virtual vector OpenCLGlobalFuncNames() const override { return vector { "Zeps" }; } virtual void Precalc() override { m_2PiOverPower = M_2PI / Zeps(m_Power); } protected: void Init() { string prefix = Prefix(); m_Params.clear(); m_Params.push_back(ParamWithName(&m_Power, prefix + "scry2_power", 4)); m_Params.push_back(ParamWithName(true, &m_2PiOverPower, prefix + "scry2_2pi_over_power"));//Precalc. } private: T m_Power; T m_2PiOverPower;//Precalc. }; /// /// Separation. /// template class SeparationVariation : public ParametricVariation { public: SeparationVariation(T weight = 1.0) : ParametricVariation("separation", eVariationId::VAR_SEPARATION, weight) { Init(); } PARVARCOPY(SeparationVariation) virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { if (helper.In.x > 0.0) helper.Out.x = m_Weight * (std::sqrt(SQR(helper.In.x) + m_XX) - helper.In.x * m_XInside); else helper.Out.x = -(m_Weight * (std::sqrt(SQR(helper.In.x) + m_XX) + helper.In.x * m_XInside)); if (helper.In.y > 0.0) helper.Out.y = m_Weight * (std::sqrt(SQR(helper.In.y) + m_YY) - helper.In.y * m_YInside); else helper.Out.y = -(m_Weight * (std::sqrt(SQR(helper.In.y) + m_YY) + helper.In.y * m_YInside)); helper.Out.z = m_Weight * helper.In.z; } virtual string OpenCLString() const override { ostringstream ss, ss2; intmax_t i = 0; ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string weight = WeightDefineString(); string x = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string xInside = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string y = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string yInside = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string xx = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string yy = "parVars[" + ToUpper(m_Params[i++].Name()) + index; ss << "\t{\n" << "\t\tif (vIn.x > (real_t)(0.0))\n" << "\t\t vOut.x = " << weight << " * (sqrt(fma(vIn.x, vIn.x, " << xx << ")) - vIn.x * " << xInside << ");\n" << "\t\telse\n" << "\t\t vOut.x = -(" << weight << " * fma(vIn.x, " << xInside << ", sqrt(fma(vIn.x, vIn.x, " << xx << "))));\n" << "\n" << "\t\tif (vIn.y > (real_t)(0.0))\n" << "\t\t vOut.y = " << weight << " * (sqrt(fma(vIn.y, vIn.y, " << yy << ")) - vIn.y * " << yInside << ");\n" << "\t\telse\n" << "\t\t vOut.y = -(" << weight << " * fma(vIn.y, " << yInside << ", sqrt(fma(vIn.y, vIn.y, " << yy << "))));\n" << "\n" << "\t\tvOut.z = " << weight << " * vIn.z;\n" << "\t}\n"; return ss.str(); } virtual void Precalc() override { m_XX = SQR(m_X); m_YY = SQR(m_Y); } virtual void Random(QTIsaac& rand) override { m_X = 1 + rand.Frand11(); m_XInside = 1 + rand.Frand11(); m_Y = rand.Frand11(); m_YInside = rand.Frand11(); } protected: void Init() { string prefix = Prefix(); m_Params.clear(); m_Params.push_back(ParamWithName(&m_X, prefix + "separation_x", 1));//Params. m_Params.push_back(ParamWithName(&m_XInside, prefix + "separation_xinside")); m_Params.push_back(ParamWithName(&m_Y, prefix + "separation_y", 1)); m_Params.push_back(ParamWithName(&m_YInside, prefix + "separation_yinside")); m_Params.push_back(ParamWithName(true, &m_XX, prefix + "separation_xx"));//Precalc. m_Params.push_back(ParamWithName(true, &m_YY, prefix + "separation_yy")); } private: T m_X;//Params. T m_XInside; T m_Y; T m_YInside; T m_XX;//Precalc. T m_YY; }; /// /// Split. /// template class SplitVariation : public ParametricVariation { public: SplitVariation(T weight = 1.0) : ParametricVariation("split", eVariationId::VAR_SPLIT, weight) { Init(); } PARVARCOPY(SplitVariation) virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { if (std::cos(helper.In.y * m_YAng) >= 0) helper.Out.x = m_Weight * helper.In.x; else helper.Out.x = -(m_Weight * helper.In.x); if (std::cos(helper.In.x * m_XAng) >= 0) helper.Out.y = m_Weight * helper.In.y; else helper.Out.y = -(m_Weight * helper.In.y); helper.Out.z = DefaultZ(helper); } virtual string OpenCLString() const override { ostringstream ss, ss2; intmax_t i = 0; ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string weight = WeightDefineString(); string xSize = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string ySize = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string xAng = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string yAng = "parVars[" + ToUpper(m_Params[i++].Name()) + index; ss << "\t{\n" << "\t\tif (cos(vIn.y * " << yAng << ") >= 0)\n" << "\t\t vOut.x = " << weight << " * vIn.x;\n" << "\t\telse\n" << "\t\t vOut.x = -(" << weight << " * vIn.x);\n" << "\n" << "\t\tif (cos(vIn.x * " << xAng << ") >= 0)\n" << "\t\t vOut.y = " << weight << " * vIn.y;\n" << "\t\telse\n" << "\t\t vOut.y = -(" << weight << " * vIn.y);\n" << "\n" << "\t\tvOut.z = " << DefaultZCl() << "\t}\n"; return ss.str(); } virtual void Precalc() override { m_XAng = T(M_PI) * m_XSize; m_YAng = T(M_PI) * m_YSize; } virtual void Random(QTIsaac& rand) override { m_XSize = rand.Frand11(); m_YSize = rand.Frand11(); } protected: void Init() { string prefix = Prefix(); m_Params.clear(); m_Params.push_back(ParamWithName(&m_XSize, prefix + "split_xsize", T(0.5)));//Params. m_Params.push_back(ParamWithName(&m_YSize, prefix + "split_ysize", T(0.5))); m_Params.push_back(ParamWithName(true, &m_XAng, prefix + "split_xang"));//Precalc. m_Params.push_back(ParamWithName(true, &m_YAng, prefix + "split_yang")); } private: T m_XSize;//Params. T m_YSize; T m_XAng;//Precalc. T m_YAng; }; /// /// Splits. /// template class SplitsVariation : public ParametricVariation { public: SplitsVariation(T weight = 1.0) : ParametricVariation("splits", eVariationId::VAR_SPLITS, weight) { Init(); } PARVARCOPY(SplitsVariation) virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { if (helper.In.x >= 0) helper.Out.x = m_Weight * (helper.In.x + m_X); else helper.Out.x = m_Weight * (helper.In.x - m_X); if (helper.In.y >= 0) helper.Out.y = m_Weight * (helper.In.y + m_Y); else helper.Out.y = m_Weight * (helper.In.y - m_Y); helper.Out.z = m_Weight * helper.In.z;//Original from flam3 does not have this, but the apo implementation does, so use Apo since it's more recent. } virtual string OpenCLString() const override { ostringstream ss, ss2; intmax_t i = 0; ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string weight = WeightDefineString(); string x = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string y = "parVars[" + ToUpper(m_Params[i++].Name()) + index; ss << "\t{\n" << "\t\tif (vIn.x >= 0)\n" << "\t\t vOut.x = " << weight << " * (vIn.x + " << x << ");\n" << "\t\telse\n" << "\t\t vOut.x = " << weight << " * (vIn.x - " << x << ");\n" << "\n" << "\t\tif (vIn.y >= 0)\n" << "\t\t vOut.y = " << weight << " * (vIn.y + " << y << ");\n" << "\t\telse\n" << "\t\t vOut.y = " << weight << " * (vIn.y - " << y << ");\n" << "\n" << "\t\tvOut.z = " << weight << " * vIn.z;\n" << "\t}\n"; return ss.str(); } virtual void Random(QTIsaac& rand) override { m_X = rand.Frand11(); m_Y = rand.Frand11(); } protected: void Init() { string prefix = Prefix(); m_Params.clear(); m_Params.push_back(ParamWithName(&m_X, prefix + "splits_x")); m_Params.push_back(ParamWithName(&m_Y, prefix + "splits_y")); } private: T m_X; T m_Y; }; /// /// Stripes. /// template class StripesVariation : public ParametricVariation { public: StripesVariation(T weight = 1.0) : ParametricVariation("stripes", eVariationId::VAR_STRIPES, weight) { Init(); } PARVARCOPY(StripesVariation) virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { T roundx = T(int(helper.In.x >= 0 ? (helper.In.x + T(0.5)) : (helper.In.x - T(0.5)))); T offsetx = helper.In.x - roundx; helper.Out.x = m_Weight * (offsetx * (1 - m_Space) + roundx); helper.Out.y = m_Weight * (helper.In.y + offsetx * offsetx * m_Warp); helper.Out.z = DefaultZ(helper); } virtual string OpenCLString() const override { ostringstream ss, ss2; intmax_t i = 0; ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string weight = WeightDefineString(); string space = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string warp = "parVars[" + ToUpper(m_Params[i++].Name()) + index; ss << "\t{\n" << "\t\treal_t roundx = (real_t)(int)(vIn.x >= 0 ? (vIn.x + (real_t)(0.5)) : (vIn.x - (real_t)(0.5)));\n" << "\t\treal_t offsetx = vIn.x - roundx;\n" << "\n" << "\t\tvOut.x = " << weight << " * fma(offsetx, (real_t)(1.0) - " << space << ", roundx);\n" << "\t\tvOut.y = " << weight << " * fma(SQR(offsetx), " << warp << ", vIn.y);\n" << "\t\tvOut.z = " << DefaultZCl() << "\t}\n"; return ss.str(); } virtual void Random(QTIsaac& rand) override { m_Params[0].Set(rand.Frand01());//Space. m_Params[1].Set(5 * rand.Frand01());//Warp. } protected: void Init() { string prefix = Prefix(); m_Params.clear(); m_Params.push_back(ParamWithName(&m_Space, prefix + "stripes_space", T(0.5), eParamType::REAL, T(0.5), 5)); m_Params.push_back(ParamWithName(&m_Warp, prefix + "stripes_warp")); } private: T m_Space; T m_Warp; }; /// /// Wedge. /// template class WedgeVariation : public ParametricVariation { public: WedgeVariation(T weight = 1.0) : ParametricVariation("wedge", eVariationId::VAR_WEDGE, weight, true, true, false, false, true) { Init(); } PARVARCOPY(WedgeVariation) virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { T r = helper.m_PrecalcSqrtSumSquares; T a = helper.m_PrecalcAtanyx + m_Swirl * r; T c = T(Floor((m_Count * a + T(M_PI)) * T(M_1_PI) * T(0.5))); a = a * m_CompFac + c * m_Angle; r = m_Weight * (r + m_Hole); helper.Out.x = r * std::cos(a); helper.Out.y = r * std::sin(a); helper.Out.z = m_Weight * helper.In.z; } virtual string OpenCLString() const override { ostringstream ss, ss2; intmax_t i = 0; ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string weight = WeightDefineString(); string angle = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string hole = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string count = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string swirl = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string compFac = "parVars[" + ToUpper(m_Params[i++].Name()) + index; ss << "\t{\n" << "\t\treal_t r = precalcSqrtSumSquares;\n" << "\t\treal_t a = fma(" << swirl << ", r, precalcAtanyx);\n" << "\t\treal_t c = floor(fma(" << count << ", a, MPI) * M1PI * (real_t)(0.5));\n" << "\n" << "\t\ta = fma(a, " << compFac << ", c * " << angle << ");\n" << "\t\tr = " << weight << " * (r + " << hole << ");\n" << "\t\tvOut.x = r * cos(a);\n" << "\t\tvOut.y = r * sin(a);\n" << "\t\tvOut.z = " << weight << " * vIn.z;\n" << "\t}\n"; return ss.str(); } virtual void Precalc() override { m_CompFac = 1 - m_Angle * m_Count * T(M_1_PI) * T(0.5); } virtual void Random(QTIsaac& rand) override { m_Angle = T(M_PI) * rand.Frand01(); m_Hole = T(0.5) * rand.Frand11(); m_Count = T(Floor(5 * rand.Frand01())) + 1; m_Swirl = rand.Frand01(); } protected: void Init() { string prefix = Prefix(); m_Params.clear(); m_Params.push_back(ParamWithName(&m_Angle, prefix + "wedge_angle", T(M_PI_2)));//Params. m_Params.push_back(ParamWithName(&m_Hole, prefix + "wedge_hole")); m_Params.push_back(ParamWithName(&m_Count, prefix + "wedge_count", 2, eParamType::INTEGER, 1)); m_Params.push_back(ParamWithName(&m_Swirl, prefix + "wedge_swirl")); m_Params.push_back(ParamWithName(true, &m_CompFac, prefix + "wedge_compfac"));//Precalc. } private: T m_Angle;//Params. T m_Hole; T m_Count; T m_Swirl; T m_CompFac;//Precalc. }; /// /// Wedge julia. /// template class WedgeJuliaVariation : public ParametricVariation { public: WedgeJuliaVariation(T weight = 1.0) : ParametricVariation("wedge_julia", eVariationId::VAR_WEDGE_JULIA, weight, true, false, false, false, true) { Init(); } PARVARCOPY(WedgeJuliaVariation) virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { T r = m_Weight * std::pow(helper.m_PrecalcSumSquares, m_Cn); auto tRand = rand.Rand(size_t(m_Rn)); T a = (helper.m_PrecalcAtanyx + M_2PI * tRand) / m_Power; T c = T(Floor((m_Count * a + T(M_PI)) * T(M_1_PI) * T(0.5))); a = a * m_Cf + c * m_Angle; helper.Out.x = r * std::cos(a); helper.Out.y = r * std::sin(a); helper.Out.z = DefaultZ(helper); } virtual string OpenCLString() const override { ostringstream ss, ss2; intmax_t i = 0; ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string weight = WeightDefineString(); string angle = "parVars[" + ToUpper(m_Params[i++].Name()) + index;//Params. string count = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string power = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string dist = "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; string cf = "parVars[" + ToUpper(m_Params[i++].Name()) + index; ss << "\t{\n" << "\t\treal_t r = " << weight << " * pow(precalcSumSquares, " << cn << ");\n" << "\t\tuint tRand = MwcNextRange(mwc, (uint)" << rn << ");\n" << "\t\treal_t a = fma(M_2PI, (real_t)tRand, precalcAtanyx) / " << power << ";\n" << "\t\treal_t c = floor(fma(" << count << ", a, MPI) * M1PI * (real_t)(0.5));\n" << "\n" << "\t\ta = fma(a, " << cf << ", c * " << angle << ");\n" << "\t\tvOut.x = r * cos(a);\n" << "\t\tvOut.y = r * sin(a);\n" << "\t\tvOut.z = " << DefaultZCl() << "\t}\n"; return ss.str(); } virtual void Precalc() override { m_Cf = 1 - m_Angle * m_Count * T(M_1_PI) * T(0.5); m_Rn = std::abs(m_Power); m_Cn = m_Dist / m_Power / 2; } virtual void Random(QTIsaac& rand) override { m_Power = T(int(5 * rand.Frand01() + 2)); m_Dist = 1; m_Count = T(int(3 * rand.Frand01() + 1)); m_Angle = T(M_PI) * rand.Frand01(); } protected: void Init() { string prefix = Prefix(); m_Params.clear(); m_Params.push_back(ParamWithName(&m_Angle, prefix + "wedge_julia_angle"));//Params. m_Params.push_back(ParamWithName(&m_Count, prefix + "wedge_julia_count", 1)); m_Params.push_back(ParamWithName(&m_Power, prefix + "wedge_julia_power", 1)); m_Params.push_back(ParamWithName(&m_Dist, prefix + "wedge_julia_dist")); m_Params.push_back(ParamWithName(true, &m_Rn, prefix + "wedge_julia_rn"));//Precalc. m_Params.push_back(ParamWithName(true, &m_Cn, prefix + "wedge_julia_cn")); m_Params.push_back(ParamWithName(true, &m_Cf, prefix + "wedge_julia_cf")); } private: T m_Angle;//Params. T m_Count; T m_Power; T m_Dist; T m_Rn;//Precalc. T m_Cn; T m_Cf; }; /// /// Wedge sph. /// template class WedgeSphVariation : public ParametricVariation { public: WedgeSphVariation(T weight = 1.0) : ParametricVariation("wedge_sph", eVariationId::VAR_WEDGE_SPH, weight, true, true, false, false, true) { Init(); } PARVARCOPY(WedgeSphVariation) virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { T r = 1 / Zeps(helper.m_PrecalcSqrtSumSquares); T a = helper.m_PrecalcAtanyx + m_Swirl * r; auto c = Floor((m_Count * a + T(M_PI)) * m_C12Pi); a = a * m_CompFac + c * m_Angle; T temp = m_Weight * (r + m_Hole); helper.Out.x = temp * std::cos(a); helper.Out.y = temp * std::sin(a); helper.Out.z = DefaultZ(helper); } virtual string OpenCLString() const override { ostringstream ss, ss2; intmax_t i = 0; ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string weight = WeightDefineString(); string angle = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string count = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string hole = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string swirl = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string c12pi = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string compfac = "parVars[" + ToUpper(m_Params[i++].Name()) + index; ss << "\t{\n" << "\t\treal_t r = (real_t)(1.0) / Zeps(precalcSqrtSumSquares);\n" << "\t\treal_t a = fma(" << swirl << ", r, precalcAtanyx);\n" << "\t\treal_t c = floor(fma(" << count << ", a, MPI) * " << c12pi << "); \n" << "\n" << "\t\ta = fma(a, " << compfac << ", c * " << angle << ");\n" << "\t\treal_t temp = " << weight << " * (r + " << hole << ");\n" << "\t\tvOut.x = temp * cos(a);\n" << "\t\tvOut.y = temp * sin(a);\n" << "\t\tvOut.z = " << DefaultZCl() << "\t}\n"; return ss.str(); } virtual vector OpenCLGlobalFuncNames() const override { return vector { "Zeps" }; } virtual void Random(QTIsaac& rand) override { m_Angle = T(M_PI) * rand.Frand01(); m_Count = T(Floor(5 * rand.Frand01())) + 1; m_Hole = T(0.5) * rand.Frand11(); m_Swirl = rand.Frand01(); } virtual void Precalc() override { m_C12Pi = T(M_1_PI) / 2; m_CompFac = 1 - m_Angle * m_Count * m_C12Pi; } protected: void Init() { string prefix = Prefix(); m_Params.clear(); m_Params.push_back(ParamWithName(&m_Angle, prefix + "wedge_sph_angle", T(M_PI_2))); m_Params.push_back(ParamWithName(&m_Count, prefix + "wedge_sph_count", 2, eParamType::INTEGER, 1)); m_Params.push_back(ParamWithName(&m_Hole, prefix + "wedge_sph_hole")); m_Params.push_back(ParamWithName(&m_Swirl, prefix + "wedge_sph_swirl")); m_Params.push_back(ParamWithName(true, &m_C12Pi, prefix + "wedge_sph_c1_2pi")); m_Params.push_back(ParamWithName(true, &m_CompFac, prefix + "wedge_sph_comp_fac")); } private: T m_Angle; T m_Count; T m_Hole; T m_Swirl; T m_C12Pi;//Precalc. T m_CompFac; }; /// /// Whorl. /// template class WhorlVariation : public ParametricVariation { public: WhorlVariation(T weight = 1.0) : ParametricVariation("whorl", eVariationId::VAR_WHORL, weight, true, true, false, false, true) { Init(); } PARVARCOPY(WhorlVariation) virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { T a, r = helper.m_PrecalcSqrtSumSquares; if (r < m_Weight) a = helper.m_PrecalcAtanyx + m_Inside / (m_Weight - r); else a = helper.m_PrecalcAtanyx + m_Outside / Zeps(m_Weight - r); helper.Out.x = m_Weight * r * std::cos(a); helper.Out.y = m_Weight * r * std::sin(a); helper.Out.z = DefaultZ(helper); } virtual string OpenCLString() const override { ostringstream ss, ss2; intmax_t i = 0; ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string weight = WeightDefineString(); string inside = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string outside = "parVars[" + ToUpper(m_Params[i++].Name()) + index; ss << "\t{\n" << "\t\treal_t a;\n" << "\t\treal_t r = precalcSqrtSumSquares;\n" << "\n" << "\t\tif (r < " << weight << ")\n" << "\t\t a = precalcAtanyx + " << inside << " / (" << weight << " - r);\n" << "\t\telse\n" << "\t\t a = precalcAtanyx + " << outside << " / Zeps(" << weight << " - r);\n" << "\n" << "\t\tvOut.x = (" << weight << " * r * cos(a));\n" << "\t\tvOut.y = (" << weight << " * r * sin(a));\n" << "\t\tvOut.z = " << DefaultZCl() << "\t}\n"; return ss.str(); } virtual vector OpenCLGlobalFuncNames() const override { return vector { "Zeps" }; } virtual void Random(QTIsaac& rand) override { m_Inside = rand.Frand01(); m_Outside = rand.Frand01(); } protected: void Init() { string prefix = Prefix(); m_Params.clear(); m_Params.push_back(ParamWithName(&m_Inside, prefix + "whorl_inside", 1)); m_Params.push_back(ParamWithName(&m_Outside, prefix + "whorl_outside", 1)); } private: T m_Inside; T m_Outside; }; /// /// Waves. /// template class Waves2Variation : public ParametricVariation { public: Waves2Variation(T weight = 1.0) : ParametricVariation("waves2", eVariationId::VAR_WAVES2, weight, true, true) { Init(); } PARVARCOPY(Waves2Variation) virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { helper.Out.x = m_Weight * (helper.In.x + m_ScaleX * std::sin(helper.In.y * m_FreqX)); helper.Out.y = m_Weight * (helper.In.y + m_ScaleY * std::sin(helper.In.x * m_FreqY)); helper.Out.z = m_Weight * (helper.In.z + m_ScaleZ * std::sin(helper.m_PrecalcSqrtSumSquares * m_FreqZ)); } virtual string OpenCLString() const override { ostringstream ss, ss2; intmax_t i = 0; ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string weight = WeightDefineString(); string freqX = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string scaleX = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string freqY = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string scaleY = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string freqZ = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string scaleZ = "parVars[" + ToUpper(m_Params[i++].Name()) + index; ss << "\t{\n" << "\t\tvOut.x = " << weight << " * fma(" << scaleX << ", sin(vIn.y * " << freqX << "), vIn.x);\n" << "\t\tvOut.y = " << weight << " * fma(" << scaleY << ", sin(vIn.x * " << freqY << "), vIn.y);\n" << "\t\tvOut.z = " << weight << " * fma(" << scaleZ << ", sin(precalcSqrtSumSquares * " << freqZ << "), vIn.z);\n" << "\t}\n"; return ss.str(); } virtual void Random(QTIsaac& rand) override { m_FreqX = 4 * rand.Frand01(); m_ScaleX = T(0.5) + rand.Frand01(); m_FreqY = 4 * rand.Frand01(); m_ScaleY = T(0.5) + rand.Frand01(); m_FreqZ = 0; m_ScaleZ = 0; } protected: void Init() { string prefix = Prefix(); m_Params.clear(); m_Params.push_back(ParamWithName(&m_FreqX, prefix + "waves2_freqx", 2)); m_Params.push_back(ParamWithName(&m_ScaleX, prefix + "waves2_scalex")); m_Params.push_back(ParamWithName(&m_FreqY, prefix + "waves2_freqy", 2)); m_Params.push_back(ParamWithName(&m_ScaleY, prefix + "waves2_scaley")); m_Params.push_back(ParamWithName(&m_FreqZ, prefix + "waves2_freqz")); m_Params.push_back(ParamWithName(&m_ScaleZ, prefix + "waves2_scalez")); } private: T m_FreqX; T m_ScaleX; T m_FreqY; T m_ScaleY; T m_FreqZ; T m_ScaleZ; }; /// /// Exp. /// template class ExpVariation : public Variation { public: ExpVariation(T weight = 1.0) : Variation("exp", eVariationId::VAR_EXP, weight) { } VARCOPY(ExpVariation) virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { T expe = m_Weight * std::exp(helper.In.x); helper.Out.x = expe * std::cos(helper.In.y); helper.Out.y = expe * std::sin(helper.In.y); helper.Out.z = DefaultZ(helper); } virtual string OpenCLString() const override { ostringstream ss; string weight = WeightDefineString(); ss << "\t{\n" << "\t\treal_t expe = " << weight << " * exp(vIn.x);\n" << "\n" << "\t\tvOut.x = expe * cos(vIn.y);\n" << "\t\tvOut.y = expe * sin(vIn.y);\n" << "\t\tvOut.z = " << DefaultZCl() << "\t}\n"; return ss.str(); } }; /// /// Exp2. /// By tatasz. /// template class Exp2Variation : public Variation { public: Exp2Variation(T weight = 1.0) : Variation("exp2", eVariationId::VAR_EXP2, weight) { } VARCOPY(Exp2Variation) virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { T ypi = helper.In.y * T(M_PI); T expe = m_Weight * std::exp(helper.In.x * T(M_PI)); helper.Out.x = expe * std::cos(ypi); helper.Out.y = expe * std::sin(ypi); helper.Out.z = DefaultZ(helper); } virtual string OpenCLString() const override { ostringstream ss; string weight = WeightDefineString(); ss << "\t{\n" << "\t\treal_t ypi = vIn.y * MPI;\n" << "\t\treal_t expe = " << weight << " * exp(vIn.x * MPI);\n" << "\n" << "\t\tvOut.x = expe * cos(ypi);\n" << "\t\tvOut.y = expe * sin(ypi);\n" << "\t\tvOut.z = " << DefaultZCl() << "\t}\n"; return ss.str(); } }; /// /// Log. /// template class LogVariation : public ParametricVariation { public: LogVariation(T weight = 1.0) : ParametricVariation("log", eVariationId::VAR_LOG, weight, true, false, false, false, true) { Init(); } PARVARCOPY(LogVariation) virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { helper.Out.x = m_Weight * std::log(helper.m_PrecalcSumSquares) * m_Denom; helper.Out.y = m_Weight * helper.m_PrecalcAtanyx; helper.Out.z = m_Weight * helper.In.z; } virtual string OpenCLString() const override { ostringstream ss, ss2; intmax_t i = 0; ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string weight = WeightDefineString(); string base = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string denom = "parVars[" + ToUpper(m_Params[i++].Name()) + index; ss << "\t{\n" << "\t\tvOut.x = " << weight << " * log(precalcSumSquares) * " << denom << ";\n" << "\t\tvOut.y = " << weight << " * precalcAtanyx;\n" << "\t\tvOut.z = " << weight << " * vIn.z;\n" << "\t}\n"; return ss.str(); } virtual void Precalc() override { m_Denom = T(0.5) / std::log(m_Base); } protected: void Init() { string prefix = Prefix(); m_Params.clear(); m_Params.push_back(ParamWithName(&m_Base, prefix + "log_base", T(M_E), eParamType::REAL, EPS, TMAX)); m_Params.push_back(ParamWithName(true, &m_Denom, prefix + "log_denom"));//Precalc. } private: T m_Base; T m_Denom;//Precalc. }; /// /// Sine. /// template class SinVariation : public Variation { public: SinVariation(T weight = 1.0) : Variation("sin", eVariationId::VAR_SIN, weight) { } VARCOPY(SinVariation) virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { if (Compat::m_Compat) { helper.Out.x = m_Weight * std::sin(helper.In.x) * std::cosh(helper.In.y); helper.Out.y = m_Weight * std::cos(helper.In.x) * std::sinh(helper.In.y); } else { T x = helper.In.x * M_PI2; T y = helper.In.y * M_PI2; helper.Out.x = m_Weight * std::sin(x) * std::cosh(y); helper.Out.y = m_Weight * std::cos(x) * std::sinh(y); } helper.Out.z = DefaultZ(helper); } virtual string OpenCLString() const override { if (Compat::m_Compat) { ostringstream ss; string weight = WeightDefineString(); ss << "\t{\n" << "\t\tvOut.x = " << weight << " * sin(vIn.x) * cosh(vIn.y);\n" << "\t\tvOut.y = " << weight << " * cos(vIn.x) * sinh(vIn.y);\n" << "\t\tvOut.z = " << DefaultZCl() << "\t}\n"; return ss.str(); } else { ostringstream ss; string weight = WeightDefineString(); ss << "\t{\n" << "\t\treal_t x = vIn.x * MPI2;\n" << "\t\treal_t y = vIn.y * MPI2;\n" << "\t\tvOut.x = " << weight << " * sin(x) * cosh(y);\n" << "\t\tvOut.y = " << weight << " * cos(x) * sinh(y);\n" << "\t\tvOut.z = " << DefaultZCl() << "\t}\n"; return ss.str(); } } }; /// /// Cosine. /// template class CosVariation : public Variation { public: CosVariation(T weight = 1.0) : Variation("cos", eVariationId::VAR_COS, weight) { } VARCOPY(CosVariation) virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { if (Compat::m_Compat) { //clamp fabs x and y to 7.104760e+002 for cosh, and |x| 7.104760e+002 for sinh helper.Out.x = m_Weight * std::cos(helper.In.x) * std::cosh(helper.In.y); helper.Out.y = -(m_Weight * std::sin(helper.In.x) * std::sinh(helper.In.y)); } else { T x = helper.In.x * M_PI2; T y = helper.In.y * M_PI2; helper.Out.x = m_Weight * std::cos(x) * std::cosh(y); helper.Out.y = m_Weight * -std::sin(x) * std::sinh(y); } helper.Out.z = DefaultZ(helper); } virtual string OpenCLString() const override { if (Compat::m_Compat) { ostringstream ss; string weight = WeightDefineString(); ss << "\t{\n" << "\t\tvOut.x = " << weight << " * cos(vIn.x) * cosh(vIn.y);\n" << "\t\tvOut.y = -(" << weight << " * sin(vIn.x) * sinh(vIn.y));\n" << "\t\tvOut.z = " << DefaultZCl() << "\t}\n"; return ss.str(); } else { ostringstream ss; string weight = WeightDefineString(); ss << "\t{\n" << "\t\treal_t x = vIn.x * MPI2;\n" << "\t\treal_t y = vIn.y * MPI2;\n" << "\t\tvOut.x = " << weight << " * cos(x) * cosh(y);\n" << "\t\tvOut.y = " << weight << " * -sin(x) * sinh(y);\n" << "\t\tvOut.z = " << DefaultZCl() << "\t}\n"; return ss.str(); } } }; /// /// Tangent. /// template class TanVariation : public Variation { public: TanVariation(T weight = 1.0) : Variation("tan", eVariationId::VAR_TAN, weight) { } VARCOPY(TanVariation) virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { if (Compat::m_Compat) { T tansin, tancos, tansinh, tancosh, tanden; sincos(2 * helper.In.x, &tansin, &tancos); tansinh = std::sinh(2 * helper.In.y); tancosh = std::cosh(2 * helper.In.y); tanden = 1 / Zeps(tancos + tancosh); helper.Out.x = m_Weight * tanden * tansin; helper.Out.y = m_Weight * tanden * tansinh; } else { T x = helper.In.x * M_PI2; T y = helper.In.y * M_PI2; T den = m_Weight / Zeps(std::cos(x) + std::cosh(y)); helper.Out.x = std::sin(x) * den; helper.Out.y = std::sinh(y) * den; } helper.Out.z = DefaultZ(helper); } virtual string OpenCLString() const override { if (Compat::m_Compat) { ostringstream ss; string weight = WeightDefineString(); ss << "\t{\n" << "\t\treal_t tansin = sin((real_t)(2.0) * vIn.x);\n" << "\t\treal_t tancos = cos((real_t)(2.0) * vIn.x);\n" << "\t\treal_t tansinh = sinh((real_t)(2.0) * vIn.y);\n" << "\t\treal_t tancosh = cosh((real_t)(2.0) * vIn.y);\n" << "\t\treal_t tanden = (real_t)(1.0) / Zeps(tancos + tancosh);\n" << "\n" << "\t\tvOut.x = " << weight << " * tanden * tansin;\n" << "\t\tvOut.y = " << weight << " * tanden * tansinh;\n" << "\t\tvOut.z = " << DefaultZCl() << "\t}\n"; return ss.str(); } else { ostringstream ss; string weight = WeightDefineString(); ss << "\t{\n" << "\t\treal_t x = vIn.x * MPI2;\n" << "\t\treal_t y = vIn.y * MPI2;\n" << "\t\treal_t den = " << weight << " / Zeps(cos(x) + cosh(y));\n" << "\n" << "\t\tvOut.x = sin(x) * den;\n" << "\t\tvOut.y = sinh(y) * den;\n" << "\t\tvOut.z = " << DefaultZCl() << "\t}\n"; return ss.str(); } } virtual vector OpenCLGlobalFuncNames() const override { return vector { "Zeps" }; } }; /// /// Sec. /// template class SecVariation : public Variation { public: SecVariation(T weight = 1.0) : Variation("sec", eVariationId::VAR_SEC, weight) { } VARCOPY(SecVariation) virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { if (Compat::m_Compat) { T secsin, seccos, secsinh, seccosh, secden; sincos(helper.In.x, &secsin, &seccos); secsinh = std::sinh(helper.In.y); seccosh = std::cosh(helper.In.y); secden = 2 / Zeps(std::cos(2 * helper.In.x) + std::cosh(2 * helper.In.y)); helper.Out.x = m_Weight * secden * seccos * seccosh; helper.Out.y = m_Weight * secden * secsin * secsinh; } else { T x = helper.In.x * T(M_PI); T y = helper.In.y * T(M_PI); T secsin, seccos, secsinh, seccosh, secden; sincos(x, &secsin, &seccos); secsinh = std::sinh(y); seccosh = std::cosh(y); secden = m_Weight * (2 / Zeps(std::cos(2 * x) + std::cosh(2 * y))); helper.Out.x = secden * seccos * seccosh; helper.Out.y = secden * secsin * secsinh; } helper.Out.z = DefaultZ(helper); } virtual string OpenCLString() const override { if (Compat::m_Compat) { ostringstream ss; string weight = WeightDefineString(); ss << "\t{\n" << "\t\treal_t secsin = sin(vIn.x);\n" << "\t\treal_t seccos = cos(vIn.x);\n" << "\t\treal_t secsinh = sinh(vIn.y);\n" << "\t\treal_t seccosh = cosh(vIn.y);\n" << "\t\treal_t secden = (real_t)(2.0) / Zeps(cos((real_t)(2.0) * vIn.x) + cosh((real_t)(2.0) * vIn.y));\n" << "\n" << "\t\tvOut.x = " << weight << " * secden * seccos * seccosh;\n" << "\t\tvOut.y = " << weight << " * secden * secsin * secsinh;\n" << "\t\tvOut.z = " << DefaultZCl() << "\t}\n"; return ss.str(); } else { ostringstream ss; string weight = WeightDefineString(); ss << "\t{\n" << "\t\treal_t x = vIn.x * MPI;\n" << "\t\treal_t y = vIn.y * MPI;\n" << "\t\treal_t secsin = sin(x);\n" << "\t\treal_t seccos = cos(x);\n" << "\t\treal_t secsinh = sinh(y);\n" << "\t\treal_t seccosh = cosh(y);\n" << "\t\treal_t secden = " << weight << " * ((real_t)(2.0) / Zeps(cos((real_t)(2.0) * x) + cosh((real_t)(2.0) * y)));\n" << "\n" << "\t\tvOut.x = secden * seccos * seccosh;\n" << "\t\tvOut.y = secden * secsin * secsinh;\n" << "\t\tvOut.z = " << DefaultZCl() << "\t}\n"; return ss.str(); } } virtual vector OpenCLGlobalFuncNames() const override { return vector { "Zeps" }; } }; /// /// Cosecant. /// template class CscVariation : public Variation { public: CscVariation(T weight = 1.0) : Variation("csc", eVariationId::VAR_CSC, weight) { } VARCOPY(CscVariation) virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { if (Compat::m_Compat) { T cscsin, csccos, cscsinh, csccosh, cscden; sincos(helper.In.x, &cscsin, &csccos); cscsinh = std::sinh(helper.In.y); csccosh = std::cosh(helper.In.y); cscden = 2 / Zeps(std::cosh(2 * helper.In.y) - std::cos(2 * helper.In.x)); helper.Out.x = m_Weight * cscden * cscsin * csccosh; helper.Out.y = -(m_Weight * cscden * csccos * cscsinh); } else { T x = helper.In.x * M_PI2; T y = helper.In.y * M_PI2; T cscsin, csccos, cscsinh, csccosh, cscden, d; sincos(x, &cscsin, &csccos); cscsinh = std::sinh(y); csccosh = std::cosh(y); d = 1 + 2 * cscsinh * cscsinh - std::cos(2 * x); cscden = 2 * m_Weight / d; helper.Out.x = cscden * cscsin * csccosh; helper.Out.y = cscden * csccos * cscsinh; } helper.Out.z = DefaultZ(helper); } virtual string OpenCLString() const override { if (Compat::m_Compat) { ostringstream ss; string weight = WeightDefineString(); ss << "\t{\n" << "\t\treal_t cscsin = sin(vIn.x);\n" << "\t\treal_t csccos = cos(vIn.x);\n" << "\t\treal_t cscsinh = sinh(vIn.y);\n" << "\t\treal_t csccosh = cosh(vIn.y);\n" << "\t\treal_t cscden = (real_t)(2.0) / Zeps(cosh((real_t)(2.0) * vIn.y) - cos((real_t)(2.0) * vIn.x));\n" << "\n" << "\t\tvOut.x = " << weight << " * cscden * cscsin * csccosh;\n" << "\t\tvOut.y = -(" << weight << " * cscden * csccos * cscsinh);\n" << "\t\tvOut.z = " << DefaultZCl() << "\t}\n"; return ss.str(); } else { ostringstream ss; string weight = WeightDefineString(); ss << "\t{\n" << "\t\treal_t x = vIn.x * MPI2;\n" << "\t\treal_t y = vIn.y * MPI2;\n" << "\t\treal_t cscsin = sin(x);\n" << "\t\treal_t csccos = cos(x);\n" << "\t\treal_t cscsinh = sinh(y);\n" << "\t\treal_t csccosh = cosh(y);\n" << "\t\treal_t d = Zeps(1 + 2 * cscsinh * cscsinh - cos(2 * x));\n" << "\t\treal_t cscden = 2 * " << weight << " / d;\n" << "\n" << "\t\tvOut.x = cscden * cscsin * csccosh;\n" << "\t\tvOut.y = cscden * csccos * cscsinh;\n" << "\t\tvOut.z = " << DefaultZCl() << "\t}\n"; return ss.str(); } } virtual vector OpenCLGlobalFuncNames() const override { return vector { "Zeps" }; } }; /// /// Cotangent. /// template class CotVariation : public Variation { public: CotVariation(T weight = 1.0) : Variation("cot", eVariationId::VAR_COT, weight) { } VARCOPY(CotVariation) virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { if (Compat::m_Compat) { T cotsin, cotcos, cotsinh, cotcosh, cotden; sincos(2 * helper.In.x, &cotsin, &cotcos); cotsinh = std::sinh(2 * helper.In.y); cotcosh = std::cosh(2 * helper.In.y); cotden = 1 / Zeps(cotcosh - cotcos); helper.Out.x = m_Weight * cotden * cotsin; helper.Out.y = m_Weight * cotden * -1 * cotsinh; } else { T x = helper.In.x * M_PI2; T y = helper.In.y * M_PI2; T cotsin, cotcos, cotsinh, cotcosh, cotden; sincos(x, &cotsin, &cotcos); cotsinh = std::sinh(y); cotcosh = std::cosh(y); cotden = m_Weight / Zeps(cotcosh - cotcos); helper.Out.x = cotden * cotsin; helper.Out.y = cotden * cotsinh; } helper.Out.z = DefaultZ(helper); } virtual string OpenCLString() const override { if (Compat::m_Compat) { ostringstream ss; string weight = WeightDefineString(); ss << "\t{\n" << "\t\treal_t cotsin = sin((real_t)(2.0) * vIn.x);\n" << "\t\treal_t cotcos = cos((real_t)(2.0) * vIn.x);\n" << "\t\treal_t cotsinh = sinh((real_t)(2.0) * vIn.y);\n" << "\t\treal_t cotcosh = cosh((real_t)(2.0) * vIn.y);\n" << "\t\treal_t cotden = (real_t)(1.0) / Zeps(cotcosh - cotcos);\n" << "\n" << "\t\tvOut.x = " << weight << " * cotden * cotsin;\n" << "\t\tvOut.y = " << weight << " * cotden * -1 * cotsinh;\n" << "\t\tvOut.z = " << DefaultZCl() << "\t}\n"; return ss.str(); } else { ostringstream ss; string weight = WeightDefineString(); ss << "\t{\n" << "\t\treal_t x = vIn.x * MPI2;\n" << "\t\treal_t y = vIn.y * MPI2;\n" << "\t\treal_t cotsin = sin(x);\n" << "\t\treal_t cotcos = cos(x);\n" << "\t\treal_t cotsinh = sinh(y);\n" << "\t\treal_t cotcosh = cosh(y);\n" << "\t\treal_t cotden = " << weight << " / Zeps(cotcosh - cotcos);\n" << "\n" << "\t\tvOut.x = cotden * cotsin;\n" << "\t\tvOut.y = cotden * cotsinh;\n" << "\t\tvOut.z = " << DefaultZCl() << "\t}\n"; return ss.str(); } } virtual vector OpenCLGlobalFuncNames() const override { return vector { "Zeps" }; } }; /// /// Sinh. /// template class SinhVariation : public Variation { public: SinhVariation(T weight = 1.0) : Variation("sinh", eVariationId::VAR_SINH, weight) { } VARCOPY(SinhVariation) virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { if (Compat::m_Compat) { T sinhsin, sinhcos, sinhsinh, sinhcosh; sincos(helper.In.y, &sinhsin, &sinhcos); sinhsinh = std::sinh(helper.In.x); sinhcosh = std::cosh(helper.In.x); helper.Out.x = m_Weight * sinhsinh * sinhcos; helper.Out.y = m_Weight * sinhcosh * sinhsin; } else { T sinhsin, sinhcos, sinhsinh, sinhcosh; T x = helper.In.x * M_PI4; T y = helper.In.y * M_PI4; sincos(y, &sinhsin, &sinhcos); sinhsinh = std::sinh(x); sinhcosh = std::cosh(x); helper.Out.x = m_Weight * sinhsinh * sinhcos; helper.Out.y = m_Weight * sinhcosh * sinhsin; } helper.Out.z = DefaultZ(helper); } virtual string OpenCLString() const override { if (Compat::m_Compat) { ostringstream ss; string weight = WeightDefineString(); ss << "\t{\n" << "\t\treal_t sinhsin = sin(vIn.y);\n" << "\t\treal_t sinhcos = cos(vIn.y);\n" << "\t\treal_t sinhsinh = sinh(vIn.x);\n" << "\t\treal_t sinhcosh = cosh(vIn.x);\n" << "\n" << "\t\tvOut.x = " << weight << " * sinhsinh * sinhcos;\n" << "\t\tvOut.y = " << weight << " * sinhcosh * sinhsin;\n" << "\t\tvOut.z = " << DefaultZCl() << "\t}\n"; return ss.str(); } else { ostringstream ss; string weight = WeightDefineString(); ss << "\t{\n" << "\t\treal_t x = vIn.x * MPI4;\n" << "\t\treal_t y = vIn.y * MPI4;\n" << "\t\treal_t sinhsin = sin(y);\n" << "\t\treal_t sinhcos = cos(y);\n" << "\t\treal_t sinhsinh = sinh(x);\n" << "\t\treal_t sinhcosh = cosh(x);\n" << "\n" << "\t\tvOut.x = " << weight << " * sinhsinh * sinhcos;\n" << "\t\tvOut.y = " << weight << " * sinhcosh * sinhsin;\n" << "\t\tvOut.z = " << DefaultZCl() << "\t}\n"; return ss.str(); } } }; /// /// Cosh. /// template class CoshVariation : public Variation { public: CoshVariation(T weight = 1.0) : Variation("cosh", eVariationId::VAR_COSH, weight) { } VARCOPY(CoshVariation) virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { if (Compat::m_Compat) { T coshsin, coshcos, coshsinh, coshcosh; sincos(helper.In.y, &coshsin, &coshcos); coshsinh = std::sinh(helper.In.x); coshcosh = std::cosh(helper.In.x); helper.Out.x = m_Weight * coshcosh * coshcos; helper.Out.y = m_Weight * coshsinh * coshsin; } else { T coshsin, coshcos, coshsinh, coshcosh; T x = helper.In.x * M_PI2; T y = helper.In.y * M_PI2; sincos(y, &coshsin, &coshcos); coshsinh = std::sinh(x); coshcosh = std::cosh(x); helper.Out.x = m_Weight * coshcosh * coshcos; helper.Out.y = m_Weight * coshsinh * coshsin; } helper.Out.z = DefaultZ(helper); } virtual string OpenCLString() const override { if (Compat::m_Compat) { ostringstream ss; string weight = WeightDefineString(); ss << "\t{\n" << "\t\treal_t coshsin = sin(vIn.y);\n" << "\t\treal_t coshcos = cos(vIn.y);\n" << "\t\treal_t coshsinh = sinh(vIn.x);\n" << "\t\treal_t coshcosh = cosh(vIn.x);\n" << "\n" << "\t\tvOut.x = " << weight << " * coshcosh * coshcos;\n" << "\t\tvOut.y = " << weight << " * coshsinh * coshsin;\n" << "\t\tvOut.z = " << DefaultZCl() << "\t}\n"; return ss.str(); } else { ostringstream ss; string weight = WeightDefineString(); ss << "\t{\n" << "\t\treal_t x = vIn.x * MPI2;\n" << "\t\treal_t y = vIn.y * MPI2;\n" << "\t\treal_t coshsin = sin(y);\n" << "\t\treal_t coshcos = cos(y);\n" << "\t\treal_t coshsinh = sinh(x);\n" << "\t\treal_t coshcosh = cosh(x);\n" << "\n" << "\t\tvOut.x = " << weight << " * coshcosh * coshcos;\n" << "\t\tvOut.y = " << weight << " * coshsinh * coshsin;\n" << "\t\tvOut.z = " << DefaultZCl() << "\t}\n"; return ss.str(); } } }; /// /// Tanh. /// template class TanhVariation : public Variation { public: TanhVariation(T weight = 1.0) : Variation("tanh", eVariationId::VAR_TANH, weight) { } VARCOPY(TanhVariation) virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { if (Compat::m_Compat) { T tanhsin, tanhcos, tanhsinh, tanhcosh, tanhden; sincos(2 * helper.In.y, &tanhsin, &tanhcos); tanhsinh = std::sinh(2 * helper.In.x); tanhcosh = std::cosh(2 * helper.In.x); tanhden = 1 / Zeps(tanhcos + tanhcosh); helper.Out.x = m_Weight * tanhden * tanhsinh; helper.Out.y = m_Weight * tanhden * tanhsin; } else { T tanhsin, tanhcos, tanhsinh, tanhcosh, tanhden; T x = helper.In.x * M_PI2; T y = helper.In.y * M_PI2; sincos(y, &tanhsin, &tanhcos); tanhsinh = std::sinh(x); tanhcosh = std::cosh(x); tanhden = m_Weight / Zeps(tanhcos + tanhcosh); helper.Out.x = tanhden * tanhsinh; helper.Out.y = tanhden * tanhsin; } helper.Out.z = DefaultZ(helper); } virtual string OpenCLString() const override { if (Compat::m_Compat) { ostringstream ss; string weight = WeightDefineString(); ss << "\t{\n" << "\t\treal_t tanhsin = sin((real_t)(2.0) * vIn.y);\n" << "\t\treal_t tanhcos = cos((real_t)(2.0) * vIn.y);\n" << "\t\treal_t tanhsinh = sinh((real_t)(2.0) * vIn.x);\n" << "\t\treal_t tanhcosh = cosh((real_t)(2.0) * vIn.x);\n" << "\t\treal_t tanhden = (real_t)(1.0) / Zeps(tanhcos + tanhcosh);\n" << "\n" << "\t\tvOut.x = " << weight << " * tanhden * tanhsinh;\n" << "\t\tvOut.y = " << weight << " * tanhden * tanhsin;\n" << "\t\tvOut.z = " << DefaultZCl() << "\t}\n"; return ss.str(); } else { ostringstream ss; string weight = WeightDefineString(); ss << "\t{\n" << "\t\treal_t x = vIn.x * MPI2;\n" << "\t\treal_t y = vIn.y * MPI2;\n" << "\t\treal_t tanhsin = sin(y);\n" << "\t\treal_t tanhcos = cos(y);\n" << "\t\treal_t tanhsinh = sinh(x);\n" << "\t\treal_t tanhcosh = cosh(x);\n" << "\t\treal_t tanhden = " << weight << " / Zeps(tanhcos + tanhcosh);\n" << "\n" << "\t\tvOut.x = tanhden * tanhsinh;\n" << "\t\tvOut.y = tanhden * tanhsin;\n" << "\t\tvOut.z = " << DefaultZCl() << "\t}\n"; return ss.str(); } } virtual vector OpenCLGlobalFuncNames() const override { return vector { "Zeps" }; } }; /// /// tanh_spiral. /// template class TanhSpiralVariation : public ParametricVariation { public: TanhSpiralVariation(T weight = 1.0) : ParametricVariation("tanh_spiral", eVariationId::VAR_TANH_SPIRAL, weight) { Init(); } PARVARCOPY(TanhSpiralVariation) virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { T t2 = (rand.Frand01() - T(0.5)) * M_2PI; T aux = Zeps(std::cos(m_A * t2) + std::cosh(t2)); helper.Out.x = m_Weight * (std::sinh(t2) / aux); helper.Out.y = m_Weight * (std::sin(m_A * t2) / aux); helper.Out.z = DefaultZ(helper); } virtual string OpenCLString() const override { ostringstream ss, ss2; intmax_t i = 0; ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string weight = WeightDefineString(); string a = "parVars[" + ToUpper(m_Params[i++].Name()) + index; ss << "\t{\n" << "\t\treal_t t2 = (MwcNext01(mwc) - 0.5) * M_2PI;\n" << "\t\treal_t aux = Zeps(cos(" << a << " * t2) + cosh(t2));\n" << "\n" << "\t\tvOut.x = " << weight << " * (sinh(t2) / aux);\n" << "\t\tvOut.y = " << weight << " * (sin(" << a << " * t2) / aux);\n" << "\t\tvOut.z = " << DefaultZCl() << "\t}\n"; return ss.str(); } virtual vector OpenCLGlobalFuncNames() const override { return vector { "Zeps" }; } protected: void Init() { string prefix = Prefix(); m_Params.clear(); m_Params.push_back(ParamWithName(&m_A, prefix + "tanh_spiral_a", 4)); } private: T m_A; }; /// /// Sech /// template class SechVariation : public Variation { public: SechVariation(T weight = 1.0) : Variation("sech", eVariationId::VAR_SECH, weight) { } VARCOPY(SechVariation) virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { if (Compat::m_Compat) { T sechsin, sechcos, sechsinh, sechcosh, sechden; sincos(helper.In.y, &sechsin, &sechcos); sechsinh = std::sinh(helper.In.x); sechcosh = std::cosh(helper.In.x); sechden = 2 / Zeps(std::cos(2 * helper.In.y) + std::cosh(2 * helper.In.x)); helper.Out.x = m_Weight * sechden * sechcos * sechcosh; helper.Out.y = -(m_Weight * sechden * sechsin * sechsinh); } else { T sechsin, sechcos, sechsinh, sechcosh, sechden; T x = helper.In.x * M_PI4; T y = helper.In.y * M_PI4; sincos(y, &sechsin, &sechcos); sechsinh = std::sinh(x); sechcosh = std::cosh(x); sechden = m_Weight * (2 / Zeps(std::cos(y * 2) + std::cosh(x * 2))); helper.Out.x = sechden * sechcos * sechcosh; helper.Out.y = sechden * sechsin * sechsinh; } helper.Out.z = DefaultZ(helper); } virtual string OpenCLString() const override { if (Compat::m_Compat) { ostringstream ss; string weight = WeightDefineString(); ss << "\t{\n" << "\t\treal_t sechsin = sin(vIn.y);\n" << "\t\treal_t sechcos = cos(vIn.y);\n" << "\t\treal_t sechsinh = sinh(vIn.x);\n" << "\t\treal_t sechcosh = cosh(vIn.x);\n" << "\t\treal_t sechden = (real_t)(2.0) / Zeps(cos((real_t)(2.0) * vIn.y) + cosh((real_t)(2.0) * vIn.x));\n" << "\n" << "\t\tvOut.x = " << weight << " * sechden * sechcos * sechcosh;\n" << "\t\tvOut.y = -(" << weight << " * sechden * sechsin * sechsinh);\n" << "\t\tvOut.z = " << DefaultZCl() << "\t}\n"; return ss.str(); } else { ostringstream ss; string weight = WeightDefineString(); ss << "\t{\n" << "\t\treal_t x = vIn.x * MPI4;\n" << "\t\treal_t y = vIn.y * MPI4;\n" << "\t\treal_t sechsin = sin(y);\n" << "\t\treal_t sechcos = cos(y);\n" << "\t\treal_t sechsinh = sinh(x);\n" << "\t\treal_t sechcosh = cosh(x);\n" << "\t\treal_t sechden = " << weight << " * ((real_t)(2.0) / Zeps(cos(y * (real_t)(2.0)) + cosh(x * (real_t)(2.0))));\n" << "\n" << "\t\tvOut.x = sechden * sechcos * sechcosh;\n" << "\t\tvOut.y = sechden * sechsin * sechsinh;\n" << "\t\tvOut.z = " << DefaultZCl() << "\t}\n"; return ss.str(); } } virtual vector OpenCLGlobalFuncNames() const override { return vector { "Zeps" }; } }; /// /// Csch. /// template class CschVariation : public Variation { public: CschVariation(T weight = 1.0) : Variation("csch", eVariationId::VAR_CSCH, weight) { } VARCOPY(CschVariation) virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { if (Compat::m_Compat) { T cschsin, cschcos, cschsinh, cschcosh, cschden; sincos(helper.In.y, &cschsin, &cschcos); cschsinh = std::sinh(helper.In.x); cschcosh = std::cosh(helper.In.x); cschden = 2 / Zeps(std::cosh(2 * helper.In.x) - std::cos(2 * helper.In.y)); helper.Out.x = m_Weight * cschden * cschsinh * cschcos; helper.Out.y = -(m_Weight * cschden * cschcosh * cschsin); } else { T cschsin, cschcos, cschsinh, cschcosh, cschden; T x = helper.In.x * M_PI4; T y = helper.In.y * M_PI4; sincos(y, &cschsin, &cschcos); cschsinh = std::sinh(x); cschcosh = std::cosh(x); cschden = m_Weight * (2 / Zeps(std::cosh(2 * x) - std::cos(2 * y))); helper.Out.x = cschden * cschsinh * cschcos; helper.Out.y = cschden * cschcosh * cschsin; } helper.Out.z = DefaultZ(helper); } virtual string OpenCLString() const override { if (Compat::m_Compat) { ostringstream ss; string weight = WeightDefineString(); ss << "\t{\n" << "\t\treal_t cschsin = sin(vIn.y);\n" << "\t\treal_t cschcos = cos(vIn.y);\n" << "\t\treal_t cschsinh = sinh(vIn.x);\n" << "\t\treal_t cschcosh = cosh(vIn.x);\n" << "\t\treal_t cschden = (real_t)(2.0) / Zeps(cosh((real_t)(2.0) * vIn.x) - cos((real_t)(2.0) * vIn.y));\n" << "\n" << "\t\tvOut.x = " << weight << " * cschden * cschsinh * cschcos;\n" << "\t\tvOut.y = -(" << weight << " * cschden * cschcosh * cschsin);\n" << "\t\tvOut.z = " << DefaultZCl() << "\t}\n"; return ss.str(); } else { ostringstream ss; string weight = WeightDefineString(); ss << "\t{\n" << "\t\treal_t x = vIn.x * MPI4;\n" << "\t\treal_t y = vIn.y * MPI4;\n" << "\t\treal_t cschsin = sin(y);\n" << "\t\treal_t cschcos = cos(y);\n" << "\t\treal_t cschsinh = sinh(x);\n" << "\t\treal_t cschcosh = cosh(x);\n" << "\t\treal_t cschden = " << weight << " * ((real_t)(2.0) / Zeps(cosh((real_t)(2.0) * x) - cos((real_t)(2.0) * y)));\n" << "\n" << "\t\tvOut.x = cschden * cschsinh * cschcos;\n" << "\t\tvOut.y = cschden * cschcosh * cschsin;\n" << "\t\tvOut.z = " << DefaultZCl() << "\t}\n"; return ss.str(); } } virtual vector OpenCLGlobalFuncNames() const override { return vector { "Zeps" }; } }; /// /// Coth. /// template class CothVariation : public Variation { public: CothVariation(T weight = 1.0) : Variation("coth", eVariationId::VAR_COTH, weight) { } VARCOPY(CothVariation) virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { if (Compat::m_Compat) { T cothsin, cothcos, cothsinh, cothcosh, cothden; sincos(2 * helper.In.y, &cothsin, &cothcos); cothsinh = std::sinh(2 * helper.In.x); cothcosh = std::cosh(2 * helper.In.x); cothden = 1 / Zeps(cothcosh - cothcos); helper.Out.x = m_Weight * cothden * cothsinh; helper.Out.y = m_Weight * cothden * cothsin; } else { T cothsin, cothcos, cothsinh, cothcosh, cothden; T x = helper.In.x * M_PI2; T y = helper.In.y * M_PI2; sincos(y, &cothsin, &cothcos); cothsinh = std::sinh(x); cothcosh = std::cosh(x); cothden = m_Weight / Zeps(cothcosh - cothcos); helper.Out.x = cothden * cothsinh; helper.Out.y = cothden * cothsin; } helper.Out.z = DefaultZ(helper); } virtual string OpenCLString() const override { if (Compat::m_Compat) { ostringstream ss; string weight = WeightDefineString(); ss << "\t{\n" << "\t\treal_t cothsin = sin((real_t)(2.0) * vIn.y);\n" << "\t\treal_t cothcos = cos((real_t)(2.0) * vIn.y);\n" << "\t\treal_t cothsinh = sinh((real_t)(2.0) * vIn.x);\n" << "\t\treal_t cothcosh = cosh((real_t)(2.0) * vIn.x);\n" << "\t\treal_t cothden = (real_t)(1.0) / Zeps(cothcosh - cothcos);\n" << "\n" << "\t\tvOut.x = " << weight << " * cothden * cothsinh;\n" << "\t\tvOut.y = " << weight << " * cothden * cothsin;\n" << "\t\tvOut.z = " << DefaultZCl() << "\t}\n"; return ss.str(); } else { ostringstream ss; string weight = WeightDefineString(); ss << "\t{\n" << "\t\treal_t x = vIn.x * MPI2;\n" << "\t\treal_t y = vIn.y * MPI2;\n" << "\t\treal_t cothsin = sin(y);\n" << "\t\treal_t cothcos = cos(y);\n" << "\t\treal_t cothsinh = sinh(x);\n" << "\t\treal_t cothcosh = cosh(x);\n" << "\t\treal_t cothden = " << weight << " / Zeps(cothcosh - cothcos);\n" << "\n" << "\t\tvOut.x = cothden * cothsinh;\n" << "\t\tvOut.y = cothden * cothsin;\n" << "\t\tvOut.z = " << DefaultZCl() << "\t}\n"; return ss.str(); } } virtual vector OpenCLGlobalFuncNames() const override { return vector { "Zeps" }; } }; /// /// Auger. /// template class AugerVariation : public ParametricVariation { public: AugerVariation(T weight = 1.0) : ParametricVariation("auger", eVariationId::VAR_AUGER, weight) { Init(); } PARVARCOPY(AugerVariation) virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { T s = std::sin(m_Freq * helper.In.x); T t = std::sin(m_Freq * helper.In.y); T dx = helper.In.x + m_AugerWeight * (m_HalfScale * t + std::abs(helper.In.x) * t); T dy = helper.In.y + m_AugerWeight * (m_HalfScale * s + std::abs(helper.In.y) * s); helper.Out.x = m_Weight * (helper.In.x + m_Symmetry * (dx - helper.In.x)); helper.Out.y = m_Weight * dy; helper.Out.z = m_Weight * helper.In.z; } virtual string OpenCLString() const override { ostringstream ss, ss2; intmax_t i = 0; ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string weight = WeightDefineString(); string symmetry = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string augerWeight = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string freq = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string scale = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string halfscale = "parVars[" + ToUpper(m_Params[i++].Name()) + index; ss << "\t{\n" << "\t\treal_t s = sin(" << freq << " * vIn.x);\n" << "\t\treal_t t = sin(" << freq << " * vIn.y);\n" << "\t\treal_t dx = fma(" << augerWeight << ", fma(" << halfscale << ", t, fabs(vIn.x) * t), vIn.x);\n" << "\t\treal_t dy = fma(" << augerWeight << ", fma(" << halfscale << ", s, fabs(vIn.y) * s), vIn.y);\n" << "\n" << "\t\tvOut.x = " << weight << " * fma(" << symmetry << ", (dx - vIn.x), vIn.x);\n" << "\t\tvOut.y = " << weight << " * dy;\n" << "\t\tvOut.z = " << weight << " * vIn.z;\n" << "\t}\n"; return ss.str(); } virtual void Random(QTIsaac& rand) override { m_Symmetry = 0; m_AugerWeight = T(0.5) + rand.Frand01() / 2; m_Freq = T(Floor(5 * rand.Frand01())) + 1; m_Scale = rand.Frand01(); } virtual void Precalc() override { m_HalfScale = m_Scale / 2; } protected: void Init() { string prefix = Prefix(); m_Params.clear(); m_Params.push_back(ParamWithName(&m_Symmetry, prefix + "auger_sym")); m_Params.push_back(ParamWithName(&m_AugerWeight, prefix + "auger_weight", T(0.5))); m_Params.push_back(ParamWithName(&m_Freq, prefix + "auger_freq", 5)); m_Params.push_back(ParamWithName(&m_Scale, prefix + "auger_scale", T(0.1))); m_Params.push_back(ParamWithName(&m_HalfScale, prefix + "auger_half_scale")); } private: T m_Symmetry; T m_AugerWeight; T m_Freq; T m_Scale; T m_HalfScale; }; /// /// Flux. /// template class FluxVariation : public ParametricVariation { public: FluxVariation(T weight = 1.0) : ParametricVariation("flux", eVariationId::VAR_FLUX, weight) { Init(); } PARVARCOPY(FluxVariation) virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { T xpw = helper.In.x + m_Weight; T xmw = helper.In.x - m_Weight; T yy = SQR(helper.In.y); T frac = std::sqrt(yy + SQR(xmw)); if (frac == 0) frac = 1; T avgr = m_Weight * (m_Spr * std::sqrt(std::sqrt(yy + SQR(xpw)) / frac)); T avga = (std::atan2(helper.In.y, xmw) - std::atan2(helper.In.y, xpw)) * T(0.5); helper.Out.x = avgr * std::cos(avga); helper.Out.y = avgr * std::sin(avga); helper.Out.z = helper.In.z;//Apo does not use weight, sums only z. Sum here for reg, else assign. } virtual string OpenCLString() const override { ostringstream ss, ss2; intmax_t i = 0; ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string weight = WeightDefineString(); string spread = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string spr = "parVars[" + ToUpper(m_Params[i++].Name()) + index; ss << "\t{\n" << "\t\treal_t xpw = vIn.x + " << weight << ";\n" << "\t\treal_t xmw = vIn.x - " << weight << ";\n" << "\t\treal_t yy = SQR(vIn.y);\n" << "\t\treal_t frac = sqrt(fma(xmw, xmw, yy));\n" << "\n" << "\t\tif (frac == (real_t)(0.0))\n" << "\t\t frac = (real_t)(1.0);\n" << "\n" << "\t\treal_t avgr = " << weight << " * (" << spr << " * sqrt(sqrt(fma(xpw, xpw, yy)) / frac));\n" << "\t\treal_t avga = (atan2(vIn.y, xmw) - atan2(vIn.y, xpw)) * (real_t)(0.5);\n" << "\n" << "\t\tvOut.x = avgr * cos(avga);\n" << "\t\tvOut.y = avgr * sin(avga);\n" << "\t\tvOut.z = vIn.z;\n" << "\t}\n"; return ss.str(); } virtual void Precalc() override { m_Spr = 2 + m_Spread; } virtual void Random(QTIsaac& rand) override { m_Spread = T(0.5) + rand.Frand01() / 2; } protected: void Init() { string prefix = Prefix(); m_Params.clear(); m_Params.push_back(ParamWithName(&m_Spread, prefix + "flux_spread"));//Params. m_Params.push_back(ParamWithName(true, &m_Spr, prefix + "flux_spr"));//Precalc. } private: T m_Spread;//Params. T m_Spr;//Precalc. }; MAKEPREPOSTVAR(Linear, linear, LINEAR) MAKEPREPOSTVAR(Sinusoidal, sinusoidal, SINUSOIDAL) MAKEPREPOSTVAR(Spherical, spherical, SPHERICAL) MAKEPREPOSTVAR(Swirl, swirl, SWIRL) MAKEPREPOSTPARVAR(Swirl3, swirl3, SWIRL3) MAKEPREPOSTPARVAR(Swirl3r, swirl3r, SWIRL3R) MAKEPREPOSTVAR(Horseshoe, horseshoe, HORSESHOE) MAKEPREPOSTVAR(Polar, polar, POLAR) MAKEPREPOSTVAR(Handkerchief, handkerchief, HANDKERCHIEF) MAKEPREPOSTVAR(Heart, heart, HEART) MAKEPREPOSTPARVAR(Disc, disc, DISC) MAKEPREPOSTVAR(Spiral, spiral, SPIRAL) MAKEPREPOSTVAR(Hyperbolic, hyperbolic, HYPERBOLIC) MAKEPREPOSTVAR(Diamond, diamond, DIAMOND) MAKEPREPOSTVAR(Ex, ex, EX) MAKEPREPOSTVAR(Julia, julia, JULIA) MAKEPREPOSTVAR(Bent, bent, BENT) MAKEPREPOSTPARVAR(Waves, waves, WAVES) MAKEPREPOSTVAR(Fisheye, fisheye, FISHEYE) MAKEPREPOSTVAR(Popcorn, popcorn, POPCORN) MAKEPREPOSTVAR(Exponential, exponential, EXPONENTIAL) MAKEPREPOSTVAR(Power, power, POWER) MAKEPREPOSTVAR(Cosine, cosine, COSINE) MAKEPREPOSTVAR(Rings, rings, RINGS) MAKEPREPOSTVAR(Fan, fan, FAN) MAKEPREPOSTPARVAR(Blob, blob, BLOB) MAKEPREPOSTPARVAR(Pdj, pdj, PDJ) MAKEPREPOSTPARVAR(Fan2, fan2, FAN2) MAKEPREPOSTPARVAR(Rings2, rings2, RINGS2) MAKEPREPOSTVAR(Eyefish, eyefish, EYEFISH) MAKEPREPOSTVAR(Bubble, bubble, BUBBLE) MAKEPREPOSTVAR(Cylinder, cylinder, CYLINDER) MAKEPREPOSTPARVAR(Perspective, perspective, PERSPECTIVE) MAKEPREPOSTVAR(Noise, noise, NOISE) MAKEPREPOSTPARVAR(JuliaNGeneric, julian, JULIAN) MAKEPREPOSTPARVAR(JuliaScope, juliascope, JULIASCOPE) MAKEPREPOSTVARASSIGN(Blur, blur, BLUR, eVariationAssignType::ASSIGNTYPE_SUM) MAKEPREPOSTVARASSIGN(GaussianBlur, gaussian_blur, GAUSSIAN_BLUR, eVariationAssignType::ASSIGNTYPE_SUM) MAKEPREPOSTVAR(Gaussian, gaussian, GAUSSIAN) MAKEPREPOSTPARVAR(RadialBlur, radial_blur, RADIAL_BLUR) //MAKEPREPOSTPARVAR(RadialGaussian, radial_gaussian, RADIAL_GAUSSIAN) MAKEPREPOSTPARVARASSIGN(Pie, pie, PIE, eVariationAssignType::ASSIGNTYPE_SUM) MAKEPREPOSTPARVAR(Ngon, ngon, NGON) MAKEPREPOSTPARVAR(Curl, curl, CURL) MAKEPREPOSTPARVAR(Rectangles, rectangles, RECTANGLES) MAKEPREPOSTVARASSIGN(Arch, arch, ARCH, eVariationAssignType::ASSIGNTYPE_SUM) MAKEPREPOSTVAR(Tangent, tangent, TANGENT) MAKEPREPOSTVARASSIGN(Square, square, SQUARE, eVariationAssignType::ASSIGNTYPE_SUM) MAKEPREPOSTVAR(Rays, rays, RAYS) MAKEPREPOSTVAR(Rays1, rays1, RAYS1) MAKEPREPOSTVAR(Rays2, rays2, RAYS2) MAKEPREPOSTVAR(Rays3, rays3, RAYS3) MAKEPREPOSTVAR(Blade, blade, BLADE) MAKEPREPOSTVAR(Secant2, secant2, SECANT2) MAKEPREPOSTVAR(TwinTrian, TwinTrian, TWINTRIAN) MAKEPREPOSTVAR(Cross, cross, CROSS) MAKEPREPOSTPARVAR(Disc2, disc2, DISC2) MAKEPREPOSTPARVAR(SuperShape, super_shape, SUPER_SHAPE) MAKEPREPOSTPARVAR(Flower, flower, FLOWER) MAKEPREPOSTPARVAR(FlowerDb, flowerdb, FLOWER_DB) MAKEPREPOSTPARVAR(Conic, conic, CONIC) MAKEPREPOSTPARVAR(Parabola, parabola, PARABOLA) MAKEPREPOSTPARVAR(Bent2, bent2, BENT2) MAKEPREPOSTPARVAR(Bipolar, bipolar, BIPOLAR) MAKEPREPOSTVAR(Boarders, boarders, BOARDERS) MAKEPREPOSTVAR(Butterfly, butterfly, BUTTERFLY) MAKEPREPOSTPARVAR(Cell, cell, CELL) MAKEPREPOSTPARVAR(Cpow, cpow, CPOW) MAKEPREPOSTPARVAR(Curve, curve, CURVE) MAKEPREPOSTVAR(Edisc, edisc, EDISC) MAKEPREPOSTPARVAR(Elliptic, elliptic, ELLIPTIC) MAKEPREPOSTPARVAR(Escher, escher, ESCHER) MAKEPREPOSTVAR(Foci, foci, FOCI) MAKEPREPOSTPARVAR(LazySusan, lazysusan, LAZYSUSAN) MAKEPREPOSTPARVAR(Loonie, loonie, LOONIE) MAKEPREPOSTPARVAR(Modulus, modulus, MODULUS) MAKEPREPOSTPARVAR(Oscilloscope, oscilloscope, OSCILLOSCOPE) MAKEPREPOSTPARVAR(Oscilloscope2, oscilloscope2, OSCILLOSCOPE2) MAKEPREPOSTPARVAR(Polar2, polar2, POLAR2) MAKEPREPOSTPARVAR(Popcorn2, popcorn2, POPCORN2) MAKEPREPOSTPARVAR(Scry, scry, SCRY) MAKEPREPOSTPARVAR(Scry2, scry2, SCRY2) MAKEPREPOSTPARVAR(Separation, separation, SEPARATION) MAKEPREPOSTPARVAR(Split, split, SPLIT) MAKEPREPOSTPARVAR(Splits, splits, SPLITS) MAKEPREPOSTPARVAR(Stripes, stripes, STRIPES) MAKEPREPOSTPARVAR(Wedge, wedge, WEDGE) MAKEPREPOSTPARVAR(WedgeJulia, wedge_julia, WEDGE_JULIA) MAKEPREPOSTPARVAR(WedgeSph, wedge_sph, WEDGE_SPH) MAKEPREPOSTPARVAR(Whorl, whorl, WHORL) MAKEPREPOSTPARVAR(Waves2, waves2, WAVES2) MAKEPREPOSTVAR(Exp, exp, EXP) MAKEPREPOSTVAR(Exp2, exp2, EXP2) MAKEPREPOSTPARVAR(Log, log, LOG) MAKEPREPOSTVAR(Sin, sin, SIN) MAKEPREPOSTVAR(Cos, cos, COS) MAKEPREPOSTVAR(Tan, tan, TAN) MAKEPREPOSTVAR(Sec, sec, SEC) MAKEPREPOSTVAR(Csc, csc, CSC) MAKEPREPOSTVAR(Cot, cot, COT) MAKEPREPOSTVAR(Sinh, sinh, SINH) MAKEPREPOSTVAR(Cosh, cosh, COSH) MAKEPREPOSTVAR(Tanh, tanh, TANH) MAKEPREPOSTPARVAR(TanhSpiral, tanh_spiral, TANH_SPIRAL) MAKEPREPOSTVAR(Sech, sech, SECH) MAKEPREPOSTVAR(Csch, csch, CSCH) MAKEPREPOSTVAR(Coth, coth, COTH) MAKEPREPOSTPARVAR(Auger, auger, AUGER) MAKEPREPOSTPARVAR(Flux, flux, FLUX) }