#pragma once #include "Variation.h" namespace EmberNs { /// /// bubble2. /// template class Bubble2Variation : public ParametricVariation { public: Bubble2Variation(T weight = 1.0) : ParametricVariation("bubble2", eVariationId::VAR_BUBBLE2, weight, true) { Init(); } PARVARCOPY(Bubble2Variation) virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { T t = Zeps(T(0.25) * (helper.m_PrecalcSumSquares + SQR(helper.In.z)) + 1); T r = m_Weight / t; helper.Out.x = helper.In.x * r * m_X; helper.Out.y = helper.In.y * r * m_Y; if (helper.In.z >= 0) helper.Out.z = m_Weight * (helper.In.z + m_Z); else helper.Out.z = m_Weight * (helper.In.z - m_Z); helper.Out.z += helper.In.z * r * m_Z;//The += is intentional. } virtual string OpenCLString() const override { ostringstream ss, ss2; intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string weight = WeightDefineString(); string x = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string y = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string z = "parVars[" + ToUpper(m_Params[i++].Name()) + index; ss << "\t{\n" << "\t\treal_t t = Zeps(fma((real_t)(0.25), fma(vIn.z, vIn.z, precalcSumSquares), (real_t)(1.0)));\n" << "\t\treal_t r = " << weight << " / t;\n" << "\n" << "\t\tvOut.x = vIn.x * r * " << x << ";\n" << "\t\tvOut.y = vIn.y * r * " << y << ";\n" << "\n" << "\t\tif (vIn.z >= 0)\n" << "\t\t vOut.z = " << weight << " * (vIn.z + " << z << ");\n" << "\t\telse\n" << "\t\t vOut.z = " << weight << " * (vIn.z - " << z << ");\n" << "\n" << "\t\tvOut.z += vIn.z * r * " << z << ";\n" << "\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_X, prefix + "bubble2_x", 1));//Original used a prefix of bubble_, which is incompatible with Ember's design. m_Params.push_back(ParamWithName(&m_Y, prefix + "bubble2_y", 1)); m_Params.push_back(ParamWithName(&m_Z, prefix + "bubble2_z")); } private: T m_X; T m_Y; T m_Z; }; /// /// CircleLinear. /// template class CircleLinearVariation : public ParametricVariation { public: CircleLinearVariation(T weight = 1.0) : ParametricVariation("CircleLinear", eVariationId::VAR_CIRCLELINEAR, weight) { Init(); } PARVARCOPY(CircleLinearVariation) virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { int m = int(Floor(T(0.5) * helper.In.x / m_Sc)); int n = int(Floor(T(0.5) * helper.In.y / m_Sc)); int m21 = m * 2 + 1; int n21 = n * 2 + 1; T x = helper.In.x - m21 * m_Sc; T y = helper.In.y - n21 * m_Sc; T u = Zeps(VarFuncs::Hypot(x, y)); T v = (T(0.3) + T(0.7) * DiscreteNoise2(m + 10, n + 3)) * m_Sc; T z1 = DiscreteNoise2(int(m + m_Seed), n); if ((z1 < m_Dens1) && (u < v)) { if (m_Reverse > 0) { if (z1 < m_Dens1 * m_Dens2) { x *= m_K; y *= m_K; } else { T z = v / u * (1 - m_K) + m_K; x *= z; y *= z; } } else { if (z1 > m_Dens1 * m_Dens2) { x *= m_K; y *= m_K; } else { T z = v / u * (1 - m_K) + m_K; x *= z; y *= z; } } } helper.Out.x = m_Weight * (x + m21 * m_Sc); helper.Out.y = m_Weight * (y + n21 * m_Sc); helper.Out.z = DefaultZ(helper); } virtual string OpenCLString() const override { ostringstream ss, ss2; intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string weight = WeightDefineString(); string sc = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string k = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string dens1 = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string dens2 = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string reverse = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string x = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string y = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string seed = "parVars[" + ToUpper(m_Params[i++].Name()) + index; ss << "\t{\n" << "\t\tint m = (int)floor((real_t)(0.5) * vIn.x / " << sc << ");\n" << "\t\tint n = (int)floor((real_t)(0.5) * vIn.y / " << sc << ");\n" << "\t\tint m21 = m * 2 + 1;\n" << "\t\tint n21 = n * 2 + 1;\n" << "\t\treal_t x = vIn.x - m21 * " << sc << ";\n" << "\t\treal_t y = vIn.y - n21 * " << sc << ";\n" << "\t\treal_t u = Zeps(Hypot(x, y));\n" << "\t\treal_t v = fma(CircleLinearDiscreteNoise2(m + 10, n + 3), (real_t)(0.7), (real_t)(0.3)) * " << sc << ";\n" << "\t\treal_t z1 = CircleLinearDiscreteNoise2((int)(m + " << seed << "), n);\n" << "\n" << "\t\tif ((z1 < " << dens1 << ") && (u < v))\n" << "\t\t{\n" << "\t\t if (" << reverse << " > 0)\n" << "\t\t {\n" << "\t\t if (z1 < " << dens1 << " * " << dens2 << ")\n" << "\t\t {\n" << "\t\t x *= " << k << ";\n" << "\t\t y *= " << k << ";\n" << "\t\t }\n" << "\t\t else\n" << "\t\t {\n" << "\t\t real_t z = fma(v / u, (1 - " << k << "), " << k << ");\n" << "\n" << "\t\t x *= z;\n" << "\t\t y *= z;\n" << "\t\t }\n" << "\t\t }\n" << "\t\t else\n" << "\t\t {\n" << "\t\t if (z1 > " << dens1 << " * " << dens2 << ")\n" << "\t\t {\n" << "\t\t x *= " << k << ";\n" << "\t\t y *= " << k << ";\n" << "\t\t }\n" << "\t\t else\n" << "\t\t {\n" << "\t\t real_t z = fma(v / u, (1 - " << k << "), " << k << ");\n" << "\n" << "\t\t x *= z;\n" << "\t\t y *= z;\n" << "\t\t }\n" << "\t\t }\n" << "\t\t}\n" << "\n" << "\t\tvOut.x = " << weight << " * fma((real_t)m21, " << sc << ", x);\n" << "\t\tvOut.y = " << weight << " * fma((real_t)n21, " << sc << ", y);\n" << "\t\tvOut.z = " << DefaultZCl() << "\t}\n"; return ss.str(); } virtual vector OpenCLGlobalFuncNames() const override { return vector { "Hypot", "Zeps" }; } virtual string OpenCLFuncsString() const override { return "real_t CircleLinearDiscreteNoise2(int x, int y)\n" "{\n" " const real_t im = 2147483647;\n" " const real_t am = 1 / im;\n" "\n" " int n = x + y * 57;\n" " n = (n << 13) ^ n;\n" " return ((n * (n * n * 15731 + 789221) + 1376312589) & 0x7fffffff) * am;\n" "}\n" "\n"; } protected: void Init() { string prefix = Prefix(); m_Params.clear(); m_Params.push_back(ParamWithName(&m_Sc, prefix + "CircleLinear_Sc", 1, eParamType::REAL_NONZERO)); m_Params.push_back(ParamWithName(&m_K, prefix + "CircleLinear_K", T(0.5))); m_Params.push_back(ParamWithName(&m_Dens1, prefix + "CircleLinear_Dens1", T(0.5))); m_Params.push_back(ParamWithName(&m_Dens2, prefix + "CircleLinear_Dens2", T(0.5))); m_Params.push_back(ParamWithName(&m_Reverse, prefix + "CircleLinear_Reverse", 1)); m_Params.push_back(ParamWithName(&m_X, prefix + "CircleLinear_X", 10)); m_Params.push_back(ParamWithName(&m_Y, prefix + "CircleLinear_Y", 10)); m_Params.push_back(ParamWithName(&m_Seed, prefix + "CircleLinear_Seed", 0, eParamType::INTEGER)); } private: T DiscreteNoise2(int x, int y) { const T im = T(2147483647); const T am = (1 / im); int n = x + y * 57; n = (n << 13) ^ n; return ((n * (n * n * 15731 + 789221) + 1376312589) & 0x7fffffff) * am; } T m_Sc; T m_K; T m_Dens1; T m_Dens2; T m_Reverse; T m_X; T m_Y; T m_Seed; }; /// /// CircleRand. /// The original would loop infinitely as x and y approached zero, so put a check for a max of 10 iters. /// template class CircleRandVariation : public ParametricVariation { public: CircleRandVariation(T weight = 1.0) : ParametricVariation("CircleRand", eVariationId::VAR_CIRCLERAND, weight) { Init(); } PARVARCOPY(CircleRandVariation) virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { intmax_t m, n, iters = 0; T x, y, u; do { x = m_X * (1 - 2 * rand.Frand01()); y = m_Y * (1 - 2 * rand.Frand01()); m = Floor(T(0.5) * x / m_Sc); n = Floor(T(0.5) * y / m_Sc); x -= (m * 2 + 1) * m_Sc; y -= (n * 2 + 1) * m_Sc; u = VarFuncs::Hypot(x, y); if (++iters > 10) break; } while ((DiscreteNoise2(int(m + m_Seed), int(n)) > m_Dens) || (u > (T(0.3) + T(0.7) * DiscreteNoise2(int(m + 10), int(n + 3))) * m_Sc)); helper.Out.x = m_Weight * (x + (m * 2 + 1) * m_Sc); helper.Out.y = m_Weight * (y + (n * 2 + 1) * m_Sc); helper.Out.z = DefaultZ(helper); } virtual string OpenCLString() const override { ostringstream ss, ss2; intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string weight = WeightDefineString(); string sc = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string dens = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string x = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string y = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string seed = "parVars[" + ToUpper(m_Params[i++].Name()) + index; ss << "\t{\n" << "\t\tint m, n, iters = 0;\n" << "\t\treal_t x, y, u;\n" << "\n" << "\t\tdo\n" << "\t\t{\n" << "\t\t x = " << x << " * (1 - 2 * MwcNext01(mwc));\n" << "\t\t y = " << y << " * (1 - 2 * MwcNext01(mwc));\n" << "\t\t m = (int)floor((real_t)(0.5) * x / " << sc << ");\n" << "\t\t n = (int)floor((real_t)(0.5) * y / " << sc << ");\n" << "\t\t x = x - (m * 2 + 1) * " << sc << ";\n" << "\t\t y = y - (n * 2 + 1) * " << sc << ";\n" << "\t\t u = Hypot(x, y);\n" << "\n" << "\t\t if (++iters > 10)\n" << "\t\t break;\n" << "\t\t}\n" << "\t\twhile ((CircleRandDiscreteNoise2((int)(m + " << seed << "), n) > " << dens << ") || (u > fma(CircleRandDiscreteNoise2(m + 10, n + 3), (real_t)(0.7), (real_t)(0.3)) * " << sc << "));\n" << "\n" << "\t\tvOut.x = " << weight << " * fma((real_t)(m * 2 + 1), " << sc << ", x);\n" << "\t\tvOut.y = " << weight << " * fma((real_t)(n * 2 + 1), " << sc << ", y);\n" << "\t\tvOut.z = " << DefaultZCl() << "\t}\n"; return ss.str(); } virtual vector OpenCLGlobalFuncNames() const override { return vector { "Hypot" }; } virtual string OpenCLFuncsString() const override { return "real_t CircleRandDiscreteNoise2(int x, int y)\n" "{\n" " const real_t im = 2147483647;\n" " const real_t am = 1 / im;\n" "\n" " int n = x + y * 57;\n" " n = (n << 13) ^ n;\n" " return ((n * (n * n * 15731 + 789221) + 1376312589) & 0x7fffffff) * am;\n" "}\n" "\n"; } protected: void Init() { string prefix = Prefix(); m_Params.clear(); m_Params.push_back(ParamWithName(&m_Sc, prefix + "CircleRand_Sc", 1, eParamType::REAL_NONZERO)); m_Params.push_back(ParamWithName(&m_Dens, prefix + "CircleRand_Dens", T(0.5))); m_Params.push_back(ParamWithName(&m_X, prefix + "CircleRand_X", 10)); m_Params.push_back(ParamWithName(&m_Y, prefix + "CircleRand_Y", 10)); m_Params.push_back(ParamWithName(&m_Seed, prefix + "CircleRand_Seed", 0, eParamType::INTEGER)); } private: T DiscreteNoise2(int x, int y) { const T im = T(2147483647); const T am = (1 / im); int n = x + y * 57; n = (n << 13) ^ n; return ((n * (n * n * 15731 + 789221) + 1376312589) & 0x7fffffff) * am; } T m_Sc; T m_Dens; T m_X; T m_Y; T m_Seed; }; /// /// CircleTrans1. /// The original would loop infinitely as x and y approached zero, so put a check for a max of 10 iters. /// template class CircleTrans1Variation : public ParametricVariation { public: CircleTrans1Variation(T weight = 1.0) : ParametricVariation("CircleTrans1", eVariationId::VAR_CIRCLETRANS1, weight) { Init(); } PARVARCOPY(CircleTrans1Variation) virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { T ux, uy, u, x, y; Trans(m_X, m_Y, helper.In.x, helper.In.y, &ux, &uy); intmax_t m = Floor(T(0.5) * ux / m_Sc); intmax_t n = Floor(T(0.5) * uy / m_Sc); x = ux - (m * 2 + 1) * m_Sc; y = uy - (n * 2 + 1) * m_Sc; u = VarFuncs::Hypot(x, y); if ((DiscreteNoise2(int(m + m_Seed), int(n)) > m_Dens) || (u > (T(0.3) + T(0.7) * DiscreteNoise2(int(m + 10), int(n + 3))) * m_Sc)) { ux = ux; uy = uy; } else { CircleR(&ux, &uy, rand); } helper.Out.x = m_Weight * ux; helper.Out.y = m_Weight * uy; helper.Out.z = DefaultZ(helper); } virtual string OpenCLString() const override { ostringstream ss, ss2; intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string weight = WeightDefineString(); string sc = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string dens = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string x = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string y = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string seed = "parVars[" + ToUpper(m_Params[i++].Name()) + index; ss << "\t{\n" << "\t\treal_t ux, uy, u, x, y;\n" << "\n" << "\t\tCircleTrans1Trans(" << x << ", " << y << ", vIn.x, vIn.y, &ux, &uy);\n" << "\n" << "\t\tint m = (int)floor((real_t)(0.5) * ux / " << sc << ");\n" << "\t\tint n = (int)floor((real_t)(0.5) * uy / " << sc << ");\n" << "\n" << "\t\tx = ux - (m * 2 + 1) * " << sc << ";\n" << "\t\ty = uy - (n * 2 + 1) * " << sc << ";\n" << "\t\tu = Hypot(x, y);\n" << "\n" << "\t\tif ((CircleTrans1DiscreteNoise2((int)(m + " << seed << "), n) > " << dens << ") || (u > fma(CircleTrans1DiscreteNoise2(m + 10, n + 3), (real_t)(0.7), (real_t)(0.3)) * " << sc << "))\n" << "\t\t{\n" << "\t\t ux = ux;\n" << "\t\t uy = uy;\n" << "\t\t}\n" << "\t\telse\n" << "\t\t{\n" << "\t\t CircleTrans1CircleR(" << x << ", " << y << ", " << sc << ", " << seed << ", " << dens << ", &ux, &uy, mwc);\n" << "\t\t}\n" << "\n" << "\t\tvOut.x = " << weight << " * ux;\n" << "\t\tvOut.y = " << weight << " * uy;\n" << "\t\tvOut.z = " << DefaultZCl() << "\t}\n"; return ss.str(); } virtual string OpenCLFuncsString() const override { return "real_t CircleTrans1DiscreteNoise2(int x, int y)\n" "{\n" " const real_t im = 2147483647;\n" " const real_t am = 1 / im;\n" "\n" " int n = x + y * 57;\n" " n = (n << 13) ^ n;\n" " return ((n * (n * n * 15731 + 789221) + 1376312589) & 0x7fffffff) * am;\n" "}\n" "\n" "void CircleTrans1Trans(real_t a, real_t b, real_t x, real_t y, real_t* x1, real_t* y1)\n" "{\n" " *x1 = fma((x - a), (real_t)(0.5), a);\n" " *y1 = fma((y - b), (real_t)(0.5), b);\n" "}\n" "\n" "void CircleTrans1CircleR(real_t mx, real_t my, real_t sc, real_t seed, real_t dens, real_t* ux, real_t* vy, uint2* mwc)\n" "{\n" " int m, n, iters = 0;\n" " real_t x, y, alpha, u;\n" "\n" " do\n" " {\n" " x = fabs(mx) * (1 - 2 * MwcNext01(mwc));\n" " y = fabs(my) * (1 - 2 * MwcNext01(mwc));\n" " m = (int)floor((real_t)(0.5) * x / sc);\n" " n = (int)floor((real_t)(0.5) * y / sc);\n" " alpha = M_2PI * MwcNext01(mwc);\n" " u = fma(CircleTrans1DiscreteNoise2(m + 10, n + 3), (real_t)(0.7), (real_t)(0.3));\n" " x = u * cos(alpha);\n" " y = u * sin(alpha);\n" "\n" " if (++iters > 10)\n" " break;\n" " }\n" " while (CircleTrans1DiscreteNoise2((int)(m + seed), n) > dens);\n" "\n" " *ux = fma((real_t)(m * 2 + 1), sc, x);\n" " *vy = fma((real_t)(n * 2 + 1), sc, y);\n" "}\n" "\n"; } virtual vector OpenCLGlobalFuncNames() const override { return vector { "Hypot" }; } virtual void Precalc() override { m_Sc = Zeps(m_Sc); } protected: void Init() { string prefix = Prefix(); m_Params.clear(); m_Params.push_back(ParamWithName(&m_Sc, prefix + "CircleTrans1_Sc", 1, eParamType::REAL_NONZERO)); m_Params.push_back(ParamWithName(&m_Dens, prefix + "CircleTrans1_Dens", T(0.5))); m_Params.push_back(ParamWithName(&m_X, prefix + "CircleTrans1_X", 10)); m_Params.push_back(ParamWithName(&m_Y, prefix + "CircleTrans1_Y", 10)); m_Params.push_back(ParamWithName(&m_Seed, prefix + "CircleTrans1_Seed", 0, eParamType::INTEGER)); } private: T DiscreteNoise2(int x, int y) { const T im = T(2147483647); const T am = (1 / im); int n = x + y * 57; n = (n << 13) ^ n; return ((n * (n * n * 15731 + 789221) + 1376312589) & 0x7fffffff) * am; } void Trans(T a, T b, T x, T y, T* x1, T* y1) { *x1 = (x - a) * T(0.5) + a; *y1 = (y - b) * T(0.5) + b; } void CircleR(T* ux, T* vy, QTIsaac& rand) { intmax_t m, n, iters = 0; T x, y, alpha, u; do { x = std::abs(m_X) * (1 - 2 * rand.Frand01()); y = std::abs(m_Y) * (1 - 2 * rand.Frand01()); m = Floor(T(0.5) * x / m_Sc); n = Floor(T(0.5) * y / m_Sc); alpha = M_2PI * rand.Frand01(); u = T(0.3) + T(0.7) * DiscreteNoise2(int(m + 10), int(n + 3)); x = u * std::cos(alpha); y = u * std::sin(alpha); if (++iters > 10) break; } while (DiscreteNoise2(int(m + m_Seed), int(n)) > m_Dens); *ux = x + (m * 2 + 1) * m_Sc; *vy = y + (n * 2 + 1) * m_Sc; } T m_Sc; T m_Dens; T m_X; T m_Y; T m_Seed; }; /// /// cubic3D. /// template class Cubic3DVariation : public ParametricVariation { public: Cubic3DVariation(T weight = 1.0) : ParametricVariation("cubic3D", eVariationId::VAR_CUBIC3D, weight) { Init(); } PARVARCOPY(Cubic3DVariation) virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { int useNode = rand.Rand() & 7;//Faster than % 8. T exnze, wynze, znxy; T lattd = m_Weight * T(0.5); T px, py, pz; exnze = 1 - (m_SmoothStyle * (1 - (std::cos(std::atan2(helper.In.x, helper.In.z))))); wynze = 1 - (m_SmoothStyle * (1 - (std::sin(std::atan2(helper.In.y, helper.In.z))))); if (m_SmoothStyle > 1) znxy = 1 - (m_SmoothStyle * (1 - ((exnze + wynze) / 2 * m_SmoothStyle))); else znxy = 1 - (m_SmoothStyle * (1 - ((exnze + wynze) * T(0.5)))); if (m_VarType == eVariationType::VARTYPE_PRE) { px = helper.In.x; py = helper.In.y; pz = helper.In.z; } else { px = outPoint.m_X; py = outPoint.m_Y; pz = outPoint.m_Z; } switch (useNode) { case 0: helper.Out.x = ((px - (m_Smooth * (1 - m_Fill) * px * exnze)) + (helper.In.x * m_Smooth * m_Fill * exnze)) + lattd; helper.Out.y = ((py - (m_Smooth * (1 - m_Fill) * py * wynze)) + (helper.In.y * m_Smooth * m_Fill * wynze)) + lattd; helper.Out.z = ((pz - (m_Smooth * (1 - m_Fill) * pz * znxy)) + (helper.In.z * m_Smooth * m_Fill * znxy)) + lattd; break; case 1: helper.Out.x = ((px - (m_Smooth * (1 - m_Fill) * px * exnze)) + (helper.In.x * m_Smooth * m_Fill * exnze)) + lattd; helper.Out.y = ((py - (m_Smooth * (1 - m_Fill) * py * wynze)) + (helper.In.y * m_Smooth * m_Fill * wynze)) - lattd; helper.Out.z = ((pz - (m_Smooth * (1 - m_Fill) * pz * znxy)) + (helper.In.z * m_Smooth * m_Fill * znxy)) + lattd; break; case 2: helper.Out.x = ((px - (m_Smooth * (1 - m_Fill) * px * exnze)) + (helper.In.x * m_Smooth * m_Fill * exnze)) + lattd; helper.Out.y = ((py - (m_Smooth * (1 - m_Fill) * py * wynze)) + (helper.In.y * m_Smooth * m_Fill * wynze)) + lattd; helper.Out.z = ((pz - (m_Smooth * (1 - m_Fill) * pz * znxy)) + (helper.In.z * m_Smooth * m_Fill * znxy)) - lattd; break; case 3: helper.Out.x = ((px - (m_Smooth * (1 - m_Fill) * px * exnze)) + (helper.In.x * m_Smooth * m_Fill * exnze)) + lattd; helper.Out.y = ((py - (m_Smooth * (1 - m_Fill) * py * wynze)) + (helper.In.y * m_Smooth * m_Fill * wynze)) - lattd; helper.Out.z = ((pz - (m_Smooth * (1 - m_Fill) * pz * znxy)) + (helper.In.z * m_Smooth * m_Fill * znxy)) - lattd; break; case 4: helper.Out.x = ((px - (m_Smooth * (1 - m_Fill) * px * exnze)) + (helper.In.x * m_Smooth * m_Fill * exnze)) - lattd; helper.Out.y = ((py - (m_Smooth * (1 - m_Fill) * py * wynze)) + (helper.In.y * m_Smooth * m_Fill * wynze)) + lattd; helper.Out.z = ((pz - (m_Smooth * (1 - m_Fill) * pz * znxy)) + (helper.In.z * m_Smooth * m_Fill * znxy)) + lattd; break; case 5: helper.Out.x = ((px - (m_Smooth * (1 - m_Fill) * px * exnze)) + (helper.In.x * m_Smooth * m_Fill * exnze)) - lattd; helper.Out.y = ((py - (m_Smooth * (1 - m_Fill) * py * wynze)) + (helper.In.y * m_Smooth * m_Fill * wynze)) - lattd; helper.Out.z = ((pz - (m_Smooth * (1 - m_Fill) * pz * znxy)) + (helper.In.z * m_Smooth * m_Fill * znxy)) + lattd; break; case 6: helper.Out.x = ((px - (m_Smooth * (1 - m_Fill) * px * exnze)) + (helper.In.x * m_Smooth * m_Fill * exnze)) - lattd; helper.Out.y = ((py - (m_Smooth * (1 - m_Fill) * py * wynze)) + (helper.In.y * m_Smooth * m_Fill * wynze)) + lattd; helper.Out.z = ((pz - (m_Smooth * (1 - m_Fill) * pz * znxy)) + (helper.In.z * m_Smooth * m_Fill * znxy)) - lattd; break; case 7: default: helper.Out.x = ((px - (m_Smooth * (1 - m_Fill) * px * exnze)) + (helper.In.x * m_Smooth * m_Fill * exnze)) - lattd; helper.Out.y = ((py - (m_Smooth * (1 - m_Fill) * py * wynze)) + (helper.In.y * m_Smooth * m_Fill * wynze)) - lattd; helper.Out.z = ((pz - (m_Smooth * (1 - m_Fill) * pz * znxy)) + (helper.In.z * m_Smooth * m_Fill * znxy)) - lattd; break; } } virtual string OpenCLString() const override { ostringstream ss, ss2; intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string weight = WeightDefineString(); string xpand = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string style = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string fill = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string smooth = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string smoothStyle = "parVars[" + ToUpper(m_Params[i++].Name()) + index; ss << "\t{\n" << "\t\tint useNode = MwcNext(mwc) & 7;\n" << "\t\treal_t exnze, wynze, znxy;\n" << "\t\treal_t lattd = " << weight << " * (real_t)(0.5);\n" << "\t\treal_t px, py, pz;\n" << "\n" << "\t\texnze = 1 - (" << smoothStyle << " * (1 - (cos(atan2(vIn.x, vIn.z)))));\n" << "\t\twynze = 1 - (" << smoothStyle << " * (1 - (sin(atan2(vIn.y, vIn.z)))));\n" << "\n" << "\t\tif (" << smoothStyle << " > 1)\n" << "\t\t znxy = 1 - (" << smoothStyle << " * (1 - ((exnze + wynze) / 2 * " << smoothStyle << ")));\n" << "\t\telse\n" << "\t\t znxy = 1 - (" << smoothStyle << " * (1 - ((exnze + wynze) * (real_t)(0.5))));\n"; if (m_VarType == eVariationType::VARTYPE_PRE) { ss << "\t\tpx = vIn.x;\n" "\t\tpy = vIn.y;\n" "\t\tpz = vIn.z;\n"; } else { ss << "\t\tpx = outPoint->m_X;\n" "\t\tpy = outPoint->m_Y;\n" "\t\tpz = outPoint->m_Z;\n"; } ss << "\t\tswitch (useNode)\n" "\t\t{\n" "\t\t case 0 :\n" "\t\t vOut.x = ((px - (" << smooth << " * (1 - " << fill << ") * px * exnze)) + (vIn.x * " << smooth << " * " << fill << " * exnze)) + lattd;\n" "\t\t vOut.y = ((py - (" << smooth << " * (1 - " << fill << ") * py * wynze)) + (vIn.y * " << smooth << " * " << fill << " * wynze)) + lattd;\n" "\t\t vOut.z = ((pz - (" << smooth << " * (1 - " << fill << ") * pz * znxy)) + (vIn.z * " << smooth << " * " << fill << " * znxy)) + lattd;\n" "\t\t break;\n" "\t\t case 1 :\n" "\t\t vOut.x = ((px - (" << smooth << " *(1 - " << fill << ") * px * exnze)) + (vIn.x * " << smooth << " * " << fill << " * exnze)) + lattd;\n" "\t\t vOut.y = ((py - (" << smooth << " *(1 - " << fill << ") * py * wynze)) + (vIn.y * " << smooth << " * " << fill << " * wynze)) - lattd;\n" "\t\t vOut.z = ((pz - (" << smooth << " *(1 - " << fill << ") * pz * znxy)) + (vIn.z * " << smooth << " * " << fill << " * znxy)) + lattd;\n" "\t\t break;\n" "\t\t case 2 :\n" "\t\t vOut.x = ((px - (" << smooth << " * (1 - " << fill << ") * px * exnze)) + (vIn.x * " << smooth << " * " << fill << " * exnze)) + lattd;\n" "\t\t vOut.y = ((py - (" << smooth << " * (1 - " << fill << ") * py * wynze)) + (vIn.y * " << smooth << " * " << fill << " * wynze)) + lattd;\n" "\t\t vOut.z = ((pz - (" << smooth << " * (1 - " << fill << ") * pz * znxy)) + (vIn.z * " << smooth << " * " << fill << " * znxy)) - lattd;\n" "\t\t break;\n" "\t\t case 3 :\n" "\t\t vOut.x = ((px - (" << smooth << " * (1 - " << fill << ") * px * exnze)) + (vIn.x * " << smooth << " * " << fill << " * exnze)) + lattd;\n" "\t\t vOut.y = ((py - (" << smooth << " * (1 - " << fill << ") * py * wynze)) + (vIn.y * " << smooth << " * " << fill << " * wynze)) - lattd;\n" "\t\t vOut.z = ((pz - (" << smooth << " * (1 - " << fill << ") * pz * znxy)) + (vIn.z * " << smooth << " * " << fill << " * znxy)) - lattd;\n" "\t\t break;\n" "\t\t case 4 :\n" "\t\t vOut.x = ((px - (" << smooth << " * (1 - " << fill << ") * px * exnze)) + (vIn.x * " << smooth << " * " << fill << " * exnze)) - lattd;\n" "\t\t vOut.y = ((py - (" << smooth << " * (1 - " << fill << ") * py * wynze)) + (vIn.y * " << smooth << " * " << fill << " * wynze)) + lattd;\n" "\t\t vOut.z = ((pz - (" << smooth << " * (1 - " << fill << ") * pz * znxy)) + (vIn.z * " << smooth << " * " << fill << " * znxy)) + lattd;\n" "\t\t break;\n" "\t\t case 5 :\n" "\t\t vOut.x = ((px - (" << smooth << " * (1 - " << fill << ") * px * exnze)) + (vIn.x * " << smooth << " * " << fill << " * exnze)) - lattd;\n" "\t\t vOut.y = ((py - (" << smooth << " * (1 - " << fill << ") * py * wynze)) + (vIn.y * " << smooth << " * " << fill << " * wynze)) - lattd;\n" "\t\t vOut.z = ((pz - (" << smooth << " * (1 - " << fill << ") * pz * znxy)) + (vIn.z * " << smooth << " * " << fill << " * znxy)) + lattd;\n" "\t\t break;\n" "\t\t case 6 :\n" "\t\t vOut.x = ((px - (" << smooth << " * (1 - " << fill << ") * px * exnze)) + (vIn.x * " << smooth << " * " << fill << " * exnze)) - lattd;\n" "\t\t vOut.y = ((py - (" << smooth << " * (1 - " << fill << ") * py * wynze)) + (vIn.y * " << smooth << " * " << fill << " * wynze)) + lattd;\n" "\t\t vOut.z = ((pz - (" << smooth << " * (1 - " << fill << ") * pz * znxy)) + (vIn.z * " << smooth << " * " << fill << " * znxy)) - lattd;\n" "\t\t break;\n" "\t\t case 7 :\n" "\t\t vOut.x = ((px - (" << smooth << " * (1 - " << fill << ") * px * exnze)) + (vIn.x * " << smooth << " * " << fill << " * exnze)) - lattd;\n" "\t\t vOut.y = ((py - (" << smooth << " * (1 - " << fill << ") * py * wynze)) + (vIn.y * " << smooth << " * " << fill << " * wynze)) - lattd;\n" "\t\t vOut.z = ((pz - (" << smooth << " * (1 - " << fill << ") * pz * znxy)) + (vIn.z * " << smooth << " * " << fill << " * znxy)) - lattd;\n" "\t\t break;\n" "\t\t}\n" "\t}\n"; return ss.str(); } virtual void Precalc() override { if (std::abs(m_Xpand) <= 1) m_Fill = m_Xpand * T(0.5); else m_Fill = std::sqrt(m_Xpand) * T(0.5); if (std::abs(m_Weight) <= T(0.5)) m_Smooth = m_Weight * 2;//Causes full effect above m_Weight = 0.5. else m_Smooth = 1; if (std::abs(m_Style) <= 1) { m_SmoothStyle = m_Style; } else { if (m_Style > 1) m_SmoothStyle = 1 + (m_Style - 1) * T(0.25); else m_SmoothStyle = (m_Style + 1) * T(0.25) - 1; } } protected: void Init() { string prefix = Prefix(); m_Params.clear(); m_Params.push_back(ParamWithName(&m_Xpand, prefix + "cubic3D_xpand", T(0.25))); m_Params.push_back(ParamWithName(&m_Style, prefix + "cubic3D_style")); m_Params.push_back(ParamWithName(true, &m_Fill, prefix + "cubic3D_fill"));//Precalc. m_Params.push_back(ParamWithName(true, &m_Smooth, prefix + "cubic3D_smooth")); m_Params.push_back(ParamWithName(true, &m_SmoothStyle, prefix + "cubic3D_smooth_style")); } private: T m_Xpand; T m_Style; T m_Fill;//Precalc. T m_Smooth; T m_SmoothStyle; }; /// /// cubicLattice_3D. /// template class CubicLattice3DVariation : public ParametricVariation { public: CubicLattice3DVariation(T weight = 1.0) : ParametricVariation("cubicLattice_3D", eVariationId::VAR_CUBIC_LATTICE3D, weight) { Init(); } PARVARCOPY(CubicLattice3DVariation) virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { int useNode = rand.Rand() & 7;//Faster than % 8. T exnze, wynze, znxy, px, py, pz, lattd = m_Weight; if (m_Style == 2) { exnze = std::cos(std::atan2(helper.In.x, helper.In.z)); wynze = std::sin(std::atan2(helper.In.y, helper.In.z)); znxy = (exnze + wynze) * T(0.5); } else { exnze = 1; wynze = 1; znxy = 1; } if (m_VarType == eVariationType::VARTYPE_PRE) { px = helper.In.x; py = helper.In.y; pz = helper.In.z; } else { px = outPoint.m_X; py = outPoint.m_Y; pz = outPoint.m_Z; } T pxtx = px + helper.In.x; T pyty = py + helper.In.y; T pztz = pz + helper.In.z; switch (useNode) { case 0: helper.Out.x = pxtx * m_Fill * exnze + lattd; helper.Out.y = pyty * m_Fill * wynze + lattd; helper.Out.z = pztz * m_Fill * znxy + lattd; break; case 1: helper.Out.x = pxtx * m_Fill * exnze + lattd; helper.Out.y = pyty * m_Fill * wynze - lattd; helper.Out.z = pztz * m_Fill * znxy + lattd; break; case 2: helper.Out.x = pxtx * m_Fill * exnze + lattd; helper.Out.y = pyty * m_Fill * wynze + lattd; helper.Out.z = pztz * m_Fill * znxy - lattd; break; case 3: helper.Out.x = pxtx * m_Fill * exnze + lattd; helper.Out.y = pyty * m_Fill * wynze - lattd; helper.Out.z = pztz * m_Fill * znxy - lattd; break; case 4: helper.Out.x = pxtx * m_Fill * exnze - lattd; helper.Out.y = pyty * m_Fill * wynze + lattd; helper.Out.z = pztz * m_Fill * znxy + lattd; break; case 5: helper.Out.x = pxtx * m_Fill * exnze - lattd; helper.Out.y = pyty * m_Fill * wynze - lattd; helper.Out.z = pztz * m_Fill * znxy + lattd; break; case 6: helper.Out.x = pxtx * m_Fill * exnze - lattd; helper.Out.y = pyty * m_Fill * wynze + lattd; helper.Out.z = pztz * m_Fill * znxy - lattd; break; case 7: default: helper.Out.x = pxtx * m_Fill * exnze - lattd; helper.Out.y = pyty * m_Fill * wynze - lattd; helper.Out.z = pztz * m_Fill * znxy - lattd; break; } } virtual string OpenCLString() const override { ostringstream ss, ss2; intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string weight = WeightDefineString(); string xpand = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string style = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string fill = "parVars[" + ToUpper(m_Params[i++].Name()) + index; ss << "\t{\n" << "\t\tint useNode = MwcNext(mwc) & 7;\n" << "\t\treal_t exnze, wynze, znxy, px, py, pz, lattd = " << weight << ";\n" << "\n" << "\t\tif (" << style << " == 2)\n" << "\t\t{\n" << "\t\t exnze = cos(atan2(vIn.x, vIn.z));\n" << "\t\t wynze = sin(atan2(vIn.y, vIn.z));\n" << "\t\t znxy = (exnze + wynze) * (real_t)(0.5);\n" << "\t\t}\n" << "\t\telse\n" << "\t\t{\n" << "\t\t exnze = 1;\n" << "\t\t wynze = 1;\n" << "\t\t znxy = 1;\n" << "\t\t}\n"; if (m_VarType == eVariationType::VARTYPE_PRE) { ss << "\t\tpx = vIn.x;\n" "\t\tpy = vIn.y;\n" "\t\tpz = vIn.z;\n"; } else { ss << "\t\tpx = outPoint->m_X;\n" "\t\tpy = outPoint->m_Y;\n" "\t\tpz = outPoint->m_Z;\n"; } ss << "\t\treal_t pxtx = px + vIn.x;\n" << "\t\treal_t pyty = py + vIn.y;\n" << "\t\treal_t pztz = pz + vIn.z;\n" << "\n" << "\t\tswitch (useNode)\n" << "\t\t{\n" << "\t\t case 0 :\n" << "\t\t vOut.x = fma(pxtx, " << fill << " * exnze, lattd);\n" << "\t\t vOut.y = fma(pyty, " << fill << " * wynze, lattd);\n" << "\t\t vOut.z = fma(pztz, " << fill << " * znxy , lattd);\n" << "\t\t break;\n" << "\t\t case 1 :\n" << "\t\t vOut.x = fma(pxtx, " << fill << " * exnze, lattd);\n" << "\t\t vOut.y = fma(pyty, " << fill << " * wynze, -lattd);\n" << "\t\t vOut.z = fma(pztz, " << fill << " * znxy, lattd);\n" << "\t\t break;\n" << "\t\t case 2 :\n" << "\t\t vOut.x = fma(pxtx, " << fill << " * exnze, lattd);\n" << "\t\t vOut.y = fma(pyty, " << fill << " * wynze, lattd);\n" << "\t\t vOut.z = fma(pztz, " << fill << " * znxy, -lattd);\n" << "\t\t break;\n" << "\t\t case 3 :\n" << "\t\t vOut.x = fma(pxtx, " << fill << " * exnze, lattd);\n" << "\t\t vOut.y = fma(pyty, " << fill << " * wynze, -lattd);\n" << "\t\t vOut.z = fma(pztz, " << fill << " * znxy, -lattd);\n" << "\t\t break;\n" << "\t\t case 4 :\n" << "\t\t vOut.x = fma(pxtx, " << fill << " * exnze, -lattd);\n" << "\t\t vOut.y = fma(pyty, " << fill << " * wynze, lattd);\n" << "\t\t vOut.z = fma(pztz, " << fill << " * znxy, lattd);\n" << "\t\t break;\n" << "\t\t case 5 :\n" << "\t\t vOut.x = fma(pxtx, " << fill << " * exnze, -lattd);\n" << "\t\t vOut.y = fma(pyty, " << fill << " * wynze, -lattd);\n" << "\t\t vOut.z = fma(pztz, " << fill << " * znxy, lattd);\n" << "\t\t break;\n" << "\t\t case 6 :\n" << "\t\t vOut.x = fma(pxtx, " << fill << " * exnze, -lattd);\n" << "\t\t vOut.y = fma(pyty, " << fill << " * wynze, lattd);\n" << "\t\t vOut.z = fma(pztz, " << fill << " * znxy, -lattd);\n" << "\t\t break;\n" << "\t\t case 7 :\n" << "\t\t vOut.x = fma(pxtx, " << fill << " * exnze, -lattd);\n" << "\t\t vOut.y = fma(pyty, " << fill << " * wynze, -lattd);\n" << "\t\t vOut.z = fma(pztz, " << fill << " * znxy, -lattd);\n" << "\t\t break;\n" << "\t\t}\n" << "\t}\n"; return ss.str(); } virtual void Precalc() override { if (std::abs(m_Xpand) <= 1) m_Fill = m_Xpand * T(0.5); else m_Fill = std::sqrt(m_Xpand) * T(0.5); } protected: void Init() { string prefix = Prefix(); m_Params.clear(); m_Params.push_back(ParamWithName(&m_Xpand, prefix + "cubicLattice_3D_xpand", T(0.2)));//Original used a prefix of cubic3D_, which is incompatible with Ember's design. m_Params.push_back(ParamWithName(&m_Style, prefix + "cubicLattice_3D_style", 1, eParamType::INTEGER, 1, 2)); m_Params.push_back(ParamWithName(true, &m_Fill, prefix + "cubicLattice_3D_fill"));//Precalc. } private: T m_Xpand; T m_Style; T m_Fill;//Precalc. }; /// /// foci_3D. /// template class Foci3DVariation : public Variation { public: Foci3DVariation(T weight = 1.0) : Variation("foci_3D", eVariationId::VAR_FOCI3D, weight, false, false, false, false, true) { } VARCOPY(Foci3DVariation) virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { T expx = std::exp(helper.In.x) * T(0.5); T expnx = T(0.25) / expx; T boot = helper.In.z == 0 ? helper.m_PrecalcAtanyx : helper.In.z; T tmp = m_Weight / Zeps(expx + expnx - (std::cos(helper.In.y) * std::cos(boot))); helper.Out.x = (expx - expnx) * tmp; helper.Out.y = std::sin(helper.In.y) * tmp; helper.Out.z = std::sin(boot) * tmp; } virtual string OpenCLString() const override { ostringstream ss; intmax_t varIndex = IndexInXform(); 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) / expx;\n" << "\t\treal_t boot = vIn.z == 0 ? precalcAtanyx : vIn.z;\n" << "\t\treal_t tmp = " << weight << " / Zeps(expx + expnx - (cos(vIn.y) * cos(boot)));\n" << "\n" << "\t\tvOut.x = (expx - expnx) * tmp;\n" << "\t\tvOut.y = sin(vIn.y) * tmp;\n" << "\t\tvOut.z = sin(boot) * tmp;\n" << "\t}\n"; return ss.str(); } virtual vector OpenCLGlobalFuncNames() const override { return vector { "Zeps" }; } }; /// /// foci_p. /// Idea by Chaosfissure. /// template class FociPVariation : public ParametricVariation { public: FociPVariation(T weight = 1.0) : ParametricVariation("foci_p", eVariationId::VAR_FOCI_P, weight) { Init(); } PARVARCOPY(FociPVariation) virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { T exp_x = Zeps(std::exp(helper.In.x)); T exp_x_2 = exp_x * m_C1; T exp_nz = m_C2 / exp_x; T cos_y = std::cos(helper.In.y); T sin_y = std::sin(helper.In.y); T r = m_Weight / Zeps(exp_x_2 + exp_nz - cos_y); helper.Out.x = (exp_x_2 - exp_nz) * r; helper.Out.y = sin_y * r; helper.Out.z = DefaultZ(helper); } virtual string OpenCLString() const override { ostringstream ss, ss2; intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string weight = WeightDefineString(); string c1 = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string c2 = "parVars[" + ToUpper(m_Params[i++].Name()) + index; ss << "\t{\n" << "\t\treal_t exp_x = Zeps(exp(vIn.x));\n" << "\t\treal_t exp_x_2 = exp_x * " << c1 << ";\n" << "\t\treal_t exp_nz = " << c2 << " / exp_x;\n" << "\t\treal_t cos_y = cos(vIn.y);\n" << "\t\treal_t sin_y = sin(vIn.y);\n" << "\t\treal_t r = " << weight << " / Zeps(exp_x_2 + exp_nz - cos_y);\n" << "\n" << "\t\tvOut.x = (exp_x_2 - exp_nz) * r;\n" << "\t\tvOut.y = sin_y * r;\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_C1, prefix + "foci_p_c1", T(0.5))); m_Params.push_back(ParamWithName(&m_C2, prefix + "foci_p_c2", T(0.5))); } private: T m_C1; T m_C2; }; /// /// ho. /// template class HoVariation : public ParametricVariation { public: HoVariation(T weight = 1.0) : ParametricVariation("ho", eVariationId::VAR_HO, weight) { Init(); } PARVARCOPY(HoVariation) virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { T uu = SQR(helper.In.x); T vv = SQR(helper.In.y); T ww = SQR(helper.In.z); T atOmegaX = std::atan2(vv, ww); T atOmegaY = std::atan2(uu, ww); T su = std::sin(helper.In.x); T cu = std::cos(helper.In.x); T sv = std::sin(helper.In.y); T cv = std::cos(helper.In.y); T cucv = cu * cv; T sucv = su * cv; T x = std::pow(std::abs(cucv), m_XPow) + (cucv * m_XPow) + (T(0.25) * atOmegaX);//Must fabs first argument to pow, because negative values will return NaN. T y = std::pow(std::abs(sucv), m_YPow) + (sucv * m_YPow) + (T(0.25) * atOmegaY);//Original did not do this and would frequently return bad values. T z = std::pow(std::abs(sv), m_ZPow) + sv * m_ZPow; helper.Out.x = m_Weight * x; helper.Out.y = m_Weight * y; helper.Out.z = m_Weight * z; } virtual string OpenCLString() const override { ostringstream ss, ss2; intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string weight = WeightDefineString(); string xpow = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string ypow = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string zpow = "parVars[" + ToUpper(m_Params[i++].Name()) + index; ss << "\t{\n" << "\t\treal_t uu = SQR(vIn.x);\n" << "\t\treal_t vv = SQR(vIn.y);\n" << "\t\treal_t ww = SQR(vIn.z);\n" << "\t\treal_t atOmegaX = atan2(vv, ww);\n" << "\t\treal_t atOmegaY = atan2(uu, ww);\n" << "\t\treal_t su = sin(vIn.x);\n" << "\t\treal_t cu = cos(vIn.x);\n" << "\t\treal_t sv = sin(vIn.y);\n" << "\t\treal_t cv = cos(vIn.y);\n" << "\t\treal_t cucv = cu * cv;\n" << "\t\treal_t sucv = su * cv;\n" << "\t\treal_t x = pow(fabs(cucv), " << xpow << ") + fma(cucv, " << xpow << ", (real_t)(0.25) * atOmegaX);\n" << "\t\treal_t y = pow(fabs(sucv), " << ypow << ") + fma(sucv, " << ypow << ", (real_t)(0.25) * atOmegaY);\n" << "\t\treal_t z = fma(sv, " << zpow << ", pow(fabs(sv), " << zpow << "));\n" << "\n" << "\t\tvOut.x = " << weight << " * x;\n" << "\t\tvOut.y = " << weight << " * y;\n" << "\t\tvOut.z = " << weight << " * z;\n" << "\t}\n"; return ss.str(); } protected: void Init() { string prefix = Prefix(); m_Params.clear(); m_Params.push_back(ParamWithName(&m_XPow, prefix + "ho_xpow", 3)); m_Params.push_back(ParamWithName(&m_YPow, prefix + "ho_ypow", 3)); m_Params.push_back(ParamWithName(&m_ZPow, prefix + "ho_zpow", 3)); } private: T m_XPow; T m_YPow; T m_ZPow; }; /// /// Julia3Dq. /// template class Julia3DqVariation : public ParametricVariation { public: Julia3DqVariation(T weight = 1.0) : ParametricVariation("julia3Dq", eVariationId::VAR_JULIA3DQ, weight, true, true, false, false, true) { Init(); } PARVARCOPY(Julia3DqVariation) virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { T temp = helper.m_PrecalcAtanyx * m_InvPower + rand.Rand() * m_InvPower2pi; T sina = std::sin(temp); T cosa = std::cos(temp); T z = helper.In.z * m_AbsInvPower; T r2d = helper.m_PrecalcSumSquares; T r = m_Weight * std::pow(r2d + SQR(z), m_HalfInvPower); T rsss = r * helper.m_PrecalcSqrtSumSquares; helper.Out.x = rsss * cosa; helper.Out.y = rsss * sina; helper.Out.z = r * z; } virtual string OpenCLString() const override { ostringstream ss, ss2; intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string weight = WeightDefineString(); string power = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string divisor = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string invPower = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string absInvPower = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string halfInvPower = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string invPower2pi = "parVars[" + ToUpper(m_Params[i++].Name()) + index; ss << "\t{\n" << "\t\treal_t temp = fma(precalcAtanyx, " << invPower << ", MwcNext(mwc) * " << invPower2pi << ");\n" << "\t\treal_t sina = sin(temp);\n" << "\t\treal_t cosa = cos(temp);\n" << "\t\treal_t z = vIn.z * " << absInvPower << ";\n" << "\t\treal_t r2d = precalcSumSquares;\n" << "\t\treal_t r = " << weight << " * pow(fma(z, z, r2d), " << halfInvPower << ");\n" << "\t\treal_t rsss = r * precalcSqrtSumSquares;\n" << "\n" << "\t\tvOut.x = rsss * cosa;\n" << "\t\tvOut.y = rsss * sina;\n" << "\t\tvOut.z = r * z;\n" << "\t}\n"; return ss.str(); } virtual void Precalc() override { m_InvPower = m_Divisor / m_Power; m_AbsInvPower = std::abs(m_InvPower); m_HalfInvPower = T(0.5) * m_InvPower - T(0.5); m_InvPower2pi = M_2PI / m_Power; } protected: void Init() { string prefix = Prefix(); m_Params.clear(); m_Params.push_back(ParamWithName(&m_Power, prefix + "julia3Dq_power", 3, eParamType::INTEGER_NONZERO)); m_Params.push_back(ParamWithName(&m_Divisor, prefix + "julia3Dq_divisor", 2, eParamType::INTEGER_NONZERO)); m_Params.push_back(ParamWithName(true, &m_InvPower, prefix + "julia3Dq_inv_power"));//Precalc. m_Params.push_back(ParamWithName(true, &m_AbsInvPower, prefix + "julia3Dq_abs_inv_power")); m_Params.push_back(ParamWithName(true, &m_HalfInvPower, prefix + "julia3Dq_half_inv_power")); m_Params.push_back(ParamWithName(true, &m_InvPower2pi, prefix + "julia3Dq_inv_power_2pi")); } private: T m_Power; T m_Divisor; T m_InvPower;//Precalc. T m_AbsInvPower; T m_HalfInvPower; T m_InvPower2pi; }; /// /// line. /// template class LineVariation : public ParametricVariation { public: LineVariation(T weight = 1.0) : ParametricVariation("line", eVariationId::VAR_LINE, weight) { Init(); } PARVARCOPY(LineVariation) virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { T r = rand.Frand01() * m_Weight; helper.Out.x = m_Ux * r; helper.Out.y = m_Uy * r; helper.Out.z = m_Uz * r; } virtual string OpenCLString() const override { ostringstream ss, ss2; intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string weight = WeightDefineString(); string delta = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string phi = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string ux = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string uy = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string uz = "parVars[" + ToUpper(m_Params[i++].Name()) + index; ss << "\t{\n" << "\t\treal_t r = MwcNext01(mwc) * " << weight << ";\n" << "\n" << "\t\tvOut.x = " << ux << " * r;\n" << "\t\tvOut.y = " << uy << " * r;\n" << "\t\tvOut.z = " << uz << " * r;\n" << "\t}\n"; return ss.str(); } virtual void Precalc() override { //Unit vector of the line. m_Ux = std::cos(m_Delta * T(M_PI)) * std::cos(m_Phi * T(M_PI)); m_Uy = std::sin(m_Delta * T(M_PI)) * std::cos(m_Phi * T(M_PI)); m_Uz = std::sin(m_Phi * T(M_PI)); T r = std::sqrt(SQR(m_Ux) + SQR(m_Uy) + SQR(m_Uz)); //Normalize. m_Ux /= r; m_Uy /= r; m_Uz /= r; } protected: void Init() { string prefix = Prefix(); m_Params.clear(); m_Params.push_back(ParamWithName(&m_Delta, prefix + "line_delta")); m_Params.push_back(ParamWithName(&m_Phi, prefix + "line_phi")); m_Params.push_back(ParamWithName(true, &m_Ux, prefix + "line_ux"));//Precalc. m_Params.push_back(ParamWithName(true, &m_Uy, prefix + "line_uy")); m_Params.push_back(ParamWithName(true, &m_Uz, prefix + "line_uz")); } private: T m_Delta; T m_Phi; T m_Ux;//Precalc. T m_Uy; T m_Uz; }; /// /// Loonie2. /// template class Loonie2Variation : public ParametricVariation { public: Loonie2Variation(T weight = 1.0) : ParametricVariation("loonie2", eVariationId::VAR_LOONIE2, weight, true, true) { Init(); } PARVARCOPY(Loonie2Variation) virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { int i; T xrt = helper.In.x, yrt = helper.In.y, swp; T r2 = xrt * m_Coss + std::abs(yrt) * m_Sins; T circle = helper.m_PrecalcSqrtSumSquares; for (i = 0; i < m_Sides - 1; i++) { swp = xrt * m_Cosa - yrt * m_Sina; yrt = xrt * m_Sina + yrt * m_Cosa; xrt = swp; r2 = std::max(r2, xrt * m_Coss + std::abs(yrt) * m_Sins); } r2 = r2 * m_Cosc + circle * m_Sinc; if (i > 1) r2 = SQR(r2); else r2 = std::abs(r2) * r2; if (r2 > 0 && (r2 < m_W2)) { T r = m_Weight * std::sqrt(std::abs(m_W2 / r2 - 1)); helper.Out.x = r * helper.In.x; helper.Out.y = r * helper.In.y; } else if (r2 < 0) { T r = m_Weight / std::sqrt(std::abs(m_W2 / r2) - 1); helper.Out.x = r * helper.In.x; helper.Out.y = r * helper.In.y; } else { helper.Out.x = m_Weight * helper.In.x; helper.Out.y = m_Weight * helper.In.y; } helper.Out.z = DefaultZ(helper); } virtual string OpenCLString() const override { ostringstream ss, ss2; intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string weight = WeightDefineString(); string index = ss2.str(); string sides = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string star = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string circle = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string w2 = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string sina = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string cosa = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string sins = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string coss = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string sinc = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string cosc = "parVars[" + ToUpper(m_Params[i++].Name()) + index; ss << "\t{\n" << "\t\tint i;\n" << "\t\treal_t xrt = vIn.x, yrt = vIn.y, swp;\n" << "\t\treal_t r2 = fma(xrt, " << coss << ", fabs(yrt) * " << sins << ");\n" << "\t\treal_t circle = precalcSqrtSumSquares;\n" << "\n" << "\t\tfor (i = 0; i < " << sides << " - 1; i++)\n" << "\t\t{\n" << "\t\t swp = fma(xrt, " << cosa << ", -(yrt * " << sina << "));\n" << "\t\t yrt = fma(xrt, " << sina << ", yrt * " << cosa << ");\n" << "\t\t xrt = swp;\n" << "\n" << "\t\t r2 = max(r2, fma(xrt, " << coss << ", fabs(yrt) * " << sins << "));\n" << "\t\t}\n" << "\n" << "\t\tr2 = fma(r2, " << cosc << ", circle * " << sinc << ");\n" << "\n" << "\t\tif (i > 1)\n" << "\t\t r2 = SQR(r2);\n" << "\t\telse\n" << "\t\t r2 = fabs(r2) * r2;\n" << "\n" << "\t\tif (r2 > 0 && (r2 < " << w2 << "))\n" << "\t\t{\n" << "\t\t real_t r = " << weight << " * sqrt(fabs(" << w2 << " / r2 - 1));\n" << "\n" << "\t\t vOut.x = r * vIn.x;\n" << "\t\t vOut.y = r * vIn.y;\n" << "\t\t}\n" << "\t\telse if (r2 < 0)\n" << "\t\t{\n" << "\t\t real_t r = " << weight << " / sqrt(fabs(" << w2 << " / r2) - 1);\n" << "\n" << "\t\t vOut.x = r * vIn.x;\n" << "\t\t vOut.y = r * vIn.y;\n" << "\t\t}\n" << "\t\telse\n" << "\t\t{\n" << "\t\t vOut.x = " << 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 { auto a = M_2PI / m_Sides; auto s = T(-M_PI_2) * m_Star; auto c = T(M_PI_2) * m_Circle; m_W2 = SQR(m_Weight); sincos(a, &m_Sina, &m_Cosa); sincos(s, &m_Sins, &m_Coss); sincos(c, &m_Sinc, &m_Cosc); } protected: void Init() { string prefix = Prefix(); m_Params.clear(); m_Params.push_back(ParamWithName(&m_Sides, prefix + "loonie2_sides", 4, eParamType::INTEGER, 1, 50)); m_Params.push_back(ParamWithName(&m_Star, prefix + "loonie2_star", 0, eParamType::REAL, -1, 1)); m_Params.push_back(ParamWithName(&m_Circle, prefix + "loonie2_circle", 0, eParamType::REAL, -1, 1)); m_Params.push_back(ParamWithName(true, &m_W2, prefix + "loonie2_w2"));//Precalc. m_Params.push_back(ParamWithName(true, &m_Sina, prefix + "loonie2_sina")); m_Params.push_back(ParamWithName(true, &m_Cosa, prefix + "loonie2_cosa")); m_Params.push_back(ParamWithName(true, &m_Sins, prefix + "loonie2_sins")); m_Params.push_back(ParamWithName(true, &m_Coss, prefix + "loonie2_coss")); m_Params.push_back(ParamWithName(true, &m_Sinc, prefix + "loonie2_sinc")); m_Params.push_back(ParamWithName(true, &m_Cosc, prefix + "loonie2_cosc")); } private: T m_Sides; T m_Star; T m_Circle; T m_W2;//Precalc. T m_Sina; T m_Cosa; T m_Sins; T m_Coss; T m_Sinc; T m_Cosc; }; /// /// Loonie3. /// template class Loonie3Variation : public ParametricVariation { public: Loonie3Variation(T weight = 1.0) : ParametricVariation("loonie3", eVariationId::VAR_LOONIE3, weight, true) { Init(); } PARVARCOPY(Loonie3Variation) virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { T r2; if (helper.In.x > EPS) r2 = SQR(helper.m_PrecalcSumSquares / helper.In.x); else r2 = 2 * m_W2; if (r2 < m_W2) { T r = m_Weight * std::sqrt(m_W2 / r2 - 1); helper.Out.x = r * helper.In.x; helper.Out.y = r * helper.In.y; } else { helper.Out.x = m_Weight * helper.In.x; helper.Out.y = m_Weight * helper.In.y; } helper.Out.z = DefaultZ(helper); } virtual string OpenCLString() const override { ostringstream ss, ss2; intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string weight = WeightDefineString(); string w2 = "parVars[" + ToUpper(m_Params[i++].Name()) + index; ss << "\t{\n" << "\t\treal_t r2;\n" << "\n" << "\t\tif (vIn.x > EPS)\n" << "\t\t r2 = SQR(precalcSumSquares / vIn.x);\n" << "\t\telse\n" << "\t\t r2 = 2 * " << w2 << ";\n" << "\n" << "\t\tif (r2 < " << w2 << ")\n" << "\t\t{\n" << "\t\t real_t r = " << weight << " * sqrt(" << w2 << " / r2 - 1);\n" << "\n" << "\t\t vOut.x = r * vIn.x;\n" << "\t\t vOut.y = r * vIn.y;\n" << "\t\t}\n" << "\t\telse\n" << "\t\t{\n" << "\t\t vOut.x = " << 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_W2 = SQR(m_Weight); } protected: void Init() { string prefix = Prefix(); m_Params.clear(); m_Params.push_back(ParamWithName(true, &m_W2, prefix + "loonie3_w2"));//Precalc. } private: T m_W2;//Precalc. }; /// /// loonie_3D. /// template class Loonie3DVariation : public ParametricVariation { public: Loonie3DVariation(T weight = 1.0) : ParametricVariation("loonie_3D", eVariationId::VAR_LOONIE3D, weight, true, false, false, false, true) { Init(); } PARVARCOPY(Loonie3DVariation) virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { T kikr = helper.m_PrecalcAtanyx; T efTez = helper.In.z == 0 ? kikr : helper.In.z; T r2 = helper.m_PrecalcSumSquares + SQR(efTez); if (r2 < m_Vv) { T r = m_Weight * std::sqrt(m_Vv / r2 - 1); helper.Out.x = r * helper.In.x; helper.Out.y = r * helper.In.y; helper.Out.z = r * efTez * T(0.5); } else { helper.Out.x = m_Weight * helper.In.x; helper.Out.y = m_Weight * helper.In.y; helper.Out.z = m_Weight * efTez * T(0.5); } } virtual string OpenCLString() const override { ostringstream ss, ss2; intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string weight = WeightDefineString(); string vv = "parVars[" + ToUpper(m_Params[i++].Name()) + index; ss << "\t{\n" << "\t\treal_t kikr = precalcAtanyx;\n" << "\t\treal_t efTez = vIn.z == 0 ? kikr : vIn.z;\n" << "\t\treal_t r2 = fma(efTez, efTez, precalcSumSquares);\n" << "\n" << "\t\tif (r2 < " << vv << ")\n" << "\t\t{\n" << "\t\t real_t r = " << weight << " * sqrt(" << vv << " / r2 - 1);\n" << "\n" << "\t\t vOut.x = r * vIn.x;\n" << "\t\t vOut.y = r * vIn.y;\n" << "\t\t vOut.z = r * efTez * (real_t)(0.5);\n" << "\t\t}\n" << "\t\telse\n" << "\t\t{\n" << "\t\t vOut.x = " << weight << " * vIn.x;\n" << "\t\t vOut.y = " << weight << " * vIn.y;\n" << "\t\t vOut.z = " << weight << " * efTez * (real_t)(0.5);\n" << "\t\t}\n" << "\t}\n"; return ss.str(); } virtual void Precalc() override { m_Vv = SQR(m_Weight); } protected: void Init() { string prefix = Prefix(); m_Params.clear(); m_Params.push_back(ParamWithName(true, &m_Vv, prefix + "loonie_3D_vv"));//Precalcs only, no params. } private: T m_Vv;//Precalcs only, no params. }; /// /// mcarpet. /// template class McarpetVariation : public ParametricVariation { public: McarpetVariation(T weight = 1.0) : ParametricVariation("mcarpet", eVariationId::VAR_MCARPET, weight, true) { Init(); } PARVARCOPY(McarpetVariation) virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { T t = helper.m_PrecalcSumSquares * T(0.25) + 1; T r = m_Weight / t; helper.Out.x = helper.In.x * r * m_X; helper.Out.y = helper.In.y * r * m_Y; helper.Out.x += (1 - (m_Twist * SQR(helper.In.x)) + helper.In.y) * m_Weight;//The += is intentional. helper.Out.y += m_Tilt * helper.In.x * m_Weight; helper.Out.z = DefaultZ(helper); } virtual string OpenCLString() const override { ostringstream ss, ss2; intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string weight = WeightDefineString(); string x = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string y = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string twist = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string tilt = "parVars[" + ToUpper(m_Params[i++].Name()) + index; ss << "\t{\n" << "\t\treal_t t = fma(precalcSumSquares, (real_t)(0.25), (real_t)(1.0));\n" << "\t\treal_t r = " << weight << " / t;\n" << "\n" << "\t\tvOut.x = vIn.x * r * " << x << ";\n" << "\t\tvOut.y = vIn.y * r * " << y << ";\n" << "\t\tvOut.x += (1 - (" << twist << " * SQR(vIn.x)) + vIn.y) * " << weight << ";\n" << "\t\tvOut.y += " << tilt << " * vIn.x * " << weight << ";\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_X, prefix + "mcarpet_x")); m_Params.push_back(ParamWithName(&m_Y, prefix + "mcarpet_y")); m_Params.push_back(ParamWithName(&m_Twist, prefix + "mcarpet_twist")); m_Params.push_back(ParamWithName(&m_Tilt, prefix + "mcarpet_tilt")); } private: T m_X; T m_Y; T m_Twist; T m_Tilt; }; /// /// waves2_3D. /// Original used a precalc for the input points, but it doesn't /// work with Ember's design (and is also likely wrong), so it gets calculated on every iter /// which is slightly slower, but more correct. /// template class Waves23DVariation : public ParametricVariation { public: Waves23DVariation(T weight = 1.0) : ParametricVariation("waves2_3D", eVariationId::VAR_WAVES23D, weight) { Init(); } PARVARCOPY(Waves23DVariation) virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { T avgxy = (helper.In.x + helper.In.y) * T(0.5); helper.Out.x = m_Weight * (helper.In.x + m_Scale * std::sin(helper.In.y * m_Freq)); helper.Out.y = m_Weight * (helper.In.y + m_Scale * std::sin(helper.In.x * m_Freq)); helper.Out.z = m_Weight * (helper.In.z + m_Scale * std::sin(avgxy * m_Freq));//Averages the XY to get Z. } virtual string OpenCLString() const override { ostringstream ss, ss2; intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string weight = WeightDefineString(); string freq = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string scale = "parVars[" + ToUpper(m_Params[i++].Name()) + index; ss << "\t{\n" << "\t\treal_t avgxy = (vIn.x + vIn.y) * (real_t)(0.5);\n" << "\n" << "\t\tvOut.x = " << weight << " * fma(" << scale << ", sin(vIn.y * " << freq << "), vIn.x);\n" << "\t\tvOut.y = " << weight << " * fma(" << scale << ", sin(vIn.x * " << freq << "), vIn.y);\n" << "\t\tvOut.z = " << weight << " * fma(" << scale << ", sin(avgxy * " << freq << "), vIn.z);\n" << "\t}\n"; return ss.str(); } protected: void Init() { string prefix = Prefix(); m_Params.clear(); m_Params.push_back(ParamWithName(&m_Freq, prefix + "waves2_3D_freq", 2)); m_Params.push_back(ParamWithName(&m_Scale, prefix + "waves2_3D_scale", 1)); } private: T m_Freq; T m_Scale; }; /// /// Pie3D. /// template class Pie3DVariation : public ParametricVariation { public: Pie3DVariation(T weight = 1.0) : ParametricVariation("pie3D", eVariationId::VAR_PIE3D, weight) { Init(); } PARVARCOPY(Pie3DVariation) virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { int sl = int(rand.Frand01() * m_Slices + T(0.5)); T a = m_Rotation + M_2PI * (sl + rand.Frand01() * m_Thickness) / m_Slices; T r = m_Weight * rand.Frand01(); helper.Out.x = r * std::cos(a); helper.Out.y = r * std::sin(a); helper.Out.z = m_Weight * std::sin(r); } virtual string OpenCLString() const override { ostringstream ss, ss2; intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string 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; ss << "\t{\n" << "\t\tint sl = (int)fma(MwcNext01(mwc), " << slices << ", (real_t)(0.5));\n" << "\t\treal_t a = fma(M_2PI, fma(MwcNext01(mwc), " << thickness << ", (real_t)(sl)) / " << slices << ", " << 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 = " << weight << " * sin(r);\n" << "\t}\n"; return ss.str(); } virtual void Random(QTIsaac& rand) override { m_Params[0].Set(10 * rand.Frand01());//Slices. m_Params[1].Set(M_2PI * rand.Frand11());//Rotation. m_Thickness = rand.Frand01(); } protected: void Init() { string prefix = Prefix(); m_Params.clear(); m_Params.push_back(ParamWithName(&m_Slices, prefix + "pie3D_slices", 6, eParamType::INTEGER_NONZERO, 1)); m_Params.push_back(ParamWithName(&m_Rotation, prefix + "pie3D_rotation", T(0.5), eParamType::REAL_CYCLIC, 0, M_2PI)); m_Params.push_back(ParamWithName(&m_Thickness, prefix + "pie3D_thickness", T(0.5), eParamType::REAL, 0, 1)); } private: T m_Slices; T m_Rotation; T m_Thickness; }; /// /// popcorn2_3D. /// template class Popcorn23DVariation : public ParametricVariation { public: Popcorn23DVariation(T weight = 1.0) : ParametricVariation("popcorn2_3D", eVariationId::VAR_POPCORN23D, weight, false, false, false, false, true) { Init(); } PARVARCOPY(Popcorn23DVariation) virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { T otherZ, tempPZ = 0; T tempTZ = helper.In.z == 0 ? m_Vv * m_SinTanC * helper.m_PrecalcAtanyx : helper.In.z; if (m_VarType == eVariationType::VARTYPE_PRE) otherZ = helper.In.z; else otherZ = outPoint.m_Z; if (otherZ == 0) tempPZ = m_Vv * m_SinTanC * helper.m_PrecalcAtanyx; helper.Out.x = m_HalfWeight * (helper.In.x + m_X * std::sin(SafeTan(m_C * helper.In.y))); helper.Out.y = m_HalfWeight * (helper.In.y + m_Y * std::sin(SafeTan(m_C * helper.In.x))); helper.Out.z = tempPZ + m_Vv * (m_Z * m_SinTanC * tempTZ); } virtual string OpenCLString() const override { ostringstream ss, ss2; int i = 0; ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string weight = WeightDefineString(); string x = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string y = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string z = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string c = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string stc = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string hw = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string vv = "parVars[" + ToUpper(m_Params[i++].Name()) + index; ss << "\t{\n" << "\t\treal_t otherZ, tempPZ = 0;\n" << "\t\treal_t tempTZ = vIn.z == 0 ? " << vv << " * " << stc << " * precalcAtanyx : vIn.z;\n"; if (m_VarType == eVariationType::VARTYPE_PRE) ss << "\t\totherZ = vIn.z;\n"; else ss << "\t\totherZ = outPoint->m_Z;\n"; ss << "\t\tif (otherZ == 0)\n" << "\t\t tempPZ = " << vv << " * " << stc << " * precalcAtanyx;\n" << "\n" << "\t\tvOut.x = " << hw << " * fma(" << x << ", sin(tan(" << c << " * vIn.y)), vIn.x);\n" << "\t\tvOut.y = " << hw << " * fma(" << y << ", sin(tan(" << c << " * vIn.x)), vIn.y);\n" << "\t\tvOut.z = fma(" << vv << ", (" << z << " * " << stc << " * tempTZ), tempPZ);\n" << "\t}\n"; return ss.str(); } virtual void Precalc() override { m_SinTanC = std::sin(SafeTan(m_C)); m_HalfWeight = m_Weight * T(0.5); if (std::abs(m_Weight) <= 1) m_Vv = std::abs(m_Weight) * m_Weight;//Sqr(m_Weight) value retaining sign. else m_Vv = m_Weight; } virtual void Random(QTIsaac& rand) override { m_X = T(0.2) + rand.Frand01(); m_Y = T(0.2) * rand.Frand01(); m_Z = T(0.2) * rand.Frand01(); m_C = 5 * rand.Frand01(); } protected: void Init() { string prefix = Prefix(); m_Params.clear(); m_Params.push_back(ParamWithName(&m_X, prefix + "popcorn2_3D_x", T(0.1))); m_Params.push_back(ParamWithName(&m_Y, prefix + "popcorn2_3D_y", T(0.1))); m_Params.push_back(ParamWithName(&m_Z, prefix + "popcorn2_3D_z", T(0.1))); m_Params.push_back(ParamWithName(&m_C, prefix + "popcorn2_3D_c", 3)); m_Params.push_back(ParamWithName(true, &m_SinTanC, prefix + "popcorn2_3D_sintanc")); m_Params.push_back(ParamWithName(true, &m_HalfWeight, prefix + "popcorn2_3D_half_weight")); m_Params.push_back(ParamWithName(true, &m_Vv, prefix + "popcorn2_3D_vv")); } private: T m_X; T m_Y; T m_Z; T m_C; T m_SinTanC;//Precalcs. T m_HalfWeight; T m_Vv; }; /// /// sinusoidal3d. /// template class Sinusoidal3DVariation : public Variation { public: Sinusoidal3DVariation(T weight = 1.0) : Variation("sinusoidal3D", eVariationId::VAR_SINUSOIDAL3D, weight) { } VARCOPY(Sinusoidal3DVariation) virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { helper.Out.x = m_Weight * std::sin(helper.In.x); helper.Out.y = m_Weight * std::sin(helper.In.y); helper.Out.z = m_Weight * (std::atan2(SQR(helper.In.x), SQR(helper.In.y)) * std::cos(helper.In.z)); } virtual string OpenCLString() const override { ostringstream ss; intmax_t varIndex = IndexInXform(); 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 << " * (atan2(SQR(vIn.x), SQR(vIn.y)) * cos(vIn.z));\n" << "\t}\n"; return ss.str(); } }; /// /// scry_3D. /// template class Scry3DVariation : public ParametricVariation { public: Scry3DVariation(T weight = 1.0) : ParametricVariation("scry_3D", eVariationId::VAR_SCRY3D, weight, true, false, false, false, true) { Init(); } PARVARCOPY(Scry3DVariation) virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { T t = helper.m_PrecalcSumSquares + SQR(helper.In.z); T r = 1 / Zeps(std::sqrt(t) * (t + m_InvWeight)); T z = helper.In.z == 0 ? helper.m_PrecalcAtanyx : helper.In.z; helper.Out.x = helper.In.x * r; helper.Out.y = helper.In.y * r; helper.Out.z = z * r; } virtual string OpenCLString() const override { ostringstream ss, ss2; int i = 0; ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string weight = WeightDefineString(); string invWeight = "parVars[" + ToUpper(m_Params[i++].Name()) + index; ss << "\t{\n" << "\t\treal_t t = fma(vIn.z, vIn.z, precalcSumSquares);\n" << "\t\treal_t r = 1 / Zeps(sqrt(t) * (t + " << invWeight << "));\n" << "\t\treal_t z = vIn.z == 0 ? precalcAtanyx : vIn.z;\n" << "\n" << "\t\tvOut.x = vIn.x * r;\n" << "\t\tvOut.y = vIn.y * r;\n" << "\t\tvOut.z = z * r;\n" << "\t}\n"; return ss.str(); } virtual void Precalc() override { m_InvWeight = 1 / Zeps(m_Weight); } virtual vector OpenCLGlobalFuncNames() const override { return vector { "Zeps" }; } protected: void Init() { string prefix = Prefix(); m_Params.clear(); m_Params.push_back(ParamWithName(true, &m_InvWeight, prefix + "scry_3D_inv_weight"));//Precalcs only, no params. } private: T m_InvWeight;//Precalcs only, no params. }; /// /// shredlin. /// template class ShredlinVariation : public ParametricVariation { public: ShredlinVariation(T weight = 1.0) : ParametricVariation("shredlin", eVariationId::VAR_SHRED_LIN, weight) { Init(); } PARVARCOPY(ShredlinVariation) virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { const int xpos = helper.In.x < 0; const int ypos = helper.In.y < 0; const T xrng = helper.In.x / m_XDistance; const T yrng = helper.In.y / m_YDistance; helper.Out.x = m_Xw * ((xrng - int(xrng)) * m_XWidth + int(xrng) + (T(0.5) - xpos) * m_1mX); helper.Out.y = m_Yw * ((yrng - int(yrng)) * m_YWidth + int(yrng) + (T(0.5) - ypos) * m_1mY); helper.Out.z = m_Weight * helper.In.z; } virtual string OpenCLString() const override { ostringstream ss, ss2; intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string weight = WeightDefineString(); string xdist = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string xwidth = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string ydist = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string ywidth = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string xw = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string yw = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string onemx = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string onemy = "parVars[" + ToUpper(m_Params[i++].Name()) + index; ss << "\t{\n" << "\t\tconst int xpos = vIn.x < 0;\n" << "\t\tconst int ypos = vIn.y < 0;\n" << "\t\tconst real_t xrng = vIn.x / " << xdist << ";\n" << "\t\tconst real_t yrng = vIn.y / " << ydist << ";\n" << "\n" << "\t\tvOut.x = " << xw << " * fma((xrng - (int)xrng), " << xwidth << ", (int)xrng + ((real_t)(0.5) - xpos) * " << onemx << ");\n" << "\t\tvOut.y = " << yw << " * fma((yrng - (int)yrng), " << ywidth << ", (int)yrng + ((real_t)(0.5) - ypos) * " << onemy << ");\n" << "\t\tvOut.z = " << weight << " * vIn.z;\n" << "\t}\n"; return ss.str(); } virtual void Precalc() override { m_Xw = m_Weight * m_XDistance; m_Yw = m_Weight * m_YDistance; m_1mX = 1 - m_XWidth; m_1mY = 1 - m_YWidth; } protected: void Init() { string prefix = Prefix(); m_Params.clear(); m_Params.push_back(ParamWithName(&m_XDistance, prefix + "shredlin_xdistance", 1, eParamType::REAL_NONZERO)); m_Params.push_back(ParamWithName(&m_XWidth, prefix + "shredlin_xwidth", T(0.5), eParamType::REAL, -1, 1)); m_Params.push_back(ParamWithName(&m_YDistance, prefix + "shredlin_ydistance", 1, eParamType::REAL_NONZERO)); m_Params.push_back(ParamWithName(&m_YWidth, prefix + "shredlin_ywidth", T(0.5), eParamType::REAL, -1, 1)); m_Params.push_back(ParamWithName(true, &m_Xw, prefix + "shredlin_xw")); m_Params.push_back(ParamWithName(true, &m_Yw, prefix + "shredlin_yw")); m_Params.push_back(ParamWithName(true, &m_1mX, prefix + "shredlin_1mx")); m_Params.push_back(ParamWithName(true, &m_1mY, prefix + "shredlin_1my")); } private: T m_XDistance; T m_XWidth; T m_YDistance; T m_YWidth; T m_Xw;//Precalc. T m_Yw; T m_1mX; T m_1mY; }; /// /// splitbrdr. /// template class SplitBrdrVariation : public ParametricVariation { public: SplitBrdrVariation(T weight = 1.0) : ParametricVariation("SplitBrdr", eVariationId::VAR_SPLIT_BRDR, weight, true) { Init(); } PARVARCOPY(SplitBrdrVariation) virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { T b = m_Weight / (helper.m_PrecalcSumSquares * T(0.25) + 1); T roundX = std::rint(helper.In.x); T roundY = std::rint(helper.In.y); T offsetX = helper.In.x - roundX; T offsetY = helper.In.y - roundY; helper.Out.x = helper.In.x * b; helper.Out.y = helper.In.y * b; if (rand.Frand01() >= T(0.75)) { helper.Out.x += m_Weight * (offsetX * T(0.5) + roundX); helper.Out.y += m_Weight * (offsetY * T(0.5) + roundY); } else { if (std::abs(offsetX) >= std::abs(offsetY)) { if (offsetX >= 0) { helper.Out.x += m_Weight * (offsetX * T(0.5) + roundX + m_X); helper.Out.y += m_Weight * (offsetY * T(0.5) + roundY + m_Y * offsetY / Zeps(offsetX)); } else { helper.Out.x += m_Weight * (offsetX * T(0.5) + roundX - m_Y); helper.Out.y += m_Weight * (offsetY * T(0.5) + roundY - m_Y * offsetY / Zeps(offsetX)); } } else { if (offsetY >= 0) { helper.Out.y += m_Weight * (offsetY * T(0.5) + roundY + m_Y); helper.Out.x += m_Weight * (offsetX * T(0.5) + roundX + offsetX / Zeps(offsetY) * m_Y); } else { helper.Out.y += m_Weight * (offsetY * T(0.5) + roundY - m_Y); helper.Out.x += m_Weight * (offsetX * T(0.5) + roundX - offsetX / Zeps(offsetY) * m_X); } } } helper.Out.x += helper.In.x * m_Px; helper.Out.y += helper.In.y * m_Py; helper.Out.z = DefaultZ(helper); } virtual string OpenCLString() const override { ostringstream ss, ss2; intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string weight = WeightDefineString(); string x = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string y = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string px = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string py = "parVars[" + ToUpper(m_Params[i++].Name()) + index; ss << "\t{\n" << "\t\treal_t b = " << weight << " / fma(precalcSumSquares, (real_t)(0.25), (real_t)(1.0));\n" << "\t\treal_t roundX = rint(vIn.x);\n" << "\t\treal_t roundY = rint(vIn.y);\n" << "\t\treal_t offsetX = vIn.x - roundX;\n" << "\t\treal_t offsetY = vIn.y - roundY;\n" << "\n" << "\t\tvOut.x = vIn.x * b;\n" << "\t\tvOut.y = vIn.y * b;\n" << "\n" << "\t\tif (MwcNext01(mwc) >= (real_t)(0.75))\n" << "\t\t{\n" << "\t\t vOut.x += " << 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 >= 0)\n" << "\t\t {\n" << "\t\t vOut.x += " << weight << " * fma(offsetX, (real_t)(0.5), roundX + " << x << ");\n" << "\t\t vOut.y += " << weight << " * fma(offsetY, (real_t)(0.5), fma(" << y << ", offsetY / Zeps(offsetX), roundY));\n" << "\t\t }\n" << "\t\t else\n" << "\t\t {\n" << "\t\t vOut.x += " << weight << " * fma(offsetX, (real_t)(0.5), roundX - " << y << ");\n" << "\t\t vOut.y += " << weight << " * fma(offsetY, (real_t)(0.5), roundY - " << y << " * offsetY / Zeps(offsetX));\n" << "\t\t }\n" << "\t\t }\n" << "\t\t else\n" << "\t\t {\n" << "\t\t if (offsetY >= 0)\n" << "\t\t {\n" << "\t\t vOut.y += " << weight << " * fma(offsetY, (real_t)(0.5), roundY + " << y << ");\n" << "\t\t vOut.x += " << weight << " * fma(offsetX, (real_t)(0.5), roundX + offsetX / Zeps(offsetY) * " << y << ");\n" << "\t\t }\n" << "\t\t else\n" << "\t\t {\n" << "\t\t vOut.y += " << weight << " * fma(offsetY, (real_t)(0.5), roundY - " << y << ");\n" << "\t\t vOut.x += " << weight << " * fma(offsetX, (real_t)(0.5), roundX - offsetX / Zeps(offsetY) * " << x << ");\n" << "\t\t }\n" << "\t\t }\n" << "\t\t}\n" << "\n" << "\t\tvOut.x += vIn.x * " << px << ";\n" << "\t\tvOut.y += vIn.y * " << py << ";\n" << "\t\tvOut.z = " << 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_X, prefix + "SplitBrdr_x", T(0.25)));//Original used a prefix of splitb_, which is incompatible with Ember's design. m_Params.push_back(ParamWithName(&m_Y, prefix + "SplitBrdr_y", T(0.25))); m_Params.push_back(ParamWithName(&m_Px, prefix + "SplitBrdr_px")); m_Params.push_back(ParamWithName(&m_Py, prefix + "SplitBrdr_py")); } private: T m_X; T m_Y; T m_Px; T m_Py; }; /// /// wdisc. /// template class WdiscVariation : public Variation { public: WdiscVariation(T weight = 1.0) : Variation("wdisc", eVariationId::VAR_WDISC, weight, true, true, false, false, true) { } VARCOPY(WdiscVariation) virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { T a = T(M_PI) / (helper.m_PrecalcSqrtSumSquares + 1); T r = helper.m_PrecalcAtanyx * T(M_1_PI); if (r > 0) a = T(M_PI) - a; 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; intmax_t varIndex = IndexInXform(); string weight = WeightDefineString(); ss << "\t{\n" << "\t\treal_t a = MPI / (precalcSqrtSumSquares + 1);\n" << "\t\treal_t r = precalcAtanyx * M1PI;\n" << "\n" << "\t\tif (r > 0)\n" << "\t\t a = MPI - a;\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(); } }; /// /// falloff. /// template class FalloffVariation : public ParametricVariation { public: FalloffVariation(T weight = 1.0) : ParametricVariation("falloff", eVariationId::VAR_FALLOFF, weight, false, false, false, false, true) { Init(); } PARVARCOPY(FalloffVariation) virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { const T ax = rand.Frand(T(-0.5), T(0.5)); const T ay = rand.Frand(T(-0.5), T(0.5)); const T az = rand.Frand(T(-0.5), T(0.5)); const T r = std::sqrt(Sqr(helper.In.x - m_X0) + Sqr(helper.In.y - m_Y0) + Sqr(helper.In.z - m_Z0)); const T rc = ((m_Invert != 0 ? std::max(1 - r, 0) : std::max(r, 0)) - m_MinDist) * m_InternalScatter;//Original called a macro named min, which internally performed max. const T rs = std::max(rc, 0); T sigma, phi, rad, sigmas, sigmac, phis, phic; T scale, denom; switch (int(m_Type)) { case 0://Linear. helper.Out.x = m_Weight * (helper.In.x + m_MulX * ax * rs); helper.Out.y = m_Weight * (helper.In.y + m_MulY * ay * rs); helper.Out.z = m_Weight * (helper.In.z + m_MulZ * az * rs); break; case 1://Radial. rad = r + m_MulX * ax * rs; phi = helper.m_PrecalcAtanyx + m_MulY * ay * rs; sigma = std::asin(r == 0 ? 0 : helper.In.z / r) + m_MulZ * az * rs; sigmas = std::sin(sigma); sigmac = std::cos(sigma); phis = std::sin(phi); phic = std::cos(phi); helper.Out.x = m_Weight * (rad * sigmac * phic); helper.Out.y = m_Weight * (rad * sigmac * phis); helper.Out.z = m_Weight * (rad * sigmas); break; case 2://Box. default: scale = Clamp(rs, 0, T(0.9)) + T(0.1); denom = 1 / scale; helper.Out.x = m_Weight * Lerp(helper.In.x, std::floor(helper.In.x * denom) + scale * ax, m_MulX * rs) + m_MulX * std::pow(ax, m_BoxPow) * rs * denom;//m_BoxPow should be an integer value held in T, helper.Out.y = m_Weight * Lerp(helper.In.y, std::floor(helper.In.y * denom) + scale * ay, m_MulY * rs) + m_MulY * std::pow(ay, m_BoxPow) * rs * denom;//so std::abs() shouldn't be necessary. helper.Out.z = m_Weight * Lerp(helper.In.z, std::floor(helper.In.z * denom) + scale * az, m_MulZ * rs) + m_MulZ * std::pow(az, m_BoxPow) * rs * denom; break; } } virtual string OpenCLString() const override { ostringstream ss, ss2; intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string weight = WeightDefineString(); string scatter = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string minDist = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string mulX = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string mulY = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string mulZ = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string x0 = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string y0 = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string z0 = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string invert = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string type = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string boxPow = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string internalScatter = "parVars[" + ToUpper(m_Params[i++].Name()) + index; ss << "\t{\n" << "\t\tconst real_t ax = MwcNext0505(mwc);\n" << "\t\tconst real_t ay = MwcNext0505(mwc);\n" << "\t\tconst real_t az = MwcNext0505(mwc);\n" << "\t\tconst real_t xmx = vIn.x - " << x0 << ";\n" << "\t\tconst real_t ymy = vIn.y - " << y0 << ";\n" << "\t\tconst real_t zmz = vIn.z - " << z0 << ";\n" << "\t\tconst real_t r = sqrt(fma(xmx, xmx, fma(ymy, ymy, SQR(zmz))));\n" << "\t\tconst real_t rc = ((" << invert << " != 0 ? max(1 - r, (real_t)(0.0)) : max(r, (real_t)(0.0))) - " << minDist << ") * " << internalScatter << ";\n" << "\t\tconst real_t rs = max(rc, (real_t)(0.0));\n" << "\n" << "\t\treal_t sigma, phi, rad, sigmas, sigmac, phis, phic;\n" << "\t\treal_t scale, denom;\n" << "\n" << "\t\tswitch ((int)" << type << ")\n" << "\t\t{\n" << "\t\t case 0:\n" << "\t\t vOut.x = " << weight << " * fma(" << mulX << ", ax * rs, vIn.x);\n" << "\t\t vOut.y = " << weight << " * fma(" << mulY << ", ay * rs, vIn.y);\n" << "\t\t vOut.z = " << weight << " * fma(" << mulZ << ", az * rs, vIn.z);\n" << "\t\t break;\n" << "\t\t case 1:\n" << "\t\t rad = fma(" << mulX << ", ax * rs, r);\n" << "\t\t phi = fma(" << mulY << ", ay * rs, precalcAtanyx);\n" << "\t\t sigma = fma(" << mulZ << ", az * rs, asin(r == 0 ? 0 : vIn.z / r));\n" << "\n" << "\t\t sigmas = sin(sigma);\n" << "\t\t sigmac = cos(sigma);\n" << "\t\t phis = sin(phi);\n" << "\t\t phic = cos(phi);\n" << "\n" << "\t\t vOut.x = " << weight << " * (rad * sigmac * phic);\n" << "\t\t vOut.y = " << weight << " * (rad * sigmac * phis);\n" << "\t\t vOut.z = " << weight << " * (rad * sigmas);\n" << "\t\t break;\n" << "\t\t case 2:\n" << "\t\t scale = clamp(rs, (real_t)(0.0), (real_t)(0.9)) + (real_t)(0.1);\n" << "\t\t denom = 1 / scale;\n" << "\t\t vOut.x = fma(" << weight << ", Lerp(vIn.x, fma(scale, ax, floor(vIn.x * denom)), " << mulX << " * rs), " << mulX << " * pow(ax, " << boxPow << ") * rs * denom);\n" << "\t\t vOut.y = fma(" << weight << ", Lerp(vIn.y, fma(scale, ay, floor(vIn.y * denom)), " << mulY << " * rs), " << mulY << " * pow(ay, " << boxPow << ") * rs * denom);\n" << "\t\t vOut.z = fma(" << weight << ", Lerp(vIn.z, fma(scale, az, floor(vIn.z * denom)), " << mulZ << " * rs), " << mulZ << " * pow(az, " << boxPow << ") * rs * denom);\n" << "\t\t break;\n" << "\t\t}\n" << "\t}\n"; return ss.str(); } virtual vector OpenCLGlobalFuncNames() const override { return vector { "Lerp" }; } virtual void Precalc() override { m_InternalScatter = T(0.04) * m_Scatter; } protected: void Init() { string prefix = Prefix(); m_Params.clear(); m_Params.push_back(ParamWithName(&m_Scatter, prefix + "falloff_scatter", 1, eParamType::REAL, EPS, TMAX)); m_Params.push_back(ParamWithName(&m_MinDist, prefix + "falloff_mindist", T(0.5), eParamType::REAL, 0, TMAX)); m_Params.push_back(ParamWithName(&m_MulX, prefix + "falloff_mul_x", 1, eParamType::REAL, 0, 1)); m_Params.push_back(ParamWithName(&m_MulY, prefix + "falloff_mul_y", 1, eParamType::REAL, 0, 1)); m_Params.push_back(ParamWithName(&m_MulZ, prefix + "falloff_mul_z", 0, eParamType::REAL, 0, 1)); m_Params.push_back(ParamWithName(&m_X0, prefix + "falloff_x0")); m_Params.push_back(ParamWithName(&m_Y0, prefix + "falloff_y0")); m_Params.push_back(ParamWithName(&m_Z0, prefix + "falloff_z0")); m_Params.push_back(ParamWithName(&m_Invert, prefix + "falloff_invert", 0, eParamType::INTEGER, 0, 1)); m_Params.push_back(ParamWithName(&m_Type, prefix + "falloff_type", 0, eParamType::INTEGER, 0, 2)); m_Params.push_back(ParamWithName(&m_BoxPow, prefix + "falloff_boxpow", 2, eParamType::INTEGER, 2, 32));//Original defaulted this to 0 which directly contradicts the specified range of 2-32. m_Params.push_back(ParamWithName(true, &m_InternalScatter, prefix + "falloff_internal_scatter")); } private: T m_Scatter; T m_MinDist; T m_MulX; T m_MulY; T m_MulZ; T m_X0; T m_Y0; T m_Z0; T m_Invert; T m_Type; T m_BoxPow; T m_InternalScatter; }; /// /// falloff2. /// template class Falloff2Variation : public ParametricVariation { public: Falloff2Variation(T weight = 1.0) : ParametricVariation("falloff2", eVariationId::VAR_FALLOFF2, weight, true, false, false, false, true) { Init(); } PARVARCOPY(Falloff2Variation) virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { const v4T random(rand.Frand(T(-0.5), T(0.5)), rand.Frand(T(-0.5), T(0.5)), rand.Frand(T(-0.5), T(0.5)), rand.Frand(T(-0.5), T(0.5))); const T distA = std::sqrt(Sqr(helper.In.x - m_X0) + Sqr(helper.In.y - m_Y0) + Sqr(helper.In.z - m_Z0)); const T distB = m_Invert != 0 ? std::max(1 - distA, 0) : std::max(distA, 0);//Original called a macro named min, which internally performed max. const T dist = std::max((distB - m_MinDist) * m_RMax, 0); switch (int(m_Type)) { case 0://Linear. { helper.Out.x = helper.In.x + m_MulX * random.x * dist; helper.Out.y = helper.In.y + m_MulY * random.y * dist; helper.Out.z = helper.In.z + m_MulZ * random.z * dist; outPoint.m_ColorX = std::abs(fmod(outPoint.m_ColorX + m_MulC * random.w * dist, T(1))); } break; case 1://Radial. if (helper.In.x == 0 && helper.In.y == 0 && helper.In.z == 0) { helper.Out.x = helper.In.x; helper.Out.y = helper.In.y; helper.Out.z = helper.In.z; } else { const T rIn = Zeps(std::sqrt(helper.m_PrecalcSumSquares + SQR(helper.In.z))); const T r = rIn + m_MulX * random.x * dist; const T phi = helper.m_PrecalcAtanyx + m_MulY * random.y * dist; const T sigma = std::asin(helper.In.z / rIn) + m_MulZ * random.z * dist; const T sigmas = std::sin(sigma); const T sigmac = std::cos(sigma); const T phis = std::sin(phi); const T phic = std::cos(phi); helper.Out.x = r * sigmac * phic; helper.Out.y = r * sigmac * phis; helper.Out.z = r * sigmas; outPoint.m_ColorX = std::abs(fmod(outPoint.m_ColorX + m_MulC * random.w * dist, T(1))); } break; case 2://Gaussian. default: { const T sigma = dist * random.y * M_2PI; const T phi = dist * random.z * T(M_PI); const T rad = dist * random.x; const T sigmas = std::sin(sigma); const T sigmac = std::cos(sigma); const T phis = std::sin(phi); const T phic = std::cos(phi); helper.Out.x = helper.In.x + m_MulX * rad * sigmac * phic; helper.Out.y = helper.In.y + m_MulY * rad * sigmac * phis; helper.Out.z = helper.In.z + m_MulZ * rad * sigmas; outPoint.m_ColorX = std::abs(fmod(outPoint.m_ColorX + m_MulC * random.w * dist, T(1))); } break; } } virtual string OpenCLString() const override { ostringstream ss, ss2; int i = 0; ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string weight = WeightDefineString(); string scatter = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string minDist = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string mulX = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string mulY = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string mulZ = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string mulC = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string x0 = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string y0 = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string z0 = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string invert = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string type = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string rMax = "parVars[" + ToUpper(m_Params[i++].Name()) + index; ss << "\t{\n" << "\t\tconst real_t randx = MwcNext0505(mwc);\n" << "\t\tconst real_t randy = MwcNext0505(mwc);\n" << "\t\tconst real_t randz = MwcNext0505(mwc);\n" << "\t\tconst real_t randc = MwcNext0505(mwc);\n" << "\t\tconst real_t xmx = vIn.x - " << x0 << ";\n" << "\t\tconst real_t ymy = vIn.y - " << y0 << ";\n" << "\t\tconst real_t zmz = vIn.z - " << z0 << ";\n" << "\t\tconst real_t distA = sqrt(fma(xmx, xmx, fma(ymy, ymy, SQR(zmz))));\n" << "\t\tconst real_t distB = " << invert << " != 0 ? max(1 - distA, (real_t)(0.0)) : max(distA, (real_t)(0.0));\n" << "\t\tconst real_t dist = max((distB - " << minDist << ") * " << rMax << ", (real_t)(0.0));\n" << "\n" << "\t\tswitch ((int)" << type << ")\n" << "\t\t{\n" << "\t\t case 0:\n" << "\t\t vOut.x = fma(" << mulX << ", randx * dist, vIn.x);\n" << "\t\t vOut.y = fma(" << mulY << ", randy * dist, vIn.y);\n" << "\t\t vOut.z = fma(" << mulZ << ", randz * dist, vIn.z);\n" << "\t\t outPoint->m_ColorX = fabs(fmod(fma(" << mulC << ", randc * dist, outPoint->m_ColorX), (real_t)(1.0)));\n" << "\t\t break;\n" << "\t\t case 1:\n" << "\t\t if (vIn.x == 0 && vIn.y == 0 && vIn.z == 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" << "\t\t else\n" << "\t\t {\n" << "\t\t real_t rIn = Zeps(sqrt(fma(vIn.z, vIn.z, precalcSumSquares)));\n" << "\t\t real_t r = fma(" << mulX << ", randx * dist, rIn);\n" << "\t\t real_t phi = fma(" << mulY << ", randy * dist, precalcAtanyx);\n" << "\t\t real_t sigma = fma(" << mulZ << ", randz * dist, asin(vIn.z / rIn));\n" << "\t\t real_t sigmas = sin(sigma);\n" << "\t\t real_t sigmac = cos(sigma);\n" << "\t\t real_t phis = sin(phi);\n" << "\t\t real_t phic = cos(phi);\n" << "\n" << "\t\t vOut.x = r * sigmac * phic;\n" << "\t\t vOut.y = r * sigmac * phis;\n" << "\t\t vOut.z = r * sigmas;\n" << "\t\t outPoint->m_ColorX = fabs(fmod(fma(" << mulC << ", randc * dist, outPoint->m_ColorX), (real_t)(1.0)));\n" << "\t\t }\n" << "\t\t break;\n" << "\t\t case 2:\n" << "\t\t {\n" << "\t\t real_t sigma = dist * randy * M_2PI;\n" << "\t\t real_t phi = dist * randz * MPI;\n" << "\t\t real_t rad = dist * randx;\n" << "\t\t real_t sigmas = sin(sigma);\n" << "\t\t real_t sigmac = cos(sigma);\n" << "\t\t real_t phis = sin(phi);\n" << "\t\t real_t phic = cos(phi);\n" << "\n" << "\t\t vOut.x = fma(" << mulX << " * rad, sigmac * phic, vIn.x);\n" << "\t\t vOut.y = fma(" << mulY << " * rad, sigmac * phis, vIn.y);\n" << "\t\t vOut.z = fma(" << mulZ << " * rad, sigmas, vIn.z);\n" << "\t\t outPoint->m_ColorX = fabs(fmod(fma(" << mulC << ", randc * dist, outPoint->m_ColorX), (real_t)(1.0)));\n" << "\t\t break;\n" << "\t\t }\n" << "\t\t}\n" << "\t}\n"; return ss.str(); } virtual vector OpenCLGlobalFuncNames() const override { return vector { "Zeps" }; } virtual void Precalc() override { m_RMax = T(0.04) * m_Scatter; } protected: void Init() { string prefix = Prefix(); m_Params.clear(); m_Params.push_back(ParamWithName(&m_Scatter, prefix + "falloff2_scatter", 1, eParamType::REAL, EPS, TMAX)); m_Params.push_back(ParamWithName(&m_MinDist, prefix + "falloff2_mindist", T(0.5), eParamType::REAL, 0, TMAX)); m_Params.push_back(ParamWithName(&m_MulX, prefix + "falloff2_mul_x", 1, eParamType::REAL, 0, 1)); m_Params.push_back(ParamWithName(&m_MulY, prefix + "falloff2_mul_y", 1, eParamType::REAL, 0, 1)); m_Params.push_back(ParamWithName(&m_MulZ, prefix + "falloff2_mul_z", 0, eParamType::REAL, 0, 1)); m_Params.push_back(ParamWithName(&m_MulC, prefix + "falloff2_mul_c", 0, eParamType::REAL, 0, 1)); m_Params.push_back(ParamWithName(&m_X0, prefix + "falloff2_x0")); m_Params.push_back(ParamWithName(&m_Y0, prefix + "falloff2_y0")); m_Params.push_back(ParamWithName(&m_Z0, prefix + "falloff2_z0")); m_Params.push_back(ParamWithName(&m_Invert, prefix + "falloff2_invert", 0, eParamType::INTEGER, 0, 1)); m_Params.push_back(ParamWithName(&m_Type, prefix + "falloff2_type", 0, eParamType::INTEGER, 0, 2)); m_Params.push_back(ParamWithName(true, &m_RMax, prefix + "falloff2_rmax")); } private: T m_Scatter; T m_MinDist; T m_MulX; T m_MulY; T m_MulZ; T m_MulC; T m_X0; T m_Y0; T m_Z0; T m_Invert; T m_Type; T m_RMax; }; /// /// falloff3. /// template class Falloff3Variation : public ParametricVariation { public: Falloff3Variation(T weight = 1.0) : ParametricVariation("falloff3", eVariationId::VAR_FALLOFF3, weight, true, false, false, false, true) { Init(); } PARVARCOPY(Falloff3Variation) virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { const v4T random(rand.Frand(T(-0.5), T(0.5)), rand.Frand(T(-0.5), T(0.5)), rand.Frand(T(-0.5), T(0.5)), rand.Frand(T(-0.5), T(0.5))); T radius; switch (int(m_BlurShape)) { case 0://Circle. radius = std::sqrt(Sqr(helper.In.x - m_CenterX) + Sqr(helper.In.y - m_CenterY) + Sqr(helper.In.z - m_CenterZ)); break; case 1://Square. default: radius = std::max(std::abs(helper.In.x - m_CenterX), std::max(std::abs(helper.In.y - m_CenterY), (std::abs(helper.In.z - m_CenterZ))));//Original called a macro named min, which internally performed max. break; } const T dist = std::max(((m_InvertDistance != 0 ? std::max(1 - radius, 0) : std::max(radius, 0)) - m_MinDistance) * m_RMax, 0); switch (int(m_BlurType)) { case 0://Gaussian. { const T sigma = dist * random.y * M_2PI; const T phi = dist * random.z * T(M_PI); const T rad = dist * random.x; const T sigmas = std::sin(sigma); const T sigmac = std::cos(sigma); const T phis = std::sin(phi); const T phic = std::cos(phi); helper.Out.x = helper.In.x + m_MulX * rad * sigmac * phic; helper.Out.y = helper.In.y + m_MulY * rad * sigmac * phis; helper.Out.z = helper.In.z + m_MulZ * rad * sigmas; outPoint.m_ColorX = std::abs(fmod(outPoint.m_ColorX + m_MulC * random.w * dist, T(1))); } break; case 1://Radial. if (helper.In.x == 0 && helper.In.y == 0 && helper.In.z == 0) { helper.Out.x = helper.In.x; helper.Out.y = helper.In.y; helper.Out.z = helper.In.z; } else { const T rIn = std::sqrt(helper.m_PrecalcSumSquares + SQR(helper.In.z)); const T r = rIn + m_MulX * random.x * dist; const T phi = helper.m_PrecalcAtanyx + m_MulY * random.y * dist; const T sigma = std::asin(helper.In.z / rIn) + m_MulZ * random.z * dist; const T sigmas = std::sin(sigma); const T sigmac = std::cos(sigma); const T phis = std::sin(phi); const T phic = std::cos(phi); helper.Out.x = r * sigmac * phic; helper.Out.y = r * sigmac * phis; helper.Out.z = r * sigmas; outPoint.m_ColorX = std::abs(fmod(outPoint.m_ColorX + m_MulC * random.w * dist, T(1))); } break; case 2://Log. default: { const T coeff = m_RMax <= EPS ? dist : dist + m_Alpha * (VarFuncs::LogMap(dist) - dist); helper.Out.x = helper.In.x + VarFuncs::LogMap(m_MulX) * VarFuncs::LogScale(random.x) * coeff; helper.Out.y = helper.In.y + VarFuncs::LogMap(m_MulY) * VarFuncs::LogScale(random.y) * coeff; helper.Out.z = helper.In.z + VarFuncs::LogMap(m_MulZ) * VarFuncs::LogScale(random.z) * coeff; outPoint.m_ColorX = std::abs(fmod(outPoint.m_ColorX + VarFuncs::LogMap(m_MulC) * VarFuncs::LogScale(random.w) * coeff, T(1))); } break; } } virtual string OpenCLString() const override { ostringstream ss, ss2; int i = 0; ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string weight = WeightDefineString(); string blurType = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string blurShape = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string blurStrength = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string minDist = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string invertDist = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string mulX = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string mulY = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string mulZ = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string mulC = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string centerX = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string centerY = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string centerZ = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string alpha = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string rMax = "parVars[" + ToUpper(m_Params[i++].Name()) + index; ss << "\t{\n" << "\t\tconst real_t randx = MwcNext0505(mwc);\n" << "\t\tconst real_t randy = MwcNext0505(mwc);\n" << "\t\tconst real_t randz = MwcNext0505(mwc);\n" << "\t\tconst real_t randc = MwcNext0505(mwc);\n" << "\t\tconst real_t xmx = vIn.x - " << centerX << ";\n" << "\t\tconst real_t ymy = vIn.y - " << centerY << ";\n" << "\t\tconst real_t zmz = vIn.z - " << centerZ << ";\n" << "\t\treal_t radius;\n" << "\n" << "\t\tswitch ((int)" << blurShape << ")\n" << "\t\t{\n" << "\t\t case 0:\n" << "\t\t radius = sqrt(fma(xmx, xmx, fma(ymy, ymy, SQR(zmz))));\n" << "\t\t break;\n" << "\t\t case 1:\n" << "\t\t radius = max(fabs(xmx), max(fabs(ymy), (fabs(zmz))));\n" << "\t\t break;\n" << "\t\t}\n" << "\n" << "\t\tconst real_t dist = max(((" << invertDist << " != 0 ? max(1 - radius, (real_t)(0.0)) : max(radius, (real_t)(0.0))) - " << minDist << ") * " << rMax << ", (real_t)(0.0));\n" << "\n" << "\t\tswitch ((int)" << blurType << ")\n" << "\t\t{\n" << "\t\tcase 0:\n" << "\t\t {\n" << "\t\t real_t sigma = dist * randy * M_2PI;\n" << "\t\t real_t phi = dist * randz * MPI;\n" << "\t\t real_t rad = dist * randx;\n" << "\t\t real_t sigmas = sin(sigma);\n" << "\t\t real_t sigmac = cos(sigma);\n" << "\t\t real_t phis = sin(phi);\n" << "\t\t real_t phic = cos(phi);\n" << "\n" << "\t\t vOut.x = fma(" << mulX << " * rad, sigmac * phic, vIn.x);\n" << "\t\t vOut.y = fma(" << mulY << " * rad, sigmac * phis, vIn.y);\n" << "\t\t vOut.z = fma(" << mulZ << " * rad, sigmas, vIn.z);\n" << "\t\t outPoint->m_ColorX = fabs(fmod(fma(" << mulC << ", randc * dist, outPoint->m_ColorX), (real_t)(1.0)));\n" << "\t\t }\n" << "\t\t break;\n" << "\t\tcase 1:\n" << "\t\t if (vIn.x == 0 && vIn.y == 0 && vIn.z == 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" << "\t\t else\n" << "\t\t {\n" << "\t\t real_t rIn = Zeps(sqrt(fma(vIn.z, vIn.z, precalcSumSquares)));\n" << "\t\t real_t r = fma(" << mulX << ", randx * dist, rIn);\n" << "\t\t real_t phi = fma(" << mulY << ", randy * dist, precalcAtanyx);\n" << "\t\t real_t sigma = fma(" << mulZ << ", randz * dist, asin(vIn.z / rIn));\n" << "\t\t real_t sigmas = sin(sigma);\n" << "\t\t real_t sigmac = cos(sigma);\n" << "\t\t real_t phis = sin(phi);\n" << "\t\t real_t phic = cos(phi);\n" << "\n" << "\t\t vOut.x = r * sigmac * phic;\n" << "\t\t vOut.y = r * sigmac * phis;\n" << "\t\t vOut.z = r * sigmas;\n" << "\t\t outPoint->m_ColorX = fabs(fmod(fma(" << mulC << ", randc * dist, outPoint->m_ColorX), (real_t)(1.0)));\n" << "\t\t }\n" << "\t\t break;\n" << "\t\tcase 2:\n" << "\t\t {\n" << "\t\t real_t coeff = " << rMax << " <= EPS ? dist : fma(" << alpha << ", (LogMap(dist) - dist), dist);\n" << "\n" << "\t\t vOut.x = fma(LogMap(" << mulX << "), LogScale(randx) * coeff, vIn.x);\n" << "\t\t vOut.y = fma(LogMap(" << mulY << "), LogScale(randy) * coeff, vIn.y);\n" << "\t\t vOut.z = fma(LogMap(" << mulZ << "), LogScale(randz) * coeff, vIn.z);\n" << "\t\t outPoint->m_ColorX = fabs(fmod(fma(LogMap(" << mulC << "), LogScale(randc) * coeff, outPoint->m_ColorX), (real_t)(1.0)));\n" << "\t\t }\n" << "\t\t break;\n" << "\t\t}\n" << "\t}\n"; return ss.str(); } virtual vector OpenCLGlobalFuncNames() const override { return vector { "SignNz", "LogMap", "LogScale", "Zeps" }; } virtual void Precalc() override { m_RMax = T(0.04) * m_BlurStrength; } protected: void Init() { string prefix = Prefix(); m_Params.clear(); m_Params.push_back(ParamWithName(&m_BlurType, prefix + "falloff3_blur_type", 0, eParamType::INTEGER, 0, 3)); m_Params.push_back(ParamWithName(&m_BlurShape, prefix + "falloff3_blur_shape", 0, eParamType::INTEGER, 0, 1)); m_Params.push_back(ParamWithName(&m_BlurStrength, prefix + "falloff3_blur_strength", 1, eParamType::REAL, EPS, TMAX)); m_Params.push_back(ParamWithName(&m_MinDistance, prefix + "falloff3_min_distance", T(0.5), eParamType::REAL, 0, TMAX)); m_Params.push_back(ParamWithName(&m_InvertDistance, prefix + "falloff3_invert_distance", 0, eParamType::INTEGER, 0, 1)); m_Params.push_back(ParamWithName(&m_MulX, prefix + "falloff3_mul_x", 1, eParamType::REAL, 0, 1)); m_Params.push_back(ParamWithName(&m_MulY, prefix + "falloff3_mul_y", 1, eParamType::REAL, 0, 1)); m_Params.push_back(ParamWithName(&m_MulZ, prefix + "falloff3_mul_z", 0, eParamType::REAL, 0, 1)); m_Params.push_back(ParamWithName(&m_MulC, prefix + "falloff3_mul_c", 0, eParamType::REAL, 0, 1)); m_Params.push_back(ParamWithName(&m_CenterX, prefix + "falloff3_center_x")); m_Params.push_back(ParamWithName(&m_CenterY, prefix + "falloff3_center_y")); m_Params.push_back(ParamWithName(&m_CenterZ, prefix + "falloff3_center_z")); m_Params.push_back(ParamWithName(&m_Alpha, prefix + "falloff3_alpha")); m_Params.push_back(ParamWithName(true, &m_RMax, prefix + "falloff3_rmax")); } private: T m_BlurType; T m_BlurShape; T m_BlurStrength; T m_MinDistance; T m_InvertDistance; T m_MulX; T m_MulY; T m_MulZ; T m_MulC; T m_CenterX; T m_CenterY; T m_CenterZ; T m_Alpha; T m_RMax; }; /// /// xtrb. /// template class XtrbVariation : public ParametricVariation { public: XtrbVariation(T weight = 1.0) : ParametricVariation("xtrb", eVariationId::VAR_XTRB, weight) { Init(); } PARVARCOPY(XtrbVariation) virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { intmax_t m, n; T alpha, beta, offsetAl, offsetBe, offsetGa, x, y; //Transfer to trilinear coordinates, normalized to real distances from triangle sides. DirectTrilinear(helper.In.x, helper.In.y, alpha, beta); m = Floor(alpha / m_S2a); offsetAl = alpha - m * m_S2a; n = Floor(beta / m_S2b); offsetBe = beta - n * m_S2b; offsetGa = m_S2c - m_Ac * offsetAl - m_Bc * offsetBe; if (offsetGa > 0) { Hex(offsetAl, offsetBe, offsetGa, alpha, beta, rand); } else { offsetAl = m_S2a - offsetAl; offsetBe = m_S2b - offsetBe; offsetGa = -offsetGa; Hex(offsetAl, offsetBe, offsetGa, alpha, beta, rand); alpha = m_S2a - alpha; beta = m_S2b - beta; } alpha += m * m_S2a; beta += n * m_S2b; InverseTrilinear(alpha, beta, x, y, rand); helper.Out.x = m_Weight * x; helper.Out.y = m_Weight * y; helper.Out.z = DefaultZ(helper); } virtual string OpenCLString() const override { ostringstream ss, ss2; intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string weight = WeightDefineString(); string power = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string radius = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string width = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string dist = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string a = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string b = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string sinC = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string cosC = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string ha = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string hb = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string hc = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string ab = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string ac = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string ba = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string bc = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string ca = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string cb = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string s2a = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string s2b = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string s2c = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string s2ab = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string s2ac = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string s2bc = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string width1 = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string width2 = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string width3 = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string absN = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string cn = "parVars[" + ToUpper(m_Params[i++].Name()) + index; ss << "\t{\n" << "\t\tint m, n;\n" << "\t\treal_t alpha, beta, offsetAl, offsetBe, offsetGa, x, y;\n" << "\n" << "\t\t{\n"//DirectTrilinear function extracted out here. << "\t\t alpha = vIn.y + " << radius << ";\n" << "\t\t beta = fma(vIn.x, " << sinC << ", fma(-vIn.y, " << cosC << ", " << radius << "));\n" << "\t\t}\n" << "\n" << "\t\tm = floor(alpha / " << s2a << ");\n" << "\t\toffsetAl = alpha - m * " << s2a << ";\n" << "\t\tn = floor(beta / " << s2b << ");\n" << "\t\toffsetBe = beta - n * " << s2b << ";\n" << "\t\toffsetGa = " << s2c << " + fma(-" << ac << ", offsetAl, -" << bc << " * offsetBe);\n" << "\n" << "\t\tif (offsetGa > 0)\n" << "\t\t{\n" << "\n" << "\t\t Hex(offsetAl, offsetBe, offsetGa,\n" << "\t\t " << width << ",\n" << "\t\t " << ha << ",\n" << "\t\t " << hb << ",\n" << "\t\t " << hc << ",\n" << "\t\t " << ab << ",\n" << "\t\t " << ba << ",\n" << "\t\t " << bc << ",\n" << "\t\t " << ca << ",\n" << "\t\t " << cb << ",\n" << "\t\t " << s2a << ",\n" << "\t\t " << s2b << ",\n" << "\t\t " << s2ab << ",\n" << "\t\t " << s2ac << ",\n" << "\t\t " << s2bc << ",\n" << "\t\t " << width1 << ",\n" << "\t\t " << width2 << ",\n" << "\t\t " << width3 << ",\n" << "\t\t &alpha, &beta, mwc);\n" << "\n" << "\t\t}\n" << "\t\telse\n" << "\t\t{\n" << "\t\t offsetAl = " << s2a << " - offsetAl;\n" << "\t\t offsetBe = " << s2b << " - offsetBe;\n" << "\t\t offsetGa = -offsetGa;\n" << "\n" << "\t\t Hex(offsetAl, offsetBe, offsetGa,\n" << "\t\t " << width << ",\n" << "\t\t " << ha << ",\n" << "\t\t " << hb << ",\n" << "\t\t " << hc << ",\n" << "\t\t " << ab << ",\n" << "\t\t " << ba << ",\n" << "\t\t " << bc << ",\n" << "\t\t " << ca << ",\n" << "\t\t " << cb << ",\n" << "\t\t " << s2a << ",\n" << "\t\t " << s2b << ",\n" << "\t\t " << s2ab << ",\n" << "\t\t " << s2ac << ",\n" << "\t\t " << s2bc << ",\n" << "\t\t " << width1 << ",\n" << "\t\t " << width2 << ",\n" << "\t\t " << width3 << ",\n" << "\t\t &alpha, &beta, mwc);\n" << "\n" << "\t\t alpha = " << s2a << " - alpha;\n" << "\t\t beta = " << s2b << " - beta;\n" << "\t\t}\n" << "\n" << "\t\talpha += m * " << s2a << ";\n" << "\t\tbeta += n * " << s2b << ";\n" << "\n" << "\t\t{\n"//InverseTrilinear function extracted out here. << "\t\t real_t inx = fma(alpha - " << radius << ", " << cosC << ", beta - " << radius << ") / " << sinC << ";\n" << "\t\t real_t iny = alpha - " << radius << ";\n" << "\t\t real_t angle = fma(M_2PI, (real_t)MwcNextRange(mwc, (int)" << absN << "), atan2(iny, inx)) / " << power << ";\n" << "\t\t real_t r = " << weight << " * pow(fma(inx, inx, SQR(iny)), " << cn << ");\n" << "\n" << "\t\t x = r * cos(angle);\n" << "\t\t y = r * sin(angle);\n" << "\t\t}\n" << "\n" << "\t\tvOut.x = " << weight << " * x;\n" << "\t\tvOut.y = " << weight << " * y;\n" << "\t\tvOut.z = " << DefaultZCl() << "\t}\n"; return ss.str(); } virtual string OpenCLFuncsString() const override { return "\n" "void Hex(real_t al, real_t be, real_t ga,\n" " real_t width,\n" " real_t ha,\n" " real_t hb,\n" " real_t hc,\n" " real_t ab,\n" " real_t ba,\n" " real_t bc,\n" " real_t ca,\n" " real_t cb,\n" " real_t s2a,\n" " real_t s2b,\n" " real_t s2ab,\n" " real_t s2ac,\n" " real_t s2bc,\n" " real_t width1,\n" " real_t width2,\n" " real_t width3,\n" " real_t* al1, real_t* be1, uint2* mwc)\n" "{\n" " real_t ga1, de1, r = MwcNext01(mwc);\n" "\n" " if (be < al)\n" " {\n" " if (ga < be)\n" " {\n" " if (r >= width3)\n" " {\n" " de1 = width * be;\n" " ga1 = width * ga;\n" " }\n" " else\n" " {\n" " ga1 = fma(width1, ga, width2 * hc * ga / be);\n" " de1 = fma(width1, be, width2 * s2ab * (3 - ga / be));\n" " }\n" "\n" " *al1 = s2a + fma(-ba, de1, - ca * ga1);\n" " *be1 = de1;\n" " }\n" " else\n" " {\n" " if (ga < al)\n" " {\n" " if (r >= width3)\n" " {\n" " ga1 = width * ga;\n" " de1 = width * be;\n" " }\n" " else\n" " {\n" " de1 = fma(width1, be, width2 * hb * be / ga);\n" " ga1 = fma(width1, ga, width2 * s2ac * (3 - be / ga));\n" " }\n" "\n" " *al1 = s2a + fma(-ba, de1, -ca * ga1);\n" " *be1 = de1;\n" " }\n" " else\n" " {\n" " if (r >= width3)\n" " {\n" " *al1 = width * al;\n" " *be1 = width * be;\n" " }\n" " else\n" " {\n" " *be1 = fma(width1, be, width2 * hb * be / al);\n" " *al1 = fma(width1, al, width2 * s2ac * (3 - be / al));\n" " }\n" " }\n" " }\n" " }\n" " else\n" " {\n" " if (ga < al)\n" " {\n" " if (r >= width3)\n" " {\n" " de1 = width * al;\n" " ga1 = width * ga;\n" " }\n" " else\n" " {\n" " ga1 = fma(width1, ga, width2 * hc * ga / al);\n" " de1 = fma(width1, al, width2 * s2ab * (3 - ga / al));\n" " }\n" "\n" " *be1 = s2b + fma(-ab, de1, -cb * ga1);\n" " *al1 = de1;\n" " }\n" " else\n" " {\n" " if (ga < be)\n" " {\n" " if (r >= width3)\n" " {\n" " ga1 = width * ga;\n" " de1 = width * al;\n" " }\n" " else\n" " {\n" " de1 = fma(width1, al, width2 * ha * al / ga);\n" " ga1 = fma(width1, ga, width2 * s2bc * (3 - al / ga));\n" " }\n" "\n" " *be1 = s2b + fma(-ab, de1, -cb * ga1);\n" " *al1 = de1;\n" " }\n" " else\n" " {\n" " if (r >= width3)\n" " {\n" " *be1 = width * be;\n" " *al1 = width * al;\n" " }\n" " else\n" " {\n" " *al1 = fma(width1, al, width2 * ha * al / be);\n" " *be1 = fma(width1, be, width2 * s2bc * (3 - al / be));\n" " }\n" " }\n" " }\n" " }\n" "}\n" "\n" ; } virtual void Precalc() override { T s2, sinA2, cosA2, sinB2, cosB2, sinC2, cosC2; T br = T(0.047) + m_A; T cr = T(0.047) + m_B; T ar = T(M_PI) - br - cr; T temp = ar / 2; sincos(temp, &sinA2, &cosA2); temp = br / 2; sincos(temp, &sinB2, &cosB2); temp = cr / 2; sincos(temp, &sinC2, &cosC2); sincos(cr, &m_SinC, &m_CosC); T a = m_Radius * (sinC2 / cosC2 + sinB2 / cosB2); T b = m_Radius * (sinC2 / cosC2 + sinA2 / cosA2); T c = m_Radius * (sinB2 / cosB2 + sinA2 / cosA2); m_Width1 = 1 - m_Width; m_Width2 = 2 * m_Width; m_Width3 = 1 - m_Width * m_Width; s2 = m_Radius * (a + b + c); m_Ha = s2 / a / 6; m_Hb = s2 / b / 6; m_Hc = s2 / c / 6; m_Ab = a / b;// a div on b m_Ac = a / c; m_Ba = b / a; m_Bc = b / c; m_Ca = c / a; m_Cb = c / b; m_S2a = 6 * m_Ha; m_S2b = 6 * m_Hb; m_S2c = 6 * m_Hc; m_S2bc = s2 / (b + c) / 6; m_S2ab = s2 / (a + b) / 6; m_S2ac = s2 / (a + c) / 6; if (m_Power == 0) m_Power = 2; m_AbsN = T(int(std::abs(m_Power))); m_Cn = m_Dist / m_Power / 2; } protected: void Init() { string prefix = Prefix(); m_Params.clear(); m_Params.push_back(ParamWithName(&m_Power, prefix + "xtrb_power", 2, eParamType::INTEGER_NONZERO)); m_Params.push_back(ParamWithName(&m_Radius, prefix + "xtrb_radius", 1)); m_Params.push_back(ParamWithName(&m_Width, prefix + "xtrb_width", T(0.5))); m_Params.push_back(ParamWithName(&m_Dist, prefix + "xtrb_dist", 1)); m_Params.push_back(ParamWithName(&m_A, prefix + "xtrb_a", 1)); m_Params.push_back(ParamWithName(&m_B, prefix + "xtrb_b", 1)); m_Params.push_back(ParamWithName(true, &m_SinC, prefix + "xtrb_sinc"));//Precalcs. m_Params.push_back(ParamWithName(true, &m_CosC, prefix + "xtrb_cosc")); m_Params.push_back(ParamWithName(true, &m_Ha, prefix + "xtrb_ha")); m_Params.push_back(ParamWithName(true, &m_Hb, prefix + "xtrb_hb")); m_Params.push_back(ParamWithName(true, &m_Hc, prefix + "xtrb_hc")); m_Params.push_back(ParamWithName(true, &m_Ab, prefix + "xtrb_ab")); m_Params.push_back(ParamWithName(true, &m_Ac, prefix + "xtrb_ac")); m_Params.push_back(ParamWithName(true, &m_Ba, prefix + "xtrb_ba")); m_Params.push_back(ParamWithName(true, &m_Bc, prefix + "xtrb_bc")); m_Params.push_back(ParamWithName(true, &m_Ca, prefix + "xtrb_ca")); m_Params.push_back(ParamWithName(true, &m_Cb, prefix + "xtrb_cb")); m_Params.push_back(ParamWithName(true, &m_S2a, prefix + "xtrb_s2a")); m_Params.push_back(ParamWithName(true, &m_S2b, prefix + "xtrb_s2b")); m_Params.push_back(ParamWithName(true, &m_S2c, prefix + "xtrb_s2c")); m_Params.push_back(ParamWithName(true, &m_S2ab, prefix + "xtrb_s2ab")); m_Params.push_back(ParamWithName(true, &m_S2ac, prefix + "xtrb_s2ac")); m_Params.push_back(ParamWithName(true, &m_S2bc, prefix + "xtrb_s2bc")); m_Params.push_back(ParamWithName(true, &m_Width1, prefix + "xtrb_width1")); m_Params.push_back(ParamWithName(true, &m_Width2, prefix + "xtrb_width2")); m_Params.push_back(ParamWithName(true, &m_Width3, prefix + "xtrb_width3")); m_Params.push_back(ParamWithName(true, &m_AbsN, prefix + "xtrb_absn")); m_Params.push_back(ParamWithName(true, &m_Cn, prefix + "xtrb_cn")); } private: inline void DirectTrilinear(T x, T y, T& al, T& be) { al = y + m_Radius; be = x * m_SinC - y * m_CosC + m_Radius; } inline void InverseTrilinear(T al, T be, T& x, T& y, QTIsaac& rand) { T inx = (be - m_Radius + (al - m_Radius) * m_CosC) / m_SinC; T iny = al - m_Radius; T angle = (std::atan2(iny, inx) + M_2PI * (rand.Rand(int(m_AbsN)))) / m_Power; T r = m_Weight * std::pow(SQR(inx) + SQR(iny), m_Cn); x = r * std::cos(angle); y = r * std::sin(angle); } void Hex(T al, T be, T ga, T& al1, T& be1, QTIsaac& rand) { T ga1, de1, r = rand.Frand01(); if (be < al) { if (ga < be) { if (r >= m_Width3) { de1 = m_Width * be; ga1 = m_Width * ga; } else { ga1 = m_Width1 * ga + m_Width2 * m_Hc * ga / be; de1 = m_Width1 * be + m_Width2 * m_S2ab * (3 - ga / be); } al1 = m_S2a - m_Ba * de1 - m_Ca * ga1; be1 = de1; } else { if (ga < al) { if (r >= m_Width3) { ga1 = m_Width * ga; de1 = m_Width * be; } else { de1 = m_Width1 * be + m_Width2 * m_Hb * be / ga; ga1 = m_Width1 * ga + m_Width2 * m_S2ac * (3 - be / ga); } al1 = m_S2a - m_Ba * de1 - m_Ca * ga1; be1 = de1; } else { if (r >= m_Width3) { al1 = m_Width * al; be1 = m_Width * be; } else { be1 = m_Width1 * be + m_Width2 * m_Hb * be / al; al1 = m_Width1 * al + m_Width2 * m_S2ac * (3 - be / al); } } } } else { if (ga < al) { if (r >= m_Width3) { de1 = m_Width * al; ga1 = m_Width * ga; } else { ga1 = m_Width1 * ga + m_Width2 * m_Hc * ga / al; de1 = m_Width1 * al + m_Width2 * m_S2ab * (3 - ga / al); } be1 = m_S2b - m_Ab * de1 - m_Cb * ga1; al1 = de1; } else { if (ga < be) { if (r >= m_Width3) { ga1 = m_Width * ga; de1 = m_Width * al; } else { de1 = m_Width1 * al + m_Width2 * m_Ha * al / ga; ga1 = m_Width1 * ga + m_Width2 * m_S2bc * (3 - al / ga); } be1 = m_S2b - m_Ab * de1 - m_Cb * ga1; al1 = de1; } else { if (r >= m_Width3) { be1 = m_Width * be; al1 = m_Width * al; } else { al1 = m_Width1 * al + m_Width2 * m_Ha * al / be; be1 = m_Width1 * be + m_Width2 * m_S2bc * (3 - al / be); } } } } } T m_Power; T m_Radius; T m_Width; T m_Dist; T m_A; T m_B; T m_SinC;//Precalcs. T m_CosC; T m_Ha; T m_Hb; T m_Hc; T m_Ab; T m_Ac; T m_Ba; T m_Bc; T m_Ca; T m_Cb; T m_S2a; T m_S2b; T m_S2c; T m_S2ab; T m_S2ac; T m_S2bc; T m_Width1; T m_Width2; T m_Width3; T m_AbsN; T m_Cn; }; /// /// hexaplay3D. /// This uses state and the OpenCL version looks different and better than the CPU. /// template class Hexaplay3DVariation : public ParametricVariation { public: Hexaplay3DVariation(T weight = 1.0) : ParametricVariation("hexaplay3D", eVariationId::VAR_HEXAPLAY3D, weight) { Init(); } PARVARCOPY(Hexaplay3DVariation) virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { if (m_FCycle > 5) { m_FCycle = 0; m_RSwtch = std::trunc(rand.Frand01() * 3);//Chooses 6 or 3 nodes. } if (m_BCycle > 2) { m_BCycle = 0; m_RSwtch = std::trunc(rand.Frand01() * 3);//Chooses 6 or 3 nodes. } int posNeg = 1; int loc; T tempx, tempy; T lrmaj = m_Weight;//Sets hexagon length radius - major plane. T boost = 1;//Boost is the separation distance between the two planes. T sumX, sumY; if (m_VarType == eVariationType::VARTYPE_REG) { sumX = outPoint.m_X; sumY = outPoint.m_Y; outPoint.m_X = 0;//Only need to clear regular, pre and post will overwrite by default. outPoint.m_Y = 0; } else { sumX = helper.In.x; sumY = helper.In.y; } if (rand.Frand01() < T(0.5)) posNeg = -1; //Determine whether one or two major planes. int majplane = 1; T abmajp = std::abs(m_MajP); if (abmajp <= 1) { majplane = 1;//Want either 1 or 2. } else { majplane = 2; boost = (abmajp - 1) * T(0.5);//Distance above and below XY plane. } //Creating Z factors relative to the planes. These will be added, whereas x and y will be assigned. //Original does += z *, so using z on the right side of = is intentional. if (majplane == 2) helper.Out.z = helper.In.z * T(0.5) * m_ZLift + (posNeg * boost); else helper.Out.z = helper.In.z * T(0.5) * m_ZLift; //Work out the segments and hexagonal nodes. if (m_RSwtch <= 1)//Occasion to build using 60 degree segments. { loc = int(m_FCycle);//Sequential nodes selection. tempx = m_Seg60[loc].x; tempy = m_Seg60[loc].y; m_FCycle++; } else//Occasion to build on 120 degree segments. { loc = int(m_BCycle);//Sequential nodes selection. tempx = m_Seg120[loc].x; tempy = m_Seg120[loc].y; m_BCycle++; } helper.Out.x = ((sumX + helper.In.x) * m_HalfScale) + (lrmaj * tempx); helper.Out.y = ((sumY + helper.In.y) * m_HalfScale) + (lrmaj * tempy); } virtual string OpenCLString() const override { ostringstream ss, ss2; intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber(); string weight = WeightDefineString(); string index = ss2.str() + "]"; string stateIndex = ss2.str(); string majp = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string scale = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string zlift = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string seg60xStartIndex = ToUpper(m_Params[i].Name()) + stateIndex; i += 6;//Precalc. string seg60yStartIndex = ToUpper(m_Params[i].Name()) + stateIndex; i += 6; string seg120xStartIndex = ToUpper(m_Params[i].Name()) + stateIndex; i += 3; string seg120yStartIndex = ToUpper(m_Params[i].Name()) + stateIndex; i += 3; string halfScale = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string rswtch = "varState->" + m_Params[i++].Name() + stateIndex;//State. string fcycle = "varState->" + m_Params[i++].Name() + stateIndex; string bcycle = "varState->" + m_Params[i++].Name() + stateIndex; ss << "\t{\n" << "\t\tif (" << fcycle << " > 5)\n" << "\t\t{\n" << "\t\t " << fcycle << " = 0;\n" << "\t\t " << rswtch << " = trunc(MwcNext01(mwc) * 3.0);\n" << "\t\t}\n" << "\n" << "\t\tif (" << bcycle << " > 2)\n" << "\t\t{\n" << "\t\t " << bcycle << " = 0;\n" << "\t\t " << rswtch << " = trunc(MwcNext01(mwc) * 3.0);\n" << "\t\t}\n" << "\t\t\n" << "\t\tint posNeg = 1;\n" << "\t\tint loc;\n" << "\t\treal_t tempx, tempy;\n" << "\t\treal_t lrmaj = " << weight << ";\n" << "\t\treal_t boost = 1;\n" << "\t\treal_t sumX, sumY;\n\n"; if (m_VarType == eVariationType::VARTYPE_REG) { ss << "\t\tsumX = outPoint->m_X;\n" << "\t\tsumY = outPoint->m_Y;\n" << "\t\toutPoint->m_X = 0;\n" << "\t\toutPoint->m_Y = 0;\n"; } else { ss << "\t\tsumX = vIn.x;\n" << "\t\tsumY = vIn.y;\n"; } ss << "\t\t\n" << "\t\tif (MwcNext01(mwc) < 0.5)\n" << "\t\t posNeg = -1;\n" << "\n" << "\t\tint majplane = 1;\n" << "\t\treal_t abmajp = fabs(" << majp << ");\n" << "\n" << "\t\tif (abmajp <= 1)\n" << "\t\t{\n" << "\t\t majplane = 1;\n" << "\t\t}\n" << "\t\telse\n" << "\t\t{\n" << "\t\t majplane = 2;\n" << "\t\t boost = (abmajp - 1) * 0.5;\n" << "\t\t}\n" << "\n" << "\t\tif (majplane == 2)\n" << "\t\t vOut.z = fma(vIn.z * 0.5, " << zlift << ", (posNeg * boost));\n" << "\t\telse\n" << "\t\t vOut.z = vIn.z * 0.5 * " << zlift << ";\n" << "\n" << "\t\tif (" << rswtch << " <= 1)\n" << "\t\t{\n" << "\t\t loc = (int)" << fcycle << ";\n" << "\t\t tempx = parVars[" << seg60xStartIndex << " + loc];\n" << "\t\t tempy = parVars[" << seg60yStartIndex << " + loc];\n" << "\t\t " << fcycle << " = " << fcycle << " + 1;\n" << "\t\t}\n" << "\t\telse\n" << "\t\t{\n" << "\t\t loc = (int)" << bcycle << ";\n" << "\t\t tempx = parVars[" << seg120xStartIndex << " + loc];\n" << "\t\t tempy = parVars[" << seg120yStartIndex << " + loc];\n" << "\t\t " << bcycle << " = " << bcycle << " + 1;\n" << "\t\t}\n" << "\n" << "\t\tvOut.x = fma((sumX + vIn.x), " << halfScale << ", (lrmaj * tempx));\n" << "\t\tvOut.y = fma((sumY + vIn.y), " << halfScale << ", (lrmaj * tempy));\n" << "\t}\n"; return ss.str(); } virtual string StateInitOpenCLString() const override { ostringstream ss, ss2; ss2 << "_" << XformIndexInEmber(); string stateIndex = ss2.str(); string prefix = Prefix(); //CPU sets fycle and bcycle to 0 at the beginning in Precalc(). //Set to random in OpenCL since a value can't be set once and kept between kernel launches without writing it back to an OpenCL buffer. ss << "\n\tvarState." << prefix << "hexaplay3D_rswtch" << stateIndex << " = trunc(MwcNext01(&mwc) * 3.0);"; ss << "\n\tvarState." << prefix << "hexaplay3D_fcycle" << stateIndex << " = trunc(MwcNext01(&mwc) * 5.0);"; ss << "\n\tvarState." << prefix << "hexaplay3D_bcycle" << stateIndex << " = trunc(MwcNext01(&mwc) * 2.0);"; return ss.str(); } virtual void Precalc() override { T hlift = std::sin(T(M_PI) / 3); m_RSwtch = std::trunc(QTIsaac::LockedFrand01() * 3);//Chooses 6 or 3 nodes. m_FCycle = 0; m_BCycle = 0; m_Seg60[0].x = 1; m_Seg60[1].x = T(0.5); m_Seg60[2].x = T(-0.5); m_Seg60[3].x = -1; m_Seg60[4].x = T(-0.5); m_Seg60[5].x = T(0.5); m_Seg60[0].y = 0; m_Seg60[1].y = hlift; m_Seg60[2].y = hlift; m_Seg60[3].y = 0; m_Seg60[4].y = -hlift; m_Seg60[5].y = -hlift; m_Seg120[0].x = 1; m_Seg120[1].x = T(-0.5); m_Seg120[2].x = T(-0.5); m_Seg120[0].y = 0; m_Seg120[1].y = hlift; m_Seg120[2].y = -hlift; m_HalfScale = m_Scale * T(0.5); } protected: void Init() { string prefix = Prefix(); m_Params.clear(); m_Params.reserve(25); m_Params.push_back(ParamWithName(&m_MajP, prefix + "hexaplay3D_majp", 1, eParamType::REAL)); m_Params.push_back(ParamWithName(&m_Scale, prefix + "hexaplay3D_scale", T(0.25), eParamType::REAL)); m_Params.push_back(ParamWithName(&m_ZLift, prefix + "hexaplay3D_zlift", T(0.25), eParamType::REAL)); m_Params.push_back(ParamWithName(true, &m_Seg60[0].x, prefix + "hexaplay3D_seg60x0"));//Precalc. m_Params.push_back(ParamWithName(true, &m_Seg60[1].x, prefix + "hexaplay3D_seg60x1")); m_Params.push_back(ParamWithName(true, &m_Seg60[2].x, prefix + "hexaplay3D_seg60x2")); m_Params.push_back(ParamWithName(true, &m_Seg60[3].x, prefix + "hexaplay3D_seg60x3")); m_Params.push_back(ParamWithName(true, &m_Seg60[4].x, prefix + "hexaplay3D_seg60x4")); m_Params.push_back(ParamWithName(true, &m_Seg60[5].x, prefix + "hexaplay3D_seg60x5")); m_Params.push_back(ParamWithName(true, &m_Seg60[0].y, prefix + "hexaplay3D_seg60y0")); m_Params.push_back(ParamWithName(true, &m_Seg60[1].y, prefix + "hexaplay3D_seg60y1")); m_Params.push_back(ParamWithName(true, &m_Seg60[2].y, prefix + "hexaplay3D_seg60y2")); m_Params.push_back(ParamWithName(true, &m_Seg60[3].y, prefix + "hexaplay3D_seg60y3")); m_Params.push_back(ParamWithName(true, &m_Seg60[4].y, prefix + "hexaplay3D_seg60y4")); m_Params.push_back(ParamWithName(true, &m_Seg60[5].y, prefix + "hexaplay3D_seg60y5")); m_Params.push_back(ParamWithName(true, &m_Seg120[0].x, prefix + "hexaplay3D_seg120x0")); m_Params.push_back(ParamWithName(true, &m_Seg120[1].x, prefix + "hexaplay3D_seg120x1")); m_Params.push_back(ParamWithName(true, &m_Seg120[2].x, prefix + "hexaplay3D_seg120x2")); m_Params.push_back(ParamWithName(true, &m_Seg120[0].y, prefix + "hexaplay3D_seg120y0")); m_Params.push_back(ParamWithName(true, &m_Seg120[1].y, prefix + "hexaplay3D_seg120y1")); m_Params.push_back(ParamWithName(true, &m_Seg120[2].y, prefix + "hexaplay3D_seg120y2")); m_Params.push_back(ParamWithName(true, &m_HalfScale, prefix + "hexaplay3D_halfscale")); m_Params.push_back(ParamWithName(true, true, &m_RSwtch, prefix + "hexaplay3D_rswtch"));//State. m_Params.push_back(ParamWithName(true, true, &m_FCycle, prefix + "hexaplay3D_fcycle")); m_Params.push_back(ParamWithName(true, true, &m_BCycle, prefix + "hexaplay3D_bcycle")); } private: T m_MajP; T m_Scale; T m_ZLift; v2T m_Seg60[6];//Precalc. v2T m_Seg120[3]; T m_HalfScale; T m_RSwtch;//State. T m_FCycle; T m_BCycle; }; /// /// hexnix3D. /// This uses state and the OpenCL version looks different and better than the CPU. /// It takes care of doing either a sum or product of the output variables internally, /// rather than relying on the calling code of Xform::Apply() to do it. /// This is because different paths do different things to helper.Out.z /// template class Hexnix3DVariation : public ParametricVariation { public: Hexnix3DVariation(T weight = 1.0) : ParametricVariation("hexnix3D", eVariationId::VAR_HEXNIX3D, weight) { Init(); } PARVARCOPY(Hexnix3DVariation) virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { if (m_FCycle > 5) { m_FCycle = 0; m_RSwtch = std::trunc(rand.Frand01() * 3);//Chooses 6 or 3 nodes. } if (m_BCycle > 2) { m_BCycle = 0; m_RSwtch = std::trunc(rand.Frand01() * 3);//Chooses 6 or 3 nodes. } T lrmaj = m_Weight; T smooth = 1; T smRotxFP = 0; T smRotyFP = 0; T smRotxFT = 0; T smRotyFT = 0; T gentleZ = 0; T sumX, sumY, sumZ; if (m_VarType == eVariationType::VARTYPE_REG) { sumX = outPoint.m_X; sumY = outPoint.m_Y; sumZ = outPoint.m_Z; outPoint.m_X = 0; outPoint.m_Y = 0;//Z is optionally cleared and assigned to below. } else { sumX = helper.In.x; sumY = helper.In.y; sumZ = helper.In.z; } if (std::abs(m_Weight) <= 0.5) smooth = m_Weight * 2; else smooth = 1; int posNeg = 1; int loc; T boost = 0; T scale = m_Scale; T scale3; T tempx, tempy; if (rand.Frand01() < T(0.5)) posNeg = -1; int majplane = 0; T abmajp = std::abs(m_MajP); if (abmajp <= 1) { majplane = 0; boost = 0; } else if (abmajp > 1 && abmajp < 2) { majplane = 1; boost = 0; } else { majplane = 2; boost = (abmajp - 2) * T(0.5); } if (majplane == 0) { helper.Out.z = smooth * helper.In.z * scale * m_ZLift; } else if (majplane == 1 && m_MajP < 0) { if (m_MajP < -1 && m_MajP >= -2) gentleZ = (abmajp - 1); else gentleZ = 1; if (posNeg < 0) helper.Out.z = -2 * (sumZ * gentleZ); } if (majplane == 2 && m_MajP < 0) { if (posNeg > 0) { helper.Out.z = (smooth * (helper.In.z * scale * m_ZLift + boost)); } else//For this case when reg, assign and zero out. For all others, sum as usual. { helper.Out.z = (sumZ - (2 * smooth * sumZ)) + (smooth * posNeg * (helper.In.z * scale * m_ZLift + boost)); if (m_VarType == eVariationType::VARTYPE_REG) outPoint.m_Z = 0; } } else helper.Out.z = smooth * (helper.In.z * scale * m_ZLift + (posNeg * boost)); if (m_RSwtch <= 1) { loc = int(rand.Frand01() * 6); tempx = m_Seg60[loc].x; tempy = m_Seg60[loc].y; scale3 = 1; m_FCycle++; } else { loc = int(rand.Frand01() * 3); tempx = m_Seg120[loc].x; tempy = m_Seg120[loc].y; scale3 = m_3side; m_BCycle++; } smRotxFP = (smooth * scale * sumX * tempx) - (smooth * scale * sumY * tempy); smRotyFP = (smooth * scale * sumY * tempx) + (smooth * scale * sumX * tempy); smRotxFT = (helper.In.x * smooth * scale * tempx) - (helper.In.y * smooth * scale * tempy); smRotyFT = (helper.In.y * smooth * scale * tempx) + (helper.In.x * smooth * scale * tempy); helper.Out.x = sumX * (1 - smooth) + smRotxFP + smRotxFT + smooth * lrmaj * scale3 * tempx; helper.Out.y = sumY * (1 - smooth) + smRotyFP + smRotyFT + smooth * lrmaj * scale3 * tempy; } virtual string OpenCLString() const override { ostringstream ss, ss2; intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber(); string weight = WeightDefineString(); string index = ss2.str() + "]"; string stateIndex = ss2.str(); string majp = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string scale = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string zlift = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string side3 = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string seg60xStartIndex = ToUpper(m_Params[i].Name()) + stateIndex; i += 6;//Precalc. string seg60yStartIndex = ToUpper(m_Params[i].Name()) + stateIndex; i += 6; string seg120xStartIndex = ToUpper(m_Params[i].Name()) + stateIndex; i += 3; string seg120yStartIndex = ToUpper(m_Params[i].Name()) + stateIndex; i += 3; string rswtch = "varState->" + m_Params[i++].Name() + stateIndex;//State. string fcycle = "varState->" + m_Params[i++].Name() + stateIndex; string bcycle = "varState->" + m_Params[i++].Name() + stateIndex; ss << "\t{\n" << "\t\tif (" << fcycle << " > 5)\n" << "\t\t{\n" << "\t\t " << fcycle << " = 0;\n" << "\t\t " << rswtch << " = trunc(MwcNext01(mwc) * 3.0);\n" << "\t\t}\n" << "\n" << "\t\tif (" << bcycle << " > 2)\n" << "\t\t{\n" << "\t\t " << bcycle << " = 0;\n" << "\t\t " << rswtch << " = trunc(MwcNext01(mwc) * 3.0);\n" << "\t\t}\n" << "\n" << "\t\treal_t lrmaj = " << weight << ";\n" << "\t\treal_t smooth = 1;\n" << "\t\treal_t smRotxFP = 0;\n" << "\t\treal_t smRotyFP = 0;\n" << "\t\treal_t smRotxFT = 0;\n" << "\t\treal_t smRotyFT = 0;\n" << "\t\treal_t gentleZ = 0;\n" << "\t\treal_t sumX, sumY, sumZ;\n\n"; if (m_VarType == eVariationType::VARTYPE_REG) { ss << "\t\tsumX = outPoint->m_X;\n" << "\t\tsumY = outPoint->m_Y;\n" << "\t\tsumZ = outPoint->m_Z;\n" << "\t\toutPoint->m_X = 0;\n" << "\t\toutPoint->m_Y = 0;\n"; } else { ss << "\t\tsumX = vIn.x;\n" << "\t\tsumY = vIn.y;\n" << "\t\tsumZ = vIn.z;\n"; } ss << "\n" << "\t\tif (fabs(lrmaj) <= 0.5)\n" << "\t\t smooth = lrmaj * 2;\n" << "\t\telse\n" << "\t\t smooth = 1;\n" << "\n" << "\t\tint posNeg = 1;\n" << "\t\tint loc;\n" << "\t\treal_t boost = 0;\n" << "\t\treal_t scale = " << scale << ";\n"//Temp will be used from here on. << "\t\treal_t scale3;\n" << "\t\treal_t tempx, tempy;\n" << "\n" << "\t\tif (MwcNext01(mwc) < 0.5)\n" << "\t\t posNeg = -1;\n" << "\n" << "\t\tint majplane = 0;\n" << "\t\treal_t abmajp = fabs(" << majp << ");\n" << "\n" << "\t\tif (abmajp <= 1)\n" << "\t\t{\n" << "\t\t majplane = 0;\n" << "\t\t boost = 0;\n" << "\t\t}\n" << "\t\telse if (abmajp > 1 && abmajp < 2)\n" << "\t\t{\n" << "\t\t majplane = 1;\n" << "\t\t boost = 0;\n" << "\t\t}\n" << "\t\telse\n" << "\t\t{\n" << "\t\t majplane = 2;\n" << "\t\t boost = (abmajp - 2) * 0.5;\n" << "\t\t}\n" << "\n" << "\t\tif (majplane == 0)\n" << "\t\t{\n" << "\t\t vOut.z = smooth * vIn.z * scale * " << zlift << ";\n" << "\t\t}\n" << "\t\telse if (majplane == 1 && " << majp << " < 0)\n" << "\t\t{\n" << "\t\t if (" << majp << " < -1 && " << majp << " >= -2)\n" << "\t\t gentleZ = (abmajp - 1);\n" << "\t\t else\n" << "\t\t gentleZ = 1;\n" << "\n" << "\t\t if (posNeg < 0)\n" << "\t\t vOut.z = -2 * (sumZ * gentleZ);\n" << "\t\t}\n" << "\n" << "\t\tif (majplane == 2 && " << majp << " < 0)\n" << "\t\t{\n" << "\t\t if (posNeg > 0)\n" << "\t\t {\n" << "\t\t vOut.z = (smooth * fma(vIn.z * scale, " << zlift << ", boost));\n" << "\t\t }\n" << "\t\t else\n" << "\t\t {\n" << "\t\t vOut.z = fma(smooth * posNeg, fma(vIn.z * scale, " << zlift << ", boost), sumZ - (2 * smooth * sumZ));\n"; if (m_VarType == eVariationType::VARTYPE_REG) ss << "\t\t outPoint->m_Z = 0;\n"; ss << "\t\t }\n" << "\t\t}\n" << "\t\telse\n" << "\t\t{\n" << "\t\t vOut.z = smooth * fma(vIn.z * scale, " << zlift << ", (posNeg * boost));\n" << "\t\t}\n" << "\n" << "\t\tif (" << rswtch << " <= 1)\n" << "\t\t{\n" << "\t\t loc = (int)(MwcNext01(mwc) * 6);\n" << "\t\t tempx = parVars[" << seg60xStartIndex << " + loc];\n" << "\t\t tempy = parVars[" << seg60yStartIndex << " + loc];\n" << "\t\t scale3 = 1;\n" << "\t\t " << fcycle << " = " << fcycle << " + 1;\n" << "\t\t}\n" << "\t\telse\n" << "\t\t{\n" << "\t\t loc = (int)(MwcNext01(mwc) * 3);\n" << "\t\t tempx = parVars[" << seg120xStartIndex << " + loc];\n" << "\t\t tempy = parVars[" << seg120yStartIndex << " + loc];\n" << "\t\t scale3 = " << side3 << ";\n" << "\t\t " << bcycle << " = " << bcycle << " + 1;\n" << "\t\t}\n" << "\n" << "\t\tsmRotxFP = fma(smooth * scale, sumX * tempx, -(smooth * scale * sumY * tempy));\n" << "\t\tsmRotyFP = fma(smooth * scale, sumY * tempx, (smooth * scale * sumX * tempy));\n" << "\t\tsmRotxFT = fma(vIn.x * smooth, scale * tempx, -(vIn.y * smooth * scale * tempy));\n" << "\t\tsmRotyFT = fma(vIn.y * smooth, scale * tempx, (vIn.x * smooth * scale * tempy));\n" << "\t\tvOut.x = fma(sumX, (1 - smooth), fma(smooth * lrmaj, scale3 * tempx, smRotxFP + smRotxFT));\n" << "\t\tvOut.y = fma(sumY, (1 - smooth), fma(smooth * lrmaj, scale3 * tempy, smRotyFP + smRotyFT));\n" << "\t}\n"; return ss.str(); } virtual string StateInitOpenCLString() const override { ostringstream ss, ss2; ss2 << "_" << XformIndexInEmber(); string stateIndex = ss2.str(); string prefix = Prefix(); //CPU sets fycle and bcycle to 0 at the beginning in Precalc(). //Set to random in OpenCL since a value can't be set once and kept between kernel launches without writing it back to an OpenCL buffer. //This doesn't seem to make a difference from setting them to 0, but do it anyway because it seems more correct. ss << "\n\tvarState." << prefix << "hexnix3D_rswtch" << stateIndex << " = trunc(MwcNext01(&mwc) * 3.0);"; ss << "\n\tvarState." << prefix << "hexnix3D_fcycle" << stateIndex << " = trunc(MwcNext01(&mwc) * 5.0);"; ss << "\n\tvarState." << prefix << "hexnix3D_bcycle" << stateIndex << " = trunc(MwcNext01(&mwc) * 2.0);"; return ss.str(); } virtual void Precalc() override { T hlift = std::sin(T(M_PI) / 3); m_RSwtch = std::trunc(QTIsaac::LockedFrand01() * 3);//Chooses 6 or 3 nodes. m_FCycle = 0; m_BCycle = 0; m_Seg60[0].x = 1; m_Seg60[1].x = T(0.5); m_Seg60[2].x = T(-0.5); m_Seg60[3].x = -1; m_Seg60[4].x = T(-0.5); m_Seg60[5].x = T(0.5); m_Seg60[0].y = 0; m_Seg60[1].y = -hlift; m_Seg60[2].y = -hlift; m_Seg60[3].y = 0; m_Seg60[4].y = hlift; m_Seg60[5].y = hlift; m_Seg120[0].x = 0; m_Seg120[1].x = std::cos(7 * T(M_PI) / 6); m_Seg120[2].x = std::cos(11 * T(M_PI) / 6); m_Seg120[0].y = -1; m_Seg120[1].y = T(0.5); m_Seg120[2].y = T(0.5); } protected: void Init() { string prefix = Prefix(); m_Params.clear(); m_Params.reserve(25); m_Params.push_back(ParamWithName(&m_MajP, prefix + "hexnix3D_majp", 1, eParamType::REAL)); m_Params.push_back(ParamWithName(&m_Scale, prefix + "hexnix3D_scale", T(0.25), eParamType::REAL)); m_Params.push_back(ParamWithName(&m_ZLift, prefix + "hexnix3D_zlift")); m_Params.push_back(ParamWithName(&m_3side, prefix + "hexnix3D_3side", T(0.667), eParamType::REAL)); m_Params.push_back(ParamWithName(true, &m_Seg60[0].x, prefix + "hexnix3D_seg60x0"));//Precalc. m_Params.push_back(ParamWithName(true, &m_Seg60[1].x, prefix + "hexnix3D_seg60x1")); m_Params.push_back(ParamWithName(true, &m_Seg60[2].x, prefix + "hexnix3D_seg60x2")); m_Params.push_back(ParamWithName(true, &m_Seg60[3].x, prefix + "hexnix3D_seg60x3")); m_Params.push_back(ParamWithName(true, &m_Seg60[4].x, prefix + "hexnix3D_seg60x4")); m_Params.push_back(ParamWithName(true, &m_Seg60[5].x, prefix + "hexnix3D_seg60x5")); m_Params.push_back(ParamWithName(true, &m_Seg60[0].y, prefix + "hexnix3D_seg60y0")); m_Params.push_back(ParamWithName(true, &m_Seg60[1].y, prefix + "hexnix3D_seg60y1")); m_Params.push_back(ParamWithName(true, &m_Seg60[2].y, prefix + "hexnix3D_seg60y2")); m_Params.push_back(ParamWithName(true, &m_Seg60[3].y, prefix + "hexnix3D_seg60y3")); m_Params.push_back(ParamWithName(true, &m_Seg60[4].y, prefix + "hexnix3D_seg60y4")); m_Params.push_back(ParamWithName(true, &m_Seg60[5].y, prefix + "hexnix3D_seg60y5")); m_Params.push_back(ParamWithName(true, &m_Seg120[0].x, prefix + "hexnix3D_seg120x0")); m_Params.push_back(ParamWithName(true, &m_Seg120[1].x, prefix + "hexnix3D_seg120x1")); m_Params.push_back(ParamWithName(true, &m_Seg120[2].x, prefix + "hexnix3D_seg120x2")); m_Params.push_back(ParamWithName(true, &m_Seg120[0].y, prefix + "hexnix3D_seg120y0")); m_Params.push_back(ParamWithName(true, &m_Seg120[1].y, prefix + "hexnix3D_seg120y1")); m_Params.push_back(ParamWithName(true, &m_Seg120[2].y, prefix + "hexnix3D_seg120y2")); m_Params.push_back(ParamWithName(true, true, &m_RSwtch, prefix + "hexnix3D_rswtch"));//State. m_Params.push_back(ParamWithName(true, true, &m_FCycle, prefix + "hexnix3D_fcycle")); m_Params.push_back(ParamWithName(true, true, &m_BCycle, prefix + "hexnix3D_bcycle")); } private: T m_MajP; T m_Scale; T m_ZLift; T m_3side; v2T m_Seg60[6];//Precalc. v2T m_Seg120[3]; T m_RSwtch;//State. T m_FCycle; T m_BCycle; }; /// /// hexcrop. /// template class HexcropVariation : public ParametricVariation { public: HexcropVariation(T weight = 1.0) : ParametricVariation("hexcrop", eVariationId::VAR_HEXCROP, weight) { Init(); } PARVARCOPY(HexcropVariation) virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { v2T i; int c = 0, n = -1, j = 5; i.x = helper.In.x + m_CenterX; i.y = helper.In.y + m_CenterY; while (++n < 6) { if ((m_P[n].y <= i.y && i.y < m_P[j].y) || (m_P[j].y <= i.y && i.y < m_P[n].y)) if (i.x < (m_P[j].x - m_P[n].x) * (i.y - m_P[n].y) / Zeps(m_P[j].y - m_P[n].y) + m_P[n].x) c ^= 1; j = n; } if (m_VarType == eVariationType::VARTYPE_REG) { helper.Out.x = c != 0 ? outPoint.m_X + i.x * m_Weight : m_Dropoff; helper.Out.y = c != 0 ? outPoint.m_Y + i.y * m_Weight : m_Dropoff; outPoint.m_X = 0; outPoint.m_Y = 0; } else { helper.Out.x = c != 0 ? i.x * m_Weight : m_Dropoff; helper.Out.y = c != 0 ? i.y * m_Weight : m_Dropoff; } helper.Out.z = m_Weight * helper.In.z; } virtual string OpenCLString() const override { ostringstream ss, ss2; intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber(); string weight = WeightDefineString(); string index = ss2.str() + "]"; string stateIndex = ss2.str(); string scalex = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string scaley = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string centerx = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string centery = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string dropoff = "parVars[" + ToUpper(m_Params[i++].Name()) + index; string pxStartIndex = ToUpper(m_Params[i].Name()) + stateIndex; i += 6;//Precalc. string pyStartIndex = ToUpper(m_Params[i].Name()) + stateIndex; ss << "\t{\n" << "\t\treal2 i;\n" << "\t\tint c = 0, n = -1, j = 5;\n" << "\n" << "\t\ti.x = vIn.x + " << centerx << ";\n" << "\t\ti.y = vIn.y + " << centery << ";\n" << "\n" << "\t\twhile (++n < 6)\n" << "\t\t{\n" << "\t\t int xjoff = " << pxStartIndex << " + j;\n" << "\t\t int xnoff = " << pxStartIndex << " + n;\n" << "\t\t int yjoff = " << pyStartIndex << " + j;\n" << "\t\t int ynoff = " << pyStartIndex << " + n;\n" << "\n" << "\t\t if ((parVars[ynoff] <= i.y && i.y < parVars[yjoff]) || (parVars[yjoff] <= i.y && i.y < parVars[ynoff]))\n" << "\t\t if (i.x < (parVars[xjoff] - parVars[xnoff]) * (i.y - parVars[ynoff]) / Zeps(parVars[yjoff] - parVars[ynoff]) + parVars[xnoff])\n" << "\t\t c ^= 1;\n" << "\n" << "\t\t j = n;\n" << "\t\t}\n" << "\n"; if (m_VarType == eVariationType::VARTYPE_REG) { ss << "\t\tvOut.x = c != 0 ? fma(i.x, " << weight << ", outPoint->m_X) : " << dropoff << ";\n" << "\t\tvOut.y = c != 0 ? fma(i.y, " << weight << ", outPoint->m_Y) : " << dropoff << ";\n" << "\t\toutPoint->m_X = 0;\n" << "\t\toutPoint->m_Y = 0;\n"; } else { ss << "\t\tvOut.x = c != 0 ? i.x * " << weight << " : " << dropoff << ";\n" << "\t\tvOut.y = c != 0 ? i.y * " << weight << " : " << dropoff << ";\n"; } ss << "\t\tvOut.z = " << weight << " * vIn.z;\n" << "\t}\n"; return ss.str(); } virtual void Precalc() override { m_P[0].x = T(-0.5000000000000000000000000000000) * m_ScaleX; m_P[0].y = T(1.0606601717798212866012665431573) * m_ScaleY; m_P[1].x = T(0.5000000000000000000000000000000) * m_ScaleX; m_P[1].y = T(1.0606601717798212866012665431573) * m_ScaleY; m_P[2].x = T(1.4142135623730950488016887242097) * m_ScaleX; m_P[2].y = T(0.0000000000000000000000000000000) * m_ScaleY; m_P[3].x = T(0.5000000000000000000000000000000) * m_ScaleX; m_P[3].y = T(-1.0606601717798212866012665431573) * m_ScaleY; m_P[4].x = T(-0.5000000000000000000000000000000) * m_ScaleX; m_P[4].y = T(-1.0606601717798212866012665431573) * m_ScaleY; m_P[5].x = T(-1.4142135623730950488016887242097) * m_ScaleX; m_P[5].y = T(0.0000000000000000000000000000000) * m_ScaleY; } virtual vector OpenCLGlobalFuncNames() const override { return vector { "Zeps" }; } protected: void Init() { string prefix = Prefix(); m_Params.clear(); m_Params.reserve(17); m_Params.push_back(ParamWithName(&m_ScaleX, prefix + "hexcrop_scale_x", 1)); m_Params.push_back(ParamWithName(&m_ScaleY, prefix + "hexcrop_scale_y", 1)); m_Params.push_back(ParamWithName(&m_CenterX, prefix + "hexcrop_center_x")); m_Params.push_back(ParamWithName(&m_CenterY, prefix + "hexcrop_center_y")); m_Params.push_back(ParamWithName(&m_Dropoff, prefix + "hexcrop_dropoff", T(1E10))); m_Params.push_back(ParamWithName(true, &m_P[0].x, prefix + "hexcrop_px0"));//Precalc. m_Params.push_back(ParamWithName(true, &m_P[1].x, prefix + "hexcrop_px1")); m_Params.push_back(ParamWithName(true, &m_P[2].x, prefix + "hexcrop_px2")); m_Params.push_back(ParamWithName(true, &m_P[3].x, prefix + "hexcrop_px3")); m_Params.push_back(ParamWithName(true, &m_P[4].x, prefix + "hexcrop_px4")); m_Params.push_back(ParamWithName(true, &m_P[5].x, prefix + "hexcrop_px5")); m_Params.push_back(ParamWithName(true, &m_P[0].y, prefix + "hexcrop_py0")); m_Params.push_back(ParamWithName(true, &m_P[1].y, prefix + "hexcrop_py1")); m_Params.push_back(ParamWithName(true, &m_P[2].y, prefix + "hexcrop_py2")); m_Params.push_back(ParamWithName(true, &m_P[3].y, prefix + "hexcrop_py3")); m_Params.push_back(ParamWithName(true, &m_P[4].y, prefix + "hexcrop_py4")); m_Params.push_back(ParamWithName(true, &m_P[5].y, prefix + "hexcrop_py5")); } private: T m_ScaleX; T m_ScaleY; T m_CenterX; T m_CenterY; T m_Dropoff; v2T m_P[6];//Precalc. }; MAKEPREPOSTPARVAR(Bubble2, bubble2, BUBBLE2) MAKEPREPOSTPARVAR(CircleLinear, CircleLinear, CIRCLELINEAR) MAKEPREPOSTPARVARASSIGN(CircleRand, CircleRand, CIRCLERAND, eVariationAssignType::ASSIGNTYPE_SUM) MAKEPREPOSTPARVAR(CircleTrans1, CircleTrans1, CIRCLETRANS1) MAKEPREPOSTPARVAR(Cubic3D, cubic3D, CUBIC3D) MAKEPREPOSTPARVAR(CubicLattice3D, cubicLattice_3D, CUBIC_LATTICE3D) MAKEPREPOSTVAR(Foci3D, foci_3D, FOCI3D) MAKEPREPOSTPARVAR(FociP, foci_p, FOCI_P) MAKEPREPOSTPARVAR(Ho, ho, HO) MAKEPREPOSTPARVAR(Julia3Dq, julia3Dq, JULIA3DQ) MAKEPREPOSTPARVARASSIGN(Line, line, LINE, eVariationAssignType::ASSIGNTYPE_SUM) MAKEPREPOSTPARVAR(Loonie2, loonie2, LOONIE2) MAKEPREPOSTPARVAR(Loonie3, loonie3, LOONIE3) MAKEPREPOSTPARVAR(Loonie3D, loonie_3D, LOONIE3D) MAKEPREPOSTPARVAR(Mcarpet, mcarpet, MCARPET) MAKEPREPOSTPARVAR(Waves23D, waves2_3D, WAVES23D) MAKEPREPOSTPARVARASSIGN(Pie3D, pie3D, PIE3D, eVariationAssignType::ASSIGNTYPE_SUM) MAKEPREPOSTPARVAR(Popcorn23D, popcorn2_3D, POPCORN23D) MAKEPREPOSTVAR(Sinusoidal3D, sinusoidal3D, SINUSOIDAL3D) MAKEPREPOSTPARVAR(Scry3D, scry_3D, SCRY3D) MAKEPREPOSTPARVAR(Shredlin, shredlin, SHRED_LIN) MAKEPREPOSTPARVAR(SplitBrdr, SplitBrdr, SPLIT_BRDR) MAKEPREPOSTVAR(Wdisc, wdisc, WDISC) MAKEPREPOSTPARVAR(Falloff, falloff, FALLOFF) MAKEPREPOSTPARVAR(Falloff2, falloff2, FALLOFF2) MAKEPREPOSTPARVAR(Falloff3, falloff3, FALLOFF3) MAKEPREPOSTPARVAR(Xtrb, xtrb, XTRB) MAKEPREPOSTPARVAR(Hexaplay3D, hexaplay3D, HEXAPLAY3D) MAKEPREPOSTPARVAR(Hexnix3D, hexnix3D, HEXNIX3D) MAKEPREPOSTPARVAR(Hexcrop, hexcrop, HEXCROP) }